aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-04-02 01:29:52 +0200
committerDario Nieuwenhuis <[email protected]>2024-04-02 11:08:03 +0200
commitc8936edb6c13eb099dfb31a4a51be2dd3bb4661e (patch)
tree0dd904e9264bc0e15ab54490cf2caa91717d9d1f
parente0f0430e2cb04f373f3e93e7abd27eba39d3eb7f (diff)
stm32/can: simplify bxcan api, merging bx::* into the main structs.
The bx::* separate structs (Can, Rx, Tx) and separate `Instance` trait are a relic from the `bxcan` crate. Remove them, move the functionality into the main structs.
-rw-r--r--embassy-stm32/src/can/bx/mod.rs1010
-rw-r--r--embassy-stm32/src/can/bxcan/filter.rs (renamed from embassy-stm32/src/can/bx/filter.rs)2
-rw-r--r--embassy-stm32/src/can/bxcan/mod.rs (renamed from embassy-stm32/src/can/bxcan.rs)342
-rw-r--r--embassy-stm32/src/can/bxcan/registers.rs510
-rw-r--r--embassy-stm32/src/can/common.rs4
-rw-r--r--embassy-stm32/src/can/fdcan.rs34
-rw-r--r--embassy-stm32/src/can/mod.rs9
-rw-r--r--examples/stm32f1/src/bin/can.rs13
-rw-r--r--examples/stm32f4/src/bin/can.rs11
-rw-r--r--examples/stm32f7/src/bin/can.rs12
-rw-r--r--tests/stm32/src/bin/can.rs19
11 files changed, 807 insertions, 1159 deletions
diff --git a/embassy-stm32/src/can/bx/mod.rs b/embassy-stm32/src/can/bx/mod.rs
deleted file mode 100644
index cd82148ba..000000000
--- a/embassy-stm32/src/can/bx/mod.rs
+++ /dev/null
@@ -1,1010 +0,0 @@
1//! Driver for the STM32 bxCAN peripheral.
2//!
3//! This crate provides a reusable driver for the bxCAN peripheral found in many low- to middle-end
4//! STM32 microcontrollers. HALs for compatible chips can reexport this crate and implement its
5//! traits to easily expose a featureful CAN driver.
6//!
7//! # Features
8//!
9//! - Supports both single- and dual-peripheral configurations (where one bxCAN instance manages the
10//! filters of a secondary instance).
11//! - Handles standard and extended frames, and data and remote frames.
12//! - Support for interrupts emitted by the bxCAN peripheral.
13//! - Transmission respects CAN IDs and protects against priority inversion (a lower-priority frame
14//! may be dequeued when enqueueing a higher-priority one).
15//! - Implements the [`embedded-hal`] traits for interoperability.
16//! - Support for both RX FIFOs (as [`Rx0`] and [`Rx1`]).
17//!
18//! # Limitations
19//!
20//! - Support for querying error states and handling error interrupts is incomplete.
21//!
22
23// Deny a few warnings in doctests, since rustdoc `allow`s many warnings by default
24#![allow(clippy::unnecessary_operation)] // lint is bugged
25
26//mod embedded_hal;
27pub mod filter;
28
29#[allow(clippy::all)] // generated code
30use core::cmp::{Ord, Ordering};
31use core::convert::Infallible;
32use core::marker::PhantomData;
33use core::mem;
34
35pub use embedded_can::{ExtendedId, Id, StandardId};
36
37/// CAN Header: includes ID and length
38pub type Header = crate::can::frame::Header;
39
40/// Data for a CAN Frame
41pub type Data = crate::can::frame::ClassicData;
42
43use crate::can::_version::Envelope;
44use crate::can::bx::filter::MasterFilters;
45use crate::can::enums::BusError;
46/// CAN Frame
47pub use crate::can::frame::Frame;
48use crate::pac::can::vals::Lec;
49
50#[derive(Debug, Copy, Clone, Eq, PartialEq)]
51pub(crate) enum RxFifo {
52 Fifo0,
53 Fifo1,
54}
55
56trait IntoBusError {
57 fn into_bus_err(self) -> Option<BusError>;
58}
59
60impl IntoBusError for Lec {
61 fn into_bus_err(self) -> Option<BusError> {
62 match self {
63 Lec::STUFF => Some(BusError::Stuff),
64 Lec::FORM => Some(BusError::Form),
65 Lec::ACK => Some(BusError::Acknowledge),
66 Lec::BITRECESSIVE => Some(BusError::BitRecessive),
67 Lec::BITDOMINANT => Some(BusError::BitDominant),
68 Lec::CRC => Some(BusError::Crc),
69 Lec::CUSTOM => Some(BusError::Software),
70 _ => None,
71 }
72 }
73}
74
75/// A bxCAN peripheral instance.
76///
77/// This trait is meant to be implemented for a HAL-specific type that represent ownership of
78/// the CAN peripheral (and any pins required by it, although that is entirely up to the HAL).
79///
80/// # Safety
81///
82/// It is only safe to implement this trait, when:
83///
84/// * The implementing type has ownership of the peripheral, preventing any other accesses to the
85/// register block.
86/// * `REGISTERS` is a pointer to that peripheral's register block and can be safely accessed for as
87/// long as ownership or a borrow of the implementing type is present.
88pub unsafe trait Instance {}
89
90/// A bxCAN instance that owns filter banks.
91///
92/// In master-slave-instance setups, only the master instance owns the filter banks, and needs to
93/// split some of them off for use by the slave instance. In that case, the master instance should
94/// implement [`FilterOwner`] and [`MasterInstance`], while the slave instance should only implement
95/// [`Instance`].
96///
97/// In single-instance configurations, the instance owns all filter banks and they can not be split
98/// off. In that case, the instance should implement [`Instance`] and [`FilterOwner`].
99///
100/// # Safety
101///
102/// This trait must only be implemented if the instance does, in fact, own its associated filter
103/// banks, and `NUM_FILTER_BANKS` must be correct.
104pub unsafe trait FilterOwner: Instance {
105 /// The total number of filter banks available to the instance.
106 ///
107 /// This is usually either 14 or 28, and should be specified in the chip's reference manual or datasheet.
108 const NUM_FILTER_BANKS: u8;
109}
110
111/// A bxCAN master instance that shares filter banks with a slave instance.
112///
113/// In master-slave-instance setups, this trait should be implemented for the master instance.
114///
115/// # Safety
116///
117/// This trait must only be implemented when there is actually an associated slave instance.
118pub unsafe trait MasterInstance: FilterOwner {}
119
120// TODO: what to do with these?
121/*
122#[derive(Debug, Copy, Clone, Eq, PartialEq, Format)]
123pub enum Error {
124 Stuff,
125 Form,
126 Acknowledgement,
127 BitRecessive,
128 BitDominant,
129 Crc,
130 Software,
131}*/
132
133/// Error that indicates that an incoming message has been lost due to buffer overrun.
134#[derive(Debug, Clone, Copy, PartialEq, Eq)]
135#[cfg_attr(feature = "defmt", derive(defmt::Format))]
136pub struct OverrunError {
137 _priv: (),
138}
139
140/// Identifier of a CAN message.
141///
142/// Can be either a standard identifier (11bit, Range: 0..0x3FF) or a
143/// extendended identifier (29bit , Range: 0..0x1FFFFFFF).
144///
145/// The `Ord` trait can be used to determine the frame’s priority this ID
146/// belongs to.
147/// Lower identifier values have a higher priority. Additionally standard frames
148/// have a higher priority than extended frames and data frames have a higher
149/// priority than remote frames.
150#[derive(Clone, Copy, Debug, PartialEq, Eq)]
151#[cfg_attr(feature = "defmt", derive(defmt::Format))]
152pub(crate) struct IdReg(u32);
153
154impl IdReg {
155 const STANDARD_SHIFT: u32 = 21;
156
157 const EXTENDED_SHIFT: u32 = 3;
158
159 const IDE_MASK: u32 = 0x0000_0004;
160
161 const RTR_MASK: u32 = 0x0000_0002;
162
163 /// Creates a new standard identifier (11bit, Range: 0..0x7FF)
164 ///
165 /// Panics for IDs outside the allowed range.
166 fn new_standard(id: StandardId) -> Self {
167 Self(u32::from(id.as_raw()) << Self::STANDARD_SHIFT)
168 }
169
170 /// Creates a new extendended identifier (29bit , Range: 0..0x1FFFFFFF).
171 ///
172 /// Panics for IDs outside the allowed range.
173 fn new_extended(id: ExtendedId) -> IdReg {
174 Self(id.as_raw() << Self::EXTENDED_SHIFT | Self::IDE_MASK)
175 }
176
177 fn from_register(reg: u32) -> IdReg {
178 Self(reg & 0xFFFF_FFFE)
179 }
180
181 /// Returns the identifier.
182 fn to_id(self) -> Id {
183 if self.is_extended() {
184 Id::Extended(unsafe { ExtendedId::new_unchecked(self.0 >> Self::EXTENDED_SHIFT) })
185 } else {
186 Id::Standard(unsafe { StandardId::new_unchecked((self.0 >> Self::STANDARD_SHIFT) as u16) })
187 }
188 }
189
190 /// Returns the identifier.
191 fn id(self) -> embedded_can::Id {
192 if self.is_extended() {
193 embedded_can::ExtendedId::new(self.0 >> Self::EXTENDED_SHIFT)
194 .unwrap()
195 .into()
196 } else {
197 embedded_can::StandardId::new((self.0 >> Self::STANDARD_SHIFT) as u16)
198 .unwrap()
199 .into()
200 }
201 }
202
203 /// Returns `true` if the identifier is an extended identifier.
204 fn is_extended(self) -> bool {
205 self.0 & Self::IDE_MASK != 0
206 }
207
208 /// Returns `true` if the identifer is part of a remote frame (RTR bit set).
209 fn rtr(self) -> bool {
210 self.0 & Self::RTR_MASK != 0
211 }
212}
213
214impl From<&embedded_can::Id> for IdReg {
215 fn from(eid: &embedded_can::Id) -> Self {
216 match eid {
217 embedded_can::Id::Standard(id) => IdReg::new_standard(StandardId::new(id.as_raw()).unwrap()),
218 embedded_can::Id::Extended(id) => IdReg::new_extended(ExtendedId::new(id.as_raw()).unwrap()),
219 }
220 }
221}
222
223impl From<IdReg> for embedded_can::Id {
224 fn from(idr: IdReg) -> Self {
225 idr.id()
226 }
227}
228
229/// `IdReg` is ordered by priority.
230impl Ord for IdReg {
231 fn cmp(&self, other: &Self) -> Ordering {
232 // When the IDs match, data frames have priority over remote frames.
233 let rtr = self.rtr().cmp(&other.rtr()).reverse();
234
235 let id_a = self.to_id();
236 let id_b = other.to_id();
237 match (id_a, id_b) {
238 (Id::Standard(a), Id::Standard(b)) => {
239 // Lower IDs have priority over higher IDs.
240 a.as_raw().cmp(&b.as_raw()).reverse().then(rtr)
241 }
242 (Id::Extended(a), Id::Extended(b)) => a.as_raw().cmp(&b.as_raw()).reverse().then(rtr),
243 (Id::Standard(a), Id::Extended(b)) => {
244 // Standard frames have priority over extended frames if their Base IDs match.
245 a.as_raw()
246 .cmp(&b.standard_id().as_raw())
247 .reverse()
248 .then(Ordering::Greater)
249 }
250 (Id::Extended(a), Id::Standard(b)) => {
251 a.standard_id().as_raw().cmp(&b.as_raw()).reverse().then(Ordering::Less)
252 }
253 }
254 }
255}
256
257impl PartialOrd for IdReg {
258 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
259 Some(self.cmp(other))
260 }
261}
262
263pub(crate) struct Registers {
264 pub canregs: crate::pac::can::Can,
265}
266
267impl Registers {
268 fn enter_init_mode(&mut self) {
269 self.canregs.mcr().modify(|reg| {
270 reg.set_sleep(false);
271 reg.set_inrq(true);
272 });
273 loop {
274 let msr = self.canregs.msr().read();
275 if !msr.slak() && msr.inak() {
276 break;
277 }
278 }
279 }
280
281 // Leaves initialization mode, enters sleep mode.
282 fn leave_init_mode(&mut self) {
283 self.canregs.mcr().modify(|reg| {
284 reg.set_sleep(true);
285 reg.set_inrq(false);
286 });
287 loop {
288 let msr = self.canregs.msr().read();
289 if msr.slak() && !msr.inak() {
290 break;
291 }
292 }
293 }
294
295 fn set_bit_timing(&mut self, bt: crate::can::util::NominalBitTiming) {
296 let prescaler = u16::from(bt.prescaler) & 0x1FF;
297 let seg1 = u8::from(bt.seg1);
298 let seg2 = u8::from(bt.seg2) & 0x7F;
299 let sync_jump_width = u8::from(bt.sync_jump_width) & 0x7F;
300 self.canregs.btr().modify(|reg| {
301 reg.set_brp(prescaler - 1);
302 reg.set_ts(0, seg1 - 1);
303 reg.set_ts(1, seg2 - 1);
304 reg.set_sjw(sync_jump_width - 1);
305 });
306 }
307
308 /// Enables or disables silent mode: Disconnects the TX signal from the pin.
309 pub fn set_silent(&self, enabled: bool) {
310 let mode = match enabled {
311 false => stm32_metapac::can::vals::Silm::NORMAL,
312 true => stm32_metapac::can::vals::Silm::SILENT,
313 };
314 self.canregs.btr().modify(|reg| reg.set_silm(mode));
315 }
316
317 /// Enables or disables automatic retransmission of messages.
318 ///
319 /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame
320 /// until it can be sent. Otherwise, it will try only once to send each frame.
321 ///
322 /// Automatic retransmission is enabled by default.
323 pub fn set_automatic_retransmit(&self, enabled: bool) {
324 self.canregs.mcr().modify(|reg| reg.set_nart(enabled));
325 }
326
327 /// Enables or disables loopback mode: Internally connects the TX and RX
328 /// signals together.
329 pub fn set_loopback(&self, enabled: bool) {
330 self.canregs.btr().modify(|reg| reg.set_lbkm(enabled));
331 }
332
333 /// Configures the automatic wake-up feature.
334 ///
335 /// This is turned off by default.
336 ///
337 /// When turned on, an incoming frame will cause the peripheral to wake up from sleep and
338 /// receive the frame. If enabled, [`Interrupt::Wakeup`] will also be triggered by the incoming
339 /// frame.
340 #[allow(dead_code)]
341 pub fn set_automatic_wakeup(&mut self, enabled: bool) {
342 self.canregs.mcr().modify(|reg| reg.set_awum(enabled));
343 }
344
345 /// Leaves initialization mode and enables the peripheral (non-blocking version).
346 ///
347 /// Usually, it is recommended to call [`CanConfig::enable`] instead. This method is only needed
348 /// if you want non-blocking initialization.
349 ///
350 /// If this returns [`WouldBlock`][nb::Error::WouldBlock], the peripheral will enable itself
351 /// in the background. The peripheral is enabled and ready to use when this method returns
352 /// successfully.
353 pub fn enable_non_blocking(&mut self) -> nb::Result<(), Infallible> {
354 let msr = self.canregs.msr().read();
355 if msr.slak() {
356 self.canregs.mcr().modify(|reg| {
357 reg.set_abom(true);
358 reg.set_sleep(false);
359 });
360 Err(nb::Error::WouldBlock)
361 } else {
362 Ok(())
363 }
364 }
365
366 /// Puts the peripheral in a sleep mode to save power.
367 ///
368 /// While in sleep mode, an incoming CAN frame will trigger [`Interrupt::Wakeup`] if enabled.
369 #[allow(dead_code)]
370 pub fn sleep(&mut self) {
371 self.canregs.mcr().modify(|reg| {
372 reg.set_sleep(true);
373 reg.set_inrq(false);
374 });
375 loop {
376 let msr = self.canregs.msr().read();
377 if msr.slak() && !msr.inak() {
378 break;
379 }
380 }
381 }
382
383 /// Disables the CAN interface.
384 ///
385 /// The peripheral is disabled by setting `RESET` in `CAN_MCR`, which causes the peripheral to
386 /// enter sleep mode.
387 pub fn reset(&self) {
388 self.canregs.mcr().write(|reg| reg.set_reset(true));
389 }
390
391 /// Wakes up from sleep mode.
392 ///
393 /// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN
394 /// frame will cause that interrupt.
395 #[allow(dead_code)]
396 pub fn wakeup(&mut self) {
397 self.canregs.mcr().modify(|reg| {
398 reg.set_sleep(false);
399 reg.set_inrq(false);
400 });
401 loop {
402 let msr = self.canregs.msr().read();
403 if !msr.slak() && !msr.inak() {
404 break;
405 }
406 }
407 }
408
409 pub fn curr_error(&self) -> Option<BusError> {
410 let err = { self.canregs.esr().read() };
411 if err.boff() {
412 return Some(BusError::BusOff);
413 } else if err.epvf() {
414 return Some(BusError::BusPassive);
415 } else if err.ewgf() {
416 return Some(BusError::BusWarning);
417 } else if let Some(err) = err.lec().into_bus_err() {
418 return Some(err);
419 }
420 None
421 }
422
423 /// Puts a CAN frame in a transmit mailbox for transmission on the bus.
424 ///
425 /// Frames are transmitted to the bus based on their priority (see [`FramePriority`]).
426 /// Transmit order is preserved for frames with identical priority.
427 ///
428 /// If all transmit mailboxes are full, and `frame` has a higher priority than the
429 /// lowest-priority message in the transmit mailboxes, transmission of the enqueued frame is
430 /// cancelled and `frame` is enqueued instead. The frame that was replaced is returned as
431 /// [`TransmitStatus::dequeued_frame`].
432 pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
433 // Get the index of the next free mailbox or the one with the lowest priority.
434 let tsr = self.canregs.tsr().read();
435 let idx = tsr.code() as usize;
436
437 let frame_is_pending = !tsr.tme(0) || !tsr.tme(1) || !tsr.tme(2);
438 let pending_frame = if frame_is_pending {
439 // High priority frames are transmitted first by the mailbox system.
440 // Frames with identical identifier shall be transmitted in FIFO order.
441 // The controller schedules pending frames of same priority based on the
442 // mailbox index instead. As a workaround check all pending mailboxes
443 // and only accept higher priority frames.
444 self.check_priority(0, frame.id().into())?;
445 self.check_priority(1, frame.id().into())?;
446 self.check_priority(2, frame.id().into())?;
447
448 let all_frames_are_pending = !tsr.tme(0) && !tsr.tme(1) && !tsr.tme(2);
449 if all_frames_are_pending {
450 // No free mailbox is available. This can only happen when three frames with
451 // ascending priority (descending IDs) were requested for transmission and all
452 // of them are blocked by bus traffic with even higher priority.
453 // To prevent a priority inversion abort and replace the lowest priority frame.
454 self.read_pending_mailbox(idx)
455 } else {
456 // There was a free mailbox.
457 None
458 }
459 } else {
460 // All mailboxes are available: Send frame without performing any checks.
461 None
462 };
463
464 self.write_mailbox(idx, frame);
465
466 let mailbox = match idx {
467 0 => Mailbox::Mailbox0,
468 1 => Mailbox::Mailbox1,
469 2 => Mailbox::Mailbox2,
470 _ => unreachable!(),
471 };
472 Ok(TransmitStatus {
473 dequeued_frame: pending_frame,
474 mailbox,
475 })
476 }
477
478 /// Returns `Ok` when the mailbox is free or if it contains pending frame with a
479 /// lower priority (higher ID) than the identifier `id`.
480 fn check_priority(&self, idx: usize, id: IdReg) -> nb::Result<(), Infallible> {
481 // Read the pending frame's id to check its priority.
482 assert!(idx < 3);
483 let tir = &self.canregs.tx(idx).tir().read();
484 //let tir = &can.tx[idx].tir.read();
485
486 // Check the priority by comparing the identifiers. But first make sure the
487 // frame has not finished the transmission (`TXRQ` == 0) in the meantime.
488 if tir.txrq() && id <= IdReg::from_register(tir.0) {
489 // There's a mailbox whose priority is higher or equal
490 // the priority of the new frame.
491 return Err(nb::Error::WouldBlock);
492 }
493
494 Ok(())
495 }
496
497 fn write_mailbox(&mut self, idx: usize, frame: &Frame) {
498 debug_assert!(idx < 3);
499
500 let mb = self.canregs.tx(idx);
501 mb.tdtr().write(|w| w.set_dlc(frame.header().len() as u8));
502
503 mb.tdlr()
504 .write(|w| w.0 = u32::from_ne_bytes(frame.data()[0..4].try_into().unwrap()));
505 mb.tdhr()
506 .write(|w| w.0 = u32::from_ne_bytes(frame.data()[4..8].try_into().unwrap()));
507 let id: IdReg = frame.id().into();
508 mb.tir().write(|w| {
509 w.0 = id.0;
510 w.set_txrq(true);
511 });
512 }
513
514 fn read_pending_mailbox(&mut self, idx: usize) -> Option<Frame> {
515 if self.abort_by_index(idx) {
516 debug_assert!(idx < 3);
517
518 let mb = self.canregs.tx(idx);
519
520 let id = IdReg(mb.tir().read().0);
521 let mut data = [0xff; 8];
522 data[0..4].copy_from_slice(&mb.tdlr().read().0.to_ne_bytes());
523 data[4..8].copy_from_slice(&mb.tdhr().read().0.to_ne_bytes());
524 let len = mb.tdtr().read().dlc();
525
526 Some(Frame::new(Header::new(id.id(), len, id.rtr()), &data).unwrap())
527 } else {
528 // Abort request failed because the frame was already sent (or being sent) on
529 // the bus. All mailboxes are now free. This can happen for small prescaler
530 // values (e.g. 1MBit/s bit timing with a source clock of 8MHz) or when an ISR
531 // has preempted the execution.
532 None
533 }
534 }
535
536 /// Tries to abort a pending frame. Returns `true` when aborted.
537 fn abort_by_index(&mut self, idx: usize) -> bool {
538 self.canregs.tsr().write(|reg| reg.set_abrq(idx, true));
539
540 // Wait for the abort request to be finished.
541 loop {
542 let tsr = self.canregs.tsr().read();
543 if false == tsr.abrq(idx) {
544 break tsr.txok(idx) == false;
545 }
546 }
547 }
548
549 /// Attempts to abort the sending of a frame that is pending in a mailbox.
550 ///
551 /// If there is no frame in the provided mailbox, or its transmission succeeds before it can be
552 /// aborted, this function has no effect and returns `false`.
553 ///
554 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
555 /// returns `true`.
556 pub fn abort(&mut self, mailbox: Mailbox) -> bool {
557 // If the mailbox is empty, the value of TXOKx depends on what happened with the previous
558 // frame in that mailbox. Only call abort_by_index() if the mailbox is not empty.
559 let tsr = self.canregs.tsr().read();
560 let mailbox_empty = match mailbox {
561 Mailbox::Mailbox0 => tsr.tme(0),
562 Mailbox::Mailbox1 => tsr.tme(1),
563 Mailbox::Mailbox2 => tsr.tme(2),
564 };
565 if mailbox_empty {
566 false
567 } else {
568 self.abort_by_index(mailbox as usize)
569 }
570 }
571
572 /// Returns `true` if no frame is pending for transmission.
573 pub fn is_idle(&self) -> bool {
574 let tsr = self.canregs.tsr().read();
575 tsr.tme(0) && tsr.tme(1) && tsr.tme(2)
576 }
577
578 /// Clears the request complete flag for all mailboxes.
579 pub fn clear_interrupt_flags(&mut self) {
580 self.canregs.tsr().write(|reg| {
581 reg.set_rqcp(0, true);
582 reg.set_rqcp(1, true);
583 reg.set_rqcp(2, true);
584 });
585 }
586
587 pub fn receive_frame_available(&self) -> bool {
588 if self.canregs.rfr(0).read().fmp() != 0 {
589 true
590 } else if self.canregs.rfr(1).read().fmp() != 0 {
591 true
592 } else {
593 false
594 }
595 }
596
597 pub fn receive_fifo(&self, fifo: crate::can::_version::bx::RxFifo) -> Option<Envelope> {
598 // Generate timestamp as early as possible
599 #[cfg(feature = "time")]
600 let ts = embassy_time::Instant::now();
601
602 use crate::pac::can::vals::Ide;
603
604 let fifo_idx = match fifo {
605 crate::can::_version::bx::RxFifo::Fifo0 => 0usize,
606 crate::can::_version::bx::RxFifo::Fifo1 => 1usize,
607 };
608 let rfr = self.canregs.rfr(fifo_idx);
609 let fifo = self.canregs.rx(fifo_idx);
610
611 // If there are no pending messages, there is nothing to do
612 if rfr.read().fmp() == 0 {
613 return None;
614 }
615
616 let rir = fifo.rir().read();
617 let id: embedded_can::Id = if rir.ide() == Ide::STANDARD {
618 embedded_can::StandardId::new(rir.stid()).unwrap().into()
619 } else {
620 let stid = (rir.stid() & 0x7FF) as u32;
621 let exid = rir.exid() & 0x3FFFF;
622 let id = (stid << 18) | (exid);
623 embedded_can::ExtendedId::new(id).unwrap().into()
624 };
625 let rdtr = fifo.rdtr().read();
626 let data_len = rdtr.dlc();
627 let rtr = rir.rtr() == stm32_metapac::can::vals::Rtr::REMOTE;
628
629 #[cfg(not(feature = "time"))]
630 let ts = rdtr.time();
631
632 let mut data: [u8; 8] = [0; 8];
633 data[0..4].copy_from_slice(&fifo.rdlr().read().0.to_ne_bytes());
634 data[4..8].copy_from_slice(&fifo.rdhr().read().0.to_ne_bytes());
635
636 let frame = Frame::new(Header::new(id, data_len, rtr), &data).unwrap();
637 let envelope = Envelope { ts, frame };
638
639 rfr.modify(|v| v.set_rfom(true));
640
641 Some(envelope)
642 }
643}
644
645/// Configuration proxy returned by [`Can::modify_config`].
646#[must_use = "`CanConfig` leaves the peripheral in uninitialized state, call `CanConfig::enable` or explicitly drop the value"]
647pub struct CanConfig<'a, I: Instance> {
648 can: &'a mut Can<I>,
649}
650
651impl<I: Instance> CanConfig<'_, I> {
652 /// Configures the bit timings.
653 ///
654 /// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter
655 /// parameters as follows:
656 ///
657 /// - *Clock Rate*: The input clock speed to the CAN peripheral (*not* the CPU clock speed).
658 /// This is the clock rate of the peripheral bus the CAN peripheral is attached to (eg. APB1).
659 /// - *Sample Point*: Should normally be left at the default value of 87.5%.
660 /// - *SJW*: Should normally be left at the default value of 1.
661 ///
662 /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
663 /// parameter to this method.
664 pub fn set_bit_timing(self, bt: crate::can::util::NominalBitTiming) -> Self {
665 self.can.registers.set_bit_timing(bt);
666 self
667 }
668
669 /// Enables or disables loopback mode: Internally connects the TX and RX
670 /// signals together.
671 pub fn set_loopback(self, enabled: bool) -> Self {
672 self.can.registers.set_loopback(enabled);
673 self
674 }
675
676 /// Enables or disables silent mode: Disconnects the TX signal from the pin.
677 pub fn set_silent(self, enabled: bool) -> Self {
678 self.can.registers.set_silent(enabled);
679 self
680 }
681
682 /// Enables or disables automatic retransmission of messages.
683 ///
684 /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame
685 /// until it can be sent. Otherwise, it will try only once to send each frame.
686 ///
687 /// Automatic retransmission is enabled by default.
688 pub fn set_automatic_retransmit(self, enabled: bool) -> Self {
689 self.can.registers.set_automatic_retransmit(enabled);
690 self
691 }
692
693 /// Leaves initialization mode and enables the peripheral.
694 ///
695 /// To sync with the CAN bus, this will block until 11 consecutive recessive bits are detected
696 /// on the bus.
697 ///
698 /// If you want to finish configuration without enabling the peripheral, you can call
699 /// [`CanConfig::leave_disabled`] or [`drop`] the [`CanConfig`] instead.
700 pub fn enable(self) {
701 self.can.registers.leave_init_mode();
702
703 match nb::block!(self.can.registers.enable_non_blocking()) {
704 Ok(()) => {}
705 Err(void) => match void {},
706 }
707
708 // Don't run the destructor.
709 mem::forget(self);
710 }
711
712 /// Leaves initialization mode, but keeps the peripheral in sleep mode.
713 ///
714 /// Before the [`Can`] instance can be used, you have to enable it by calling
715 /// [`Can::enable_non_blocking`].
716 pub fn leave_disabled(self) {
717 self.can.registers.leave_init_mode();
718 }
719}
720
721impl<I: Instance> Drop for CanConfig<'_, I> {
722 #[inline]
723 fn drop(&mut self) {
724 self.can.registers.leave_init_mode();
725 }
726}
727
728/// Builder returned by [`Can::builder`].
729#[must_use = "`CanBuilder` leaves the peripheral in uninitialized state, call `CanBuilder::enable` or `CanBuilder::leave_disabled`"]
730pub struct CanBuilder<I: Instance> {
731 can: Can<I>,
732}
733
734impl<I: Instance> CanBuilder<I> {
735 /// Configures the bit timings.
736 ///
737 /// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter
738 /// parameters as follows:
739 ///
740 /// - *Clock Rate*: The input clock speed to the CAN peripheral (*not* the CPU clock speed).
741 /// This is the clock rate of the peripheral bus the CAN peripheral is attached to (eg. APB1).
742 /// - *Sample Point*: Should normally be left at the default value of 87.5%.
743 /// - *SJW*: Should normally be left at the default value of 1.
744 ///
745 /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
746 /// parameter to this method.
747 pub fn set_bit_timing(mut self, bt: crate::can::util::NominalBitTiming) -> Self {
748 self.can.registers.set_bit_timing(bt);
749 self
750 }
751 /// Enables or disables loopback mode: Internally connects the TX and RX
752 /// signals together.
753 pub fn set_loopback(self, enabled: bool) -> Self {
754 self.can.registers.set_loopback(enabled);
755 self
756 }
757
758 /// Enables or disables silent mode: Disconnects the TX signal from the pin.
759 pub fn set_silent(self, enabled: bool) -> Self {
760 self.can.registers.set_silent(enabled);
761 self
762 }
763
764 /// Enables or disables automatic retransmission of messages.
765 ///
766 /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame
767 /// until it can be sent. Otherwise, it will try only once to send each frame.
768 ///
769 /// Automatic retransmission is enabled by default.
770 pub fn set_automatic_retransmit(self, enabled: bool) -> Self {
771 self.can.registers.set_automatic_retransmit(enabled);
772 self
773 }
774
775 /// Leaves initialization mode and enables the peripheral.
776 ///
777 /// To sync with the CAN bus, this will block until 11 consecutive recessive bits are detected
778 /// on the bus.
779 ///
780 /// If you want to finish configuration without enabling the peripheral, you can call
781 /// [`CanBuilder::leave_disabled`] instead.
782 pub fn enable(mut self) -> Can<I> {
783 self.leave_init_mode();
784
785 match nb::block!(self.can.registers.enable_non_blocking()) {
786 Ok(()) => self.can,
787 Err(void) => match void {},
788 }
789 }
790
791 /// Returns the [`Can`] interface without enabling it.
792 ///
793 /// This leaves initialization mode, but keeps the peripheral in sleep mode instead of enabling
794 /// it.
795 ///
796 /// Before the [`Can`] instance can be used, you have to enable it by calling
797 /// [`Can::enable_non_blocking`].
798 pub fn leave_disabled(mut self) -> Can<I> {
799 self.leave_init_mode();
800 self.can
801 }
802
803 /// Leaves initialization mode, enters sleep mode.
804 fn leave_init_mode(&mut self) {
805 self.can.registers.leave_init_mode();
806 }
807}
808
809/// Interface to a bxCAN peripheral.
810pub struct Can<I: Instance> {
811 instance: I,
812 canregs: crate::pac::can::Can,
813 pub(crate) registers: Registers,
814}
815
816impl<I> Can<I>
817where
818 I: Instance,
819{
820 /// Creates a [`CanBuilder`] for constructing a CAN interface.
821 pub fn builder(instance: I, canregs: crate::pac::can::Can) -> CanBuilder<I> {
822 let mut can_builder = CanBuilder {
823 can: Can {
824 instance,
825 canregs,
826 registers: Registers { canregs },
827 },
828 };
829
830 can_builder.can.registers.enter_init_mode();
831
832 can_builder
833 }
834
835 /// Disables the CAN interface and returns back the raw peripheral it was created from.
836 ///
837 /// The peripheral is disabled by setting `RESET` in `CAN_MCR`, which causes the peripheral to
838 /// enter sleep mode.
839 pub fn free(self) -> I {
840 self.registers.reset();
841 self.instance
842 }
843
844 /// Configure bit timings and silent/loop-back mode.
845 ///
846 /// Calling this method will enter initialization mode.
847 pub fn modify_config(&mut self) -> CanConfig<'_, I> {
848 self.registers.enter_init_mode();
849
850 CanConfig { can: self }
851 }
852
853 /// Puts a CAN frame in a free transmit mailbox for transmission on the bus.
854 ///
855 /// Frames are transmitted to the bus based on their priority (see [`FramePriority`]).
856 /// Transmit order is preserved for frames with identical priority.
857 ///
858 /// If all transmit mailboxes are full, and `frame` has a higher priority than the
859 /// lowest-priority message in the transmit mailboxes, transmission of the enqueued frame is
860 /// cancelled and `frame` is enqueued instead. The frame that was replaced is returned as
861 /// [`TransmitStatus::dequeued_frame`].
862 pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
863 // Safety: We have a `&mut self` and have unique access to the peripheral.
864 unsafe { Tx::<I>::conjure(self.canregs).transmit(frame) }
865 }
866
867 /// Returns `true` if no frame is pending for transmission.
868 pub fn is_transmitter_idle(&self) -> bool {
869 // Safety: Read-only operation.
870 unsafe { Tx::<I>::conjure(self.canregs).is_idle() }
871 }
872
873 /// Attempts to abort the sending of a frame that is pending in a mailbox.
874 ///
875 /// If there is no frame in the provided mailbox, or its transmission succeeds before it can be
876 /// aborted, this function has no effect and returns `false`.
877 ///
878 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
879 /// returns `true`.
880 pub fn abort(&mut self, mailbox: Mailbox) -> bool {
881 // Safety: We have a `&mut self` and have unique access to the peripheral.
882 unsafe { Tx::<I>::conjure(self.canregs).abort(mailbox) }
883 }
884
885 pub(crate) fn split_by_ref(&mut self) -> (Tx<I>, Rx<I>) {
886 // Safety: We take `&mut self` and the return value lifetimes are tied to `self`'s lifetime.
887 let tx = unsafe { Tx::conjure(self.canregs) };
888 let rx0 = unsafe { Rx::conjure() };
889 (tx, rx0)
890 }
891}
892
893impl<I: FilterOwner> Can<I> {
894 /// Accesses the filter banks owned by this CAN peripheral.
895 ///
896 /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master
897 /// peripheral instead.
898 pub fn modify_filters(&mut self) -> MasterFilters<'_, I> {
899 unsafe { MasterFilters::new(self.canregs) }
900 }
901}
902
903/// Marker for Tx half
904pub struct Tx<I> {
905 _can: PhantomData<I>,
906 pub(crate) registers: Registers,
907}
908
909impl<I> Tx<I>
910where
911 I: Instance,
912{
913 unsafe fn conjure(canregs: crate::pac::can::Can) -> Self {
914 Self {
915 _can: PhantomData,
916 registers: Registers { canregs }, //canregs,
917 }
918 }
919
920 /// Puts a CAN frame in a transmit mailbox for transmission on the bus.
921 ///
922 /// Frames are transmitted to the bus based on their priority (see [`FramePriority`]).
923 /// Transmit order is preserved for frames with identical priority.
924 ///
925 /// If all transmit mailboxes are full, and `frame` has a higher priority than the
926 /// lowest-priority message in the transmit mailboxes, transmission of the enqueued frame is
927 /// cancelled and `frame` is enqueued instead. The frame that was replaced is returned as
928 /// [`TransmitStatus::dequeued_frame`].
929 pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
930 self.registers.transmit(frame)
931 }
932
933 /// Attempts to abort the sending of a frame that is pending in a mailbox.
934 ///
935 /// If there is no frame in the provided mailbox, or its transmission succeeds before it can be
936 /// aborted, this function has no effect and returns `false`.
937 ///
938 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
939 /// returns `true`.
940 pub fn abort(&mut self, mailbox: Mailbox) -> bool {
941 self.registers.abort(mailbox)
942 }
943
944 /// Returns `true` if no frame is pending for transmission.
945 pub fn is_idle(&self) -> bool {
946 self.registers.is_idle()
947 }
948
949 /// Clears the request complete flag for all mailboxes.
950 pub fn clear_interrupt_flags(&mut self) {
951 self.registers.clear_interrupt_flags()
952 }
953}
954
955/// Marker for Rx half
956pub struct Rx<I> {
957 _can: PhantomData<I>,
958}
959
960impl<I> Rx<I>
961where
962 I: Instance,
963{
964 unsafe fn conjure() -> Self {
965 Self { _can: PhantomData }
966 }
967}
968
969/// Identifies one of the two receive FIFOs.
970#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
971#[cfg_attr(feature = "defmt", derive(defmt::Format))]
972pub enum Fifo {
973 /// First receive FIFO
974 Fifo0 = 0,
975 /// Second receive FIFO
976 Fifo1 = 1,
977}
978
979/// Identifies one of the three transmit mailboxes.
980#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
981#[cfg_attr(feature = "defmt", derive(defmt::Format))]
982pub enum Mailbox {
983 /// Transmit mailbox 0
984 Mailbox0 = 0,
985 /// Transmit mailbox 1
986 Mailbox1 = 1,
987 /// Transmit mailbox 2
988 Mailbox2 = 2,
989}
990
991/// Contains information about a frame enqueued for transmission via [`Can::transmit`] or
992/// [`Tx::transmit`].
993pub struct TransmitStatus {
994 dequeued_frame: Option<Frame>,
995 mailbox: Mailbox,
996}
997
998impl TransmitStatus {
999 /// Returns the lower-priority frame that was dequeued to make space for the new frame.
1000 #[inline]
1001 pub fn dequeued_frame(&self) -> Option<&Frame> {
1002 self.dequeued_frame.as_ref()
1003 }
1004
1005 /// Returns the [`Mailbox`] the frame was enqueued in.
1006 #[inline]
1007 pub fn mailbox(&self) -> Mailbox {
1008 self.mailbox
1009 }
1010}
diff --git a/embassy-stm32/src/can/bx/filter.rs b/embassy-stm32/src/can/bxcan/filter.rs
index 51766aa31..9940c7f50 100644
--- a/embassy-stm32/src/can/bx/filter.rs
+++ b/embassy-stm32/src/can/bxcan/filter.rs
@@ -2,7 +2,7 @@
2 2
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4 4
5use crate::can::bx::{ExtendedId, Fifo, FilterOwner, Id, Instance, MasterInstance, StandardId}; 5use super::{ExtendedId, Fifo, FilterOwner, Id, Instance, MasterInstance, StandardId};
6 6
7const F32_RTR: u32 = 0b010; // set the RTR bit to match remote frames 7const F32_RTR: u32 = 0b010; // set the RTR bit to match remote frames
8const F32_IDE: u32 = 0b100; // set the IDE bit to match extended identifiers 8const F32_IDE: u32 = 0b100; // set the IDE bit to match extended identifiers
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan/mod.rs
index fd6a79092..65fd0e9c2 100644
--- a/embassy-stm32/src/can/bxcan.rs
+++ b/embassy-stm32/src/can/bxcan/mod.rs
@@ -1,29 +1,27 @@
1pub mod filter;
2mod registers;
3
1use core::future::poll_fn; 4use core::future::poll_fn;
2use core::marker::PhantomData; 5use core::marker::PhantomData;
3use core::ops::{Deref, DerefMut};
4use core::task::Poll; 6use core::task::Poll;
5 7
6pub mod bx;
7
8pub use bx::{filter, Data, ExtendedId, Fifo, Frame, Header, Id, StandardId};
9use embassy_hal_internal::{into_ref, PeripheralRef}; 8use embassy_hal_internal::{into_ref, PeripheralRef};
10use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 9use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
11use embassy_sync::channel::Channel; 10use embassy_sync::channel::Channel;
12use embassy_sync::waitqueue::AtomicWaker; 11use embassy_sync::waitqueue::AtomicWaker;
12pub use embedded_can::{ExtendedId, Id, StandardId};
13 13
14use self::filter::MasterFilters;
15use self::registers::{Registers, RxFifo};
16pub use super::common::{BufferedCanReceiver, BufferedCanSender};
17use super::frame::{Envelope, Frame};
18use super::util;
19use crate::can::enums::{BusError, TryReadError};
14use crate::gpio::AFType; 20use crate::gpio::AFType;
15use crate::interrupt::typelevel::Interrupt; 21use crate::interrupt::typelevel::Interrupt;
16use crate::rcc::RccPeripheral; 22use crate::rcc::RccPeripheral;
17use crate::{interrupt, peripherals, Peripheral}; 23use crate::{interrupt, peripherals, Peripheral};
18 24
19pub mod enums;
20pub mod frame;
21pub mod util;
22pub use frame::Envelope;
23
24mod common;
25pub use self::common::{BufferedCanReceiver, BufferedCanSender};
26
27/// Interrupt handler. 25/// Interrupt handler.
28pub struct TxInterruptHandler<T: Instance> { 26pub struct TxInterruptHandler<T: Instance> {
29 _phantom: PhantomData<T>, 27 _phantom: PhantomData<T>,
@@ -80,9 +78,72 @@ impl<T: Instance> interrupt::typelevel::Handler<T::SCEInterrupt> for SceInterrup
80 } 78 }
81} 79}
82 80
81/// Configuration proxy returned by [`Can::modify_config`].
82pub struct CanConfig<'a, T: Instance> {
83 can: PhantomData<&'a mut T>,
84}
85
86impl<T: Instance> CanConfig<'_, T> {
87 /// Configures the bit timings.
88 ///
89 /// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter
90 /// parameters as follows:
91 ///
92 /// - *Clock Rate*: The input clock speed to the CAN peripheral (*not* the CPU clock speed).
93 /// This is the clock rate of the peripheral bus the CAN peripheral is attached to (eg. APB1).
94 /// - *Sample Point*: Should normally be left at the default value of 87.5%.
95 /// - *SJW*: Should normally be left at the default value of 1.
96 ///
97 /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
98 /// parameter to this method.
99 pub fn set_bit_timing(self, bt: crate::can::util::NominalBitTiming) -> Self {
100 Registers(T::regs()).set_bit_timing(bt);
101 self
102 }
103
104 /// Configure the CAN bit rate.
105 ///
106 /// This is a helper that internally calls `set_bit_timing()`[Self::set_bit_timing].
107 pub fn set_bitrate(self, bitrate: u32) -> Self {
108 let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap();
109 self.set_bit_timing(bit_timing)
110 }
111
112 /// Enables or disables loopback mode: Internally connects the TX and RX
113 /// signals together.
114 pub fn set_loopback(self, enabled: bool) -> Self {
115 Registers(T::regs()).set_loopback(enabled);
116 self
117 }
118
119 /// Enables or disables silent mode: Disconnects the TX signal from the pin.
120 pub fn set_silent(self, enabled: bool) -> Self {
121 Registers(T::regs()).set_silent(enabled);
122 self
123 }
124
125 /// Enables or disables automatic retransmission of messages.
126 ///
127 /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame
128 /// until it can be sent. Otherwise, it will try only once to send each frame.
129 ///
130 /// Automatic retransmission is enabled by default.
131 pub fn set_automatic_retransmit(self, enabled: bool) -> Self {
132 Registers(T::regs()).set_automatic_retransmit(enabled);
133 self
134 }
135}
136
137impl<T: Instance> Drop for CanConfig<'_, T> {
138 #[inline]
139 fn drop(&mut self) {
140 Registers(T::regs()).leave_init_mode();
141 }
142}
143
83/// CAN driver 144/// CAN driver
84pub struct Can<'d, T: Instance> { 145pub struct Can<'d, T: Instance> {
85 can: crate::can::bx::Can<BxcanInstance<'d, T>>, 146 peri: PeripheralRef<'d, T>,
86} 147}
87 148
88/// Error returned by `try_write` 149/// Error returned by `try_write`
@@ -145,14 +206,25 @@ impl<'d, T: Instance> Can<'d, T> {
145 rx.set_as_af(rx.af_num(), AFType::Input); 206 rx.set_as_af(rx.af_num(), AFType::Input);
146 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 207 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
147 208
148 let can = crate::can::bx::Can::builder(BxcanInstance(peri), T::regs()).leave_disabled(); 209 Registers(T::regs()).leave_init_mode();
149 Self { can } 210
211 Self { peri }
150 } 212 }
151 213
152 /// Set CAN bit rate. 214 /// Set CAN bit rate.
153 pub fn set_bitrate(&mut self, bitrate: u32) { 215 pub fn set_bitrate(&mut self, bitrate: u32) {
154 let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap(); 216 let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap();
155 self.can.modify_config().set_bit_timing(bit_timing).leave_disabled(); 217 self.modify_config().set_bit_timing(bit_timing);
218 }
219
220 /// Configure bit timings and silent/loop-back mode.
221 ///
222 /// Calling this method will enter initialization mode. You must enable the peripheral
223 /// again afterwards with [`enable`](Self::enable).
224 pub fn modify_config(&mut self) -> CanConfig<'_, T> {
225 Registers(T::regs()).enter_init_mode();
226
227 CanConfig { can: PhantomData }
156 } 228 }
157 229
158 /// Enables the peripheral and synchronizes with the bus. 230 /// Enables the peripheral and synchronizes with the bus.
@@ -160,7 +232,7 @@ impl<'d, T: Instance> Can<'d, T> {
160 /// This will wait for 11 consecutive recessive bits (bus idle state). 232 /// This will wait for 11 consecutive recessive bits (bus idle state).
161 /// Contrary to enable method from bxcan library, this will not freeze the executor while waiting. 233 /// Contrary to enable method from bxcan library, this will not freeze the executor while waiting.
162 pub async fn enable(&mut self) { 234 pub async fn enable(&mut self) {
163 while self.registers.enable_non_blocking().is_err() { 235 while Registers(T::regs()).enable_non_blocking().is_err() {
164 // SCE interrupt is only generated for entering sleep mode, but not leaving. 236 // SCE interrupt is only generated for entering sleep mode, but not leaving.
165 // Yield to allow other tasks to execute while can bus is initializing. 237 // Yield to allow other tasks to execute while can bus is initializing.
166 embassy_futures::yield_now().await; 238 embassy_futures::yield_now().await;
@@ -170,19 +242,19 @@ impl<'d, T: Instance> Can<'d, T> {
170 /// Queues the message to be sent. 242 /// Queues the message to be sent.
171 /// 243 ///
172 /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure. 244 /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure.
173 pub async fn write(&mut self, frame: &Frame) -> crate::can::bx::TransmitStatus { 245 pub async fn write(&mut self, frame: &Frame) -> TransmitStatus {
174 self.split().0.write(frame).await 246 self.split().0.write(frame).await
175 } 247 }
176 248
177 /// Attempts to transmit a frame without blocking. 249 /// Attempts to transmit a frame without blocking.
178 /// 250 ///
179 /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full. 251 /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full.
180 pub fn try_write(&mut self, frame: &Frame) -> Result<crate::can::bx::TransmitStatus, TryWriteError> { 252 pub fn try_write(&mut self, frame: &Frame) -> Result<TransmitStatus, TryWriteError> {
181 self.split().0.try_write(frame) 253 self.split().0.try_write(frame)
182 } 254 }
183 255
184 /// Waits for a specific transmit mailbox to become empty 256 /// Waits for a specific transmit mailbox to become empty
185 pub async fn flush(&self, mb: crate::can::bx::Mailbox) { 257 pub async fn flush(&self, mb: Mailbox) {
186 CanTx::<T>::flush_inner(mb).await 258 CanTx::<T>::flush_inner(mb).await
187 } 259 }
188 260
@@ -196,6 +268,22 @@ impl<'d, T: Instance> Can<'d, T> {
196 CanTx::<T>::flush_all_inner().await 268 CanTx::<T>::flush_all_inner().await
197 } 269 }
198 270
271 /// Attempts to abort the sending of a frame that is pending in a mailbox.
272 ///
273 /// If there is no frame in the provided mailbox, or its transmission succeeds before it can be
274 /// aborted, this function has no effect and returns `false`.
275 ///
276 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
277 /// returns `true`.
278 pub fn abort(&mut self, mailbox: Mailbox) -> bool {
279 Registers(T::regs()).abort(mailbox)
280 }
281
282 /// Returns `true` if no frame is pending for transmission.
283 pub fn is_transmitter_idle(&self) -> bool {
284 Registers(T::regs()).is_idle()
285 }
286
199 /// Read a CAN frame. 287 /// Read a CAN frame.
200 /// 288 ///
201 /// If no CAN frame is in the RX buffer, this will wait until there is one. 289 /// If no CAN frame is in the RX buffer, this will wait until there is one.
@@ -221,8 +309,14 @@ impl<'d, T: Instance> Can<'d, T> {
221 /// 309 ///
222 /// Useful for doing separate transmit/receive tasks. 310 /// Useful for doing separate transmit/receive tasks.
223 pub fn split<'c>(&'c mut self) -> (CanTx<'d, T>, CanRx<'d, T>) { 311 pub fn split<'c>(&'c mut self) -> (CanTx<'d, T>, CanRx<'d, T>) {
224 let (tx, rx) = self.can.split_by_ref(); 312 (
225 (CanTx { tx }, CanRx { rx }) 313 CanTx {
314 _peri: unsafe { self.peri.clone_unchecked() },
315 },
316 CanRx {
317 peri: unsafe { self.peri.clone_unchecked() },
318 },
319 )
226 } 320 }
227 321
228 /// Return a buffered instance of driver. User must supply Buffers 322 /// Return a buffered instance of driver. User must supply Buffers
@@ -239,10 +333,13 @@ impl<'d, T: Instance> Can<'d, T> {
239 } 333 }
240} 334}
241 335
242impl<'d, T: Instance> AsMut<crate::can::bx::Can<BxcanInstance<'d, T>>> for Can<'d, T> { 336impl<'d, T: FilterOwner> Can<'d, T> {
243 /// Get mutable access to the lower-level driver from the `bxcan` crate. 337 /// Accesses the filter banks owned by this CAN peripheral.
244 fn as_mut(&mut self) -> &mut crate::can::bx::Can<BxcanInstance<'d, T>> { 338 ///
245 &mut self.can 339 /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master
340 /// peripheral instead.
341 pub fn modify_filters(&mut self) -> MasterFilters<'_, T> {
342 unsafe { MasterFilters::new(T::regs()) }
246 } 343 }
247} 344}
248 345
@@ -288,17 +385,17 @@ impl<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Buffer
288 385
289/// CAN driver, transmit half. 386/// CAN driver, transmit half.
290pub struct CanTx<'d, T: Instance> { 387pub struct CanTx<'d, T: Instance> {
291 tx: crate::can::bx::Tx<BxcanInstance<'d, T>>, 388 _peri: PeripheralRef<'d, T>,
292} 389}
293 390
294impl<'d, T: Instance> CanTx<'d, T> { 391impl<'d, T: Instance> CanTx<'d, T> {
295 /// Queues the message to be sent. 392 /// Queues the message to be sent.
296 /// 393 ///
297 /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure. 394 /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure.
298 pub async fn write(&mut self, frame: &Frame) -> crate::can::bx::TransmitStatus { 395 pub async fn write(&mut self, frame: &Frame) -> TransmitStatus {
299 poll_fn(|cx| { 396 poll_fn(|cx| {
300 T::state().tx_mode.register(cx.waker()); 397 T::state().tx_mode.register(cx.waker());
301 if let Ok(status) = self.tx.transmit(frame) { 398 if let Ok(status) = Registers(T::regs()).transmit(frame) {
302 return Poll::Ready(status); 399 return Poll::Ready(status);
303 } 400 }
304 401
@@ -310,11 +407,11 @@ impl<'d, T: Instance> CanTx<'d, T> {
310 /// Attempts to transmit a frame without blocking. 407 /// Attempts to transmit a frame without blocking.
311 /// 408 ///
312 /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full. 409 /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full.
313 pub fn try_write(&mut self, frame: &Frame) -> Result<crate::can::bx::TransmitStatus, TryWriteError> { 410 pub fn try_write(&mut self, frame: &Frame) -> Result<TransmitStatus, TryWriteError> {
314 self.tx.transmit(frame).map_err(|_| TryWriteError::Full) 411 Registers(T::regs()).transmit(frame).map_err(|_| TryWriteError::Full)
315 } 412 }
316 413
317 async fn flush_inner(mb: crate::can::bx::Mailbox) { 414 async fn flush_inner(mb: Mailbox) {
318 poll_fn(|cx| { 415 poll_fn(|cx| {
319 T::state().tx_mode.register(cx.waker()); 416 T::state().tx_mode.register(cx.waker());
320 if T::regs().tsr().read().tme(mb.index()) { 417 if T::regs().tsr().read().tme(mb.index()) {
@@ -327,7 +424,7 @@ impl<'d, T: Instance> CanTx<'d, T> {
327 } 424 }
328 425
329 /// Waits for a specific transmit mailbox to become empty 426 /// Waits for a specific transmit mailbox to become empty
330 pub async fn flush(&self, mb: crate::can::bx::Mailbox) { 427 pub async fn flush(&self, mb: Mailbox) {
331 Self::flush_inner(mb).await 428 Self::flush_inner(mb).await
332 } 429 }
333 430
@@ -336,9 +433,9 @@ impl<'d, T: Instance> CanTx<'d, T> {
336 T::state().tx_mode.register(cx.waker()); 433 T::state().tx_mode.register(cx.waker());
337 434
338 let tsr = T::regs().tsr().read(); 435 let tsr = T::regs().tsr().read();
339 if tsr.tme(crate::can::bx::Mailbox::Mailbox0.index()) 436 if tsr.tme(Mailbox::Mailbox0.index())
340 || tsr.tme(crate::can::bx::Mailbox::Mailbox1.index()) 437 || tsr.tme(Mailbox::Mailbox1.index())
341 || tsr.tme(crate::can::bx::Mailbox::Mailbox2.index()) 438 || tsr.tme(Mailbox::Mailbox2.index())
342 { 439 {
343 return Poll::Ready(()); 440 return Poll::Ready(());
344 } 441 }
@@ -358,9 +455,9 @@ impl<'d, T: Instance> CanTx<'d, T> {
358 T::state().tx_mode.register(cx.waker()); 455 T::state().tx_mode.register(cx.waker());
359 456
360 let tsr = T::regs().tsr().read(); 457 let tsr = T::regs().tsr().read();
361 if tsr.tme(crate::can::bx::Mailbox::Mailbox0.index()) 458 if tsr.tme(Mailbox::Mailbox0.index())
362 && tsr.tme(crate::can::bx::Mailbox::Mailbox1.index()) 459 && tsr.tme(Mailbox::Mailbox1.index())
363 && tsr.tme(crate::can::bx::Mailbox::Mailbox2.index()) 460 && tsr.tme(Mailbox::Mailbox2.index())
364 { 461 {
365 return Poll::Ready(()); 462 return Poll::Ready(());
366 } 463 }
@@ -375,12 +472,28 @@ impl<'d, T: Instance> CanTx<'d, T> {
375 Self::flush_all_inner().await 472 Self::flush_all_inner().await
376 } 473 }
377 474
475 /// Attempts to abort the sending of a frame that is pending in a mailbox.
476 ///
477 /// If there is no frame in the provided mailbox, or its transmission succeeds before it can be
478 /// aborted, this function has no effect and returns `false`.
479 ///
480 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
481 /// returns `true`.
482 pub fn abort(&mut self, mailbox: Mailbox) -> bool {
483 Registers(T::regs()).abort(mailbox)
484 }
485
486 /// Returns `true` if no frame is pending for transmission.
487 pub fn is_idle(&self) -> bool {
488 Registers(T::regs()).is_idle()
489 }
490
378 /// Return a buffered instance of driver. User must supply Buffers 491 /// Return a buffered instance of driver. User must supply Buffers
379 pub fn buffered<const TX_BUF_SIZE: usize>( 492 pub fn buffered<const TX_BUF_SIZE: usize>(
380 self, 493 self,
381 txb: &'static mut TxBuf<TX_BUF_SIZE>, 494 txb: &'static mut TxBuf<TX_BUF_SIZE>,
382 ) -> BufferedCanTx<'d, T, TX_BUF_SIZE> { 495 ) -> BufferedCanTx<'d, T, TX_BUF_SIZE> {
383 BufferedCanTx::new(self.tx, txb) 496 BufferedCanTx::new(self, txb)
384 } 497 }
385} 498}
386 499
@@ -389,19 +502,19 @@ pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame,
389 502
390/// Buffered CAN driver, transmit half. 503/// Buffered CAN driver, transmit half.
391pub struct BufferedCanTx<'d, T: Instance, const TX_BUF_SIZE: usize> { 504pub struct BufferedCanTx<'d, T: Instance, const TX_BUF_SIZE: usize> {
392 _tx: crate::can::bx::Tx<BxcanInstance<'d, T>>, 505 _tx: CanTx<'d, T>,
393 tx_buf: &'static TxBuf<TX_BUF_SIZE>, 506 tx_buf: &'static TxBuf<TX_BUF_SIZE>,
394} 507}
395 508
396impl<'d, T: Instance, const TX_BUF_SIZE: usize> BufferedCanTx<'d, T, TX_BUF_SIZE> { 509impl<'d, T: Instance, const TX_BUF_SIZE: usize> BufferedCanTx<'d, T, TX_BUF_SIZE> {
397 fn new(_tx: crate::can::bx::Tx<BxcanInstance<'d, T>>, tx_buf: &'static TxBuf<TX_BUF_SIZE>) -> Self { 510 fn new(_tx: CanTx<'d, T>, tx_buf: &'static TxBuf<TX_BUF_SIZE>) -> Self {
398 Self { _tx, tx_buf }.setup() 511 Self { _tx, tx_buf }.setup()
399 } 512 }
400 513
401 fn setup(self) -> Self { 514 fn setup(self) -> Self {
402 // We don't want interrupts being processed while we change modes. 515 // We don't want interrupts being processed while we change modes.
403 critical_section::with(|_| unsafe { 516 critical_section::with(|_| unsafe {
404 let tx_inner = self::common::ClassicBufferedTxInner { 517 let tx_inner = super::common::ClassicBufferedTxInner {
405 tx_receiver: self.tx_buf.receiver().into(), 518 tx_receiver: self.tx_buf.receiver().into(),
406 }; 519 };
407 T::mut_state().tx_mode = TxMode::Buffered(tx_inner); 520 T::mut_state().tx_mode = TxMode::Buffered(tx_inner);
@@ -435,7 +548,7 @@ impl<'d, T: Instance, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, T, TX
435/// CAN driver, receive half. 548/// CAN driver, receive half.
436#[allow(dead_code)] 549#[allow(dead_code)]
437pub struct CanRx<'d, T: Instance> { 550pub struct CanRx<'d, T: Instance> {
438 rx: crate::can::bx::Rx<BxcanInstance<'d, T>>, 551 peri: PeripheralRef<'d, T>,
439} 552}
440 553
441impl<'d, T: Instance> CanRx<'d, T> { 554impl<'d, T: Instance> CanRx<'d, T> {
@@ -465,7 +578,7 @@ impl<'d, T: Instance> CanRx<'d, T> {
465 self, 578 self,
466 rxb: &'static mut RxBuf<RX_BUF_SIZE>, 579 rxb: &'static mut RxBuf<RX_BUF_SIZE>,
467 ) -> BufferedCanRx<'d, T, RX_BUF_SIZE> { 580 ) -> BufferedCanRx<'d, T, RX_BUF_SIZE> {
468 BufferedCanRx::new(self.rx, rxb) 581 BufferedCanRx::new(self, rxb)
469 } 582 }
470} 583}
471 584
@@ -474,19 +587,19 @@ pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<
474 587
475/// CAN driver, receive half in Buffered mode. 588/// CAN driver, receive half in Buffered mode.
476pub struct BufferedCanRx<'d, T: Instance, const RX_BUF_SIZE: usize> { 589pub struct BufferedCanRx<'d, T: Instance, const RX_BUF_SIZE: usize> {
477 _rx: crate::can::bx::Rx<BxcanInstance<'d, T>>, 590 _rx: CanRx<'d, T>,
478 rx_buf: &'static RxBuf<RX_BUF_SIZE>, 591 rx_buf: &'static RxBuf<RX_BUF_SIZE>,
479} 592}
480 593
481impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE> { 594impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE> {
482 fn new(_rx: crate::can::bx::Rx<BxcanInstance<'d, T>>, rx_buf: &'static RxBuf<RX_BUF_SIZE>) -> Self { 595 fn new(_rx: CanRx<'d, T>, rx_buf: &'static RxBuf<RX_BUF_SIZE>) -> Self {
483 BufferedCanRx { _rx, rx_buf }.setup() 596 BufferedCanRx { _rx, rx_buf }.setup()
484 } 597 }
485 598
486 fn setup(self) -> Self { 599 fn setup(self) -> Self {
487 // We don't want interrupts being processed while we change modes. 600 // We don't want interrupts being processed while we change modes.
488 critical_section::with(|_| unsafe { 601 critical_section::with(|_| unsafe {
489 let rx_inner = self::common::ClassicBufferedRxInner { 602 let rx_inner = super::common::ClassicBufferedRxInner {
490 rx_sender: self.rx_buf.sender().into(), 603 rx_sender: self.rx_buf.sender().into(),
491 }; 604 };
492 T::mut_state().rx_mode = RxMode::Buffered(rx_inner); 605 T::mut_state().rx_mode = RxMode::Buffered(rx_inner);
@@ -511,8 +624,7 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE
511 Err(e) => Err(TryReadError::BusError(e)), 624 Err(e) => Err(TryReadError::BusError(e)),
512 } 625 }
513 } else { 626 } else {
514 let registers = crate::can::bx::Registers { canregs: T::regs() }; 627 if let Some(err) = Registers(T::regs()).curr_error() {
515 if let Some(err) = registers.curr_error() {
516 return Err(TryReadError::BusError(err)); 628 return Err(TryReadError::BusError(err));
517 } else { 629 } else {
518 Err(TryReadError::Empty) 630 Err(TryReadError::Empty)
@@ -544,8 +656,6 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, T, RX
544 } 656 }
545} 657}
546 658
547use crate::can::bx::RxFifo;
548
549impl<'d, T: Instance> Drop for Can<'d, T> { 659impl<'d, T: Instance> Drop for Can<'d, T> {
550 fn drop(&mut self) { 660 fn drop(&mut self) {
551 // Cannot call `free()` because it moves the instance. 661 // Cannot call `free()` because it moves the instance.
@@ -555,35 +665,62 @@ impl<'d, T: Instance> Drop for Can<'d, T> {
555 } 665 }
556} 666}
557 667
558impl<'d, T: Instance> Deref for Can<'d, T> { 668/// Identifies one of the two receive FIFOs.
559 type Target = crate::can::bx::Can<BxcanInstance<'d, T>>; 669#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
670#[cfg_attr(feature = "defmt", derive(defmt::Format))]
671pub enum Fifo {
672 /// First receive FIFO
673 Fifo0 = 0,
674 /// Second receive FIFO
675 Fifo1 = 1,
676}
560 677
561 fn deref(&self) -> &Self::Target { 678/// Identifies one of the three transmit mailboxes.
562 &self.can 679#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
563 } 680#[cfg_attr(feature = "defmt", derive(defmt::Format))]
681pub enum Mailbox {
682 /// Transmit mailbox 0
683 Mailbox0 = 0,
684 /// Transmit mailbox 1
685 Mailbox1 = 1,
686 /// Transmit mailbox 2
687 Mailbox2 = 2,
564} 688}
565 689
566impl<'d, T: Instance> DerefMut for Can<'d, T> { 690/// Contains information about a frame enqueued for transmission via [`Can::transmit`] or
567 fn deref_mut(&mut self) -> &mut Self::Target { 691/// [`Tx::transmit`].
568 &mut self.can 692pub struct TransmitStatus {
569 } 693 dequeued_frame: Option<Frame>,
694 mailbox: Mailbox,
570} 695}
571 696
572use crate::can::enums::{BusError, TryReadError}; 697impl TransmitStatus {
698 /// Returns the lower-priority frame that was dequeued to make space for the new frame.
699 #[inline]
700 pub fn dequeued_frame(&self) -> Option<&Frame> {
701 self.dequeued_frame.as_ref()
702 }
703
704 /// Returns the [`Mailbox`] the frame was enqueued in.
705 #[inline]
706 pub fn mailbox(&self) -> Mailbox {
707 self.mailbox
708 }
709}
573 710
574pub(crate) enum RxMode { 711pub(crate) enum RxMode {
575 NonBuffered(AtomicWaker), 712 NonBuffered(AtomicWaker),
576 Buffered(crate::can::_version::common::ClassicBufferedRxInner), 713 Buffered(super::common::ClassicBufferedRxInner),
577} 714}
578 715
579impl RxMode { 716impl RxMode {
580 pub fn on_interrupt<T: Instance>(&self, fifo: crate::can::_version::bx::RxFifo) { 717 pub fn on_interrupt<T: Instance>(&self, fifo: RxFifo) {
581 match self { 718 match self {
582 Self::NonBuffered(waker) => { 719 Self::NonBuffered(waker) => {
583 // Disable interrupts until read 720 // Disable interrupts until read
584 let fifo_idx = match fifo { 721 let fifo_idx = match fifo {
585 crate::can::_version::bx::RxFifo::Fifo0 => 0usize, 722 RxFifo::Fifo0 => 0usize,
586 crate::can::_version::bx::RxFifo::Fifo1 => 1usize, 723 RxFifo::Fifo1 => 1usize,
587 }; 724 };
588 T::regs().ier().write(|w| { 725 T::regs().ier().write(|w| {
589 w.set_fmpie(fifo_idx, false); 726 w.set_fmpie(fifo_idx, false);
@@ -591,10 +728,8 @@ impl RxMode {
591 waker.wake(); 728 waker.wake();
592 } 729 }
593 Self::Buffered(buf) => { 730 Self::Buffered(buf) => {
594 let regsisters = crate::can::bx::Registers { canregs: T::regs() };
595
596 loop { 731 loop {
597 match regsisters.receive_fifo(fifo) { 732 match Registers(T::regs()).receive_fifo(fifo) {
598 Some(envelope) => { 733 Some(envelope) => {
599 // NOTE: consensus was reached that if rx_queue is full, packets should be dropped 734 // NOTE: consensus was reached that if rx_queue is full, packets should be dropped
600 let _ = buf.rx_sender.try_send(Ok(envelope)); 735 let _ = buf.rx_sender.try_send(Ok(envelope));
@@ -628,13 +763,13 @@ impl RxMode {
628 pub fn try_read<T: Instance>(&self) -> Result<Envelope, TryReadError> { 763 pub fn try_read<T: Instance>(&self) -> Result<Envelope, TryReadError> {
629 match self { 764 match self {
630 Self::NonBuffered(_) => { 765 Self::NonBuffered(_) => {
631 let registers = crate::can::bx::Registers { canregs: T::regs() }; 766 let registers = Registers(T::regs());
632 if let Some(msg) = registers.receive_fifo(super::bx::RxFifo::Fifo0) { 767 if let Some(msg) = registers.receive_fifo(RxFifo::Fifo0) {
633 T::regs().ier().write(|w| { 768 T::regs().ier().write(|w| {
634 w.set_fmpie(0, true); 769 w.set_fmpie(0, true);
635 }); 770 });
636 Ok(msg) 771 Ok(msg)
637 } else if let Some(msg) = registers.receive_fifo(super::bx::RxFifo::Fifo1) { 772 } else if let Some(msg) = registers.receive_fifo(RxFifo::Fifo1) {
638 T::regs().ier().write(|w| { 773 T::regs().ier().write(|w| {
639 w.set_fmpie(1, true); 774 w.set_fmpie(1, true);
640 }); 775 });
@@ -655,8 +790,7 @@ impl RxMode {
655 Self::NonBuffered(waker) => { 790 Self::NonBuffered(waker) => {
656 poll_fn(|cx| { 791 poll_fn(|cx| {
657 waker.register(cx.waker()); 792 waker.register(cx.waker());
658 let registers = crate::can::bx::Registers { canregs: T::regs() }; 793 if Registers(T::regs()).receive_frame_available() {
659 if registers.receive_frame_available() {
660 Poll::Ready(()) 794 Poll::Ready(())
661 } else { 795 } else {
662 Poll::Pending 796 Poll::Pending
@@ -673,15 +807,13 @@ impl RxMode {
673 807
674enum TxMode { 808enum TxMode {
675 NonBuffered(AtomicWaker), 809 NonBuffered(AtomicWaker),
676 Buffered(self::common::ClassicBufferedTxInner), 810 Buffered(super::common::ClassicBufferedTxInner),
677} 811}
678 812
679impl TxMode { 813impl TxMode {
680 pub fn buffer_free<T: Instance>(&self) -> bool { 814 pub fn buffer_free<T: Instance>(&self) -> bool {
681 let tsr = T::regs().tsr().read(); 815 let tsr = T::regs().tsr().read();
682 tsr.tme(crate::can::bx::Mailbox::Mailbox0.index()) 816 tsr.tme(Mailbox::Mailbox0.index()) || tsr.tme(Mailbox::Mailbox1.index()) || tsr.tme(Mailbox::Mailbox2.index())
683 || tsr.tme(crate::can::bx::Mailbox::Mailbox1.index())
684 || tsr.tme(crate::can::bx::Mailbox::Mailbox2.index())
685 } 817 }
686 pub fn on_interrupt<T: Instance>(&self) { 818 pub fn on_interrupt<T: Instance>(&self) {
687 match &T::state().tx_mode { 819 match &T::state().tx_mode {
@@ -690,8 +822,7 @@ impl TxMode {
690 while self.buffer_free::<T>() { 822 while self.buffer_free::<T>() {
691 match buf.tx_receiver.try_receive() { 823 match buf.tx_receiver.try_receive() {
692 Ok(frame) => { 824 Ok(frame) => {
693 let mut registers = crate::can::bx::Registers { canregs: T::regs() }; 825 _ = Registers(T::regs()).transmit(&frame);
694 _ = registers.transmit(&frame);
695 } 826 }
696 Err(_) => { 827 Err(_) => {
697 break; 828 break;
@@ -738,7 +869,7 @@ trait SealedInstance {
738 869
739/// CAN instance trait. 870/// CAN instance trait.
740#[allow(private_bounds)] 871#[allow(private_bounds)]
741pub trait Instance: SealedInstance + RccPeripheral + 'static { 872pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral + 'static {
742 /// TX interrupt for this instance. 873 /// TX interrupt for this instance.
743 type TXInterrupt: crate::interrupt::typelevel::Interrupt; 874 type TXInterrupt: crate::interrupt::typelevel::Interrupt;
744 /// RX0 interrupt for this instance. 875 /// RX0 interrupt for this instance.
@@ -749,10 +880,35 @@ pub trait Instance: SealedInstance + RccPeripheral + 'static {
749 type SCEInterrupt: crate::interrupt::typelevel::Interrupt; 880 type SCEInterrupt: crate::interrupt::typelevel::Interrupt;
750} 881}
751 882
752/// BXCAN instance newtype. 883/// A bxCAN instance that owns filter banks.
753pub struct BxcanInstance<'a, T>(PeripheralRef<'a, T>); 884///
885/// In master-slave-instance setups, only the master instance owns the filter banks, and needs to
886/// split some of them off for use by the slave instance. In that case, the master instance should
887/// implement [`FilterOwner`] and [`MasterInstance`], while the slave instance should only implement
888/// [`Instance`].
889///
890/// In single-instance configurations, the instance owns all filter banks and they can not be split
891/// off. In that case, the instance should implement [`Instance`] and [`FilterOwner`].
892///
893/// # Safety
894///
895/// This trait must only be implemented if the instance does, in fact, own its associated filter
896/// banks, and `NUM_FILTER_BANKS` must be correct.
897pub unsafe trait FilterOwner: Instance {
898 /// The total number of filter banks available to the instance.
899 ///
900 /// This is usually either 14 or 28, and should be specified in the chip's reference manual or datasheet.
901 const NUM_FILTER_BANKS: u8;
902}
754 903
755unsafe impl<'d, T: Instance> crate::can::bx::Instance for BxcanInstance<'d, T> {} 904/// A bxCAN master instance that shares filter banks with a slave instance.
905///
906/// In master-slave-instance setups, this trait should be implemented for the master instance.
907///
908/// # Safety
909///
910/// This trait must only be implemented when there is actually an associated slave instance.
911pub unsafe trait MasterInstance: FilterOwner {}
756 912
757foreach_peripheral!( 913foreach_peripheral!(
758 (can, $inst:ident) => { 914 (can, $inst:ident) => {
@@ -782,7 +938,7 @@ foreach_peripheral!(
782 938
783foreach_peripheral!( 939foreach_peripheral!(
784 (can, CAN) => { 940 (can, CAN) => {
785 unsafe impl<'d> crate::can::bx::FilterOwner for BxcanInstance<'d, peripherals::CAN> { 941 unsafe impl FilterOwner for peripherals::CAN {
786 const NUM_FILTER_BANKS: u8 = 14; 942 const NUM_FILTER_BANKS: u8 = 14;
787 } 943 }
788 }; 944 };
@@ -797,19 +953,19 @@ foreach_peripheral!(
797 ))] { 953 ))] {
798 // Most L4 devices and some F7 devices use the name "CAN1" 954 // Most L4 devices and some F7 devices use the name "CAN1"
799 // even if there is no "CAN2" peripheral. 955 // even if there is no "CAN2" peripheral.
800 unsafe impl<'d> crate::can::bx::FilterOwner for BxcanInstance<'d, peripherals::CAN1> { 956 unsafe impl FilterOwner for peripherals::CAN1 {
801 const NUM_FILTER_BANKS: u8 = 14; 957 const NUM_FILTER_BANKS: u8 = 14;
802 } 958 }
803 } else { 959 } else {
804 unsafe impl<'d> crate::can::bx::FilterOwner for BxcanInstance<'d, peripherals::CAN1> { 960 unsafe impl FilterOwner for peripherals::CAN1 {
805 const NUM_FILTER_BANKS: u8 = 28; 961 const NUM_FILTER_BANKS: u8 = 28;
806 } 962 }
807 unsafe impl<'d> crate::can::bx::MasterInstance for BxcanInstance<'d, peripherals::CAN1> {} 963 unsafe impl MasterInstance for peripherals::CAN1 {}
808 } 964 }
809 } 965 }
810 }; 966 };
811 (can, CAN3) => { 967 (can, CAN3) => {
812 unsafe impl<'d> crate::can::bx::FilterOwner for BxcanInstance<'d, peripherals::CAN3> { 968 unsafe impl FilterOwner for peripherals::CAN3 {
813 const NUM_FILTER_BANKS: u8 = 14; 969 const NUM_FILTER_BANKS: u8 = 14;
814 } 970 }
815 }; 971 };
@@ -822,12 +978,12 @@ trait Index {
822 fn index(&self) -> usize; 978 fn index(&self) -> usize;
823} 979}
824 980
825impl Index for crate::can::bx::Mailbox { 981impl Index for Mailbox {
826 fn index(&self) -> usize { 982 fn index(&self) -> usize {
827 match self { 983 match self {
828 crate::can::bx::Mailbox::Mailbox0 => 0, 984 Mailbox::Mailbox0 => 0,
829 crate::can::bx::Mailbox::Mailbox1 => 1, 985 Mailbox::Mailbox1 => 1,
830 crate::can::bx::Mailbox::Mailbox2 => 2, 986 Mailbox::Mailbox2 => 2,
831 } 987 }
832 } 988 }
833} 989}
diff --git a/embassy-stm32/src/can/bxcan/registers.rs b/embassy-stm32/src/can/bxcan/registers.rs
new file mode 100644
index 000000000..732567797
--- /dev/null
+++ b/embassy-stm32/src/can/bxcan/registers.rs
@@ -0,0 +1,510 @@
1use core::cmp::Ordering;
2use core::convert::Infallible;
3
4pub use embedded_can::{ExtendedId, Id, StandardId};
5use stm32_metapac::can::vals::Lec;
6
7use super::{Mailbox, TransmitStatus};
8use crate::can::enums::BusError;
9use crate::can::frame::{Envelope, Frame, Header};
10
11pub(crate) struct Registers(pub crate::pac::can::Can);
12
13impl Registers {
14 pub fn enter_init_mode(&mut self) {
15 self.0.mcr().modify(|reg| {
16 reg.set_sleep(false);
17 reg.set_inrq(true);
18 });
19 loop {
20 let msr = self.0.msr().read();
21 if !msr.slak() && msr.inak() {
22 break;
23 }
24 }
25 }
26
27 // Leaves initialization mode, enters sleep mode.
28 pub fn leave_init_mode(&mut self) {
29 self.0.mcr().modify(|reg| {
30 reg.set_sleep(true);
31 reg.set_inrq(false);
32 });
33 loop {
34 let msr = self.0.msr().read();
35 if msr.slak() && !msr.inak() {
36 break;
37 }
38 }
39 }
40
41 pub fn set_bit_timing(&mut self, bt: crate::can::util::NominalBitTiming) {
42 let prescaler = u16::from(bt.prescaler) & 0x1FF;
43 let seg1 = u8::from(bt.seg1);
44 let seg2 = u8::from(bt.seg2) & 0x7F;
45 let sync_jump_width = u8::from(bt.sync_jump_width) & 0x7F;
46 self.0.btr().modify(|reg| {
47 reg.set_brp(prescaler - 1);
48 reg.set_ts(0, seg1 - 1);
49 reg.set_ts(1, seg2 - 1);
50 reg.set_sjw(sync_jump_width - 1);
51 });
52 }
53
54 /// Enables or disables silent mode: Disconnects the TX signal from the pin.
55 pub fn set_silent(&self, enabled: bool) {
56 let mode = match enabled {
57 false => stm32_metapac::can::vals::Silm::NORMAL,
58 true => stm32_metapac::can::vals::Silm::SILENT,
59 };
60 self.0.btr().modify(|reg| reg.set_silm(mode));
61 }
62
63 /// Enables or disables automatic retransmission of messages.
64 ///
65 /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame
66 /// until it can be sent. Otherwise, it will try only once to send each frame.
67 ///
68 /// Automatic retransmission is enabled by default.
69 pub fn set_automatic_retransmit(&self, enabled: bool) {
70 self.0.mcr().modify(|reg| reg.set_nart(enabled));
71 }
72
73 /// Enables or disables loopback mode: Internally connects the TX and RX
74 /// signals together.
75 pub fn set_loopback(&self, enabled: bool) {
76 self.0.btr().modify(|reg| reg.set_lbkm(enabled));
77 }
78
79 /// Configures the automatic wake-up feature.
80 ///
81 /// This is turned off by default.
82 ///
83 /// When turned on, an incoming frame will cause the peripheral to wake up from sleep and
84 /// receive the frame. If enabled, [`Interrupt::Wakeup`] will also be triggered by the incoming
85 /// frame.
86 #[allow(dead_code)]
87 pub fn set_automatic_wakeup(&mut self, enabled: bool) {
88 self.0.mcr().modify(|reg| reg.set_awum(enabled));
89 }
90
91 /// Leaves initialization mode and enables the peripheral (non-blocking version).
92 ///
93 /// Usually, it is recommended to call [`CanConfig::enable`] instead. This method is only needed
94 /// if you want non-blocking initialization.
95 ///
96 /// If this returns [`WouldBlock`][nb::Error::WouldBlock], the peripheral will enable itself
97 /// in the background. The peripheral is enabled and ready to use when this method returns
98 /// successfully.
99 pub fn enable_non_blocking(&mut self) -> nb::Result<(), Infallible> {
100 let msr = self.0.msr().read();
101 if msr.slak() {
102 self.0.mcr().modify(|reg| {
103 reg.set_abom(true);
104 reg.set_sleep(false);
105 });
106 Err(nb::Error::WouldBlock)
107 } else {
108 Ok(())
109 }
110 }
111
112 /// Puts the peripheral in a sleep mode to save power.
113 ///
114 /// While in sleep mode, an incoming CAN frame will trigger [`Interrupt::Wakeup`] if enabled.
115 #[allow(dead_code)]
116 pub fn sleep(&mut self) {
117 self.0.mcr().modify(|reg| {
118 reg.set_sleep(true);
119 reg.set_inrq(false);
120 });
121 loop {
122 let msr = self.0.msr().read();
123 if msr.slak() && !msr.inak() {
124 break;
125 }
126 }
127 }
128
129 /// Wakes up from sleep mode.
130 ///
131 /// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN
132 /// frame will cause that interrupt.
133 #[allow(dead_code)]
134 pub fn wakeup(&mut self) {
135 self.0.mcr().modify(|reg| {
136 reg.set_sleep(false);
137 reg.set_inrq(false);
138 });
139 loop {
140 let msr = self.0.msr().read();
141 if !msr.slak() && !msr.inak() {
142 break;
143 }
144 }
145 }
146
147 pub fn curr_error(&self) -> Option<BusError> {
148 let err = { self.0.esr().read() };
149 if err.boff() {
150 return Some(BusError::BusOff);
151 } else if err.epvf() {
152 return Some(BusError::BusPassive);
153 } else if err.ewgf() {
154 return Some(BusError::BusWarning);
155 } else if err.lec() != Lec::NOERROR {
156 return Some(match err.lec() {
157 Lec::STUFF => BusError::Stuff,
158 Lec::FORM => BusError::Form,
159 Lec::ACK => BusError::Acknowledge,
160 Lec::BITRECESSIVE => BusError::BitRecessive,
161 Lec::BITDOMINANT => BusError::BitDominant,
162 Lec::CRC => BusError::Crc,
163 Lec::CUSTOM => BusError::Software,
164 Lec::NOERROR => unreachable!(),
165 });
166 }
167 None
168 }
169
170 /// Puts a CAN frame in a transmit mailbox for transmission on the bus.
171 ///
172 /// Frames are transmitted to the bus based on their priority (see [`FramePriority`]).
173 /// Transmit order is preserved for frames with identical priority.
174 ///
175 /// If all transmit mailboxes are full, and `frame` has a higher priority than the
176 /// lowest-priority message in the transmit mailboxes, transmission of the enqueued frame is
177 /// cancelled and `frame` is enqueued instead. The frame that was replaced is returned as
178 /// [`TransmitStatus::dequeued_frame`].
179 pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
180 // Get the index of the next free mailbox or the one with the lowest priority.
181 let tsr = self.0.tsr().read();
182 let idx = tsr.code() as usize;
183
184 let frame_is_pending = !tsr.tme(0) || !tsr.tme(1) || !tsr.tme(2);
185 let pending_frame = if frame_is_pending {
186 // High priority frames are transmitted first by the mailbox system.
187 // Frames with identical identifier shall be transmitted in FIFO order.
188 // The controller schedules pending frames of same priority based on the
189 // mailbox index instead. As a workaround check all pending mailboxes
190 // and only accept higher priority frames.
191 self.check_priority(0, frame.id().into())?;
192 self.check_priority(1, frame.id().into())?;
193 self.check_priority(2, frame.id().into())?;
194
195 let all_frames_are_pending = !tsr.tme(0) && !tsr.tme(1) && !tsr.tme(2);
196 if all_frames_are_pending {
197 // No free mailbox is available. This can only happen when three frames with
198 // ascending priority (descending IDs) were requested for transmission and all
199 // of them are blocked by bus traffic with even higher priority.
200 // To prevent a priority inversion abort and replace the lowest priority frame.
201 self.read_pending_mailbox(idx)
202 } else {
203 // There was a free mailbox.
204 None
205 }
206 } else {
207 // All mailboxes are available: Send frame without performing any checks.
208 None
209 };
210
211 self.write_mailbox(idx, frame);
212
213 let mailbox = match idx {
214 0 => Mailbox::Mailbox0,
215 1 => Mailbox::Mailbox1,
216 2 => Mailbox::Mailbox2,
217 _ => unreachable!(),
218 };
219 Ok(TransmitStatus {
220 dequeued_frame: pending_frame,
221 mailbox,
222 })
223 }
224
225 /// Returns `Ok` when the mailbox is free or if it contains pending frame with a
226 /// lower priority (higher ID) than the identifier `id`.
227 fn check_priority(&self, idx: usize, id: IdReg) -> nb::Result<(), Infallible> {
228 // Read the pending frame's id to check its priority.
229 assert!(idx < 3);
230 let tir = &self.0.tx(idx).tir().read();
231 //let tir = &can.tx[idx].tir.read();
232
233 // Check the priority by comparing the identifiers. But first make sure the
234 // frame has not finished the transmission (`TXRQ` == 0) in the meantime.
235 if tir.txrq() && id <= IdReg::from_register(tir.0) {
236 // There's a mailbox whose priority is higher or equal
237 // the priority of the new frame.
238 return Err(nb::Error::WouldBlock);
239 }
240
241 Ok(())
242 }
243
244 fn write_mailbox(&mut self, idx: usize, frame: &Frame) {
245 debug_assert!(idx < 3);
246
247 let mb = self.0.tx(idx);
248 mb.tdtr().write(|w| w.set_dlc(frame.header().len() as u8));
249
250 mb.tdlr()
251 .write(|w| w.0 = u32::from_ne_bytes(frame.data()[0..4].try_into().unwrap()));
252 mb.tdhr()
253 .write(|w| w.0 = u32::from_ne_bytes(frame.data()[4..8].try_into().unwrap()));
254 let id: IdReg = frame.id().into();
255 mb.tir().write(|w| {
256 w.0 = id.0;
257 w.set_txrq(true);
258 });
259 }
260
261 fn read_pending_mailbox(&mut self, idx: usize) -> Option<Frame> {
262 if self.abort_by_index(idx) {
263 debug_assert!(idx < 3);
264
265 let mb = self.0.tx(idx);
266
267 let id = IdReg(mb.tir().read().0);
268 let mut data = [0xff; 8];
269 data[0..4].copy_from_slice(&mb.tdlr().read().0.to_ne_bytes());
270 data[4..8].copy_from_slice(&mb.tdhr().read().0.to_ne_bytes());
271 let len = mb.tdtr().read().dlc();
272
273 Some(Frame::new(Header::new(id.id(), len, id.rtr()), &data).unwrap())
274 } else {
275 // Abort request failed because the frame was already sent (or being sent) on
276 // the bus. All mailboxes are now free. This can happen for small prescaler
277 // values (e.g. 1MBit/s bit timing with a source clock of 8MHz) or when an ISR
278 // has preempted the execution.
279 None
280 }
281 }
282
283 /// Tries to abort a pending frame. Returns `true` when aborted.
284 fn abort_by_index(&mut self, idx: usize) -> bool {
285 self.0.tsr().write(|reg| reg.set_abrq(idx, true));
286
287 // Wait for the abort request to be finished.
288 loop {
289 let tsr = self.0.tsr().read();
290 if false == tsr.abrq(idx) {
291 break tsr.txok(idx) == false;
292 }
293 }
294 }
295
296 /// Attempts to abort the sending of a frame that is pending in a mailbox.
297 ///
298 /// If there is no frame in the provided mailbox, or its transmission succeeds before it can be
299 /// aborted, this function has no effect and returns `false`.
300 ///
301 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
302 /// returns `true`.
303 pub fn abort(&mut self, mailbox: Mailbox) -> bool {
304 // If the mailbox is empty, the value of TXOKx depends on what happened with the previous
305 // frame in that mailbox. Only call abort_by_index() if the mailbox is not empty.
306 let tsr = self.0.tsr().read();
307 let mailbox_empty = match mailbox {
308 Mailbox::Mailbox0 => tsr.tme(0),
309 Mailbox::Mailbox1 => tsr.tme(1),
310 Mailbox::Mailbox2 => tsr.tme(2),
311 };
312 if mailbox_empty {
313 false
314 } else {
315 self.abort_by_index(mailbox as usize)
316 }
317 }
318
319 /// Returns `true` if no frame is pending for transmission.
320 pub fn is_idle(&self) -> bool {
321 let tsr = self.0.tsr().read();
322 tsr.tme(0) && tsr.tme(1) && tsr.tme(2)
323 }
324
325 pub fn receive_frame_available(&self) -> bool {
326 if self.0.rfr(0).read().fmp() != 0 {
327 true
328 } else if self.0.rfr(1).read().fmp() != 0 {
329 true
330 } else {
331 false
332 }
333 }
334
335 pub fn receive_fifo(&self, fifo: RxFifo) -> Option<Envelope> {
336 // Generate timestamp as early as possible
337 #[cfg(feature = "time")]
338 let ts = embassy_time::Instant::now();
339
340 use crate::pac::can::vals::Ide;
341
342 let fifo_idx = match fifo {
343 RxFifo::Fifo0 => 0usize,
344 RxFifo::Fifo1 => 1usize,
345 };
346 let rfr = self.0.rfr(fifo_idx);
347 let fifo = self.0.rx(fifo_idx);
348
349 // If there are no pending messages, there is nothing to do
350 if rfr.read().fmp() == 0 {
351 return None;
352 }
353
354 let rir = fifo.rir().read();
355 let id: embedded_can::Id = if rir.ide() == Ide::STANDARD {
356 embedded_can::StandardId::new(rir.stid()).unwrap().into()
357 } else {
358 let stid = (rir.stid() & 0x7FF) as u32;
359 let exid = rir.exid() & 0x3FFFF;
360 let id = (stid << 18) | (exid);
361 embedded_can::ExtendedId::new(id).unwrap().into()
362 };
363 let rdtr = fifo.rdtr().read();
364 let data_len = rdtr.dlc();
365 let rtr = rir.rtr() == stm32_metapac::can::vals::Rtr::REMOTE;
366
367 #[cfg(not(feature = "time"))]
368 let ts = rdtr.time();
369
370 let mut data: [u8; 8] = [0; 8];
371 data[0..4].copy_from_slice(&fifo.rdlr().read().0.to_ne_bytes());
372 data[4..8].copy_from_slice(&fifo.rdhr().read().0.to_ne_bytes());
373
374 let frame = Frame::new(Header::new(id, data_len, rtr), &data).unwrap();
375 let envelope = Envelope { ts, frame };
376
377 rfr.modify(|v| v.set_rfom(true));
378
379 Some(envelope)
380 }
381}
382
383/// Identifier of a CAN message.
384///
385/// Can be either a standard identifier (11bit, Range: 0..0x3FF) or a
386/// extendended identifier (29bit , Range: 0..0x1FFFFFFF).
387///
388/// The `Ord` trait can be used to determine the frame’s priority this ID
389/// belongs to.
390/// Lower identifier values have a higher priority. Additionally standard frames
391/// have a higher priority than extended frames and data frames have a higher
392/// priority than remote frames.
393#[derive(Clone, Copy, Debug, PartialEq, Eq)]
394#[cfg_attr(feature = "defmt", derive(defmt::Format))]
395pub(crate) struct IdReg(u32);
396
397impl IdReg {
398 const STANDARD_SHIFT: u32 = 21;
399
400 const EXTENDED_SHIFT: u32 = 3;
401
402 const IDE_MASK: u32 = 0x0000_0004;
403
404 const RTR_MASK: u32 = 0x0000_0002;
405
406 /// Creates a new standard identifier (11bit, Range: 0..0x7FF)
407 ///
408 /// Panics for IDs outside the allowed range.
409 fn new_standard(id: StandardId) -> Self {
410 Self(u32::from(id.as_raw()) << Self::STANDARD_SHIFT)
411 }
412
413 /// Creates a new extendended identifier (29bit , Range: 0..0x1FFFFFFF).
414 ///
415 /// Panics for IDs outside the allowed range.
416 fn new_extended(id: ExtendedId) -> IdReg {
417 Self(id.as_raw() << Self::EXTENDED_SHIFT | Self::IDE_MASK)
418 }
419
420 fn from_register(reg: u32) -> IdReg {
421 Self(reg & 0xFFFF_FFFE)
422 }
423
424 /// Returns the identifier.
425 fn to_id(self) -> Id {
426 if self.is_extended() {
427 Id::Extended(unsafe { ExtendedId::new_unchecked(self.0 >> Self::EXTENDED_SHIFT) })
428 } else {
429 Id::Standard(unsafe { StandardId::new_unchecked((self.0 >> Self::STANDARD_SHIFT) as u16) })
430 }
431 }
432
433 /// Returns the identifier.
434 fn id(self) -> embedded_can::Id {
435 if self.is_extended() {
436 embedded_can::ExtendedId::new(self.0 >> Self::EXTENDED_SHIFT)
437 .unwrap()
438 .into()
439 } else {
440 embedded_can::StandardId::new((self.0 >> Self::STANDARD_SHIFT) as u16)
441 .unwrap()
442 .into()
443 }
444 }
445
446 /// Returns `true` if the identifier is an extended identifier.
447 fn is_extended(self) -> bool {
448 self.0 & Self::IDE_MASK != 0
449 }
450
451 /// Returns `true` if the identifer is part of a remote frame (RTR bit set).
452 fn rtr(self) -> bool {
453 self.0 & Self::RTR_MASK != 0
454 }
455}
456
457impl From<&embedded_can::Id> for IdReg {
458 fn from(eid: &embedded_can::Id) -> Self {
459 match eid {
460 embedded_can::Id::Standard(id) => IdReg::new_standard(StandardId::new(id.as_raw()).unwrap()),
461 embedded_can::Id::Extended(id) => IdReg::new_extended(ExtendedId::new(id.as_raw()).unwrap()),
462 }
463 }
464}
465
466impl From<IdReg> for embedded_can::Id {
467 fn from(idr: IdReg) -> Self {
468 idr.id()
469 }
470}
471
472/// `IdReg` is ordered by priority.
473impl Ord for IdReg {
474 fn cmp(&self, other: &Self) -> Ordering {
475 // When the IDs match, data frames have priority over remote frames.
476 let rtr = self.rtr().cmp(&other.rtr()).reverse();
477
478 let id_a = self.to_id();
479 let id_b = other.to_id();
480 match (id_a, id_b) {
481 (Id::Standard(a), Id::Standard(b)) => {
482 // Lower IDs have priority over higher IDs.
483 a.as_raw().cmp(&b.as_raw()).reverse().then(rtr)
484 }
485 (Id::Extended(a), Id::Extended(b)) => a.as_raw().cmp(&b.as_raw()).reverse().then(rtr),
486 (Id::Standard(a), Id::Extended(b)) => {
487 // Standard frames have priority over extended frames if their Base IDs match.
488 a.as_raw()
489 .cmp(&b.standard_id().as_raw())
490 .reverse()
491 .then(Ordering::Greater)
492 }
493 (Id::Extended(a), Id::Standard(b)) => {
494 a.standard_id().as_raw().cmp(&b.as_raw()).reverse().then(Ordering::Less)
495 }
496 }
497 }
498}
499
500impl PartialOrd for IdReg {
501 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
502 Some(self.cmp(other))
503 }
504}
505
506#[derive(Debug, Copy, Clone, Eq, PartialEq)]
507pub(crate) enum RxFifo {
508 Fifo0,
509 Fifo1,
510}
diff --git a/embassy-stm32/src/can/common.rs b/embassy-stm32/src/can/common.rs
index 570761b19..a54b54f6e 100644
--- a/embassy-stm32/src/can/common.rs
+++ b/embassy-stm32/src/can/common.rs
@@ -1,7 +1,7 @@
1use embassy_sync::channel::{DynamicReceiver, DynamicSender}; 1use embassy_sync::channel::{DynamicReceiver, DynamicSender};
2 2
3use crate::can::_version::enums::*; 3use super::enums::*;
4use crate::can::_version::frame::*; 4use super::frame::*;
5 5
6pub(crate) struct ClassicBufferedRxInner { 6pub(crate) struct ClassicBufferedRxInner {
7 pub rx_sender: DynamicSender<'static, Result<Envelope, BusError>>, 7 pub rx_sender: DynamicSender<'static, Result<Envelope, BusError>>,
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs
index 2ccf4b093..e31821ca2 100644
--- a/embassy-stm32/src/can/fdcan.rs
+++ b/embassy-stm32/src/can/fdcan.rs
@@ -14,19 +14,15 @@ use crate::interrupt::typelevel::Interrupt;
14use crate::rcc::RccPeripheral; 14use crate::rcc::RccPeripheral;
15use crate::{interrupt, peripherals, Peripheral}; 15use crate::{interrupt, peripherals, Peripheral};
16 16
17mod common;
18pub mod enums;
19pub(crate) mod fd; 17pub(crate) mod fd;
20pub mod frame;
21mod util;
22 18
23use enums::*; 19use self::fd::config::*;
24use fd::config::*; 20use self::fd::filter::*;
25use fd::filter::*; 21pub use self::fd::{config, filter};
26pub use fd::{config, filter}; 22pub use super::common::{BufferedCanReceiver, BufferedCanSender};
27use frame::*; 23use super::enums::*;
28 24use super::frame::*;
29pub use self::common::{BufferedCanReceiver, BufferedCanSender}; 25use super::util;
30 26
31/// Timestamp for incoming packets. Use Embassy time when enabled. 27/// Timestamp for incoming packets. Use Embassy time when enabled.
32#[cfg(feature = "time")] 28#[cfg(feature = "time")]
@@ -439,10 +435,10 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
439 fn setup(self) -> Self { 435 fn setup(self) -> Self {
440 // We don't want interrupts being processed while we change modes. 436 // We don't want interrupts being processed while we change modes.
441 critical_section::with(|_| unsafe { 437 critical_section::with(|_| unsafe {
442 let rx_inner = self::common::ClassicBufferedRxInner { 438 let rx_inner = super::common::ClassicBufferedRxInner {
443 rx_sender: self.rx_buf.sender().into(), 439 rx_sender: self.rx_buf.sender().into(),
444 }; 440 };
445 let tx_inner = self::common::ClassicBufferedTxInner { 441 let tx_inner = super::common::ClassicBufferedTxInner {
446 tx_receiver: self.tx_buf.receiver().into(), 442 tx_receiver: self.tx_buf.receiver().into(),
447 }; 443 };
448 T::mut_state().rx_mode = RxMode::ClassicBuffered(rx_inner); 444 T::mut_state().rx_mode = RxMode::ClassicBuffered(rx_inner);
@@ -555,10 +551,10 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
555 fn setup(self) -> Self { 551 fn setup(self) -> Self {
556 // We don't want interrupts being processed while we change modes. 552 // We don't want interrupts being processed while we change modes.
557 critical_section::with(|_| unsafe { 553 critical_section::with(|_| unsafe {
558 let rx_inner = self::common::FdBufferedRxInner { 554 let rx_inner = super::common::FdBufferedRxInner {
559 rx_sender: self.rx_buf.sender().into(), 555 rx_sender: self.rx_buf.sender().into(),
560 }; 556 };
561 let tx_inner = self::common::FdBufferedTxInner { 557 let tx_inner = super::common::FdBufferedTxInner {
562 tx_receiver: self.tx_buf.receiver().into(), 558 tx_receiver: self.tx_buf.receiver().into(),
563 }; 559 };
564 T::mut_state().rx_mode = RxMode::FdBuffered(rx_inner); 560 T::mut_state().rx_mode = RxMode::FdBuffered(rx_inner);
@@ -649,8 +645,8 @@ impl<'c, 'd, T: Instance> CanRx<'d, T> {
649 645
650enum RxMode { 646enum RxMode {
651 NonBuffered(AtomicWaker), 647 NonBuffered(AtomicWaker),
652 ClassicBuffered(self::common::ClassicBufferedRxInner), 648 ClassicBuffered(super::common::ClassicBufferedRxInner),
653 FdBuffered(self::common::FdBufferedRxInner), 649 FdBuffered(super::common::FdBufferedRxInner),
654} 650}
655 651
656impl RxMode { 652impl RxMode {
@@ -758,8 +754,8 @@ impl RxMode {
758 754
759enum TxMode { 755enum TxMode {
760 NonBuffered(AtomicWaker), 756 NonBuffered(AtomicWaker),
761 ClassicBuffered(self::common::ClassicBufferedTxInner), 757 ClassicBuffered(super::common::ClassicBufferedTxInner),
762 FdBuffered(self::common::FdBufferedTxInner), 758 FdBuffered(super::common::FdBufferedTxInner),
763} 759}
764 760
765impl TxMode { 761impl TxMode {
diff --git a/embassy-stm32/src/can/mod.rs b/embassy-stm32/src/can/mod.rs
index 915edb3a6..410a6bfcb 100644
--- a/embassy-stm32/src/can/mod.rs
+++ b/embassy-stm32/src/can/mod.rs
@@ -1,7 +1,14 @@
1//! Controller Area Network (CAN) 1//! Controller Area Network (CAN)
2#![macro_use] 2#![macro_use]
3 3
4#[cfg_attr(can_bxcan, path = "bxcan.rs")] 4#[cfg_attr(can_bxcan, path = "bxcan/mod.rs")]
5#[cfg_attr(any(can_fdcan_v1, can_fdcan_h7), path = "fdcan.rs")] 5#[cfg_attr(any(can_fdcan_v1, can_fdcan_h7), path = "fdcan.rs")]
6mod _version; 6mod _version;
7pub use _version::*; 7pub use _version::*;
8
9mod common;
10pub mod enums;
11pub mod frame;
12pub mod util;
13
14pub use frame::Frame;
diff --git a/examples/stm32f1/src/bin/can.rs b/examples/stm32f1/src/bin/can.rs
index 90cb9e46b..1c13d623d 100644
--- a/examples/stm32f1/src/bin/can.rs
+++ b/examples/stm32f1/src/bin/can.rs
@@ -3,8 +3,9 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::can::frame::Envelope;
6use embassy_stm32::can::{ 7use embassy_stm32::can::{
7 filter, Can, Envelope, Fifo, Frame, Id, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId, 8 filter, Can, Fifo, Frame, Id, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId,
8 TxInterruptHandler, 9 TxInterruptHandler,
9}; 10};
10use embassy_stm32::peripherals::CAN; 11use embassy_stm32::peripherals::CAN;
@@ -55,17 +56,13 @@ async fn main(_spawner: Spawner) {
55 56
56 let mut can = Can::new(p.CAN, p.PB8, p.PB9, Irqs); 57 let mut can = Can::new(p.CAN, p.PB8, p.PB9, Irqs);
57 58
58 can.as_mut() 59 can.modify_filters()
59 .modify_filters()
60 .enable_bank(0, Fifo::Fifo0, filter::Mask32::accept_all()); 60 .enable_bank(0, Fifo::Fifo0, filter::Mask32::accept_all());
61 61
62 can.as_mut() 62 can.modify_config()
63 .modify_config()
64 .set_loopback(false) 63 .set_loopback(false)
65 .set_silent(false) 64 .set_silent(false)
66 .leave_disabled(); 65 .set_bitrate(250_000);
67
68 can.set_bitrate(250_000);
69 66
70 can.enable().await; 67 can.enable().await;
71 let mut i: u8 = 0; 68 let mut i: u8 = 0;
diff --git a/examples/stm32f4/src/bin/can.rs b/examples/stm32f4/src/bin/can.rs
index 71b9453eb..cedc057a7 100644
--- a/examples/stm32f4/src/bin/can.rs
+++ b/examples/stm32f4/src/bin/can.rs
@@ -35,17 +35,12 @@ async fn main(_spawner: Spawner) {
35 35
36 let mut can = Can::new(p.CAN1, p.PA11, p.PA12, Irqs); 36 let mut can = Can::new(p.CAN1, p.PA11, p.PA12, Irqs);
37 37
38 can.as_mut() 38 can.modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all());
39 .modify_filters()
40 .enable_bank(0, Fifo::Fifo0, Mask32::accept_all());
41 39
42 can.as_mut() 40 can.modify_config()
43 .modify_config()
44 .set_loopback(true) // Receive own frames 41 .set_loopback(true) // Receive own frames
45 .set_silent(true) 42 .set_silent(true)
46 .leave_disabled(); 43 .set_bitrate(1_000_000);
47
48 can.set_bitrate(1_000_000);
49 44
50 can.enable().await; 45 can.enable().await;
51 46
diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs
index 221ac2a05..e32b4d3df 100644
--- a/examples/stm32f7/src/bin/can.rs
+++ b/examples/stm32f7/src/bin/can.rs
@@ -47,20 +47,18 @@ async fn main(spawner: Spawner) {
47 47
48 static CAN: StaticCell<Can<'static, CAN3>> = StaticCell::new(); 48 static CAN: StaticCell<Can<'static, CAN3>> = StaticCell::new();
49 let can = CAN.init(Can::new(p.CAN3, p.PA8, p.PA15, Irqs)); 49 let can = CAN.init(Can::new(p.CAN3, p.PA8, p.PA15, Irqs));
50 can.as_mut() 50 can.modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all());
51 .modify_filters()
52 .enable_bank(0, Fifo::Fifo0, Mask32::accept_all());
53 51
54 can.as_mut() 52 can.modify_config()
55 .modify_config()
56 .set_bit_timing(can::util::NominalBitTiming { 53 .set_bit_timing(can::util::NominalBitTiming {
57 prescaler: NonZeroU16::new(2).unwrap(), 54 prescaler: NonZeroU16::new(2).unwrap(),
58 seg1: NonZeroU8::new(13).unwrap(), 55 seg1: NonZeroU8::new(13).unwrap(),
59 seg2: NonZeroU8::new(2).unwrap(), 56 seg2: NonZeroU8::new(2).unwrap(),
60 sync_jump_width: NonZeroU8::new(1).unwrap(), 57 sync_jump_width: NonZeroU8::new(1).unwrap(),
61 }) // http://www.bittiming.can-wiki.info/ 58 }) // http://www.bittiming.can-wiki.info/
62 .set_loopback(true) 59 .set_loopback(true);
63 .enable(); 60
61 can.enable().await;
64 62
65 let (tx, mut rx) = can.split(); 63 let (tx, mut rx) = can.split();
66 64
diff --git a/tests/stm32/src/bin/can.rs b/tests/stm32/src/bin/can.rs
index 74d84c42f..551764458 100644
--- a/tests/stm32/src/bin/can.rs
+++ b/tests/stm32/src/bin/can.rs
@@ -8,9 +8,10 @@ mod common;
8use common::*; 8use common::*;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_stm32::bind_interrupts; 10use embassy_stm32::bind_interrupts;
11use embassy_stm32::can::bx::filter::Mask32; 11use embassy_stm32::can::filter::Mask32;
12use embassy_stm32::can::bx::Fifo; 12use embassy_stm32::can::{
13use embassy_stm32::can::{Can, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler}; 13 Can, Fifo, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler,
14};
14use embassy_stm32::gpio::{Input, Pull}; 15use embassy_stm32::gpio::{Input, Pull};
15use embassy_stm32::peripherals::CAN1; 16use embassy_stm32::peripherals::CAN1;
16use embassy_time::Duration; 17use embassy_time::Duration;
@@ -51,17 +52,15 @@ async fn main(_spawner: Spawner) {
51 52
52 info!("Configuring can..."); 53 info!("Configuring can...");
53 54
54 can.as_mut() 55 can.modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all());
55 .modify_filters()
56 .enable_bank(0, Fifo::Fifo0, Mask32::accept_all());
57 56
58 can.set_bitrate(1_000_000); 57 can.modify_config()
59 can.as_mut()
60 .modify_config()
61 .set_loopback(true) // Receive own frames 58 .set_loopback(true) // Receive own frames
62 .set_silent(true) 59 .set_silent(true)
63 // .set_bit_timing(0x001c0003) 60 // .set_bit_timing(0x001c0003)
64 .enable(); 61 .set_bitrate(1_000_000);
62
63 can.enable().await;
65 64
66 info!("Can configured"); 65 info!("Can configured");
67 66