diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs index 65fd0e9c2..d43ce778d 100644 --- a/embassy-stm32/src/can/bxcan/mod.rs +++ b/embassy-stm32/src/can/bxcan/mod.rs @@ -67,12 +67,20 @@ pub struct SceInterruptHandler { impl interrupt::typelevel::Handler for SceInterruptHandler { unsafe fn on_interrupt() { - // info!("sce irq"); + info!("sce irq"); let msr = T::regs().msr(); let msr_val = msr.read(); if msr_val.erri() { - msr.modify(|v| v.set_erri(true)); + info!("Error interrupt"); + // Disable the interrupt, but don't acknowledge the error, so that it can be + // forwarded off the the bus message consumer. If we don't provide some way for + // downstream code to determine that it has already provided this bus error instance + // to the bus message consumer, we are doomed to re-provide a single error instance for + // an indefinite amount of time. + let ier = T::regs().ier(); + ier.modify(|i| i.set_errie(false)); + T::state().err_waker.wake(); } } @@ -180,6 +188,9 @@ impl<'d, T: Instance> Can<'d, T> { w.set_fmpie(0, true); w.set_fmpie(1, true); w.set_tmeie(true); + w.set_bofie(true); + w.set_epvie(true); + w.set_ewgie(true); }); T::regs().mcr().write(|w| { diff --git a/embassy-stm32/src/can/bxcan/registers.rs b/embassy-stm32/src/can/bxcan/registers.rs index 732567797..225b25d8a 100644 --- a/embassy-stm32/src/can/bxcan/registers.rs +++ b/embassy-stm32/src/can/bxcan/registers.rs @@ -145,7 +145,21 @@ impl Registers { } pub fn curr_error(&self) -> Option { - let err = { self.0.esr().read() }; + if !self.0.msr().read().erri() { + // This ensures that once a single error instance has + // been acknowledged and forwared to the bus message consumer + // we don't continue to re-forward the same error occurrance for an + // in-definite amount of time. + return None; + } + + // Since we have not already acknowledge the error, and the interrupt was + // disabled in the ISR, we will acknowledge the current error and re-enable the interrupt + // so futher errors are captured + self.0.msr().modify(|m| m.set_erri(true)); + self.0.ier().modify(|i| i.set_errie(true)); + + let err = self.0.esr().read(); if err.boff() { return Some(BusError::BusOff); } else if err.epvf() {