first CAN test works
This commit is contained in:
parent
d4163c5021
commit
172e319720
@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
cortex-m-rt = "0.7"
|
cortex-m-rt = "0.7"
|
||||||
cfg-if = "1"
|
cfg-if = "1"
|
||||||
embedded-io = "0.6"
|
embedded-io = "0.6"
|
||||||
|
embedded-can = "0.4"
|
||||||
embedded-hal-async = "1"
|
embedded-hal-async = "1"
|
||||||
embedded-io-async = "0.6"
|
embedded-io-async = "0.6"
|
||||||
|
|
||||||
|
@ -31,26 +31,66 @@ async fn main(_spawner: Spawner) {
|
|||||||
va416xx_embassy::init(dp.tim15, dp.tim14, &clocks);
|
va416xx_embassy::init(dp.tim15, dp.tim14, &clocks);
|
||||||
defmt::info!("creating CAN peripheral driver");
|
defmt::info!("creating CAN peripheral driver");
|
||||||
defmt::info!("clocks: {}", clocks);
|
defmt::info!("clocks: {}", clocks);
|
||||||
let clk_config = ClockConfig::from_bitrate_and_segments(&clocks, 250.kHz(), 4, 14, 5)
|
let clk_config = ClockConfig::from_bitrate_and_segments(&clocks, 250.kHz(), 14, 5, 4)
|
||||||
.expect("CAN clock config error");
|
.expect("CAN clock config error");
|
||||||
let mut can = Can::new(dp.can0, clk_config);
|
let mut can = Can::new(dp.can0, clk_config);
|
||||||
can.set_loopback(true);
|
can.modify_control(|mut val| {
|
||||||
can.set_bufflock(true);
|
val.set_loopback(true);
|
||||||
|
val.set_ignore_ack(true);
|
||||||
|
val.set_internal(true);
|
||||||
|
val.set_bufflock(true);
|
||||||
|
val.set_diag_enable(true);
|
||||||
|
val
|
||||||
|
});
|
||||||
can.set_base_mask_for_all_match();
|
can.set_base_mask_for_all_match();
|
||||||
can.enable();
|
can.enable();
|
||||||
|
let err_counter = can.read_error_counters();
|
||||||
|
defmt::info!(
|
||||||
|
"error count tx {}, error count rx {}",
|
||||||
|
err_counter.transmit(),
|
||||||
|
err_counter.receive()
|
||||||
|
);
|
||||||
let mut channels = can.take_channels().unwrap();
|
let mut channels = can.take_channels().unwrap();
|
||||||
// Transmit channel.
|
// Transmit channel.
|
||||||
let mut tx = CanTx::new(channels.take(0).unwrap(), None);
|
let mut tx = CanTx::new(channels.take(0).unwrap(), None);
|
||||||
// Base channel which has dedicated mask.
|
// Base channel which has dedicated mask.
|
||||||
let mut rx = CanRx::new(channels.take(14).unwrap());
|
let mut rx_dedicated = CanRx::new(channels.take(1).unwrap());
|
||||||
let send_frame = CanFrame::Normal(CanFrameNormal::new(
|
// Base channel which has dedicated mask.
|
||||||
can::Id::Standard(can::StandardId::new(0x1).unwrap()),
|
let mut rx_base = CanRx::new(channels.take(14).unwrap());
|
||||||
&[1, 2, 3, 4],
|
let standard_id = can::StandardId::new(0x42).unwrap();
|
||||||
));
|
let send_frame = CanFrame::Normal(
|
||||||
|
CanFrameNormal::new(can::Id::Standard(standard_id), &[1, 2, 3, 4]).unwrap(),
|
||||||
|
);
|
||||||
|
rx_dedicated
|
||||||
|
.configure_for_reception_with_standard_id(standard_id, false)
|
||||||
|
.unwrap();
|
||||||
|
rx_base.configure_for_reception();
|
||||||
defmt::info!("sending CAN frame");
|
defmt::info!("sending CAN frame");
|
||||||
tx.transmit_frame(send_frame).unwrap();
|
tx.transmit_frame(send_frame).unwrap();
|
||||||
let _frame = nb::block!(rx.receive(true)).expect("invalid CAN rx state");
|
let frame = nb::block!(rx_dedicated.receive(true)).expect("invalid CAN rx state");
|
||||||
defmt::info!("received CAN frame with data");
|
let err_counter = can.read_error_counters();
|
||||||
|
defmt::info!(
|
||||||
|
"error count tx {}, error count rx {}",
|
||||||
|
err_counter.transmit(),
|
||||||
|
err_counter.receive()
|
||||||
|
);
|
||||||
|
let diag = can.read_error_diagnostics();
|
||||||
|
defmt::info!("EFID: {}, EBID: {}", diag.efid(), diag.ebid());
|
||||||
|
match frame {
|
||||||
|
CanFrame::Normal(can_frame_normal) => match can_frame_normal.id() {
|
||||||
|
can::Id::Standard(standard_id) => {
|
||||||
|
defmt::info!(
|
||||||
|
"received CAN frame with ID {} and data {}",
|
||||||
|
standard_id.as_raw(),
|
||||||
|
can_frame_normal.data()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
can::Id::Extended(_) => (),
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
defmt::error!("received unexpected CAN remote frame");
|
||||||
|
}
|
||||||
|
}
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ categories = ["embedded", "no-std", "hardware-support"]
|
|||||||
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
|
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
|
||||||
va416xx = { version = "0.4", features = ["critical-section"], default-features = false }
|
va416xx = { version = "0.4", features = ["critical-section"], default-features = false }
|
||||||
derive-mmio = { version = "0.4", git = "https://github.com/knurling-rs/derive-mmio.git" }
|
derive-mmio = { version = "0.4", git = "https://github.com/knurling-rs/derive-mmio.git" }
|
||||||
|
static_assertions = "1.1"
|
||||||
vorago-shared-periphs = { git = "https://egit.irs.uni-stuttgart.de/rust/vorago-shared-periphs.git", features = ["vor4x"] }
|
vorago-shared-periphs = { git = "https://egit.irs.uni-stuttgart.de/rust/vorago-shared-periphs.git", features = ["vor4x"] }
|
||||||
|
|
||||||
libm = "0.2"
|
libm = "0.2"
|
||||||
|
@ -12,25 +12,31 @@ pub struct CanFrameNormal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CanFrameNormal {
|
impl CanFrameNormal {
|
||||||
pub fn new(id: embedded_can::Id, data: &[u8]) -> Self {
|
pub fn new(id: embedded_can::Id, data: &[u8]) -> Result<Self, InvalidDataSizeError> {
|
||||||
|
if data.len() > 8 {
|
||||||
|
return Err(InvalidDataSizeError(data.len()));
|
||||||
|
}
|
||||||
let size = data.len();
|
let size = data.len();
|
||||||
let mut data_array = [0; 8];
|
let mut data_array = [0; 8];
|
||||||
data_array[..size].copy_from_slice(data);
|
data_array[0..size].copy_from_slice(data);
|
||||||
Self {
|
Ok(Self {
|
||||||
id,
|
id,
|
||||||
size,
|
size,
|
||||||
data: data_array,
|
data: data_array,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn id(&self) -> embedded_can::Id {
|
pub fn id(&self) -> embedded_can::Id {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn data(&self) -> &[u8] {
|
pub fn data(&self) -> &[u8] {
|
||||||
&self.data[..self.size]
|
&self.data[0..self.dlc()]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn dlc(&self) -> usize {
|
pub fn dlc(&self) -> usize {
|
||||||
self.size
|
self.size
|
||||||
}
|
}
|
||||||
@ -76,8 +82,11 @@ impl From<CanFrameRtr> for CanFrame {
|
|||||||
|
|
||||||
impl embedded_can::Frame for CanFrame {
|
impl embedded_can::Frame for CanFrame {
|
||||||
fn new(id: impl Into<embedded_can::Id>, data: &[u8]) -> Option<Self> {
|
fn new(id: impl Into<embedded_can::Id>, data: &[u8]) -> Option<Self> {
|
||||||
|
if data.len() > 8 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let id: embedded_can::Id = id.into();
|
let id: embedded_can::Id = id.into();
|
||||||
Some(Self::Normal(CanFrameNormal::new(id, data)))
|
Some(Self::Normal(CanFrameNormal::new(id, data).unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_remote(id: impl Into<embedded_can::Id>, dlc: usize) -> Option<Self> {
|
fn new_remote(id: impl Into<embedded_can::Id>, dlc: usize) -> Option<Self> {
|
||||||
|
@ -73,15 +73,19 @@ impl CanChannelLowLevel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.msg_buf.reset();
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read_state(&self) -> Result<BufferState, u8> {
|
pub fn read_state(&self) -> Result<BufferState, u8> {
|
||||||
self.msg_buf.read_stat_ctrl().status()
|
self.msg_buf.read_stat_ctrl().state()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn write_state(&mut self, buffer_state: BufferState) {
|
pub fn write_state(&mut self, buffer_state: BufferState) {
|
||||||
self.msg_buf.modify_stat_ctrl(|mut val| {
|
self.msg_buf.modify_stat_ctrl(|mut val| {
|
||||||
val.set_status(buffer_state);
|
val.set_state(buffer_state);
|
||||||
val
|
val
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -95,7 +99,7 @@ impl CanChannelLowLevel {
|
|||||||
if let Some(tx_priority) = tx_priority {
|
if let Some(tx_priority) = tx_priority {
|
||||||
val.set_priority(tx_priority);
|
val.set_priority(tx_priority);
|
||||||
}
|
}
|
||||||
val.set_status(BufferState::TxNotActive);
|
val.set_state(BufferState::TxNotActive);
|
||||||
val
|
val
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -135,7 +139,7 @@ impl CanChannelLowLevel {
|
|||||||
BufStatusAndControl::builder()
|
BufStatusAndControl::builder()
|
||||||
.with_dlc(u4::new(0))
|
.with_dlc(u4::new(0))
|
||||||
.with_priority(u4::new(0))
|
.with_priority(u4::new(0))
|
||||||
.with_status(BufferState::RxReady)
|
.with_state(BufferState::RxReady)
|
||||||
.build(),
|
.build(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -144,6 +148,10 @@ impl CanChannelLowLevel {
|
|||||||
let is_remote = frame.is_remote_frame();
|
let is_remote = frame.is_remote_frame();
|
||||||
self.write_id(frame.id(), is_remote);
|
self.write_id(frame.id(), is_remote);
|
||||||
let dlc = frame.dlc();
|
let dlc = frame.dlc();
|
||||||
|
self.msg_buf.modify_stat_ctrl(|mut ctrl| {
|
||||||
|
ctrl.set_dlc(u4::new(dlc as u8));
|
||||||
|
ctrl
|
||||||
|
});
|
||||||
if !is_remote {
|
if !is_remote {
|
||||||
self.msg_buf
|
self.msg_buf
|
||||||
.write_data0(TwoBytesData::new_with_raw_value(0));
|
.write_data0(TwoBytesData::new_with_raw_value(0));
|
||||||
@ -155,35 +163,35 @@ impl CanChannelLowLevel {
|
|||||||
.write_data3(TwoBytesData::new_with_raw_value(0));
|
.write_data3(TwoBytesData::new_with_raw_value(0));
|
||||||
for idx in 0..dlc {
|
for idx in 0..dlc {
|
||||||
match idx {
|
match idx {
|
||||||
0 => self.msg_buf.modify_data3(|mut val| {
|
0 => self.msg_buf.modify_data0(|mut val| {
|
||||||
val.set_data_upper_byte(frame.data()[idx]);
|
val.set_data_upper_byte(frame.data()[idx]);
|
||||||
val
|
val
|
||||||
}),
|
}),
|
||||||
1 => self.msg_buf.modify_data3(|mut val| {
|
1 => self.msg_buf.modify_data0(|mut val| {
|
||||||
val.set_data_lower_byte(frame.data()[idx]);
|
val.set_data_lower_byte(frame.data()[idx]);
|
||||||
val
|
val
|
||||||
}),
|
}),
|
||||||
2 => self.msg_buf.modify_data2(|mut val| {
|
2 => self.msg_buf.modify_data1(|mut val| {
|
||||||
val.set_data_upper_byte(frame.data()[idx]);
|
val.set_data_upper_byte(frame.data()[idx]);
|
||||||
val
|
val
|
||||||
}),
|
}),
|
||||||
3 => self.msg_buf.modify_data2(|mut val| {
|
3 => self.msg_buf.modify_data1(|mut val| {
|
||||||
val.set_data_lower_byte(frame.data()[idx]);
|
val.set_data_lower_byte(frame.data()[idx]);
|
||||||
val
|
val
|
||||||
}),
|
}),
|
||||||
4 => self.msg_buf.modify_data1(|mut val| {
|
4 => self.msg_buf.modify_data2(|mut val| {
|
||||||
val.set_data_upper_byte(frame.data()[idx]);
|
val.set_data_upper_byte(frame.data()[idx]);
|
||||||
val
|
val
|
||||||
}),
|
}),
|
||||||
5 => self.msg_buf.modify_data1(|mut val| {
|
5 => self.msg_buf.modify_data2(|mut val| {
|
||||||
val.set_data_lower_byte(frame.data()[idx]);
|
val.set_data_lower_byte(frame.data()[idx]);
|
||||||
val
|
val
|
||||||
}),
|
}),
|
||||||
6 => self.msg_buf.modify_data0(|mut val| {
|
6 => self.msg_buf.modify_data3(|mut val| {
|
||||||
val.set_data_upper_byte(frame.data()[idx]);
|
val.set_data_upper_byte(frame.data()[idx]);
|
||||||
val
|
val
|
||||||
}),
|
}),
|
||||||
7 => self.msg_buf.modify_data0(|mut val| {
|
7 => self.msg_buf.modify_data3(|mut val| {
|
||||||
val.set_data_lower_byte(frame.data()[idx]);
|
val.set_data_lower_byte(frame.data()[idx]);
|
||||||
val
|
val
|
||||||
}),
|
}),
|
||||||
@ -191,11 +199,7 @@ impl CanChannelLowLevel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.msg_buf.modify_stat_ctrl(|mut ctrl| {
|
self.write_state(BufferState::TxOnce);
|
||||||
ctrl.set_dlc(u4::new(dlc as u8));
|
|
||||||
ctrl.set_status(BufferState::TxOnce);
|
|
||||||
ctrl
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_error_interrupt(&mut self, enable_translation: bool) {
|
pub fn enable_error_interrupt(&mut self, enable_translation: bool) {
|
||||||
@ -273,14 +277,14 @@ impl CanChannelLowLevel {
|
|||||||
let mut data: [u8; 8] = [0; 8];
|
let mut data: [u8; 8] = [0; 8];
|
||||||
let mut read_data = |dlc: u4| {
|
let mut read_data = |dlc: u4| {
|
||||||
(0..dlc.as_usize()).for_each(|i| match i {
|
(0..dlc.as_usize()).for_each(|i| match i {
|
||||||
0 => data[i] = data3.data_upper_byte().as_u8(),
|
0 => data[i] = data0.data_upper_byte().as_u8(),
|
||||||
1 => data[i] = data3.data_lower_byte().as_u8(),
|
1 => data[i] = data0.data_lower_byte().as_u8(),
|
||||||
2 => data[i] = data2.data_upper_byte().as_u8(),
|
2 => data[i] = data1.data_upper_byte().as_u8(),
|
||||||
3 => data[i] = data2.data_lower_byte().as_u8(),
|
3 => data[i] = data1.data_lower_byte().as_u8(),
|
||||||
4 => data[i] = data1.data_upper_byte().as_u8(),
|
4 => data[i] = data2.data_upper_byte().as_u8(),
|
||||||
5 => data[i] = data1.data_lower_byte().as_u8(),
|
5 => data[i] = data2.data_lower_byte().as_u8(),
|
||||||
6 => data[i] = data0.data_upper_byte().as_u8(),
|
6 => data[i] = data3.data_upper_byte().as_u8(),
|
||||||
7 => data[i] = data0.data_lower_byte().as_u8(),
|
7 => data[i] = data3.data_lower_byte().as_u8(),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -309,7 +313,7 @@ impl CanChannelLowLevel {
|
|||||||
} else {
|
} else {
|
||||||
let dlc = self.msg_buf.read_stat_ctrl().dlc();
|
let dlc = self.msg_buf.read_stat_ctrl().dlc();
|
||||||
read_data(dlc);
|
read_data(dlc);
|
||||||
CanFrameNormal::new(id, &data[0..dlc.as_usize()]).into()
|
CanFrameNormal::new(id, &data[0..dlc.as_usize()]).unwrap().into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,20 +125,16 @@ impl ClockConfig {
|
|||||||
if bitrate.raw() == 0 {
|
if bitrate.raw() == 0 {
|
||||||
return Err(ClockConfigError::BitrateIsZero);
|
return Err(ClockConfigError::BitrateIsZero);
|
||||||
}
|
}
|
||||||
let mut prescaler = roundf(
|
let nominal_bit_time = 1 + tseg1 as u32 + tseg2 as u32;
|
||||||
clocks.apb1().raw() as f32
|
let prescaler =
|
||||||
/ (bitrate.raw() as f32 * (1.0 + tseg1.as_u32() as f32 + tseg2.as_u32() as f32)),
|
roundf(clocks.apb1().raw() as f32 / (bitrate.raw() as f32 * nominal_bit_time as f32))
|
||||||
) as u32;
|
as u32;
|
||||||
// defmt::info!("calc prescaler: {}", prescaler);
|
|
||||||
if !(PRESCALER_MIN as u32..=PRESCALER_MAX as u32).contains(&prescaler) {
|
if !(PRESCALER_MIN as u32..=PRESCALER_MAX as u32).contains(&prescaler) {
|
||||||
return Err(ClockConfigError::CanNotFindPrescaler);
|
return Err(ClockConfigError::CanNotFindPrescaler);
|
||||||
}
|
}
|
||||||
|
|
||||||
let actual_bitrate = (clocks.apb1().raw() as f32)
|
let actual_bitrate = (clocks.apb1().raw() as f32) / (prescaler * nominal_bit_time) as f32;
|
||||||
/ (prescaler * (1 + tseg1.as_u32() + tseg2.as_u32())) as f32;
|
let bitrate_deviation = calculate_bitrate_deviation(actual_bitrate, bitrate);
|
||||||
let bitrate_deviation =
|
|
||||||
((actual_bitrate as i32 - bitrate.raw() as i32).abs() as f32) / bitrate.raw() as f32;
|
|
||||||
//defmt::info!("actual bitrate: {}, target {}", actual_bitrate, bitrate);
|
|
||||||
if bitrate_deviation > MAX_BITRATE_DEVIATION {
|
if bitrate_deviation > MAX_BITRATE_DEVIATION {
|
||||||
return Err(ClockConfigError::BitrateErrorTooLarge);
|
return Err(ClockConfigError::BitrateErrorTooLarge);
|
||||||
}
|
}
|
||||||
@ -392,6 +388,16 @@ impl Can {
|
|||||||
&mut self.regs
|
&mut self.regs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn read_error_counters(&self) -> regs::ErrorCounter {
|
||||||
|
self.regs.read_error_counter()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn read_error_diagnostics(&self) -> regs::DiagnosticRegister {
|
||||||
|
self.regs.read_diag()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn id(&self) -> CanId {
|
pub fn id(&self) -> CanId {
|
||||||
self.id
|
self.id
|
||||||
@ -403,11 +409,11 @@ impl Can {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_loopback(&mut self, enable: bool) {
|
pub fn modify_control<F>(&mut self, f: F)
|
||||||
self.regs.modify_control(|mut val| {
|
where
|
||||||
val.set_loopback(enable);
|
F: FnOnce(Control) -> Control,
|
||||||
val
|
{
|
||||||
});
|
self.regs.modify_control(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -436,10 +442,29 @@ pub enum TxState {
|
|||||||
AwaitingRemoteFrameReply,
|
AwaitingRemoteFrameReply,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub enum InvalidTxState {
|
||||||
|
State(TxState),
|
||||||
|
BufferState(BufferState),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TxState> for InvalidTxState {
|
||||||
|
fn from(state: TxState) -> Self {
|
||||||
|
InvalidTxState::State(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BufferState> for InvalidTxState {
|
||||||
|
fn from(state: BufferState) -> Self {
|
||||||
|
InvalidTxState::BufferState(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
#[error("invalid tx state {0:?}")]
|
#[error("invalid tx state {0:?}")]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct InvalidTxStateError(pub TxState);
|
pub struct InvalidTxStateError(pub InvalidTxState);
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
@ -474,20 +499,25 @@ impl CanTx {
|
|||||||
self.mode = TxState::Idle;
|
self.mode = TxState::Idle;
|
||||||
}
|
}
|
||||||
if self.mode != TxState::Idle {
|
if self.mode != TxState::Idle {
|
||||||
return Err(InvalidTxStateError(self.mode));
|
return Err(InvalidTxStateError(self.mode.into()));
|
||||||
}
|
}
|
||||||
if !frame.is_remote_frame() {
|
if !frame.is_remote_frame() {
|
||||||
self.mode = TxState::TransmittingDataFrame;
|
self.mode = TxState::TransmittingDataFrame;
|
||||||
} else {
|
} else {
|
||||||
self.mode = TxState::TransmittingRemoteFrame;
|
self.mode = TxState::TransmittingRemoteFrame;
|
||||||
}
|
}
|
||||||
|
if let Ok(state) = self.ll.read_state() {
|
||||||
|
if state != BufferState::TxNotActive {
|
||||||
|
return Err(InvalidTxStateError(state.into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
self.ll.transmit_frame_unchecked(frame);
|
self.ll.transmit_frame_unchecked(frame);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn data_frame_transfer_done(&mut self) -> nb::Result<(), InvalidTxStateError> {
|
pub fn data_frame_transfer_done(&mut self) -> nb::Result<(), InvalidTxStateError> {
|
||||||
if self.mode != TxState::TransmittingDataFrame {
|
if self.mode != TxState::TransmittingDataFrame {
|
||||||
return Err(nb::Error::Other(InvalidTxStateError(self.mode)));
|
return Err(nb::Error::Other(InvalidTxStateError(self.mode.into())));
|
||||||
}
|
}
|
||||||
let status = self.ll.read_state();
|
let status = self.ll.read_state();
|
||||||
if status.is_err() {
|
if status.is_err() {
|
||||||
@ -503,7 +533,7 @@ impl CanTx {
|
|||||||
|
|
||||||
pub fn remote_frame_transfer_done(&mut self) -> nb::Result<CanRx, InvalidTxStateError> {
|
pub fn remote_frame_transfer_done(&mut self) -> nb::Result<CanRx, InvalidTxStateError> {
|
||||||
if self.mode != TxState::TransmittingRemoteFrame {
|
if self.mode != TxState::TransmittingRemoteFrame {
|
||||||
return Err(nb::Error::Other(InvalidTxStateError(self.mode)));
|
return Err(nb::Error::Other(InvalidTxStateError(self.mode.into())));
|
||||||
}
|
}
|
||||||
let status = self.ll.read_state();
|
let status = self.ll.read_state();
|
||||||
if status.is_err() {
|
if status.is_err() {
|
||||||
@ -570,7 +600,7 @@ impl CanRx {
|
|||||||
return Err(nb::Error::WouldBlock);
|
return Err(nb::Error::WouldBlock);
|
||||||
}
|
}
|
||||||
let status = status.unwrap();
|
let status = status.unwrap();
|
||||||
if status == BufferState::RxReady || status == BufferState::RxOverrun {
|
if status == BufferState::RxFull || status == BufferState::RxOverrun {
|
||||||
self.mode = RxState::Idle;
|
self.mode = RxState::Idle;
|
||||||
if reconfigure_for_reception {
|
if reconfigure_for_reception {
|
||||||
self.ll.write_state(BufferState::RxReady);
|
self.ll.write_state(BufferState::RxReady);
|
||||||
|
@ -46,7 +46,7 @@ pub struct BufStatusAndControl {
|
|||||||
#[bits(4..=7, rw)]
|
#[bits(4..=7, rw)]
|
||||||
priority: u4,
|
priority: u4,
|
||||||
#[bits(0..=3, rw)]
|
#[bits(0..=3, rw)]
|
||||||
status: Option<BufferState>,
|
state: Option<BufferState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -68,10 +68,10 @@ impl Timestamp {
|
|||||||
#[bitbybit::bitfield(u32, default = 0x0)]
|
#[bitbybit::bitfield(u32, default = 0x0)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TwoBytesData {
|
pub struct TwoBytesData {
|
||||||
|
#[bits(0..=7, rw)]
|
||||||
|
data_lower_byte: u8,
|
||||||
#[bits(8..=15, rw)]
|
#[bits(8..=15, rw)]
|
||||||
data_upper_byte: u8,
|
data_upper_byte: u8,
|
||||||
#[bits(8..=15, rw)]
|
|
||||||
data_lower_byte: u8,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(derive_mmio::Mmio)]
|
#[derive(derive_mmio::Mmio)]
|
||||||
@ -87,14 +87,16 @@ pub struct CanMsgBuf {
|
|||||||
id1: BaseId,
|
id1: BaseId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_assertions::const_assert_eq!(core::mem::size_of::<CanMsgBuf>(), 0x20);
|
||||||
|
|
||||||
impl MmioCanMsgBuf<'_> {
|
impl MmioCanMsgBuf<'_> {
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
self.write_stat_ctrl(BufStatusAndControl::new_with_raw_value(0));
|
self.write_stat_ctrl(BufStatusAndControl::new_with_raw_value(0));
|
||||||
self.write_timestamp(Timestamp::new(0));
|
self.write_timestamp(Timestamp::new(0));
|
||||||
self.write_data3(TwoBytesData::new_with_raw_value(0));
|
|
||||||
self.write_data2(TwoBytesData::new_with_raw_value(0));
|
|
||||||
self.write_data1(TwoBytesData::new_with_raw_value(0));
|
|
||||||
self.write_data0(TwoBytesData::new_with_raw_value(0));
|
self.write_data0(TwoBytesData::new_with_raw_value(0));
|
||||||
|
self.write_data1(TwoBytesData::new_with_raw_value(0));
|
||||||
|
self.write_data2(TwoBytesData::new_with_raw_value(0));
|
||||||
|
self.write_data3(TwoBytesData::new_with_raw_value(0));
|
||||||
self.write_id1(BaseId::new_with_raw_value(0));
|
self.write_id1(BaseId::new_with_raw_value(0));
|
||||||
self.write_id0(ExtendedId::new_with_raw_value(0));
|
self.write_id0(ExtendedId::new_with_raw_value(0));
|
||||||
}
|
}
|
||||||
@ -387,6 +389,8 @@ pub struct Can {
|
|||||||
timer: u32,
|
timer: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_assertions::const_assert_eq!(core::mem::size_of::<Can>(), 0x238);
|
||||||
|
|
||||||
impl Can {
|
impl Can {
|
||||||
/// Create a new CAN MMIO instance for peripheral 0.
|
/// Create a new CAN MMIO instance for peripheral 0.
|
||||||
///
|
///
|
||||||
|
Loading…
x
Reference in New Issue
Block a user