embassy-rs/embassy · critical
ErevidIsZero
Error message
ErevidIsZero
What it means
During enc28j60::Device::init, after the clock-ready (CLKRDY) wait, the driver reads the EREVID register (silicon revision ID, bank 3) and panics if it reads 0. EREVID == 0 means the SPI read did not return a valid revision ID, which indicates the chip is not responding correctly (wiring/SPI issues, a fake/counterfeit module, or unsupported silicon). The library treats this as an unrecoverable hardware sanity check.
Solutions
- Verify SPI wiring (CS, SCK, MISO, MOSI), SPI mode 0, and a stable 3.3 V supply; scope/check MISO during the EREVID read.
- Test basic SPI communication first (e.g. read ECON1 and write/read back) before init to isolate bus problems.
- If using a cheap module, check for counterfeit ENC28J60 silicon — many clones report EREVID 0; consider a fallback that logs and continues.
- Patch the driver to warn instead of panic (replace panic!("ErevidIsZero") with a logged warning) if your hardware tolerates revision 0.
Example fix
// before (driver)
if self.read_control_register(bank3::Register::EREVID) == 0 {
panic!("ErevidIsZero");
}
// after (driver)
let erevid = self.read_control_register(bank3::Register::EREVID);
if erevid == 0 {
defmt::warn!("enc28j60: EREVID is 0 (counterfeit or SPI issue?), continuing");
}
// caller-side guard: verify SPI echo before init
// let econ1 = dev.read_control_register(common::Register::ECON1);
// assert!(econ1 == expected, "SPI bus not responding correctly"); Defensive patterns
Strategy: validation
Validate before calling
// Rust: verify SPI bus responds before calling init
fn spi_bus_alive<D>(dev: &mut D) -> bool
where D: read_control_register(...)
{
// write a known pattern to ECON1 and read it back
let probe = dev.read_control_register(common::Register::ECON1);
probe != 0xFF && probe != 0x00 // all-0xFF/all-0x00 usually means no chip / floating bus
} Type guard
// Rust: guard the EREVID read yourself before driver init
fn erevid_valid(dev: &mut Device<Spi>) -> bool {
dev.read_control_register(bank3::Register::EREVID) != 0
} Try / catch
// Rust panics cannot be caught in embedded; gate init instead:
if !spi_bus_alive(&mut dev) {
defmt::error!("enc28j60: SPI bus not responding; check wiring/power");
return Err(InitError::Bus);
}
dev.init(mac_addr); // safe once bus sanity-checked Prevention
- Verify SPI mode 0, CS wiring, and 3.3 V supply before first init.
- Do a write/read-back register probe at boot to detect bus problems early.
- Be aware counterfeit ENC28J60 modules legitimately report EREVID 0 — buy from reputable sources or tolerate revision 0.
- Keep SPI traces short and add proper decoupling on breadboard setups.
When it happens
Trigger: Calling enc28j60::Device::init when EREVID reads back 0: missing/incorrect SPI mode (must be mode 0), wrong CS pin or miswired MISO/MOSI, insufficient power, counterfeit ENC28J60 modules returning 0, or reading bank-3 register EREVID before the SPI interface is functional.
Common situations: Breadboard wiring with long/unstable SPI traces; power supply below 3.14 V; cheap clone modules where EREVID legitimately reads 0; forgetting to set the correct bank before reading EREVID in a modified driver; using a partially broken SPI bus where other reads appear to work.
Related errors
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/30b406627f9889f3.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-net-enc28j60/src/lib.rs:102
embassy_time::block_for(Duration::from_millis(5));
rst.set_high().unwrap();
embassy_time::block_for(Duration::from_millis(5));
} else {
embassy_time::block_for(Duration::from_millis(5));
self.soft_reset();
embassy_time::block_for(Duration::from_millis(5));
}
debug!(
"enc28j60: erevid {=u8:x}",
self.read_control_register(bank3::Register::EREVID)
);
debug!("enc28j60: waiting for clk");
while common::ESTAT(self.read_control_register(common::Register::ESTAT)).clkrdy() == 0 {}
debug!("enc28j60: clk ok");
if self.read_control_register(bank3::Register::EREVID) == 0 {
panic!("ErevidIsZero");
}
// disable CLKOUT output
self.write_control_register(bank3::Register::ECOCON, 0);
self.init_rx();
// TX start
// "It is recommended that an even address be used for ETXST"
debug_assert_eq!(TXST % 2, 0);
self.write_control_register(bank0::Register::ETXSTL, TXST.low());
self.write_control_register(bank0::Register::ETXSTH, TXST.high());
// TX end is set in `transmit`
// MAC initialization (see section 6.5)
// 1. Set the MARXEN bit in MACON1 to enable the MAC to receive frames.
self.write_control_register(View on GitHub (pinned to 463a07b963)