aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaarten de Vries <[email protected]>2024-05-22 17:13:38 +0200
committerMaarten de Vries <[email protected]>2024-05-27 16:10:08 +0200
commit807e573994d046d0cd00e631db111fafd2627559 (patch)
tree35d30b84fb36fff9a85b0f9b305df751da897bc7
parent854ae5da8fde2b2b33b6ad3c5de1a1d441b4d6b3 (diff)
embassy_stm32: allow scheduling lower priority frames in bxcan driver
-rw-r--r--embassy-stm32/src/can/bxcan/mod.rs16
-rw-r--r--embassy-stm32/src/can/bxcan/registers.rs10
2 files changed, 18 insertions, 8 deletions
diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs
index 05b1b83d8..0ac4cdab6 100644
--- a/embassy-stm32/src/can/bxcan/mod.rs
+++ b/embassy-stm32/src/can/bxcan/mod.rs
@@ -324,7 +324,13 @@ impl<'d, T: Instance> Can<'d, T> {
324 324
325 /// Attempts to transmit a frame without blocking. 325 /// Attempts to transmit a frame without blocking.
326 /// 326 ///
327 /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full. 327 /// Returns [Err(TryWriteError::Full)] if the frame can not be queued for transmission now.
328 ///
329 /// If FIFO scheduling is enabled, any empty mailbox will be used.
330 ///
331 /// Otherwise, the frame will only be accepted if there is no frame with the same priority already queued.
332 /// This is done to work around a hardware limitation that could lead to out-of-order delivery
333 /// of frames with the same priority.
328 pub fn try_write(&mut self, frame: &Frame) -> Result<TransmitStatus, TryWriteError> { 334 pub fn try_write(&mut self, frame: &Frame) -> Result<TransmitStatus, TryWriteError> {
329 self.split().0.try_write(frame) 335 self.split().0.try_write(frame)
330 } 336 }
@@ -487,7 +493,13 @@ impl<'d, T: Instance> CanTx<'d, T> {
487 493
488 /// Attempts to transmit a frame without blocking. 494 /// Attempts to transmit a frame without blocking.
489 /// 495 ///
490 /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full. 496 /// Returns [Err(TryWriteError::Full)] if the frame can not be queued for transmission now.
497 ///
498 /// If FIFO scheduling is enabled, any empty mailbox will be used.
499 ///
500 /// Otherwise, the frame will only be accepted if there is no frame with the same priority already queued.
501 /// This is done to work around a hardware limitation that could lead to out-of-order delivery
502 /// of frames with the same priority.
491 pub fn try_write(&mut self, frame: &Frame) -> Result<TransmitStatus, TryWriteError> { 503 pub fn try_write(&mut self, frame: &Frame) -> Result<TransmitStatus, TryWriteError> {
492 Registers(T::regs()).transmit(frame).map_err(|_| TryWriteError::Full) 504 Registers(T::regs()).transmit(frame).map_err(|_| TryWriteError::Full)
493 } 505 }
diff --git a/embassy-stm32/src/can/bxcan/registers.rs b/embassy-stm32/src/can/bxcan/registers.rs
index a0519cd1f..ad27e0744 100644
--- a/embassy-stm32/src/can/bxcan/registers.rs
+++ b/embassy-stm32/src/can/bxcan/registers.rs
@@ -239,7 +239,7 @@ impl Registers {
239 // Frames with identical priority should be transmitted in FIFO order, 239 // Frames with identical priority should be transmitted in FIFO order,
240 // but the controller schedules pending frames of same priority based on the 240 // but the controller schedules pending frames of same priority based on the
241 // mailbox index. As a workaround check all pending mailboxes and only accept 241 // mailbox index. As a workaround check all pending mailboxes and only accept
242 // higher priority frames. 242 // frames with a different priority.
243 self.check_priority(0, frame.id().into())?; 243 self.check_priority(0, frame.id().into())?;
244 self.check_priority(1, frame.id().into())?; 244 self.check_priority(1, frame.id().into())?;
245 self.check_priority(2, frame.id().into())?; 245 self.check_priority(2, frame.id().into())?;
@@ -276,18 +276,16 @@ impl Registers {
276 } 276 }
277 277
278 /// Returns `Ok` when the mailbox is free or if it contains pending frame with a 278 /// Returns `Ok` when the mailbox is free or if it contains pending frame with a
279 /// lower priority (higher ID) than the identifier `id`. 279 /// different priority from the identifier `id`.
280 fn check_priority(&self, idx: usize, id: IdReg) -> nb::Result<(), Infallible> { 280 fn check_priority(&self, idx: usize, id: IdReg) -> nb::Result<(), Infallible> {
281 // Read the pending frame's id to check its priority. 281 // Read the pending frame's id to check its priority.
282 assert!(idx < 3); 282 assert!(idx < 3);
283 let tir = &self.0.tx(idx).tir().read(); 283 let tir = &self.0.tx(idx).tir().read();
284 //let tir = &can.tx[idx].tir.read();
285 284
286 // Check the priority by comparing the identifiers. But first make sure the 285 // Check the priority by comparing the identifiers. But first make sure the
287 // frame has not finished the transmission (`TXRQ` == 0) in the meantime. 286 // frame has not finished the transmission (`TXRQ` == 0) in the meantime.
288 if tir.txrq() && id <= IdReg::from_register(tir.0) { 287 if tir.txrq() && id == IdReg::from_register(tir.0) {
289 // There's a mailbox whose priority is higher or equal 288 // There's a mailbox whose priority is equal to the priority of the new frame.
290 // the priority of the new frame.
291 return Err(nb::Error::WouldBlock); 289 return Err(nb::Error::WouldBlock);
292 } 290 }
293 291