Skip to content

Commit e33591a

Browse files
committed
can: Documentation and example cleanup
1 parent b9f2de1 commit e33591a

File tree

5 files changed

+79
-50
lines changed

5 files changed

+79
-50
lines changed

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ codegen-units = 1
9898
[profile.release]
9999
codegen-units = 1
100100
debug = true
101-
opt-level = "s"
102101
lto = true
103102

104103
[[example]]

examples/can-echo.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Simple CAN example. Requires a transceiver connected to PB5 and PB6.
2+
13
#![no_main]
24
#![no_std]
35

@@ -22,14 +24,13 @@ fn main() -> ! {
2224
// resonator must be used.
2325
rcc.cfgr.use_hse(8.mhz()).freeze(&mut flash.acr);
2426

25-
let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);
27+
let mut can2 = Can::new(dp.CAN2, &mut rcc.apb1);
2628

27-
// Select some pins for CAN2.
29+
// Select pins for CAN2.
30+
let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);
2831
let can_rx_pin = gpiob.pb5.into_floating_input(&mut gpiob.crl);
2932
let can_tx_pin = gpiob.pb6.into_alternate_push_pull(&mut gpiob.crl);
3033
let mut afio = dp.AFIO.constrain(&mut rcc.apb2);
31-
32-
let mut can2 = Can::new(dp.CAN2, &mut rcc.apb1);
3334
can2.assign_pins((can_tx_pin, can_rx_pin), &mut afio.mapr);
3435

3536
can2.configure(|config| {
@@ -38,9 +39,6 @@ fn main() -> ! {
3839
config.set_bit_timing(0x001c_0003);
3940
});
4041

41-
// Get the transmitter part.
42-
let mut tx = can2.take_tx().unwrap();
43-
4442
// Filters are required to use the receiver part of CAN2.
4543
// Because the filter banks are part of CAN1 we first need to enable CAN1
4644
// and split the filters between the peripherals to use them for CAN2.
@@ -51,7 +49,10 @@ fn main() -> ! {
5149
let (_filters1, mut filters2) = can1.split_filters(0).unwrap();
5250
assert_eq!(filters2.num_available(), NUM_FILTER_BANKS);
5351
filters2.add(&Filter::accept_all()).unwrap(); // Receive all messages.
52+
53+
// Split the peripheral into transmitter and receiver parts.
5454
let mut rx = can2.take_rx(filters2).unwrap();
55+
let mut tx = can2.take_tx().unwrap();
5556

5657
// Sync to the bus and start normal operation.
5758
block!(can2.enable()).ok();

examples/can-loopback.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
//! Showcases advanced CAN filter capabilities.
2+
//! Does not require additional transceiver hardware.
3+
14
#![no_main]
25
#![no_std]
36

47
use panic_halt as _;
58

69
use cortex_m_rt::entry;
10+
use embedded_hal::digital::v2::OutputPin;
711
use nb::block;
812
use stm32f1xx_hal::{
913
can::{Can, Filter, Frame},
@@ -37,10 +41,8 @@ fn main() -> ! {
3741
config.set_silent(true);
3842
});
3943

40-
// Get the transmitter part.
41-
let mut tx = can.take_tx().unwrap();
42-
4344
// Use advanced configurations for the first three filter banks.
45+
// More details can be found in the reference manual of the device.
4446
#[cfg(not(feature = "connectivity"))]
4547
let mut filters = can
4648
.split_filters_advanced(0x0000_0006, 0xFFFF_FFFA, 0x0000_0007)
@@ -52,6 +54,9 @@ fn main() -> ! {
5254

5355
assert_eq!(filters.num_available(), 8);
5456

57+
// The order of the added filters is important: it must match configuration
58+
// of the `split_filters_advanced()` method.
59+
5560
// Matches 0, 1, 2
5661
filters
5762
.add_standard([
@@ -75,7 +80,9 @@ fn main() -> ! {
7580
])
7681
.unwrap();
7782

83+
// Split the peripheral into transmitter and receiver parts.
7884
let mut rx = can.take_rx(filters).unwrap();
85+
let mut tx = can.take_tx().unwrap();
7986

8087
// Sync to the bus and start normal operation.
8188
block!(can.enable()).ok();
@@ -95,5 +102,9 @@ fn main() -> ! {
95102
assert!(rx.receive().is_err());
96103
}
97104

105+
let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);
106+
let mut led = gpiob.pb9.into_push_pull_output(&mut gpiob.crh);
107+
led.set_high().unwrap();
108+
98109
loop {}
99110
}

examples/can-rtfm.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
//! transmission the interrupt is reentered and more data is fetched from the
77
//! queue.
88
//! Received frames are simply echoed back. In contrast to the naive `can-echo`
9-
//! example the echo messages are also correctly prioritized by the transmit
10-
//! queue.
9+
//! example all messages are also correctly prioritized by the transmit queue.
10+
1111
#![no_main]
1212
#![no_std]
1313

@@ -64,26 +64,24 @@ const APP: () = {
6464
.pclk2(72.mhz())
6565
.freeze(&mut flash.acr);
6666

67-
let mut gpiob = cx.device.GPIOB.split(&mut rcc.apb2);
68-
let mut afio = cx.device.AFIO.constrain(&mut rcc.apb2);
67+
let mut can2 = Can::new(cx.device.CAN2, &mut rcc.apb1);
6968

69+
// Select pins for CAN2.
70+
let mut gpiob = cx.device.GPIOB.split(&mut rcc.apb2);
7071
let can_rx_pin = gpiob.pb5.into_floating_input(&mut gpiob.crl);
7172
let can_tx_pin = gpiob.pb6.into_alternate_push_pull(&mut gpiob.crl);
72-
73-
let mut can2 = Can::new(cx.device.CAN2, &mut rcc.apb1);
73+
let mut afio = cx.device.AFIO.constrain(&mut rcc.apb2);
7474
can2.assign_pins((can_tx_pin, can_rx_pin), &mut afio.mapr);
7575

7676
can2.configure(|config| {
7777
// APB1 (PCLK1): 36MHz, Bit rate: 125kBit/s, Sample Point 87.5%
7878
// Value was calculated with http://www.bittiming.can-wiki.info/
79-
config.set_bit_timing(0x001c0011);
79+
config.set_bit_timing(0x001c_0011);
8080
});
8181

82-
let mut can_tx = can2.take_tx().unwrap();
83-
can_tx.enable_interrupt();
84-
let can_tx_queue = BinaryHeap::new();
85-
CanFramePool::grow(CAN_POOL_MEMORY);
86-
82+
// Filters are required to use the receiver part of CAN2.
83+
// Because the filter banks are part of CAN1 we first need to enable CAN1
84+
// and split the filters between the peripherals to use them for CAN2.
8785
let mut can1 = Can::new(cx.device.CAN1, &mut rcc.apb1);
8886
let (_, mut filters) = can1.split_filters(0).unwrap();
8987

@@ -100,6 +98,13 @@ const APP: () = {
10098
let mut can_rx = can2.take_rx(filters).unwrap();
10199
can_rx.enable_interrupts();
102100

101+
let mut can_tx = can2.take_tx().unwrap();
102+
can_tx.enable_interrupt();
103+
104+
let can_tx_queue = BinaryHeap::new();
105+
CanFramePool::grow(CAN_POOL_MEMORY);
106+
107+
// Sync to the bus and start normal operation.
103108
can2.enable().ok();
104109

105110
init::LateResources {

src/can.rs

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,9 @@ use core::{
4545
/// Can be either a standard identifier (11bit, Range: 0..0x3FF) or a
4646
/// extendended identifier (29bit , Range: 0..0x1FFFFFFF).
4747
///
48-
/// The `Ord` trait is can be used to determine the frame’s priority this ID
49-
/// belongs to. This works because the EID and RTR flags are included in the
50-
/// underlying integer representaiton.
51-
/// Lower identifier values mean higher priority. Additionally standard frames
48+
/// The `Ord` trait can be used to determine the frame’s priority this ID
49+
/// belongs to.
50+
/// Lower identifier values have a higher priority. Additionally standard frames
5251
/// have a higher priority than extended frames and data frames have a higher
5352
/// priority than remote frames.
5453
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -67,15 +66,15 @@ impl Id {
6766

6867
/// Creates a new standard identifier (11bit, Range: 0..0x7FF)
6968
///
70-
/// Ids outside the allowed range are silently truncated.
69+
/// IDs outside the allowed range are silently truncated.
7170
pub fn new_standard(id: u32) -> Self {
7271
assert!(id < 0x7FF);
7372
Self(id << Self::STANDARD_SHIFT)
7473
}
7574

7675
/// Creates a new extendended identifier (29bit , Range: 0..0x1FFFFFFF).
7776
///
78-
/// Ids outside the allowed range are silently truncated.
77+
/// IDs outside the allowed range are silently truncated.
7978
pub fn new_extended(id: u32) -> Id {
8079
assert!(id < 0x1FFF_FFFF);
8180
Self(id << Self::EXTENDED_SHIFT | Self::IDE_MASK)
@@ -161,12 +160,12 @@ impl Frame {
161160
frame
162161
}
163162

164-
/// Creates ane new frame with a standard identifier.
163+
/// Creates a new frame with a standard identifier.
165164
pub fn new_standard(id: u32, data: &[u8]) -> Self {
166165
Self::new(Id::new_standard(id), data)
167166
}
168167

169-
/// Creates ane new frame with an extended identifier.
168+
/// Creates a new frame with an extended identifier.
170169
pub fn new_extended(id: u32, data: &[u8]) -> Self {
171170
Self::new(Id::new_extended(id), data)
172171
}
@@ -181,22 +180,22 @@ impl Frame {
181180
self
182181
}
183182

184-
/// Returns true if this `Frame` is a extended frame
183+
/// Returns true if this frame is an extended frame
185184
pub fn is_extended(&self) -> bool {
186185
self.id.is_extended()
187186
}
188187

189-
/// Returns true if this `Frame` is a standard frame
188+
/// Returns true if this frame is a standard frame
190189
pub fn is_standard(&self) -> bool {
191190
self.id.is_standard()
192191
}
193192

194-
/// Returns true if this `Frame` is a remote frame
193+
/// Returns true if this frame is a remote frame
195194
pub fn is_remote_frame(&self) -> bool {
196195
self.id.rtr()
197196
}
198197

199-
/// Returns true if this `Frame` is a data frame
198+
/// Returns true if this frame is a data frame
200199
pub fn is_data_frame(&self) -> bool {
201200
!self.is_remote_frame()
202201
}
@@ -297,8 +296,11 @@ impl traits::Pins for (PB6<Alternate<PushPull>>, PB5<Input<Floating>>) {
297296
}
298297
}
299298

299+
/// Number of supported filter banks.
300300
#[cfg(not(feature = "connectivity"))]
301301
pub const NUM_FILTER_BANKS: usize = 14;
302+
303+
/// Number of supported filter banks.
302304
#[cfg(feature = "connectivity")]
303305
pub const NUM_FILTER_BANKS: usize = 28;
304306

@@ -309,7 +311,7 @@ pub struct CanConfig<Instance> {
309311

310312
impl<Instance> CanConfig<Instance>
311313
where
312-
Instance: traits::Instance<Bus = APB1>,
314+
Instance: traits::Instance,
313315
{
314316
/// Configures the bit timings.
315317
///
@@ -322,13 +324,14 @@ where
322324
});
323325
}
324326

325-
/// Enables or disables loopback mode: Internally connects the TX to RX.
327+
/// Enables or disables loopback mode: Internally connects the TX and RX
328+
/// signals together.
326329
pub fn set_loopback(&mut self, enabled: bool) {
327330
let can = unsafe { &*Instance::REGISTERS };
328331
can.btr.modify(|_, w| w.lbkm().bit(enabled));
329332
}
330333

331-
/// Enables or disables silent mode: Disconnects TX from the pin.
334+
/// Enables or disables silent mode: Disconnects the TX signal from the pin.
332335
pub fn set_silent(&mut self, enabled: bool) {
333336
let can = unsafe { &*Instance::REGISTERS };
334337
can.btr.modify(|_, w| w.silm().bit(enabled));
@@ -417,7 +420,6 @@ where
417420
let can = unsafe { &*Instance::REGISTERS };
418421
let msr = can.msr.read();
419422
if msr.slak().bit_is_set() {
420-
// TODO: Make automatic bus-off management configurable.
421423
can.mcr
422424
.modify(|_, w| w.abom().set_bit().sleep().clear_bit());
423425
Err(nb::Error::WouldBlock)
@@ -486,7 +488,7 @@ impl Can<CAN1> {
486488
/// `split_idx` can be in the range `0..NUM_FILTER_BANKS` and decides the number
487489
/// of filters assigned to each peripheral. A value of `0` means all filter
488490
/// banks are used for CAN2 while `NUM_FILTER_BANKS` reserves all filter banks
489-
/// for CAN2.
491+
/// for CAN1.
490492
#[cfg(feature = "connectivity")]
491493
pub fn split_filters(&mut self, split_idx: usize) -> Option<(Filters<CAN1>, Filters<CAN2>)> {
492494
// Set all filter banks to 32bit scale and mask mode.
@@ -570,7 +572,7 @@ impl Can<CAN1> {
570572
}
571573
}
572574

573-
/// A masked filter configuration.
575+
/// Filter with an optional mask.
574576
pub struct Filter {
575577
id: u32,
576578
mask: u32,
@@ -636,9 +638,17 @@ impl Filter {
636638
}
637639
}
638640

639-
fn as_16bit_filter(reg: u32) -> u32 {
641+
fn reg_to_16bit(reg: u32) -> u32 {
640642
(reg & Id::STANDARD_MASK) >> 16 | (reg & Id::IDE_MASK) << 1 | (reg & Id::RTR_MASK) << 3
641643
}
644+
645+
fn id_to_16bit(&self) -> u32 {
646+
Self::reg_to_16bit(self.id)
647+
}
648+
649+
fn mask_to_16bit(&self) -> u32 {
650+
Self::reg_to_16bit(self.mask)
651+
}
642652
}
643653

644654
/// Interface to the filter banks of a CAN peripheral.
@@ -663,6 +673,9 @@ where
663673
}
664674

665675
/// Returns the number of available filters.
676+
///
677+
/// This can number can be larger than the number of filter banks if
678+
/// `Can::split_filters_advanced()` was used.
666679
pub fn num_available(&self) -> usize {
667680
let can = unsafe { &*CAN1::ptr() };
668681

@@ -714,8 +727,8 @@ where
714727
self.check_config(idx, false, false)?;
715728
self.write_filter_bank(
716729
idx,
717-
Filter::as_16bit_filter(filters[0].mask) << 16 | Filter::as_16bit_filter(filters[0].id),
718-
Filter::as_16bit_filter(filters[1].mask) << 16 | Filter::as_16bit_filter(filters[1].id),
730+
filters[0].mask_to_16bit() << 16 | filters[0].id_to_16bit(),
731+
filters[1].mask_to_16bit() << 16 | filters[1].id_to_16bit(),
719732
);
720733
Ok(())
721734
}
@@ -735,8 +748,8 @@ where
735748
self.check_config(idx, true, false)?;
736749
self.write_filter_bank(
737750
idx,
738-
Filter::as_16bit_filter(filters[1].id) << 16 | Filter::as_16bit_filter(filters[0].id),
739-
Filter::as_16bit_filter(filters[3].id) << 16 | Filter::as_16bit_filter(filters[2].id),
751+
filters[1].id_to_16bit() << 16 | filters[0].id_to_16bit(),
752+
filters[3].id_to_16bit() << 16 | filters[2].id_to_16bit(),
740753
);
741754
Ok(())
742755
}
@@ -772,7 +785,7 @@ where
772785
self.count += 1;
773786
}
774787

775-
/// Disables all enabled filters.
788+
/// Disables all enabled filter banks.
776789
pub fn clear(&mut self) {
777790
let can = unsafe { &*CAN1::ptr() };
778791

@@ -805,9 +818,9 @@ where
805818
/// Puts a CAN frame in a free transmit mailbox for transmission on the bus.
806819
///
807820
/// Frames are transmitted to the bus based on their priority (identifier).
808-
/// Transmit order is preserved for frames with identical identifiers.
809-
/// If all transmit mailboxes are full a higher priority frame replaces the
810-
/// lowest priority frame which is returned as `Ok(Some(frame))`.
821+
/// Transmit order is preserved for frames with of identifiers.
822+
/// If all transmit mailboxes are full, a higher priority frame replaces the
823+
/// lowest priority frame, which is returned as `Ok(Some(frame))`.
811824
pub fn transmit(&mut self, frame: &Frame) -> nb::Result<Option<Frame>, Infallible> {
812825
let can = unsafe { &*Instance::REGISTERS };
813826

0 commit comments

Comments
 (0)