mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-25 08:12:30 +00:00
CAN: Unify API's between BXCAN and FDCAN. Use Envelope for all read methods instead of a tuple sometimes.
This commit is contained in:
parent
f5daa50a7b
commit
2217b80278
@ -40,12 +40,11 @@ pub type Header = crate::can::frame::Header;
|
||||
/// Data for a CAN Frame
|
||||
pub type Data = crate::can::frame::ClassicData;
|
||||
|
||||
/// CAN Frame
|
||||
pub type Frame = crate::can::frame::ClassicFrame;
|
||||
|
||||
use crate::can::_version::Envelope;
|
||||
use crate::can::bx::filter::MasterFilters;
|
||||
use crate::can::enums::BusError;
|
||||
/// CAN Frame
|
||||
pub use crate::can::frame::Frame;
|
||||
use crate::pac::can::vals::Lec;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
|
@ -19,22 +19,10 @@ use crate::{interrupt, peripherals, Peripheral};
|
||||
pub mod enums;
|
||||
pub mod frame;
|
||||
pub mod util;
|
||||
pub use frame::Envelope;
|
||||
|
||||
mod common;
|
||||
pub use self::common::{BufferedCanReceiver, BufferedCanSender, Timestamp};
|
||||
|
||||
/// Contains CAN frame and additional metadata.
|
||||
///
|
||||
/// Timestamp is available if `time` feature is enabled.
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct Envelope {
|
||||
/// Reception time.
|
||||
#[cfg(feature = "time")]
|
||||
pub ts: embassy_time::Instant,
|
||||
/// The actual CAN frame.
|
||||
pub frame: Frame,
|
||||
}
|
||||
pub use self::common::{BufferedCanReceiver, BufferedCanSender};
|
||||
|
||||
/// Interrupt handler.
|
||||
pub struct TxInterruptHandler<T: Instance> {
|
||||
@ -276,7 +264,7 @@ impl<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Buffer
|
||||
}
|
||||
|
||||
/// Async read frame from RX buffer.
|
||||
pub async fn read(&mut self) -> Result<(Frame, Timestamp), BusError> {
|
||||
pub async fn read(&mut self) -> Result<Envelope, BusError> {
|
||||
self.rx.read().await
|
||||
}
|
||||
|
||||
@ -482,8 +470,7 @@ impl<'d, T: Instance> CanRx<'d, T> {
|
||||
}
|
||||
|
||||
/// User supplied buffer for RX Buffering
|
||||
pub type RxBuf<const BUF_SIZE: usize> =
|
||||
Channel<CriticalSectionRawMutex, Result<(Frame, Timestamp), BusError>, BUF_SIZE>;
|
||||
pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>;
|
||||
|
||||
/// CAN driver, receive half in Buffered mode.
|
||||
pub struct BufferedCanRx<'d, T: Instance, const RX_BUF_SIZE: usize> {
|
||||
@ -508,7 +495,7 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE
|
||||
}
|
||||
|
||||
/// Async read frame from RX buffer.
|
||||
pub async fn read(&mut self) -> Result<(Frame, Timestamp), BusError> {
|
||||
pub async fn read(&mut self) -> Result<Envelope, BusError> {
|
||||
self.rx_buf.receive().await
|
||||
}
|
||||
|
||||
@ -520,7 +507,7 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE
|
||||
RxMode::Buffered(_) => {
|
||||
if let Ok(result) = self.rx_buf.try_receive() {
|
||||
match result {
|
||||
Ok((frame, ts)) => Ok(Envelope { ts, frame }),
|
||||
Ok(envelope) => Ok(envelope),
|
||||
Err(e) => Err(TryReadError::BusError(e)),
|
||||
}
|
||||
} else {
|
||||
@ -610,7 +597,7 @@ impl RxMode {
|
||||
match regsisters.receive_fifo(fifo) {
|
||||
Some(envelope) => {
|
||||
// NOTE: consensus was reached that if rx_queue is full, packets should be dropped
|
||||
let _ = buf.rx_sender.try_send(Ok((envelope.frame, envelope.ts)));
|
||||
let _ = buf.rx_sender.try_send(Ok(envelope));
|
||||
}
|
||||
None => return,
|
||||
};
|
||||
|
@ -3,25 +3,17 @@ use embassy_sync::channel::{DynamicReceiver, DynamicSender};
|
||||
use crate::can::_version::enums::*;
|
||||
use crate::can::_version::frame::*;
|
||||
|
||||
/// Timestamp for incoming packets. Use Embassy time when enabled.
|
||||
#[cfg(feature = "time")]
|
||||
pub type Timestamp = embassy_time::Instant;
|
||||
|
||||
/// Timestamp for incoming packets.
|
||||
#[cfg(not(feature = "time"))]
|
||||
pub type Timestamp = u16;
|
||||
|
||||
pub(crate) struct ClassicBufferedRxInner {
|
||||
pub rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>,
|
||||
pub rx_sender: DynamicSender<'static, Result<Envelope, BusError>>,
|
||||
}
|
||||
pub(crate) struct ClassicBufferedTxInner {
|
||||
pub tx_receiver: DynamicReceiver<'static, ClassicFrame>,
|
||||
pub tx_receiver: DynamicReceiver<'static, Frame>,
|
||||
}
|
||||
|
||||
#[cfg(any(can_fdcan_v1, can_fdcan_h7))]
|
||||
|
||||
pub(crate) struct FdBufferedRxInner {
|
||||
pub rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>,
|
||||
pub rx_sender: DynamicSender<'static, Result<FdEnvelope, BusError>>,
|
||||
}
|
||||
|
||||
#[cfg(any(can_fdcan_v1, can_fdcan_h7))]
|
||||
@ -32,20 +24,20 @@ pub(crate) struct FdBufferedTxInner {
|
||||
/// Sender that can be used for sending CAN frames.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct BufferedCanSender {
|
||||
pub(crate) tx_buf: embassy_sync::channel::DynamicSender<'static, ClassicFrame>,
|
||||
pub(crate) tx_buf: embassy_sync::channel::DynamicSender<'static, Frame>,
|
||||
pub(crate) waker: fn(),
|
||||
}
|
||||
|
||||
impl BufferedCanSender {
|
||||
/// Async write frame to TX buffer.
|
||||
pub fn try_write(&mut self, frame: ClassicFrame) -> Result<(), embassy_sync::channel::TrySendError<ClassicFrame>> {
|
||||
pub fn try_write(&mut self, frame: Frame) -> Result<(), embassy_sync::channel::TrySendError<Frame>> {
|
||||
self.tx_buf.try_send(frame)?;
|
||||
(self.waker)();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Async write frame to TX buffer.
|
||||
pub async fn write(&mut self, frame: ClassicFrame) {
|
||||
pub async fn write(&mut self, frame: Frame) {
|
||||
self.tx_buf.send(frame).await;
|
||||
(self.waker)();
|
||||
}
|
||||
@ -57,5 +49,4 @@ impl BufferedCanSender {
|
||||
}
|
||||
|
||||
/// 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, Result<(ClassicFrame, Timestamp), BusError>>;
|
||||
pub type BufferedCanReceiver = embassy_sync::channel::DynamicReceiver<'static, Result<Envelope, BusError>>;
|
||||
|
@ -397,13 +397,13 @@ impl Registers {
|
||||
|
||||
/// Moves out of ConfigMode and into specified mode
|
||||
#[inline]
|
||||
pub fn into_mode(mut self, config: FdCanConfig, mode: crate::can::_version::FdcanOperatingMode) {
|
||||
pub fn into_mode(mut self, config: FdCanConfig, mode: crate::can::_version::OperatingMode) {
|
||||
match mode {
|
||||
crate::can::FdcanOperatingMode::InternalLoopbackMode => self.set_loopback_mode(LoopbackMode::Internal),
|
||||
crate::can::FdcanOperatingMode::ExternalLoopbackMode => self.set_loopback_mode(LoopbackMode::External),
|
||||
crate::can::FdcanOperatingMode::NormalOperationMode => self.set_normal_operations(true),
|
||||
crate::can::FdcanOperatingMode::RestrictedOperationMode => self.set_restricted_operations(true),
|
||||
crate::can::FdcanOperatingMode::BusMonitoringMode => self.set_bus_monitoring_mode(true),
|
||||
crate::can::OperatingMode::InternalLoopbackMode => self.set_loopback_mode(LoopbackMode::Internal),
|
||||
crate::can::OperatingMode::ExternalLoopbackMode => self.set_loopback_mode(LoopbackMode::External),
|
||||
crate::can::OperatingMode::NormalOperationMode => self.set_normal_operations(true),
|
||||
crate::can::OperatingMode::RestrictedOperationMode => self.set_restricted_operations(true),
|
||||
crate::can::OperatingMode::BusMonitoringMode => self.set_bus_monitoring_mode(true),
|
||||
}
|
||||
self.leave_init_mode(config);
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT1Interrupt> for IT1Interrup
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
/// Different operating modes
|
||||
pub enum FdcanOperatingMode {
|
||||
pub enum OperatingMode {
|
||||
//PoweredDownMode,
|
||||
//ConfigMode,
|
||||
/// This mode can be used for a “Hot Selftest”, meaning the FDCAN can be tested without
|
||||
@ -148,7 +148,7 @@ pub enum FdcanOperatingMode {
|
||||
|
||||
/// FDCAN Configuration instance instance
|
||||
/// Create instance of this first
|
||||
pub struct FdcanConfigurator<'d, T: Instance> {
|
||||
pub struct CanConfigurator<'d, T: Instance> {
|
||||
config: crate::can::fd::config::FdCanConfig,
|
||||
/// Reference to internals.
|
||||
instance: FdcanInstance<'d, T>,
|
||||
@ -169,7 +169,7 @@ fn calc_ns_per_timer_tick<T: Instance>(mode: crate::can::fd::config::FrameTransm
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> FdcanConfigurator<'d, T> {
|
||||
impl<'d, T: Instance> CanConfigurator<'d, T> {
|
||||
/// Creates a new Fdcan instance, keeping the peripheral in sleep mode.
|
||||
/// You must call [Fdcan::enable_non_blocking] to use the peripheral.
|
||||
pub fn new(
|
||||
@ -179,7 +179,7 @@ impl<'d, T: Instance> FdcanConfigurator<'d, T> {
|
||||
_irqs: impl interrupt::typelevel::Binding<T::IT0Interrupt, IT0InterruptHandler<T>>
|
||||
+ interrupt::typelevel::Binding<T::IT1Interrupt, IT1InterruptHandler<T>>
|
||||
+ 'd,
|
||||
) -> FdcanConfigurator<'d, T> {
|
||||
) -> CanConfigurator<'d, T> {
|
||||
into_ref!(peri, rx, tx);
|
||||
|
||||
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||
@ -273,13 +273,13 @@ impl<'d, T: Instance> FdcanConfigurator<'d, T> {
|
||||
}
|
||||
|
||||
/// Start in mode.
|
||||
pub fn start(self, mode: FdcanOperatingMode) -> Fdcan<'d, T> {
|
||||
pub fn start(self, mode: OperatingMode) -> Can<'d, T> {
|
||||
let ns_per_timer_tick = calc_ns_per_timer_tick::<T>(self.config.frame_transmit);
|
||||
critical_section::with(|_| unsafe {
|
||||
T::mut_state().ns_per_timer_tick = ns_per_timer_tick;
|
||||
});
|
||||
T::registers().into_mode(self.config, mode);
|
||||
let ret = Fdcan {
|
||||
let ret = Can {
|
||||
config: self.config,
|
||||
instance: self.instance,
|
||||
_mode: mode,
|
||||
@ -288,30 +288,30 @@ impl<'d, T: Instance> FdcanConfigurator<'d, T> {
|
||||
}
|
||||
|
||||
/// Start, entering mode. Does same as start(mode)
|
||||
pub fn into_normal_mode(self) -> Fdcan<'d, T> {
|
||||
self.start(FdcanOperatingMode::NormalOperationMode)
|
||||
pub fn into_normal_mode(self) -> Can<'d, T> {
|
||||
self.start(OperatingMode::NormalOperationMode)
|
||||
}
|
||||
|
||||
/// Start, entering mode. Does same as start(mode)
|
||||
pub fn into_internal_loopback_mode(self) -> Fdcan<'d, T> {
|
||||
self.start(FdcanOperatingMode::InternalLoopbackMode)
|
||||
pub fn into_internal_loopback_mode(self) -> Can<'d, T> {
|
||||
self.start(OperatingMode::InternalLoopbackMode)
|
||||
}
|
||||
|
||||
/// Start, entering mode. Does same as start(mode)
|
||||
pub fn into_external_loopback_mode(self) -> Fdcan<'d, T> {
|
||||
self.start(FdcanOperatingMode::ExternalLoopbackMode)
|
||||
pub fn into_external_loopback_mode(self) -> Can<'d, T> {
|
||||
self.start(OperatingMode::ExternalLoopbackMode)
|
||||
}
|
||||
}
|
||||
|
||||
/// FDCAN Instance
|
||||
pub struct Fdcan<'d, T: Instance> {
|
||||
pub struct Can<'d, T: Instance> {
|
||||
config: crate::can::fd::config::FdCanConfig,
|
||||
/// Reference to internals.
|
||||
instance: FdcanInstance<'d, T>,
|
||||
_mode: FdcanOperatingMode,
|
||||
_mode: OperatingMode,
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Fdcan<'d, T> {
|
||||
impl<'d, T: Instance> Can<'d, T> {
|
||||
/// Flush one of the TX mailboxes.
|
||||
pub async fn flush(&self, idx: usize) {
|
||||
poll_fn(|cx| {
|
||||
@ -334,12 +334,12 @@ impl<'d, T: Instance> Fdcan<'d, T> {
|
||||
/// frame is dropped from the mailbox, it is returned. If no lower-priority frames
|
||||
/// can be replaced, this call asynchronously waits for a frame to be successfully
|
||||
/// transmitted, then tries again.
|
||||
pub async fn write(&mut self, frame: &ClassicFrame) -> Option<ClassicFrame> {
|
||||
pub async fn write(&mut self, frame: &Frame) -> Option<Frame> {
|
||||
T::state().tx_mode.write::<T>(frame).await
|
||||
}
|
||||
|
||||
/// Returns the next received message frame
|
||||
pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> {
|
||||
pub async fn read(&mut self) -> Result<Envelope, BusError> {
|
||||
T::state().rx_mode.read_classic::<T>().await
|
||||
}
|
||||
|
||||
@ -352,19 +352,19 @@ impl<'d, T: Instance> Fdcan<'d, T> {
|
||||
}
|
||||
|
||||
/// Returns the next received message frame
|
||||
pub async fn read_fd(&mut self) -> Result<(FdFrame, Timestamp), BusError> {
|
||||
pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> {
|
||||
T::state().rx_mode.read_fd::<T>().await
|
||||
}
|
||||
|
||||
/// Split instance into separate Tx(write) and Rx(read) portions
|
||||
pub fn split(self) -> (FdcanTx<'d, T>, FdcanRx<'d, T>) {
|
||||
pub fn split(self) -> (CanTx<'d, T>, CanRx<'d, T>) {
|
||||
(
|
||||
FdcanTx {
|
||||
CanTx {
|
||||
config: self.config,
|
||||
_instance: self.instance,
|
||||
_mode: self._mode,
|
||||
},
|
||||
FdcanRx {
|
||||
CanRx {
|
||||
_instance1: PhantomData::<T>,
|
||||
_instance2: T::regs(),
|
||||
_mode: self._mode,
|
||||
@ -373,8 +373,8 @@ impl<'d, T: Instance> Fdcan<'d, T> {
|
||||
}
|
||||
|
||||
/// Join split rx and tx portions back together
|
||||
pub fn join(tx: FdcanTx<'d, T>, rx: FdcanRx<'d, T>) -> Self {
|
||||
Fdcan {
|
||||
pub fn join(tx: CanTx<'d, T>, rx: CanRx<'d, T>) -> Self {
|
||||
Can {
|
||||
config: tx.config,
|
||||
//_instance2: T::regs(),
|
||||
instance: tx._instance,
|
||||
@ -402,17 +402,16 @@ impl<'d, T: Instance> Fdcan<'d, T> {
|
||||
}
|
||||
|
||||
/// User supplied buffer for RX Buffering
|
||||
pub type RxBuf<const BUF_SIZE: usize> =
|
||||
Channel<CriticalSectionRawMutex, Result<(ClassicFrame, Timestamp), BusError>, BUF_SIZE>;
|
||||
pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>;
|
||||
|
||||
/// 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, Frame, BUF_SIZE>;
|
||||
|
||||
/// Buffered FDCAN Instance
|
||||
pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
|
||||
_instance1: PhantomData<T>,
|
||||
_instance2: &'d crate::pac::can::Fdcan,
|
||||
_mode: FdcanOperatingMode,
|
||||
_mode: OperatingMode,
|
||||
tx_buf: &'static TxBuf<TX_BUF_SIZE>,
|
||||
rx_buf: &'static RxBuf<RX_BUF_SIZE>,
|
||||
}
|
||||
@ -423,7 +422,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
|
||||
fn new(
|
||||
_instance1: PhantomData<T>,
|
||||
_instance2: &'d crate::pac::can::Fdcan,
|
||||
_mode: FdcanOperatingMode,
|
||||
_mode: OperatingMode,
|
||||
tx_buf: &'static TxBuf<TX_BUF_SIZE>,
|
||||
rx_buf: &'static RxBuf<RX_BUF_SIZE>,
|
||||
) -> Self {
|
||||
@ -453,13 +452,13 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
|
||||
}
|
||||
|
||||
/// Async write frame to TX buffer.
|
||||
pub async fn write(&mut self, frame: ClassicFrame) {
|
||||
pub async fn write(&mut self, frame: Frame) {
|
||||
self.tx_buf.send(frame).await;
|
||||
T::IT0Interrupt::pend(); // Wake for Tx
|
||||
}
|
||||
|
||||
/// Async read frame from RX buffer.
|
||||
pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> {
|
||||
pub async fn read(&mut self) -> Result<Envelope, BusError> {
|
||||
self.rx_buf.receive().await
|
||||
}
|
||||
|
||||
@ -489,8 +488,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr
|
||||
}
|
||||
|
||||
/// User supplied buffer for RX Buffering
|
||||
pub type RxFdBuf<const BUF_SIZE: usize> =
|
||||
Channel<CriticalSectionRawMutex, Result<(FdFrame, Timestamp), BusError>, BUF_SIZE>;
|
||||
pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<FdEnvelope, BusError>, BUF_SIZE>;
|
||||
|
||||
/// User supplied buffer for TX buffering
|
||||
pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>;
|
||||
@ -499,7 +497,7 @@ pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFra
|
||||
pub struct BufferedCanFd<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
|
||||
_instance1: PhantomData<T>,
|
||||
_instance2: &'d crate::pac::can::Fdcan,
|
||||
_mode: FdcanOperatingMode,
|
||||
_mode: OperatingMode,
|
||||
tx_buf: &'static TxFdBuf<TX_BUF_SIZE>,
|
||||
rx_buf: &'static RxFdBuf<RX_BUF_SIZE>,
|
||||
}
|
||||
@ -532,7 +530,7 @@ impl BufferedFdCanSender {
|
||||
}
|
||||
|
||||
/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
|
||||
pub type BufferedFdCanReceiver = DynamicReceiver<'static, Result<(FdFrame, Timestamp), BusError>>;
|
||||
pub type BufferedFdCanReceiver = DynamicReceiver<'static, Result<FdEnvelope, BusError>>;
|
||||
|
||||
impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
|
||||
BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE>
|
||||
@ -540,7 +538,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
|
||||
fn new(
|
||||
_instance1: PhantomData<T>,
|
||||
_instance2: &'d crate::pac::can::Fdcan,
|
||||
_mode: FdcanOperatingMode,
|
||||
_mode: OperatingMode,
|
||||
tx_buf: &'static TxFdBuf<TX_BUF_SIZE>,
|
||||
rx_buf: &'static RxFdBuf<RX_BUF_SIZE>,
|
||||
) -> Self {
|
||||
@ -576,7 +574,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
|
||||
}
|
||||
|
||||
/// Async read frame from RX buffer.
|
||||
pub async fn read(&mut self) -> Result<(FdFrame, Timestamp), BusError> {
|
||||
pub async fn read(&mut self) -> Result<FdEnvelope, BusError> {
|
||||
self.rx_buf.receive().await
|
||||
}
|
||||
|
||||
@ -606,25 +604,25 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr
|
||||
}
|
||||
|
||||
/// FDCAN Rx only Instance
|
||||
pub struct FdcanRx<'d, T: Instance> {
|
||||
pub struct CanRx<'d, T: Instance> {
|
||||
_instance1: PhantomData<T>,
|
||||
_instance2: &'d crate::pac::can::Fdcan,
|
||||
_mode: FdcanOperatingMode,
|
||||
_mode: OperatingMode,
|
||||
}
|
||||
|
||||
/// FDCAN Tx only Instance
|
||||
pub struct FdcanTx<'d, T: Instance> {
|
||||
pub struct CanTx<'d, T: Instance> {
|
||||
config: crate::can::fd::config::FdCanConfig,
|
||||
_instance: FdcanInstance<'d, T>, //(PeripheralRef<'a, T>);
|
||||
_mode: FdcanOperatingMode,
|
||||
_mode: OperatingMode,
|
||||
}
|
||||
|
||||
impl<'c, 'd, T: Instance> FdcanTx<'d, T> {
|
||||
impl<'c, 'd, T: Instance> CanTx<'d, T> {
|
||||
/// Queues the message to be sent but exerts backpressure. If a lower-priority
|
||||
/// frame is dropped from the mailbox, it is returned. If no lower-priority frames
|
||||
/// can be replaced, this call asynchronously waits for a frame to be successfully
|
||||
/// transmitted, then tries again.
|
||||
pub async fn write(&mut self, frame: &ClassicFrame) -> Option<ClassicFrame> {
|
||||
pub async fn write(&mut self, frame: &Frame) -> Option<Frame> {
|
||||
T::state().tx_mode.write::<T>(frame).await
|
||||
}
|
||||
|
||||
@ -637,14 +635,14 @@ impl<'c, 'd, T: Instance> FdcanTx<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'c, 'd, T: Instance> FdcanRx<'d, T> {
|
||||
impl<'c, 'd, T: Instance> CanRx<'d, T> {
|
||||
/// Returns the next received message frame
|
||||
pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> {
|
||||
pub async fn read(&mut self) -> Result<Envelope, BusError> {
|
||||
T::state().rx_mode.read_classic::<T>().await
|
||||
}
|
||||
|
||||
/// Returns the next received message frame
|
||||
pub async fn read_fd(&mut self) -> Result<(FdFrame, Timestamp), BusError> {
|
||||
pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> {
|
||||
T::state().rx_mode.read_fd::<T>().await
|
||||
}
|
||||
}
|
||||
@ -672,18 +670,50 @@ impl RxMode {
|
||||
waker.wake();
|
||||
}
|
||||
RxMode::ClassicBuffered(buf) => {
|
||||
if let Some(result) = self.read::<T, _>() {
|
||||
if let Some(result) = self.try_read::<T>() {
|
||||
let _ = buf.rx_sender.try_send(result);
|
||||
}
|
||||
}
|
||||
RxMode::FdBuffered(buf) => {
|
||||
if let Some(result) = self.read::<T, _>() {
|
||||
if let Some(result) = self.try_read_fd::<T>() {
|
||||
let _ = buf.rx_sender.try_send(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//async fn read_classic<T: Instance>(&self) -> Result<Envelope, BusError> {
|
||||
fn try_read<T: Instance>(&self) -> Option<Result<Envelope, BusError>> {
|
||||
if let Some((frame, ts)) = T::registers().read(0) {
|
||||
let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
|
||||
Some(Ok(Envelope { ts, frame }))
|
||||
} else if let Some((frame, ts)) = T::registers().read(1) {
|
||||
let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
|
||||
Some(Ok(Envelope { ts, frame }))
|
||||
} else if let Some(err) = T::registers().curr_error() {
|
||||
// TODO: this is probably wrong
|
||||
Some(Err(err))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
//async fn read_classic<T: Instance>(&self) -> Result<Envelope, BusError> {
|
||||
fn try_read_fd<T: Instance>(&self) -> Option<Result<FdEnvelope, BusError>> {
|
||||
if let Some((frame, ts)) = T::registers().read(0) {
|
||||
let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
|
||||
Some(Ok(FdEnvelope { ts, frame }))
|
||||
} else if let Some((frame, ts)) = T::registers().read(1) {
|
||||
let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
|
||||
Some(Ok(FdEnvelope { ts, frame }))
|
||||
} else if let Some(err) = T::registers().curr_error() {
|
||||
// TODO: this is probably wrong
|
||||
Some(Err(err))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@ -711,12 +741,18 @@ impl RxMode {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn read_classic<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> {
|
||||
self.read_async::<T, _>().await
|
||||
async fn read_classic<T: Instance>(&self) -> Result<Envelope, BusError> {
|
||||
match self.read_async::<T, _>().await {
|
||||
Ok((frame, ts)) => Ok(Envelope { ts, frame }),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> {
|
||||
self.read_async::<T, _>().await
|
||||
async fn read_fd<T: Instance>(&self) -> Result<FdEnvelope, BusError> {
|
||||
match self.read_async::<T, _>().await {
|
||||
Ok((frame, ts)) => Ok(FdEnvelope { ts, frame }),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -761,7 +797,7 @@ impl TxMode {
|
||||
/// frame is dropped from the mailbox, it is returned. If no lower-priority frames
|
||||
/// can be replaced, this call asynchronously waits for a frame to be successfully
|
||||
/// transmitted, then tries again.
|
||||
async fn write<T: Instance>(&self, frame: &ClassicFrame) -> Option<ClassicFrame> {
|
||||
async fn write<T: Instance>(&self, frame: &Frame) -> Option<Frame> {
|
||||
self.write_generic::<T, _>(frame).await
|
||||
}
|
||||
|
||||
|
@ -136,19 +136,20 @@ impl ClassicData {
|
||||
}
|
||||
}
|
||||
|
||||
/// Frame with up to 8 bytes of data payload as per Classic CAN
|
||||
/// Frame with up to 8 bytes of data payload as per Classic(non-FD) CAN
|
||||
/// For CAN-FD support use FdFrame
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct ClassicFrame {
|
||||
pub struct Frame {
|
||||
can_header: Header,
|
||||
data: ClassicData,
|
||||
}
|
||||
|
||||
impl ClassicFrame {
|
||||
impl Frame {
|
||||
/// Create a new CAN classic Frame
|
||||
pub fn new(can_header: Header, raw_data: &[u8]) -> Result<Self, FrameCreateError> {
|
||||
let data = ClassicData::new(raw_data)?;
|
||||
Ok(ClassicFrame { can_header, data: data })
|
||||
Ok(Frame { can_header, data: data })
|
||||
}
|
||||
|
||||
/// Creates a new data frame.
|
||||
@ -206,9 +207,9 @@ impl ClassicFrame {
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_can::Frame for ClassicFrame {
|
||||
impl embedded_can::Frame for Frame {
|
||||
fn new(id: impl Into<embedded_can::Id>, raw_data: &[u8]) -> Option<Self> {
|
||||
let frameopt = ClassicFrame::new(Header::new(id.into(), raw_data.len() as u8, false), raw_data);
|
||||
let frameopt = Frame::new(Header::new(id.into(), raw_data.len() as u8, false), raw_data);
|
||||
match frameopt {
|
||||
Ok(frame) => Some(frame),
|
||||
Err(_) => None,
|
||||
@ -216,7 +217,7 @@ impl embedded_can::Frame for ClassicFrame {
|
||||
}
|
||||
fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> {
|
||||
if len <= 8 {
|
||||
let frameopt = ClassicFrame::new(Header::new(id.into(), len as u8, true), &[0; 8]);
|
||||
let frameopt = Frame::new(Header::new(id.into(), len as u8, true), &[0; 8]);
|
||||
match frameopt {
|
||||
Ok(frame) => Some(frame),
|
||||
Err(_) => None,
|
||||
@ -245,7 +246,7 @@ impl embedded_can::Frame for ClassicFrame {
|
||||
}
|
||||
}
|
||||
|
||||
impl CanHeader for ClassicFrame {
|
||||
impl CanHeader for Frame {
|
||||
fn from_header(header: Header, data: &[u8]) -> Result<Self, FrameCreateError> {
|
||||
Self::new(header, data)
|
||||
}
|
||||
@ -255,10 +256,32 @@ impl CanHeader for ClassicFrame {
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains CAN frame and additional metadata.
|
||||
///
|
||||
/// Timestamp is available if `time` feature is enabled.
|
||||
/// For CAN-FD support use FdEnvelope
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct Envelope {
|
||||
/// Reception time.
|
||||
#[cfg(feature = "time")]
|
||||
pub ts: embassy_time::Instant,
|
||||
/// The actual CAN frame.
|
||||
pub frame: Frame,
|
||||
}
|
||||
|
||||
impl Envelope {
|
||||
/// Convert into a tuple
|
||||
pub fn parts(self) -> (Frame, embassy_time::Instant) {
|
||||
(self.frame, self.ts)
|
||||
}
|
||||
}
|
||||
|
||||
/// Payload of a (FD)CAN data frame.
|
||||
///
|
||||
/// Contains 0 to 64 Bytes of data.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct FdData {
|
||||
pub(crate) bytes: [u8; 64],
|
||||
}
|
||||
@ -308,6 +331,7 @@ impl FdData {
|
||||
|
||||
/// Frame with up to 8 bytes of data payload as per Fd CAN
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct FdFrame {
|
||||
can_header: Header,
|
||||
data: FdData,
|
||||
@ -410,3 +434,23 @@ impl CanHeader for FdFrame {
|
||||
self.header()
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains CAN FD frame and additional metadata.
|
||||
///
|
||||
/// Timestamp is available if `time` feature is enabled.
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct FdEnvelope {
|
||||
/// Reception time.
|
||||
#[cfg(feature = "time")]
|
||||
pub ts: embassy_time::Instant,
|
||||
/// The actual CAN frame.
|
||||
pub frame: FdFrame,
|
||||
}
|
||||
|
||||
impl FdEnvelope {
|
||||
/// Convert into a tuple
|
||||
pub fn parts(self) -> (FdFrame, embassy_time::Instant) {
|
||||
(self.frame, self.ts)
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
||||
heapless = { version = "0.8", default-features = false }
|
||||
nb = "1.0.0"
|
||||
static_cell = "2.0.0"
|
||||
|
||||
[profile.dev]
|
||||
opt-level = "s"
|
||||
|
@ -4,11 +4,12 @@
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::can::{
|
||||
filter, Can, Fifo, Frame, Id, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId,
|
||||
filter, Can, Envelope, Fifo, Frame, Id, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId,
|
||||
TxInterruptHandler,
|
||||
};
|
||||
use embassy_stm32::peripherals::CAN;
|
||||
use embassy_stm32::{bind_interrupts, Config};
|
||||
use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
@ -21,6 +22,27 @@ bind_interrupts!(struct Irqs {
|
||||
// This example is configured to work with real CAN transceivers on B8/B9.
|
||||
// See other examples for loopback.
|
||||
|
||||
fn handle_frame(env: Envelope, read_mode: &str) {
|
||||
match env.frame.id() {
|
||||
Id::Extended(id) => {
|
||||
defmt::println!(
|
||||
"{} Extended Frame id={:x} {:02x}",
|
||||
read_mode,
|
||||
id.as_raw(),
|
||||
env.frame.data()
|
||||
);
|
||||
}
|
||||
Id::Standard(id) => {
|
||||
defmt::println!(
|
||||
"{} Standard Frame id={:x} {:02x}",
|
||||
read_mode,
|
||||
id.as_raw(),
|
||||
env.frame.data()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let p = embassy_stm32::init(Config::default());
|
||||
@ -28,6 +50,9 @@ async fn main(_spawner: Spawner) {
|
||||
// Set alternate pin mapping to B8/B9
|
||||
embassy_stm32::pac::AFIO.mapr().modify(|w| w.set_can1_remap(2));
|
||||
|
||||
static RX_BUF: StaticCell<embassy_stm32::can::RxBuf<10>> = StaticCell::new();
|
||||
static TX_BUF: StaticCell<embassy_stm32::can::TxBuf<10>> = StaticCell::new();
|
||||
|
||||
let mut can = Can::new(p.CAN, p.PB8, p.PB9, Irqs);
|
||||
|
||||
can.as_mut()
|
||||
@ -43,21 +68,72 @@ async fn main(_spawner: Spawner) {
|
||||
can.set_bitrate(250_000);
|
||||
|
||||
can.enable().await;
|
||||
|
||||
let mut i: u8 = 0;
|
||||
|
||||
/*
|
||||
// Example for using buffered Tx and Rx without needing to
|
||||
// split first as is done below.
|
||||
let mut can = can.buffered(
|
||||
TX_BUF.init(embassy_stm32::can::TxBuf::<10>::new()),
|
||||
RX_BUF.init(embassy_stm32::can::RxBuf::<10>::new()));
|
||||
loop {
|
||||
let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap();
|
||||
can.write(&tx_frame).await;
|
||||
|
||||
match can.read().await {
|
||||
Ok(env) => match env.frame.id() {
|
||||
Id::Extended(id) => {
|
||||
defmt::println!("Extended Frame id={:x} {:02x}", id.as_raw(), env.frame.data());
|
||||
Ok((frame, ts)) => {
|
||||
handle_frame(Envelope { ts, frame }, "Buf");
|
||||
}
|
||||
Id::Standard(id) => {
|
||||
defmt::println!("Standard Frame id={:x} {:02x}", id.as_raw(), env.frame.data());
|
||||
Err(err) => {
|
||||
defmt::println!("Error {}", err);
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
*/
|
||||
let (mut tx, mut rx) = can.split();
|
||||
|
||||
// This example shows using the wait_not_empty API before try read
|
||||
while i < 3 {
|
||||
let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap();
|
||||
tx.write(&tx_frame).await;
|
||||
|
||||
rx.wait_not_empty().await;
|
||||
let env = rx.try_read().unwrap();
|
||||
handle_frame(env, "Wait");
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// This example shows using the full async non-buffered API
|
||||
while i < 6 {
|
||||
let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap();
|
||||
tx.write(&tx_frame).await;
|
||||
|
||||
match rx.read().await {
|
||||
Ok(env) => {
|
||||
handle_frame(env, "NoBuf");
|
||||
}
|
||||
Err(err) => {
|
||||
defmt::println!("Error {}", err);
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// This example shows using buffered RX and TX. User passes in desired buffer (size)
|
||||
// It's possible this way to have just RX or TX buffered.
|
||||
let mut rx = rx.buffered(RX_BUF.init(embassy_stm32::can::RxBuf::<10>::new()));
|
||||
let mut tx = tx.buffered(TX_BUF.init(embassy_stm32::can::TxBuf::<10>::new()));
|
||||
|
||||
loop {
|
||||
let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap();
|
||||
tx.write(&tx_frame).await;
|
||||
|
||||
match rx.read().await {
|
||||
Ok(envelope) => {
|
||||
handle_frame(envelope, "Buf");
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
defmt::println!("Error {}", err);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ async fn main(_spawner: Spawner) {
|
||||
}
|
||||
let peripherals = embassy_stm32::init(config);
|
||||
|
||||
let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
|
||||
let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
|
||||
|
||||
can.set_extended_filter(
|
||||
can::filter::ExtendedFilterSlot::_0,
|
||||
@ -56,21 +56,22 @@ async fn main(_spawner: Spawner) {
|
||||
info!("Configured");
|
||||
|
||||
let mut can = can.start(match use_fd {
|
||||
true => can::FdcanOperatingMode::InternalLoopbackMode,
|
||||
false => can::FdcanOperatingMode::NormalOperationMode,
|
||||
true => can::OperatingMode::InternalLoopbackMode,
|
||||
false => can::OperatingMode::NormalOperationMode,
|
||||
});
|
||||
|
||||
let mut i = 0;
|
||||
let mut last_read_ts = embassy_time::Instant::now();
|
||||
|
||||
loop {
|
||||
let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
info!("Writing frame");
|
||||
|
||||
_ = can.write(&frame).await;
|
||||
|
||||
match can.read().await {
|
||||
Ok((rx_frame, ts)) => {
|
||||
Ok(envelope) => {
|
||||
let (ts, rx_frame) = (envelope.ts, envelope.frame);
|
||||
let delta = (ts - last_read_ts).as_millis();
|
||||
last_read_ts = ts;
|
||||
info!(
|
||||
@ -105,7 +106,8 @@ async fn main(_spawner: Spawner) {
|
||||
}
|
||||
|
||||
match can.read_fd().await {
|
||||
Ok((rx_frame, ts)) => {
|
||||
Ok(envelope) => {
|
||||
let (ts, rx_frame) = (envelope.ts, envelope.frame);
|
||||
let delta = (ts - last_read_ts).as_millis();
|
||||
last_read_ts = ts;
|
||||
info!(
|
||||
@ -129,12 +131,13 @@ async fn main(_spawner: Spawner) {
|
||||
let (mut tx, mut rx) = can.split();
|
||||
// With split
|
||||
loop {
|
||||
let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
info!("Writing frame");
|
||||
_ = tx.write(&frame).await;
|
||||
|
||||
match rx.read().await {
|
||||
Ok((rx_frame, ts)) => {
|
||||
Ok(envelope) => {
|
||||
let (ts, rx_frame) = (envelope.ts, envelope.frame);
|
||||
let delta = (ts - last_read_ts).as_millis();
|
||||
last_read_ts = ts;
|
||||
info!(
|
||||
@ -156,7 +159,7 @@ async fn main(_spawner: Spawner) {
|
||||
}
|
||||
}
|
||||
|
||||
let can = can::Fdcan::join(tx, rx);
|
||||
let can = can::Can::join(tx, rx);
|
||||
|
||||
info!("\n\n\nBuffered\n");
|
||||
if use_fd {
|
||||
@ -173,7 +176,8 @@ async fn main(_spawner: Spawner) {
|
||||
_ = can.write(frame).await;
|
||||
|
||||
match can.read().await {
|
||||
Ok((rx_frame, ts)) => {
|
||||
Ok(envelope) => {
|
||||
let (ts, rx_frame) = (envelope.ts, envelope.frame);
|
||||
let delta = (ts - last_read_ts).as_millis();
|
||||
last_read_ts = ts;
|
||||
info!(
|
||||
@ -198,7 +202,7 @@ async fn main(_spawner: Spawner) {
|
||||
RX_BUF.init(can::RxBuf::<10>::new()),
|
||||
);
|
||||
loop {
|
||||
let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
info!("Writing frame");
|
||||
|
||||
// You can use any of these approaches to send. The writer makes it
|
||||
@ -208,7 +212,8 @@ async fn main(_spawner: Spawner) {
|
||||
can.writer().write(frame).await;
|
||||
|
||||
match can.read().await {
|
||||
Ok((rx_frame, ts)) => {
|
||||
Ok(envelope) => {
|
||||
let (ts, rx_frame) = (envelope.ts, envelope.frame);
|
||||
let delta = (ts - last_read_ts).as_millis();
|
||||
last_read_ts = ts;
|
||||
info!(
|
||||
|
@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) {
|
||||
|
||||
let peripherals = embassy_stm32::init(config);
|
||||
|
||||
let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
|
||||
let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
|
||||
|
||||
// 250k bps
|
||||
can.set_bitrate(250_000);
|
||||
@ -38,12 +38,13 @@ async fn main(_spawner: Spawner) {
|
||||
let mut last_read_ts = embassy_time::Instant::now();
|
||||
|
||||
loop {
|
||||
let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
info!("Writing frame");
|
||||
_ = can.write(&frame).await;
|
||||
|
||||
match can.read().await {
|
||||
Ok((rx_frame, ts)) => {
|
||||
Ok(envelope) => {
|
||||
let (rx_frame, ts) = envelope.parts();
|
||||
let delta = (ts - last_read_ts).as_millis();
|
||||
last_read_ts = ts;
|
||||
info!(
|
||||
@ -69,12 +70,13 @@ async fn main(_spawner: Spawner) {
|
||||
let (mut tx, mut rx) = can.split();
|
||||
// With split
|
||||
loop {
|
||||
let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
info!("Writing frame");
|
||||
_ = tx.write(&frame).await;
|
||||
|
||||
match rx.read().await {
|
||||
Ok((rx_frame, ts)) => {
|
||||
Ok(envelope) => {
|
||||
let (rx_frame, ts) = envelope.parts();
|
||||
let delta = (ts - last_read_ts).as_millis();
|
||||
last_read_ts = ts;
|
||||
info!(
|
||||
|
@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) {
|
||||
|
||||
let peripherals = embassy_stm32::init(config);
|
||||
|
||||
let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
|
||||
let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
|
||||
|
||||
// 250k bps
|
||||
can.set_bitrate(250_000);
|
||||
@ -38,12 +38,13 @@ async fn main(_spawner: Spawner) {
|
||||
let mut last_read_ts = embassy_time::Instant::now();
|
||||
|
||||
loop {
|
||||
let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
info!("Writing frame");
|
||||
_ = can.write(&frame).await;
|
||||
|
||||
match can.read().await {
|
||||
Ok((rx_frame, ts)) => {
|
||||
Ok(envelope) => {
|
||||
let (rx_frame, ts) = envelope.parts();
|
||||
let delta = (ts - last_read_ts).as_millis();
|
||||
last_read_ts = ts;
|
||||
info!(
|
||||
@ -69,12 +70,13 @@ async fn main(_spawner: Spawner) {
|
||||
let (mut tx, mut rx) = can.split();
|
||||
// With split
|
||||
loop {
|
||||
let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
info!("Writing frame");
|
||||
_ = tx.write(&frame).await;
|
||||
|
||||
match rx.read().await {
|
||||
Ok((rx_frame, ts)) => {
|
||||
Ok(envelope) => {
|
||||
let (rx_frame, ts) = envelope.parts();
|
||||
let delta = (ts - last_read_ts).as_millis();
|
||||
last_read_ts = ts;
|
||||
info!(
|
||||
|
@ -79,8 +79,8 @@ async fn main(_spawner: Spawner) {
|
||||
let options = options();
|
||||
let peripherals = embassy_stm32::init(options.config);
|
||||
|
||||
let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs1);
|
||||
let mut can2 = can::FdcanConfigurator::new(peripherals.FDCAN2, peripherals.PB12, peripherals.PB13, Irqs2);
|
||||
let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs1);
|
||||
let mut can2 = can::CanConfigurator::new(peripherals.FDCAN2, peripherals.PB12, peripherals.PB13, Irqs2);
|
||||
|
||||
// 250k bps
|
||||
can.set_bitrate(250_000);
|
||||
@ -102,13 +102,13 @@ async fn main(_spawner: Spawner) {
|
||||
|
||||
let mut i: u8 = 0;
|
||||
loop {
|
||||
let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap();
|
||||
let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap();
|
||||
|
||||
info!("Transmitting frame...");
|
||||
let tx_ts = Instant::now();
|
||||
can.write(&tx_frame).await;
|
||||
|
||||
let (frame, timestamp) = can.read().await.unwrap();
|
||||
let (frame, timestamp) = can.read().await.unwrap().parts();
|
||||
info!("Frame received!");
|
||||
|
||||
// Check data.
|
||||
@ -139,13 +139,13 @@ async fn main(_spawner: Spawner) {
|
||||
|
||||
let mut i: u8 = 0;
|
||||
loop {
|
||||
let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap();
|
||||
let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap();
|
||||
|
||||
info!("Transmitting frame...");
|
||||
let tx_ts = Instant::now();
|
||||
can2.write(&tx_frame).await;
|
||||
|
||||
let (frame, timestamp) = can2.read().await.unwrap();
|
||||
let (frame, timestamp) = can2.read().await.unwrap().parts();
|
||||
info!("Frame received!");
|
||||
|
||||
//print_regs().await;
|
||||
@ -182,20 +182,20 @@ async fn main(_spawner: Spawner) {
|
||||
// in each FIFO so make sure we write enough to fill them both up before reading.
|
||||
for i in 0..3 {
|
||||
// Try filling up the RX FIFO0 buffers with standard packets
|
||||
let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap();
|
||||
let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap();
|
||||
info!("Transmitting frame {}", i);
|
||||
can.write(&tx_frame).await;
|
||||
}
|
||||
for i in 3..max_buffered {
|
||||
// Try filling up the RX FIFO0 buffers with extended packets
|
||||
let tx_frame = can::frame::ClassicFrame::new_extended(0x1232344, &[i; 1]).unwrap();
|
||||
let tx_frame = can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap();
|
||||
info!("Transmitting frame {}", i);
|
||||
can.write(&tx_frame).await;
|
||||
}
|
||||
|
||||
// Try and receive all 6 packets
|
||||
for i in 0..max_buffered {
|
||||
let (frame, _ts) = can.read().await.unwrap();
|
||||
let (frame, _ts) = can.read().await.unwrap().parts();
|
||||
match frame.id() {
|
||||
embedded_can::Id::Extended(id) => {
|
||||
info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
|
||||
@ -210,20 +210,20 @@ async fn main(_spawner: Spawner) {
|
||||
let (mut tx, mut rx) = can.split();
|
||||
for i in 0..3 {
|
||||
// Try filling up the RX FIFO0 buffers with standard packets
|
||||
let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap();
|
||||
let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap();
|
||||
info!("Transmitting frame {}", i);
|
||||
tx.write(&tx_frame).await;
|
||||
}
|
||||
for i in 3..max_buffered {
|
||||
// Try filling up the RX FIFO0 buffers with extended packets
|
||||
let tx_frame = can::frame::ClassicFrame::new_extended(0x1232344, &[i; 1]).unwrap();
|
||||
let tx_frame = can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap();
|
||||
info!("Transmitting frame {}", i);
|
||||
tx.write(&tx_frame).await;
|
||||
}
|
||||
|
||||
// Try and receive all 6 packets
|
||||
for i in 0..max_buffered {
|
||||
let (frame, _ts) = rx.read().await.unwrap();
|
||||
let (frame, _ts) = rx.read().await.unwrap().parts();
|
||||
match frame.id() {
|
||||
embedded_can::Id::Extended(id) => {
|
||||
info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
|
||||
|
Loading…
Reference in New Issue
Block a user