Skip to content

Commit d18a5cc

Browse files
committed
Add gpio PeripheralRef and use volatile for direct register access.
1 parent a8e875e commit d18a5cc

File tree

1 file changed

+40
-30
lines changed

1 file changed

+40
-30
lines changed

esp-hal-common/src/twai/mod.rs

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
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")]
108
use embedded_can::{nb::Can, Error, ErrorKind, ExtendedId, Frame, Id, StandardId};
119
#[cfg(not(feature = "eh1"))]
@@ -35,20 +33,25 @@ pub struct EspTwaiFrame {
3533
}
3634

3735
impl 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)]
449454
unsafe 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

Comments
 (0)