diff options
| author | Eric Yanush <[email protected]> | 2024-04-22 01:45:09 -0600 |
|---|---|---|
| committer | Eric Yanush <[email protected]> | 2024-04-22 01:46:24 -0600 |
| commit | 6e1290b3f14f141fd2f53d001ef56186b2b80a42 (patch) | |
| tree | 4f8a037406a28552c554ea68b5273f6dbbd2b8b2 | |
| parent | a5b006268b7a20ff4ea6ad0d9090c6a6f2bb4602 (diff) | |
Ensure bus errors are forwarded only once, enable bus off/passive/warning interrupts
| -rw-r--r-- | embassy-stm32/src/can/bxcan/mod.rs | 15 | ||||
| -rw-r--r-- | embassy-stm32/src/can/bxcan/registers.rs | 16 |
2 files changed, 28 insertions, 3 deletions
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<T: Instance> { | |||
| 67 | 67 | ||
| 68 | impl<T: Instance> interrupt::typelevel::Handler<T::SCEInterrupt> for SceInterruptHandler<T> { | 68 | impl<T: Instance> interrupt::typelevel::Handler<T::SCEInterrupt> for SceInterruptHandler<T> { |
| 69 | unsafe fn on_interrupt() { | 69 | unsafe fn on_interrupt() { |
| 70 | // info!("sce irq"); | 70 | info!("sce irq"); |
| 71 | let msr = T::regs().msr(); | 71 | let msr = T::regs().msr(); |
| 72 | let msr_val = msr.read(); | 72 | let msr_val = msr.read(); |
| 73 | 73 | ||
| 74 | if msr_val.erri() { | 74 | if msr_val.erri() { |
| 75 | msr.modify(|v| v.set_erri(true)); | 75 | info!("Error interrupt"); |
| 76 | // Disable the interrupt, but don't acknowledge the error, so that it can be | ||
| 77 | // forwarded off the the bus message consumer. If we don't provide some way for | ||
| 78 | // downstream code to determine that it has already provided this bus error instance | ||
| 79 | // to the bus message consumer, we are doomed to re-provide a single error instance for | ||
| 80 | // an indefinite amount of time. | ||
| 81 | let ier = T::regs().ier(); | ||
| 82 | ier.modify(|i| i.set_errie(false)); | ||
| 83 | |||
| 76 | T::state().err_waker.wake(); | 84 | T::state().err_waker.wake(); |
| 77 | } | 85 | } |
| 78 | } | 86 | } |
| @@ -180,6 +188,9 @@ impl<'d, T: Instance> Can<'d, T> { | |||
| 180 | w.set_fmpie(0, true); | 188 | w.set_fmpie(0, true); |
| 181 | w.set_fmpie(1, true); | 189 | w.set_fmpie(1, true); |
| 182 | w.set_tmeie(true); | 190 | w.set_tmeie(true); |
| 191 | w.set_bofie(true); | ||
| 192 | w.set_epvie(true); | ||
| 193 | w.set_ewgie(true); | ||
| 183 | }); | 194 | }); |
| 184 | 195 | ||
| 185 | T::regs().mcr().write(|w| { | 196 | 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 { | |||
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | pub fn curr_error(&self) -> Option<BusError> { | 147 | pub fn curr_error(&self) -> Option<BusError> { |
| 148 | let err = { self.0.esr().read() }; | 148 | if !self.0.msr().read().erri() { |
| 149 | // This ensures that once a single error instance has | ||
| 150 | // been acknowledged and forwared to the bus message consumer | ||
| 151 | // we don't continue to re-forward the same error occurrance for an | ||
| 152 | // in-definite amount of time. | ||
| 153 | return None; | ||
| 154 | } | ||
| 155 | |||
| 156 | // Since we have not already acknowledge the error, and the interrupt was | ||
| 157 | // disabled in the ISR, we will acknowledge the current error and re-enable the interrupt | ||
| 158 | // so futher errors are captured | ||
| 159 | self.0.msr().modify(|m| m.set_erri(true)); | ||
| 160 | self.0.ier().modify(|i| i.set_errie(true)); | ||
| 161 | |||
| 162 | let err = self.0.esr().read(); | ||
| 149 | if err.boff() { | 163 | if err.boff() { |
| 150 | return Some(BusError::BusOff); | 164 | return Some(BusError::BusOff); |
| 151 | } else if err.epvf() { | 165 | } else if err.epvf() { |
