Merge pull request #2658 from MaxiluxSystems/fdcan-buffered-read-consistent

stm32: fdcan: merge read impls, add setter for TxBufferMode, rename Queue -> Priority
This commit is contained in:
Dario Nieuwenhuis 2024-03-06 20:44:48 +00:00 committed by GitHub
commit 5e92973136
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 50 additions and 34 deletions

View File

@ -292,14 +292,14 @@ impl Default for GlobalFilter {
pub enum TxBufferMode { pub enum TxBufferMode {
/// TX FIFO operation - In this mode CAN frames are trasmitted strictly in write order. /// TX FIFO operation - In this mode CAN frames are trasmitted strictly in write order.
Fifo, Fifo,
/// TX queue operation - In this mode CAN frames are transmitted according to CAN priority. /// TX priority queue operation - In this mode CAN frames are transmitted according to CAN priority.
Queue, Priority,
} }
impl From<TxBufferMode> for crate::pac::can::vals::Tfqm { impl From<TxBufferMode> for crate::pac::can::vals::Tfqm {
fn from(value: TxBufferMode) -> Self { fn from(value: TxBufferMode) -> Self {
match value { match value {
TxBufferMode::Queue => Self::QUEUE, TxBufferMode::Priority => Self::QUEUE,
TxBufferMode::Fifo => Self::FIFO, TxBufferMode::Fifo => Self::FIFO,
} }
} }
@ -308,7 +308,7 @@ impl From<TxBufferMode> for crate::pac::can::vals::Tfqm {
impl From<crate::pac::can::vals::Tfqm> for TxBufferMode { impl From<crate::pac::can::vals::Tfqm> for TxBufferMode {
fn from(value: crate::pac::can::vals::Tfqm) -> Self { fn from(value: crate::pac::can::vals::Tfqm) -> Self {
match value { match value {
crate::pac::can::vals::Tfqm::QUEUE => Self::Queue, crate::pac::can::vals::Tfqm::QUEUE => Self::Priority,
crate::pac::can::vals::Tfqm::FIFO => Self::Fifo, crate::pac::can::vals::Tfqm::FIFO => Self::Fifo,
} }
} }
@ -354,7 +354,7 @@ pub struct FdCanConfig {
pub timestamp_source: TimestampSource, pub timestamp_source: TimestampSource,
/// Configures the Global Filter /// Configures the Global Filter
pub global_filter: GlobalFilter, pub global_filter: GlobalFilter,
/// TX buffer mode (FIFO or queue) /// TX buffer mode (FIFO or priority queue)
pub tx_buffer_mode: TxBufferMode, pub tx_buffer_mode: TxBufferMode,
} }
@ -445,6 +445,13 @@ impl FdCanConfig {
self.global_filter = filter; self.global_filter = filter;
self self
} }
/// Sets the TX buffer mode (FIFO or priority queue)
#[inline]
pub const fn set_tx_buffer_mode(mut self, txbm: TxBufferMode) -> Self {
self.tx_buffer_mode = txbm;
self
}
} }
impl Default for FdCanConfig { impl Default for FdCanConfig {
@ -462,7 +469,7 @@ impl Default for FdCanConfig {
clock_divider: ClockDivider::_1, clock_divider: ClockDivider::_1,
timestamp_source: TimestampSource::None, timestamp_source: TimestampSource::None,
global_filter: GlobalFilter::default(), global_filter: GlobalFilter::default(),
tx_buffer_mode: TxBufferMode::Queue, tx_buffer_mode: TxBufferMode::Priority,
} }
} }
} }

View File

@ -398,7 +398,8 @@ impl<'d, T: Instance> Fdcan<'d, T> {
} }
/// User supplied buffer for RX Buffering /// User supplied buffer for RX Buffering
pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, (ClassicFrame, Timestamp), BUF_SIZE>; pub type RxBuf<const BUF_SIZE: usize> =
Channel<CriticalSectionRawMutex, Result<(ClassicFrame, Timestamp), BusError>, BUF_SIZE>;
/// User supplied buffer for TX buffering /// User supplied buffer for TX buffering
pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, ClassicFrame, BUF_SIZE>; pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, ClassicFrame, BUF_SIZE>;
@ -440,7 +441,8 @@ impl BufferedCanSender {
} }
/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
pub type BufferedCanReceiver = embassy_sync::channel::DynamicReceiver<'static, (ClassicFrame, Timestamp)>; pub type BufferedCanReceiver =
embassy_sync::channel::DynamicReceiver<'static, Result<(ClassicFrame, Timestamp), BusError>>;
impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE>
@ -485,7 +487,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
/// Async read frame from RX buffer. /// Async read frame from RX buffer.
pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> { pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> {
Ok(self.rx_buf.receive().await) self.rx_buf.receive().await
} }
/// Returns a sender that can be used for sending CAN frames. /// Returns a sender that can be used for sending CAN frames.
@ -514,7 +516,8 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr
} }
/// User supplied buffer for RX Buffering /// User supplied buffer for RX Buffering
pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, (FdFrame, Timestamp), BUF_SIZE>; pub type RxFdBuf<const BUF_SIZE: usize> =
Channel<CriticalSectionRawMutex, Result<(FdFrame, Timestamp), BusError>, BUF_SIZE>;
/// User supplied buffer for TX buffering /// User supplied buffer for TX buffering
pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>; pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>;
@ -556,7 +559,8 @@ impl BufferedFdCanSender {
} }
/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
pub type BufferedFdCanReceiver = embassy_sync::channel::DynamicReceiver<'static, (FdFrame, Timestamp)>; pub type BufferedFdCanReceiver =
embassy_sync::channel::DynamicReceiver<'static, Result<(FdFrame, Timestamp), BusError>>;
impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE>
@ -601,7 +605,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
/// Async read frame from RX buffer. /// Async read frame from RX buffer.
pub async fn read(&mut self) -> Result<(FdFrame, Timestamp), BusError> { pub async fn read(&mut self) -> Result<(FdFrame, Timestamp), BusError> {
Ok(self.rx_buf.receive().await) self.rx_buf.receive().await
} }
/// Returns a sender that can be used for sending CAN frames. /// Returns a sender that can be used for sending CAN frames.
@ -685,14 +689,14 @@ pub(crate) mod sealed {
use crate::can::frame::{ClassicFrame, FdFrame}; use crate::can::frame::{ClassicFrame, FdFrame};
pub struct ClassicBufferedRxInner { pub struct ClassicBufferedRxInner {
pub rx_sender: DynamicSender<'static, (ClassicFrame, Timestamp)>, pub rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>,
} }
pub struct ClassicBufferedTxInner { pub struct ClassicBufferedTxInner {
pub tx_receiver: DynamicReceiver<'static, ClassicFrame>, pub tx_receiver: DynamicReceiver<'static, ClassicFrame>,
} }
pub struct FdBufferedRxInner { pub struct FdBufferedRxInner {
pub rx_sender: DynamicSender<'static, (FdFrame, Timestamp)>, pub rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>,
} }
pub struct FdBufferedTxInner { pub struct FdBufferedTxInner {
pub tx_receiver: DynamicReceiver<'static, FdFrame>, pub tx_receiver: DynamicReceiver<'static, FdFrame>,
@ -721,46 +725,51 @@ pub(crate) mod sealed {
waker.wake(); waker.wake();
} }
RxMode::ClassicBuffered(buf) => { RxMode::ClassicBuffered(buf) => {
if let Some(r) = T::registers().read(fifonr) { if let Some(result) = self.read::<T, _>() {
let ts = T::calc_timestamp(T::state().ns_per_timer_tick, r.1); let _ = buf.rx_sender.try_send(result);
let _ = buf.rx_sender.try_send((r.0, ts));
} }
} }
RxMode::FdBuffered(buf) => { RxMode::FdBuffered(buf) => {
if let Some(r) = T::registers().read(fifonr) { if let Some(result) = self.read::<T, _>() {
let ts = T::calc_timestamp(T::state().ns_per_timer_tick, r.1); let _ = buf.rx_sender.try_send(result);
let _ = buf.rx_sender.try_send((r.0, ts));
} }
} }
} }
} }
async fn read<T: Instance, F: CanHeader>(&self) -> Result<(F, Timestamp), BusError> { fn read<T: Instance, F: CanHeader>(&self) -> Option<Result<(F, Timestamp), BusError>> {
if let Some((msg, ts)) = T::registers().read(0) {
let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
Some(Ok((msg, ts)))
} else if let Some((msg, ts)) = T::registers().read(1) {
let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
Some(Ok((msg, ts)))
} else if let Some(err) = T::registers().curr_error() {
// TODO: this is probably wrong
Some(Err(err))
} else {
None
}
}
async fn read_async<T: Instance, F: CanHeader>(&self) -> Result<(F, Timestamp), BusError> {
poll_fn(|cx| { poll_fn(|cx| {
T::state().err_waker.register(cx.waker()); T::state().err_waker.register(cx.waker());
self.register(cx.waker()); self.register(cx.waker());
match self.read::<T, _>() {
if let Some((msg, ts)) = T::registers().read(0) { Some(result) => Poll::Ready(result),
let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); None => Poll::Pending,
return Poll::Ready(Ok((msg, ts)));
} else if let Some((msg, ts)) = T::registers().read(1) {
let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
return Poll::Ready(Ok((msg, ts)));
} else if let Some(err) = T::registers().curr_error() {
// TODO: this is probably wrong
return Poll::Ready(Err(err));
} }
Poll::Pending
}) })
.await .await
} }
pub async fn read_classic<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> { pub async fn read_classic<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> {
self.read::<T, _>().await self.read_async::<T, _>().await
} }
pub async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> { pub async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> {
self.read::<T, _>().await self.read_async::<T, _>().await
} }
} }