44//! controllers. It supports Standard Frame Format (11-bit) and Extended Frame
55//! Format (29-bit) frame identifiers.
66
7- use core:: slice:: { from_raw_parts, from_raw_parts_mut} ;
8-
97#[ cfg( feature = "eh1" ) ]
108use embedded_can:: { nb:: Can , Error , ErrorKind , ExtendedId , Frame , Id , StandardId } ;
119#[ cfg( not( feature = "eh1" ) ) ]
@@ -35,20 +33,25 @@ pub struct EspTwaiFrame {
3533}
3634
3735impl EspTwaiFrame {
38- /// Make a new frame from an id and a slice of the TWAI_DATA_x_REG
39- /// registers.
40- fn new_from_data_registers ( id : impl Into < Id > , data : & [ u32 ] ) -> Self {
41- let mut d: [ u8 ; 8 ] = [ 0 ; 8 ] ;
36+ /// Make a new frame from an id, pointer to the TWAI_DATA_x_REG registers,
37+ /// and the length of the data payload (dlc).
38+ ///
39+ /// # Safety
40+ /// This is unsafe because it directly accesses peripheral registers.
41+ unsafe fn new_from_data_registers (
42+ id : impl Into < Id > ,
43+ registers : * const u32 ,
44+ dlc : usize ,
45+ ) -> Self {
46+ let mut data: [ u8 ; 8 ] = [ 0 ; 8 ] ;
4247
4348 // Copy the data from the memory mapped peripheral into actual memory.
44- for ( src, dest) in data. iter ( ) . zip ( d. iter_mut ( ) ) {
45- * dest = * src as u8 ;
46- }
49+ copy_from_data_register ( & mut data[ ..dlc] , registers) ;
4750
4851 Self {
4952 id : id. into ( ) ,
50- data : d ,
51- dlc : data . len ( ) ,
53+ data,
54+ dlc : dlc ,
5255 is_remote : false ,
5356 }
5457 }
@@ -198,8 +201,8 @@ where
198201{
199202 pub fn new < TX : OutputPin , RX : InputPin > (
200203 peripheral : impl Peripheral < P = T > + ' d ,
201- mut tx_pin : TX ,
202- mut rx_pin : RX ,
204+ tx_pin : impl Peripheral < P = TX > + ' d ,
205+ rx_pin : impl Peripheral < P = RX > + ' d ,
203206 clock_control : & mut PeripheralClockControl ,
204207 clocks : & Clocks ,
205208 baud_rate : BaudRate ,
@@ -208,6 +211,7 @@ where
208211 clock_control. enable ( crate :: system:: Peripheral :: Twai ) ;
209212
210213 // Set up the GPIO pins.
214+ crate :: into_ref!( tx_pin, rx_pin) ;
211215 tx_pin. connect_peripheral_to_output ( OutputSignal :: TWAI_TX ) ;
212216 rx_pin. connect_input_to_peripheral ( InputSignal :: TWAI_RX ) ;
213217
@@ -430,11 +434,11 @@ impl Error for EspTwaiError {
430434/// memory-mapped registers. Specifically, this function is used with the
431435/// TWAI_DATA_x_REG registers which has different results based on the mode of
432436/// the peripheral.
433- unsafe fn _copy_from_data_register ( dest : & mut [ u8 ] , src : * const u32 ) {
434- let src = from_raw_parts ( src , dest . len ( ) ) ;
435-
436- for ( dest , src ) in dest . iter_mut ( ) . zip ( src . iter ( ) ) {
437- * dest = * src as u8 ;
437+ # [ inline ( always ) ]
438+ unsafe fn copy_from_data_register ( dest : & mut [ u8 ] , src : * const u32 ) {
439+ for ( i , dest ) in dest . iter_mut ( ) . enumerate ( ) {
440+ // Perform a volatile read to avoid compiler optimizations.
441+ * dest = src. add ( i ) . read_volatile ( ) as u8 ;
438442 }
439443}
440444
@@ -446,11 +450,11 @@ unsafe fn _copy_from_data_register(dest: &mut [u8], src: *const u32) {
446450/// memory-mapped registers. Specifically, this function is used with the
447451/// TWAI_DATA_x_REG registers which has different results based on the mode of
448452/// the peripheral.
453+ #[ inline( always) ]
449454unsafe fn copy_to_data_register ( dest : * mut u32 , src : & [ u8 ] ) {
450- let dest = from_raw_parts_mut ( dest, src. len ( ) ) ;
451-
452- for ( dest, src) in dest. iter_mut ( ) . zip ( src. iter ( ) ) {
453- * dest = * src as u32 ;
455+ for ( i, src) in src. iter ( ) . enumerate ( ) {
456+ // Perform a volatile write to avoid compiler optimizations.
457+ dest. add ( i) . write_volatile ( * src as u32 ) ;
454458 }
455459}
456460
@@ -625,10 +629,13 @@ where
625629 if is_data_frame {
626630 // Create a new frame from the contents of the appropriate TWAI_DATA_x_REG
627631 // registers.
628- let register_data = unsafe {
629- from_raw_parts ( self . peripheral . register_block ( ) . data_3 . as_ptr ( ) , dlc)
630- } ;
631- EspTwaiFrame :: new_from_data_registers ( id, register_data)
632+ unsafe {
633+ EspTwaiFrame :: new_from_data_registers (
634+ id,
635+ self . peripheral . register_block ( ) . data_3 . as_ptr ( ) ,
636+ dlc,
637+ )
638+ }
632639 } else {
633640 EspTwaiFrame :: new_remote ( id, dlc) . unwrap ( )
634641 }
@@ -674,10 +681,13 @@ where
674681 let id = ExtendedId :: new ( raw_id) . unwrap ( ) ;
675682
676683 if is_data_frame {
677- let register_data = unsafe {
678- from_raw_parts ( self . peripheral . register_block ( ) . data_5 . as_ptr ( ) , dlc)
679- } ;
680- EspTwaiFrame :: new_from_data_registers ( id, register_data)
684+ unsafe {
685+ EspTwaiFrame :: new_from_data_registers (
686+ id,
687+ self . peripheral . register_block ( ) . data_5 . as_ptr ( ) ,
688+ dlc,
689+ )
690+ }
681691 } else {
682692 EspTwaiFrame :: new_remote ( id, dlc) . unwrap ( )
683693 }
0 commit comments