added RTR example

This commit is contained in:
2025-05-13 14:45:49 +02:00
parent 37ec9114b3
commit d661c940fe
4 changed files with 110 additions and 56 deletions

View File

@ -1,7 +1,6 @@
use core::{
future::Future,
sync::atomic::{AtomicU8, Ordering},
usize,
};
use crate::can::regs::BufferState;

View File

@ -90,10 +90,7 @@ impl CanChannelLowLevel {
});
}
pub fn configure_for_transmission(
&mut self,
tx_priority: Option<u4>,
) -> Result<(), InvalidBufferIndexError> {
pub fn configure_for_transmission(&mut self, tx_priority: Option<u4>) {
self.msg_buf.modify_stat_ctrl(|mut val| {
val.set_dlc(u4::new(0));
if let Some(tx_priority) = tx_priority {
@ -102,28 +99,18 @@ impl CanChannelLowLevel {
val.set_state(BufferState::TxNotActive);
val
});
Ok(())
}
pub fn set_standard_id(
&mut self,
standard_id: embedded_can::StandardId,
set_rtr: bool,
) -> Result<(), InvalidBufferIndexError> {
pub fn set_standard_id(&mut self, standard_id: embedded_can::StandardId, set_rtr: bool) {
let mut id1_reg = standard_id.as_raw() << 5;
if set_rtr {
id1_reg |= 1 << 4;
}
self.msg_buf
.write_id1(BaseId::new_with_raw_value(id1_reg as u32));
Ok(())
}
pub fn set_extended_id(
&mut self,
extended_id: embedded_can::ExtendedId,
set_rtr: bool,
) -> Result<(), InvalidBufferIndexError> {
pub fn set_extended_id(&mut self, extended_id: embedded_can::ExtendedId, set_rtr: bool) {
let id_raw = extended_id.as_raw();
let id1_reg = (((id_raw >> 18) & 0x7FF) << 4) as u16 | ((id_raw >> 15) & 0b111) as u16;
self.msg_buf
@ -131,7 +118,6 @@ impl CanChannelLowLevel {
let id0_reg = ((id_raw & 0x7FFF) << 1) as u16 | set_rtr as u16;
self.msg_buf
.write_id0(ExtendedId::new_with_raw_value(id0_reg as u32));
Ok(())
}
pub fn configure_for_reception(&mut self) {
@ -313,7 +299,9 @@ impl CanChannelLowLevel {
} else {
let dlc = self.msg_buf.read_stat_ctrl().dlc();
read_data(dlc);
CanFrameNormal::new(id, &data[0..dlc.as_usize()]).unwrap().into()
CanFrameNormal::new(id, &data[0..dlc.as_usize()])
.unwrap()
.into()
}
}
}

View File

@ -486,16 +486,23 @@ pub struct CanTx {
impl CanTx {
pub fn new(mut ll: CanChannelLowLevel, tx_priority: Option<u4>) -> Self {
ll.configure_for_transmission(tx_priority).unwrap();
ll.configure_for_transmission(tx_priority);
Self {
ll,
mode: TxState::Idle,
}
}
/// Start transmitting a frame.
///
/// The frame transmission can be polled/awaited to completion using the [Self::transfer_done]
/// method.
///
/// This function will return a [state error][InvalidTxStateError] if a transmission is already
/// active and/or the transmit buffer has an invalid state.
pub fn transmit_frame(&mut self, frame: CanFrame) -> Result<(), InvalidTxStateError> {
if self.mode == TxState::AwaitingRemoteFrameReply {
self.ll.configure_for_transmission(None).unwrap();
self.ll.configure_for_transmission(None);
self.mode = TxState::Idle;
}
if self.mode != TxState::Idle {
@ -515,7 +522,10 @@ impl CanTx {
Ok(())
}
pub fn data_frame_transfer_done(&mut self) -> nb::Result<(), InvalidTxStateError> {
/// Poll whether an active data frame transmission is done.
///
/// Returns a [state error][InvalidTxStateError] if no transmission is active.
pub fn transfer_done(&mut self) -> nb::Result<(), InvalidTxStateError> {
if self.mode != TxState::TransmittingDataFrame {
return Err(nb::Error::Other(InvalidTxStateError(self.mode.into())));
}
@ -531,7 +541,10 @@ impl CanTx {
Err(nb::Error::WouldBlock)
}
pub fn remote_frame_transfer_done(&mut self) -> nb::Result<CanRx, InvalidTxStateError> {
/// Poll whether an active remote frame transmission is done.
///
/// Returns a [state error][InvalidTxStateError] if no transmission is active.
pub fn remote_transfer_done(&mut self) -> nb::Result<CanRx, InvalidTxStateError> {
if self.mode != TxState::TransmittingRemoteFrame {
return Err(nb::Error::Other(InvalidTxStateError(self.mode.into())));
}
@ -549,6 +562,11 @@ impl CanTx {
}
Err(nb::Error::WouldBlock)
}
pub fn reset(&mut self) {
self.ll.reset();
self.mode = TxState::Idle;
}
}
pub struct CanRx {
@ -567,20 +585,18 @@ impl CanRx {
&mut self,
standard_id: embedded_can::StandardId,
set_rtr: bool,
) -> Result<(), InvalidBufferIndexError> {
self.ll.set_standard_id(standard_id, set_rtr)?;
) {
self.ll.set_standard_id(standard_id, set_rtr);
self.configure_for_reception();
Ok(())
}
pub fn configure_for_reception_with_extended_id(
&mut self,
extended_id: embedded_can::ExtendedId,
set_rtr: bool,
) -> Result<(), InvalidBufferIndexError> {
self.ll.set_extended_id(extended_id, set_rtr)?;
) {
self.ll.set_extended_id(extended_id, set_rtr);
self.configure_for_reception();
Ok(())
}
pub fn configure_for_reception(&mut self) {
@ -588,6 +604,14 @@ impl CanRx {
self.mode = RxState::Receiving;
}
#[inline]
pub fn frame_available(&self) -> bool {
self.ll
.read_state()
.is_ok_and(|state| state == BufferState::RxFull || state == BufferState::RxOverrun)
}
/// Poll for frame reception. Returns the frame if one is available.
pub fn receive(
&mut self,
reconfigure_for_reception: bool,