@@ -17,7 +17,6 @@ use crate::gpio::gpioa;
17
17
use crate :: gpio:: AF9 ;
18
18
use crate :: rcc:: APB1 ;
19
19
use crate :: stm32;
20
- use heapless:: { consts:: U8 , Vec } ;
21
20
use nb:: { self , Error } ;
22
21
23
22
use core:: sync:: atomic:: { AtomicU8 , Ordering } ;
@@ -29,7 +28,9 @@ const MAX_EXTENDED_ID: u32 = 0x1FFF_FFFF;
29
28
/// u16 and u32 respectively are used here despite the fact that the upper bits are unused.
30
29
#[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
31
30
pub enum CanId {
31
+ /// Standard 11bit Identifier (0..=0x7FF)
32
32
BaseId ( u16 ) ,
33
+ /// Extended 29bit Identifier (0..=0x1FFF_FFFF)
33
34
ExtendedId ( u32 ) ,
34
35
}
35
36
@@ -39,8 +40,12 @@ pub enum CanId {
39
40
/// of actual size, but this could be improved in the future using const-generics.
40
41
#[ derive( Debug , Clone , Eq , PartialEq ) ]
41
42
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 ] ,
44
49
}
45
50
46
51
/// Can Frame Filter Mode
@@ -78,6 +83,7 @@ pub struct CanFilter {
78
83
79
84
static FILTER_INDEX : AtomicU8 = AtomicU8 :: new ( 0 ) ;
80
85
86
+ /// Controll Area Network (CAN) Peripheral
81
87
pub struct Can {
82
88
can : stm32:: CAN ,
83
89
_rx : gpioa:: PA11 < AF9 > ,
@@ -97,14 +103,22 @@ pub struct CanTransmitter {
97
103
_tx : gpioa:: PA12 < AF9 > ,
98
104
}
99
105
106
+ // TODO Use wrapper type around interal pac definition
100
107
/// CAN Interrupt events
101
108
pub enum Event {
109
+ /// FIFO 0 message pending interrupt
102
110
Fifo0Fmp ,
111
+ /// FIFO 1 message pending interrupt
103
112
Fifo1Fmp ,
113
+ /// FIFO 0 full interupt enable
104
114
Fifo0Full ,
115
+ /// FIFO 1 full interupt enable
105
116
Fifo1Full ,
117
+ /// FIFO 0 overrun interrupt enable
106
118
Fifo0Ovr ,
119
+ /// FIFO 1 overrun interrupt enable
107
120
Fifo1Ovr ,
121
+ /// Transmit mailbox empty interrupt
108
122
Txe ,
109
123
}
110
124
@@ -146,7 +160,7 @@ impl embedded_hal_can::Frame for CanFrame {
146
160
147
161
#[ inline( always) ]
148
162
fn data ( & self ) -> Option < & [ u8 ] > {
149
- if self . data . len ( ) > 0 {
163
+ if self . dlc > 0 {
150
164
Some ( & self . data )
151
165
} else {
152
166
None
@@ -238,12 +252,13 @@ impl CanFilterData {
238
252
}
239
253
240
254
impl Can {
241
- pub fn can (
255
+ /// Initialize the CAN Peripheral
256
+ pub fn new (
242
257
can : stm32:: CAN ,
243
258
rx : gpioa:: PA11 < AF9 > ,
244
259
tx : gpioa:: PA12 < AF9 > ,
245
260
apb1 : & mut APB1 ,
246
- ) -> Can {
261
+ ) -> Self {
247
262
apb1. enr ( ) . modify ( |_, w| w. canen ( ) . enabled ( ) ) ;
248
263
can. mcr . modify ( |_, w| w. sleep ( ) . clear_bit ( ) ) ;
249
264
can. mcr . modify ( |_, w| w. inrq ( ) . set_bit ( ) ) ;
@@ -372,29 +387,27 @@ impl embedded_hal_can::Transmitter for CanTransmitter {
372
387
} ) ,
373
388
}
374
389
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 ( ) {
379
392
// NOTE(unsafe): full 8bit write is unsafe via the svd2rust api
380
393
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 ) ) ,
390
403
_ => unreachable ! ( ) ,
391
404
}
392
405
}
393
406
}
394
407
395
408
// NOTE(unsafe): full 8bit write is unsafe via the svd2rust api
396
409
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 ) } ) ;
398
411
399
412
tx. tir . modify ( |_, w| w. rtr ( ) . clear_bit ( ) ) ;
400
413
} else {
@@ -417,23 +430,23 @@ impl Receiver for CanFifo {
417
430
418
431
let rx = & can. rx [ self . idx ] ;
419
432
if can. rfr [ self . idx ] . read ( ) . fmp ( ) . bits ( ) > 0 {
420
- let mut data = Vec :: < _ , U8 > :: new ( ) ;
433
+ let mut data: [ u8 ; 8 ] = [ 0 ; 8 ] ;
421
434
422
- let len = rx. rdtr . read ( ) . dlc ( ) . bits ( ) as usize ;
435
+ let len: usize = rx. rdtr . read ( ) . dlc ( ) . bits ( ) . into ( ) ;
423
436
424
437
let data_low = rx. rdlr . read ( ) ;
425
438
let data_high = rx. rdhr . read ( ) ;
426
439
427
440
for i in 0 ..len {
428
441
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 ( ) ,
437
450
_ => unreachable ! ( ) ,
438
451
}
439
452
}
@@ -450,7 +463,11 @@ impl Receiver for CanFifo {
450
463
// Release the mailbox
451
464
can. rfr [ self . idx ] . modify ( |_, w| w. rfom ( ) . set_bit ( ) ) ;
452
465
453
- let frame = CanFrame { id : rcv_id, data } ;
466
+ let frame = CanFrame {
467
+ id : rcv_id,
468
+ dlc : len,
469
+ data,
470
+ } ;
454
471
455
472
return Ok ( frame) ;
456
473
}
@@ -528,25 +545,38 @@ impl Receiver for CanFifo {
528
545
}
529
546
530
547
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( ) ) ) ;
538
558
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
540
566
}
541
567
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) ) ;
545
575
546
- pub fn remote_frame ( id : CanId ) -> CanFrame {
547
576
CanFrame {
548
577
id,
549
- data : Vec :: < _ , _ > :: new ( ) ,
578
+ dlc,
579
+ data : [ 0 ; 8 ] ,
550
580
}
551
581
}
552
582
}
0 commit comments