aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Yanush <[email protected]>2024-04-22 01:45:09 -0600
committerEric Yanush <[email protected]>2024-04-22 01:46:24 -0600
commit6e1290b3f14f141fd2f53d001ef56186b2b80a42 (patch)
tree4f8a037406a28552c554ea68b5273f6dbbd2b8b2
parenta5b006268b7a20ff4ea6ad0d9090c6a6f2bb4602 (diff)
Ensure bus errors are forwarded only once, enable bus off/passive/warning interrupts
-rw-r--r--embassy-stm32/src/can/bxcan/mod.rs15
-rw-r--r--embassy-stm32/src/can/bxcan/registers.rs16
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
68impl<T: Instance> interrupt::typelevel::Handler<T::SCEInterrupt> for SceInterruptHandler<T> { 68impl<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() {