Skip to content

Commit 8ec4356

Browse files
committed
Refactor CanFrame
- Add missings documentation - Remove heapless dependency - Change CanFrame construction interface
1 parent 6ac2760 commit 8ec4356

File tree

3 files changed

+78
-52
lines changed

3 files changed

+78
-52
lines changed

Cargo.toml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ doc-comment = "0.3.3"
3838
version = "0.1.0"
3939
optional = true
4040

41-
[dependencies.heapless]
42-
version = "0.5.5"
43-
optional = true
44-
4541
[dependencies.bare-metal]
4642
version = "0.2"
4743
features = ["const-fn"]
@@ -66,7 +62,7 @@ unproven = ["embedded-hal/unproven"]
6662
device-selected = []
6763
direct-call-deprecated = []
6864
rt = ["stm32f3/rt"]
69-
can = ["embedded-hal-can", "heapless"]
65+
can = ["embedded-hal-can"]
7066

7167
gpio-f302 = []
7268
gpio-f303 = []

examples/can.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn main() -> ! {
4242
let can_tx = gpioa.pa12.into_af9(&mut gpioa.moder, &mut gpioa.afrh);
4343

4444
// Initialize the CAN peripheral
45-
let can = Can::can(dp.CAN, can_rx, can_tx, &mut rcc.apb1);
45+
let can = Can::new(dp.CAN, can_rx, can_tx, &mut rcc.apb1);
4646

4747
// Uncomment the following line to enable CAN interrupts
4848
// can.listen(Event::Fifo0Fmp);
@@ -66,7 +66,7 @@ fn main() -> ! {
6666
asm::delay(100_000);
6767
let data: [u8; 1] = [0];
6868

69-
let frame = CanFrame::data_frame(CanId::BaseId(ID), &data);
69+
let frame = CanFrame::new_data(CanId::BaseId(ID), &data);
7070

7171
block!(can_tx.transmit(&frame)).expect("Cannot send first CAN frame");
7272

@@ -81,7 +81,7 @@ fn main() -> ! {
8181
}
8282

8383
let data: [u8; 1] = [counter];
84-
let frame = CanFrame::data_frame(CanId::BaseId(ID), &data);
84+
let frame = CanFrame::new_data(CanId::BaseId(ID), &data);
8585

8686
block!(can_tx.transmit(&frame)).expect("Cannot send CAN frame");
8787
}

src/can.rs

Lines changed: 74 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use crate::gpio::gpioa;
1717
use crate::gpio::AF9;
1818
use crate::rcc::APB1;
1919
use crate::stm32;
20-
use heapless::{consts::U8, Vec};
2120
use nb::{self, Error};
2221

2322
use core::sync::atomic::{AtomicU8, Ordering};
@@ -29,7 +28,9 @@ const MAX_EXTENDED_ID: u32 = 0x1FFF_FFFF;
2928
/// u16 and u32 respectively are used here despite the fact that the upper bits are unused.
3029
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
3130
pub enum CanId {
31+
/// Standard 11bit Identifier (0..=0x7FF)
3232
BaseId(u16),
33+
/// Extended 29bit Identifier (0..=0x1FFF_FFFF)
3334
ExtendedId(u32),
3435
}
3536

@@ -39,8 +40,12 @@ pub enum CanId {
3940
/// of actual size, but this could be improved in the future using const-generics.
4041
#[derive(Debug, Clone, Eq, PartialEq)]
4142
pub struct CanFrame {
42-
pub id: CanId,
43-
pub data: Vec<u8, U8>,
43+
/// CAN Frame ID
44+
id: CanId,
45+
/// Data Length Code (range 0..=8)
46+
dlc: usize,
47+
/// Data Frame
48+
data: [u8; 8],
4449
}
4550

4651
/// Can Frame Filter Mode
@@ -78,6 +83,7 @@ pub struct CanFilter {
7883

7984
static FILTER_INDEX: AtomicU8 = AtomicU8::new(0);
8085

86+
/// Controll Area Network (CAN) Peripheral
8187
pub struct Can {
8288
can: stm32::CAN,
8389
_rx: gpioa::PA11<AF9>,
@@ -97,14 +103,22 @@ pub struct CanTransmitter {
97103
_tx: gpioa::PA12<AF9>,
98104
}
99105

106+
// TODO Use wrapper type around interal pac definition
100107
/// CAN Interrupt events
101108
pub enum Event {
109+
/// FIFO 0 message pending interrupt
102110
Fifo0Fmp,
111+
/// FIFO 1 message pending interrupt
103112
Fifo1Fmp,
113+
/// FIFO 0 full interupt enable
104114
Fifo0Full,
115+
/// FIFO 1 full interupt enable
105116
Fifo1Full,
117+
/// FIFO 0 overrun interrupt enable
106118
Fifo0Ovr,
119+
/// FIFO 1 overrun interrupt enable
107120
Fifo1Ovr,
121+
/// Transmit mailbox empty interrupt
108122
Txe,
109123
}
110124

@@ -146,7 +160,7 @@ impl embedded_hal_can::Frame for CanFrame {
146160

147161
#[inline(always)]
148162
fn data(&self) -> Option<&[u8]> {
149-
if self.data.len() > 0 {
163+
if self.dlc > 0 {
150164
Some(&self.data)
151165
} else {
152166
None
@@ -238,12 +252,13 @@ impl CanFilterData {
238252
}
239253

240254
impl Can {
241-
pub fn can(
255+
/// Initialize the CAN Peripheral
256+
pub fn new(
242257
can: stm32::CAN,
243258
rx: gpioa::PA11<AF9>,
244259
tx: gpioa::PA12<AF9>,
245260
apb1: &mut APB1,
246-
) -> Can {
261+
) -> Self {
247262
apb1.enr().modify(|_, w| w.canen().enabled());
248263
can.mcr.modify(|_, w| w.sleep().clear_bit());
249264
can.mcr.modify(|_, w| w.inrq().set_bit());
@@ -372,29 +387,27 @@ impl embedded_hal_can::Transmitter for CanTransmitter {
372387
}),
373388
}
374389

375-
if frame.data().is_some() {
376-
for j in 0..frame.data.len() {
377-
let val = &frame.data[j];
378-
390+
if let Some(data) = frame.data() {
391+
for (i, d) in data.iter().enumerate() {
379392
// NOTE(unsafe): full 8bit write is unsafe via the svd2rust api
380393
unsafe {
381-
match j {
382-
0 => tx.tdlr.modify(|_, w| w.data0().bits(*val)),
383-
1 => tx.tdlr.modify(|_, w| w.data1().bits(*val)),
384-
2 => tx.tdlr.modify(|_, w| w.data2().bits(*val)),
385-
3 => tx.tdlr.modify(|_, w| w.data3().bits(*val)),
386-
4 => tx.tdhr.modify(|_, w| w.data4().bits(*val)),
387-
5 => tx.tdhr.modify(|_, w| w.data5().bits(*val)),
388-
6 => tx.tdhr.modify(|_, w| w.data6().bits(*val)),
389-
7 => tx.tdhr.modify(|_, w| w.data7().bits(*val)),
394+
match i {
395+
0 => tx.tdlr.modify(|_, w| w.data0().bits(*d)),
396+
1 => tx.tdlr.modify(|_, w| w.data1().bits(*d)),
397+
2 => tx.tdlr.modify(|_, w| w.data2().bits(*d)),
398+
3 => tx.tdlr.modify(|_, w| w.data3().bits(*d)),
399+
4 => tx.tdhr.modify(|_, w| w.data4().bits(*d)),
400+
5 => tx.tdhr.modify(|_, w| w.data5().bits(*d)),
401+
6 => tx.tdhr.modify(|_, w| w.data6().bits(*d)),
402+
7 => tx.tdhr.modify(|_, w| w.data7().bits(*d)),
390403
_ => unreachable!(),
391404
}
392405
}
393406
}
394407

395408
// NOTE(unsafe): full 8bit write is unsafe via the svd2rust api
396409
tx.tdtr
397-
.modify(|_, w| unsafe { w.dlc().bits(frame.data.len() as u8) });
410+
.modify(|_, w| unsafe { w.dlc().bits(data.len() as u8) });
398411

399412
tx.tir.modify(|_, w| w.rtr().clear_bit());
400413
} else {
@@ -417,23 +430,23 @@ impl Receiver for CanFifo {
417430

418431
let rx = &can.rx[self.idx];
419432
if can.rfr[self.idx].read().fmp().bits() > 0 {
420-
let mut data = Vec::<_, U8>::new();
433+
let mut data: [u8; 8] = [0; 8];
421434

422-
let len = rx.rdtr.read().dlc().bits() as usize;
435+
let len: usize = rx.rdtr.read().dlc().bits().into();
423436

424437
let data_low = rx.rdlr.read();
425438
let data_high = rx.rdhr.read();
426439

427440
for i in 0..len {
428441
match i {
429-
0 => data.push(data_low.data0().bits()).unwrap(),
430-
1 => data.push(data_low.data1().bits()).unwrap(),
431-
2 => data.push(data_low.data2().bits()).unwrap(),
432-
3 => data.push(data_low.data3().bits()).unwrap(),
433-
4 => data.push(data_high.data4().bits()).unwrap(),
434-
5 => data.push(data_high.data5().bits()).unwrap(),
435-
6 => data.push(data_high.data6().bits()).unwrap(),
436-
7 => data.push(data_high.data7().bits()).unwrap(),
442+
0 => data[0] = data_low.data0().bits(),
443+
1 => data[1] = data_low.data1().bits(),
444+
2 => data[2] = data_low.data2().bits(),
445+
3 => data[3] = data_low.data3().bits(),
446+
4 => data[4] = data_high.data4().bits(),
447+
5 => data[5] = data_high.data5().bits(),
448+
6 => data[6] = data_high.data6().bits(),
449+
7 => data[7] = data_high.data7().bits(),
437450
_ => unreachable!(),
438451
}
439452
}
@@ -450,7 +463,11 @@ impl Receiver for CanFifo {
450463
// Release the mailbox
451464
can.rfr[self.idx].modify(|_, w| w.rfom().set_bit());
452465

453-
let frame = CanFrame { id: rcv_id, data };
466+
let frame = CanFrame {
467+
id: rcv_id,
468+
dlc: len,
469+
data,
470+
};
454471

455472
return Ok(frame);
456473
}
@@ -528,25 +545,38 @@ impl Receiver for CanFifo {
528545
}
529546

530547
impl CanFrame {
531-
pub fn new_with_len(id: CanId, src: &[u8], length: usize) -> CanFrame {
532-
assert!(length <= 8, "CAN Frames can have at most 8 data bytes");
533-
534-
let mut data = Vec::<u8, U8>::new();
535-
536-
// The vector is always empty and the data size has alreay been checked, this will always succeed
537-
data.extend_from_slice(src).unwrap();
548+
/// Create a new Can Frame
549+
///
550+
/// `src` content is copied into internal buffer
551+
/// and handled internally.
552+
///
553+
/// # Panics
554+
///
555+
/// This function will panic if length of `data` is greater than `8`
556+
pub fn new_data(id: CanId, data: &[u8]) -> CanFrame {
557+
assert!((0..8).contains(&data.len()));
538558

539-
CanFrame { id, data }
559+
let mut frame = Self {
560+
id,
561+
dlc: data.len(),
562+
data: [0; 8],
563+
};
564+
frame.data[0..data.len()].copy_from_slice(data);
565+
frame
540566
}
541567

542-
pub fn data_frame(id: CanId, data: &[u8]) -> CanFrame {
543-
CanFrame::new_with_len(id, data, data.len())
544-
}
568+
/// Crate a new remote Can Frame
569+
///
570+
/// # Panics
571+
///
572+
/// This function will panic if `dlc` is not inside the vliad range `0..=8`.
573+
pub fn new_remote(id: CanId, dlc: usize) -> CanFrame {
574+
assert!((0..=8).contains(&dlc));
545575

546-
pub fn remote_frame(id: CanId) -> CanFrame {
547576
CanFrame {
548577
id,
549-
data: Vec::<_, _>::new(),
578+
dlc,
579+
data: [0; 8],
550580
}
551581
}
552582
}

0 commit comments

Comments
 (0)