diff --git a/Cargo.toml b/Cargo.toml index d75663fc..038f31db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,10 @@ static_assertions = "1.1" version = "0.7.7" features = ["critical-section-single-core"] +[dependencies.fdcan] +version = "0.1.2" +features = ["fdcan_g0_g4_l5"] + [dependencies.cast] version = "0.2.7" default-features = false diff --git a/examples/can-echo.rs b/examples/can-echo.rs index 2c4fed4d..d458a3ed 100644 --- a/examples/can-echo.rs +++ b/examples/can-echo.rs @@ -2,19 +2,19 @@ #![no_std] use crate::hal::{ - fdcan::{ - config::NominalBitTiming, - filter::{StandardFilter, StandardFilterSlot}, - frame::{FrameFormat, TxFrameHeader}, - id::StandardId, - FdCan, - }, + can::CanExt, gpio::{GpioExt as _, Speed}, nb::block, rcc::{Config, RccExt, SysClockSrc}, stm32::Peripherals, time::U32Ext, }; +use fdcan::{ + config::NominalBitTiming, + filter::{StandardFilter, StandardFilterSlot}, + frame::{FrameFormat, TxFrameHeader}, + id::StandardId, +}; use stm32g4xx_hal as hal; use core::num::{NonZeroU16, NonZeroU8}; @@ -59,10 +59,7 @@ fn main() -> ! { let tx = gpiob.pb9.into_alternate().set_speed(Speed::VeryHigh); info!("-- Create CAN 1 instance"); - let can = FdCan::new(dp.FDCAN1, tx, rx, &rcc); - - info!("-- Set CAN 1 in Config Mode"); - let mut can = can.into_config_mode(); + let mut can = dp.FDCAN1.fdcan(tx, rx, &rcc); can.set_protocol_exception_handling(false); info!("-- Configure nominal timing"); @@ -87,10 +84,8 @@ fn main() -> ! { // let tx = gpiob.pb13.into_alternate().set_speed(Speed::VeryHigh); // info!("-- Create CAN 2 instance"); - // let can = FdCan::new(dp.FDCAN2, tx, rx, &rcc); - - // info!("-- Set CAN in Config Mode"); - // let mut can = can.into_config_mode(); + // let mut can = dp.FDCAN2.fdcan(tx, rx, &rcc); + // can.set_protocol_exception_handling(false); // info!("-- Configure nominal timing"); // can.set_nominal_bit_timing(btr); @@ -109,7 +104,7 @@ fn main() -> ! { let mut can = can1; info!("Create Message Data"); - let mut buffer = [0xAAAAAAAA, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x0]; + let mut buffer: [u8; 8] = [0xAA, 0xAA, 0xAA, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF]; info!("Create Message Header"); let header = TxFrameHeader { len: 2 * 4, @@ -121,30 +116,11 @@ fn main() -> ! { info!("Initial Header: {:#X?}", &header); info!("Transmit initial message"); - block!(can.transmit(header, &mut |b| { - let len = b.len(); - b[..len].clone_from_slice(&buffer[..len]); - },)) - .unwrap(); + block!(can.transmit(header, &buffer)).unwrap(); loop { - if let Ok(rxheader) = block!(can.receive0(&mut |h, b| { - info!("Received Header: {:#X?}", &h); - info!("received data: {:X?}", &b); - - for (i, d) in b.iter().enumerate() { - buffer[i] = *d; - } - h - })) { - block!( - can.transmit(rxheader.unwrap().to_tx_header(None), &mut |b| { - let len = b.len(); - b[..len].clone_from_slice(&buffer[..len]); - info!("Transmit: {:X?}", b); - }) - ) - .unwrap(); + if let Ok(rxheader) = block!(can.receive0(&mut buffer)) { + block!(can.transmit(rxheader.unwrap().to_tx_header(None), &mut buffer)).unwrap(); } } } diff --git a/src/can.rs b/src/can.rs index 112ddaff..6ecebd17 100644 --- a/src/can.rs +++ b/src/can.rs @@ -1,21 +1,76 @@ //! # Controller Area Network (CAN) Interface //! -use crate::fdcan; -use crate::fdcan::message_ram; -// use crate::stm32::{self, FDCAN1, FDCAN2, FDCAN3}; -use crate::rcc::Rcc; -use crate::stm32; +use crate::rcc::{self, Rcc}; +use fdcan; mod sealed { - // Prevent creation outside of this module - pub trait Sealed {} /// A TX pin configured for CAN communication pub trait Tx {} /// An RX pin configured for CAN communication pub trait Rx {} } +/// Select an FDCAN Clock Source +#[allow(dead_code)] +enum FdCanClockSource { + /// Select HSE as the FDCAN clock source + HSE = 0b00, + /// Select PLL "Q" clock as the FDCAN clock source + PLLQ = 0b01, + /// Select "P" clock as the FDCAN clock source + PCLK = 0b10, + //Reserved = 0b10, +} + +/// Storage type for the CAN controller +#[derive(Debug)] +pub struct Can { + rb: FDCAN, +} +#[allow(dead_code)] +impl Can { + /// Returns a reference to the inner peripheral + fn inner(&self) -> &FDCAN { + &self.rb + } +} + +/// Extension trait for CAN controller +pub trait CanExt: Sized +where + Self: rcc::Instance, + Can: fdcan::Instance, +{ + fn fdcan( + self, + _tx: TX, + _rx: RX, + rcc: &Rcc, + ) -> fdcan::FdCan, fdcan::ConfigMode> + where + TX: sealed::Tx, + RX: sealed::Rx, + { + Self::enable(&rcc.rb); + + if rcc.rb.ccipr.read().fdcansel().is_hse() { + // Select P clock as FDCAN clock source + rcc.rb.ccipr.modify(|_, w| { + // This is sound, as `FdCanClockSource` only contains valid values for this field. + unsafe { + w.fdcansel().bits(FdCanClockSource::PCLK as u8); + } + + w + }); + } + + self.fdcan_unchecked() + } + + fn fdcan_unchecked(self) -> fdcan::FdCan, fdcan::ConfigMode>; +} /// Implements sealed::{Tx,Rx} for pins associated with a CAN peripheral macro_rules! pins { ($PER:ident => @@ -23,28 +78,26 @@ macro_rules! pins { rx: [ $($( #[ $pmetarx:meta ] )* $rx:ident<$rxaf:ident>),+ $(,)? ])) => { $( $( #[ $pmetatx ] )* - impl crate::can::sealed::Tx<$PER> for $tx> {} + impl sealed::Tx<$PER> for $tx> {} )+ $( $( #[ $pmetarx ] )* - impl crate::can::sealed::Rx<$PER> for $rx> {} + impl sealed::Rx<$PER> for $rx> {} )+ }; } mod fdcan1 { - use super::FdCan; - use crate::fdcan; - use crate::fdcan::message_ram; + use super::sealed; + use super::{Can, CanExt}; use crate::gpio::{ gpioa::{PA11, PA12}, gpiob::{PB8, PB9}, gpiod::{PD0, PD1}, AF9, }; - use crate::rcc::Rcc; - use crate::stm32; use crate::stm32::FDCAN1; + use fdcan; // All STM32G4 models with CAN support these pins pins! { @@ -62,34 +115,22 @@ mod fdcan1 { ) } - unsafe impl fdcan::Instance for FdCan { - const REGISTERS: *mut stm32::fdcan::RegisterBlock = FDCAN1::ptr() as *mut _; - } - - unsafe impl message_ram::MsgRamExt for FdCan { - const MSG_RAM: *mut message_ram::RegisterBlock = (0x4000_a400 as *mut _); + impl Can { + pub fn fdcan1(rb: FDCAN1) -> fdcan::FdCan { + fdcan::FdCan::new(Self { rb }).into_config_mode() + } } - - /// Implements sealed::Sealed and Enable for a CAN peripheral (e.g. CAN1) - impl crate::can::sealed::Sealed for crate::stm32::FDCAN1 {} - impl crate::can::Enable for crate::stm32::FDCAN1 { - #[inline(always)] - fn enable(rcc: &Rcc) { - // TODO: make this configurable - // Select P clock as FDCAN clock source - rcc.rb.ccipr.modify(|_, w| { - // This is sound, as `0b10` is a valid value for this field. - unsafe { - w.fdcansel().bits(0b10); - } - - w - }); - - // Enable peripheral - rcc.rb.apb1enr1.modify(|_, w| w.fdcanen().set_bit()); + impl CanExt for FDCAN1 { + fn fdcan_unchecked(self) -> fdcan::FdCan, fdcan::ConfigMode> { + Can::fdcan1(self) } } + unsafe impl fdcan::Instance for Can { + const REGISTERS: *mut fdcan::RegisterBlock = FDCAN1::ptr() as *mut _; + } + unsafe impl fdcan::message_ram::Instance for Can { + const MSG_RAM: *mut fdcan::message_ram::RegisterBlock = (0x4000_ac00 as *mut _); + } } #[cfg(any( @@ -102,15 +143,15 @@ mod fdcan1 { feature = "stm32g4A1", ))] mod fdcan2 { - use super::FdCan; - use crate::fdcan; - use crate::fdcan::message_ram; + use super::sealed; + use super::{Can, CanExt}; use crate::gpio::{ gpiob::{PB12, PB13, PB5, PB6}, AF9, }; - use crate::rcc::Rcc; - use crate::stm32::{self, FDCAN2}; + use crate::stm32::FDCAN2; + use fdcan; + use fdcan::message_ram; pins! { FDCAN2 => ( @@ -124,34 +165,22 @@ mod fdcan2 { ]) } - unsafe impl fdcan::Instance for FdCan { - const REGISTERS: *mut stm32::fdcan::RegisterBlock = FDCAN2::ptr() as *mut _; - } - - unsafe impl message_ram::MsgRamExt for FdCan { - // const MSG_RAM: *mut message_ram::RegisterBlock = (0x4000_a754 as *mut _); - const MSG_RAM: *mut message_ram::RegisterBlock = (0x4000_a750 as *mut _); + impl Can { + pub fn fdcan2(rb: FDCAN2) -> fdcan::FdCan { + fdcan::FdCan::new(Self { rb }).into_config_mode() + } } - - impl crate::can::sealed::Sealed for crate::stm32::FDCAN2 {} - impl crate::can::Enable for crate::stm32::FDCAN2 { - #[inline(always)] - fn enable(rcc: &Rcc) { - // Enable peripheral - rcc.rb.apb1enr1.modify(|_, w| w.fdcanen().set_bit()); - - // TODO: make this configurable - // Select P clock as FDCAN clock source - rcc.rb.ccipr.modify(|_, w| { - // This is sound, as `0b10` is a valid value for this field. - unsafe { - w.fdcansel().bits(0b10); - } - - w - }); + impl CanExt for FDCAN2 { + fn fdcan_unchecked(self) -> fdcan::FdCan, fdcan::ConfigMode> { + Can::fdcan2(self) } } + unsafe impl fdcan::Instance for Can { + const REGISTERS: *mut fdcan::RegisterBlock = FDCAN2::ptr() as *mut _; + } + unsafe impl fdcan::message_ram::Instance for Can { + const MSG_RAM: *mut message_ram::RegisterBlock = (0x4000_a750 as *mut _); + } } #[cfg(any( @@ -161,16 +190,16 @@ mod fdcan2 { feature = "stm32g484", ))] mod fdcan3 { - use super::FdCan; - use crate::fdcan; - use crate::fdcan::message_ram; + use super::sealed; + use super::{Can, CanExt}; use crate::gpio::{ gpioa::{PA15, PA8}, gpiob::{PB3, PB4}, AF11, }; - use crate::rcc::Rcc; - use crate::stm32::{self, FDCAN3}; + use crate::stm32::FDCAN3; + use fdcan; + use fdcan::message_ram; pins! { FDCAN3 => ( @@ -184,43 +213,20 @@ mod fdcan3 { ]) } - unsafe impl fdcan::Instance for FdCan { - const REGISTERS: *mut stm32::fdcan::RegisterBlock = FDCAN3::ptr() as *mut _; + impl Can { + pub fn fdcan3(rb: FDCAN3) -> fdcan::FdCan { + fdcan::FdCan::new(Self { rb }).into_config_mode() + } } - - unsafe impl message_ram::MsgRamExt for FdCan { - const MSG_RAM: *mut message_ram::RegisterBlock = (0x4000_aaa0 as *mut _); + impl CanExt for FDCAN3 { + fn fdcan_unchecked(self) -> fdcan::FdCan, fdcan::ConfigMode> { + Can::fdcan3(self) + } } -} - -/// Enable/disable peripheral -pub trait Enable: sealed::Sealed { - /// Enables this peripheral by setting the associated enable bit in an RCC enable register - fn enable(rcc: &Rcc); -} - -/// Interface to the CAN peripheral. -pub struct FdCan { - _peripheral: Instance, -} - -impl FdCan -where - Instance: Enable, -{ - /// Creates a CAN interface. - pub fn new(can: Instance, tx: TX, rx: RX, rcc: &Rcc) -> FdCan - where - TX: sealed::Tx, - RX: sealed::Rx, - { - Instance::enable(rcc); - //TODO: Set Speed to VeryHigh? - FdCan { _peripheral: can } + unsafe impl fdcan::Instance for Can { + const REGISTERS: *mut fdcan::RegisterBlock = FDCAN3::ptr() as *mut _; } - - pub fn new_unchecked(can: Instance, rcc: &Rcc) -> FdCan { - Instance::enable(rcc); - FdCan { _peripheral: can } + unsafe impl fdcan::message_ram::Instance for Can { + const MSG_RAM: *mut message_ram::RegisterBlock = (0x4000_aaa0 as *mut _); } } diff --git a/src/fdcan/config.rs b/src/fdcan/config.rs deleted file mode 100644 index 6831e401..00000000 --- a/src/fdcan/config.rs +++ /dev/null @@ -1,454 +0,0 @@ -pub use super::interrupt::{Interrupt, InterruptLine, Interrupts}; -use core::num::{NonZeroU16, NonZeroU8}; - -/// Configures the bit timings. -/// -/// You can use to calculate the `btr` parameter. Enter -/// parameters as follows: -/// -/// - *Clock Rate*: The input clock speed to the CAN peripheral (*not* the CPU clock speed). -/// This is the clock rate of the peripheral bus the CAN peripheral is attached to (eg. APB1). -/// - *Sample Point*: Should normally be left at the default value of 87.5%. -/// - *SJW*: Should normally be left at the default value of 1. -/// -/// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr` -/// parameter to this method. -#[derive(Clone, Copy, Debug)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub struct NominalBitTiming { - /// Value by which the oscillator frequency is divided for generating the bit time quanta. The bit - /// time is built up from a multiple of this quanta. Valid values are 1 to 512. - pub prescaler: NonZeroU16, - /// Valid values are 1 to 128. - pub seg1: NonZeroU8, - /// Valid values are 1 to 255. - pub seg2: NonZeroU8, - /// Valid values are 1 to 128. - pub sync_jump_width: NonZeroU8, -} -impl NominalBitTiming { - #[inline] - pub(crate) fn nbrp(&self) -> u16 { - u16::from(self.prescaler) & 0x1FF - } - #[inline] - pub(crate) fn ntseg1(&self) -> u8 { - u8::from(self.seg1) - } - #[inline] - pub(crate) fn ntseg2(&self) -> u8 { - u8::from(self.seg2) & 0x7F - } - #[inline] - pub(crate) fn nsjw(&self) -> u8 { - u8::from(self.sync_jump_width) & 0x7F - } -} - -impl Default for NominalBitTiming { - #[inline] - fn default() -> Self { - Self { - prescaler: NonZeroU16::new(1).unwrap(), - seg1: NonZeroU8::new(0xA).unwrap(), - seg2: NonZeroU8::new(0x3).unwrap(), - sync_jump_width: NonZeroU8::new(0x3).unwrap(), - } - } -} - -/// Configures the data bit timings for the FdCan Variable Bitrates. -/// This is not used when frame_transmit is set to anything other than AllowFdCanAndBRS. -#[derive(Clone, Copy, Debug)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub struct DataBitTiming { - /// Tranceiver Delay Compensation - pub transceiver_delay_compensation: bool, - /// The value by which the oscillator frequency is divided to generate the bit time quanta. The bit - /// time is built up from a multiple of this quanta. Valid values for the Baud Rate Prescaler are 1 - /// to 31. - pub prescaler: NonZeroU8, - /// Valid values are 1 to 31. - pub seg1: NonZeroU8, - /// Valid values are 1 to 15. - pub seg2: NonZeroU8, - /// Must always be smaller than DTSEG2, valid values are 1 to 15. - pub sync_jump_width: NonZeroU8, -} -impl DataBitTiming { - // #[inline] - // fn tdc(&self) -> u8 { - // let tsd = self.transceiver_delay_compensation as u8; - // //TODO: stm32g4 does not export the TDC field - // todo!() - // } - #[inline] - pub(crate) fn dbrp(&self) -> u8 { - u8::from(self.prescaler) & 0x1F - } - #[inline] - pub(crate) fn dtseg1(&self) -> u8 { - u8::from(self.seg1) & 0x1F - } - #[inline] - pub(crate) fn dtseg2(&self) -> u8 { - u8::from(self.seg2) & 0x0F - } - #[inline] - pub(crate) fn dsjw(&self) -> u8 { - u8::from(self.sync_jump_width) & 0x0F - } -} - -impl Default for DataBitTiming { - #[inline] - fn default() -> Self { - Self { - transceiver_delay_compensation: false, - prescaler: NonZeroU8::new(1).unwrap(), - seg1: NonZeroU8::new(0xA).unwrap(), - seg2: NonZeroU8::new(0x3).unwrap(), - sync_jump_width: NonZeroU8::new(0x3).unwrap(), - } - } -} - -/// Configures which modes to use -/// Individual headers can contain a desire to be send via FdCan -/// or use Bit rate switching. But if this general setting does not allow -/// that, only classic CAN is used instead. -#[derive(Clone, Copy, Debug)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum FrameTransmissionConfig { - /// Only allow Classic CAN message Frames - ClassicCanOnly, - /// Allow (non-brs) FdCAN Message Frames - AllowFdCan, - /// Allow FdCAN Message Frames and allow Bit Rate Switching - AllowFdCanAndBRS, -} - -/// -#[derive(Clone, Copy, Debug)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum ClockDivider { - /// Divide by 1 - _1 = 0b0000, - /// Divide by 2 - _2 = 0b0001, - /// Divide by 4 - _4 = 0b0010, - /// Divide by 6 - _6 = 0b0011, - /// Divide by 8 - _8 = 0b0100, - /// Divide by 10 - _10 = 0b0101, - /// Divide by 12 - _12 = 0b0110, - /// Divide by 14 - _14 = 0b0111, - /// Divide by 16 - _16 = 0b1000, - /// Divide by 18 - _18 = 0b1001, - /// Divide by 20 - _20 = 0b1010, - /// Divide by 22 - _22 = 0b1011, - /// Divide by 24 - _24 = 0b1100, - /// Divide by 26 - _26 = 0b1101, - /// Divide by 28 - _28 = 0b1110, - /// Divide by 30 - _30 = 0b1111, -} - -/// Prescaler of the Timestamp counter -#[derive(Clone, Copy, Debug)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum TimestampPrescaler { - /// 1 - _1 = 1, - /// 2 - _2 = 2, - /// 3 - _3 = 3, - /// 4 - _4 = 4, - /// 5 - _5 = 5, - /// 6 - _6 = 6, - /// 7 - _7 = 7, - /// 8 - _8 = 8, - /// 9 - _9 = 9, - /// 10 - _10 = 10, - /// 11 - _11 = 11, - /// 12 - _12 = 12, - /// 13 - _13 = 13, - /// 14 - _14 = 14, - /// 15 - _15 = 15, - /// 16 - _16 = 16, -} - -/// Selects the source of the Timestamp counter -#[derive(Clone, Copy, Debug)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum TimestampSource { - /// The Timestamp counter is disabled - None, - /// Using the FdCan input clock as the Timstamp counter's source, - /// and using a specific prescaler - Prescaler(TimestampPrescaler), - /// Using TIM3 as a source - FromTIM3, -} - -/// How to handle frames in the global filter -#[derive(Clone, Copy, Debug)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum NonMatchingFilter { - /// Frames will go to Fifo0 when they do no match any specific filter - IntoRxFifo0 = 0b00, - /// Frames will go to Fifo1 when they do no match any specific filter - IntoRxFifo1 = 0b01, - /// Frames will be rejected when they do not match any specific filter - Reject = 0b11, -} - -/// How to handle frames which do not match a specific filter -#[derive(Clone, Copy, Debug)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub struct GlobalFilter { - /// How to handle non-matching standard frames - pub handle_standard_frames: NonMatchingFilter, - - /// How to handle non-matching extended frames - pub handle_extended_frames: NonMatchingFilter, - - /// How to handle remote standard frames - pub reject_remote_standard_frames: bool, - - /// How to handle remote extended frames - pub reject_remote_extended_frames: bool, -} -impl GlobalFilter { - /// Reject all non-matching and remote frames - pub const fn reject_all() -> Self { - Self { - handle_standard_frames: NonMatchingFilter::Reject, - handle_extended_frames: NonMatchingFilter::Reject, - reject_remote_standard_frames: true, - reject_remote_extended_frames: true, - } - } - - /// How to handle non-matching standard frames - pub const fn set_handle_standard_frames(mut self, filter: NonMatchingFilter) -> Self { - self.handle_standard_frames = filter; - self - } - /// How to handle non-matching exteded frames - pub const fn set_handle_extended_frames(mut self, filter: NonMatchingFilter) -> Self { - self.handle_extended_frames = filter; - self - } - /// How to handle remote standard frames - pub const fn set_reject_remote_standard_frames(mut self, filter: bool) -> Self { - self.reject_remote_standard_frames = filter; - self - } - /// How to handle remote extended frames - pub const fn set_reject_remote_extended_frames(mut self, filter: bool) -> Self { - self.reject_remote_extended_frames = filter; - self - } -} -impl Default for GlobalFilter { - #[inline] - fn default() -> Self { - Self { - handle_standard_frames: NonMatchingFilter::IntoRxFifo0, - handle_extended_frames: NonMatchingFilter::IntoRxFifo0, - reject_remote_standard_frames: false, - reject_remote_extended_frames: false, - } - } -} - -/// FdCan Config Struct -#[derive(Clone, Copy, Debug)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub struct FdCanConfig { - /// Nominal Bit Timings - pub nbtr: NominalBitTiming, - /// (Variable) Data Bit Timings - pub dbtr: DataBitTiming, - /// Enables or disables automatic retransmission of messages - /// - /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame - /// util it can be sent. Otherwise, it will try only once to send each frame. - /// - /// Automatic retransmission is enabled by default. - pub automatic_retransmit: bool, - /// Enabled or disables the pausing between transmissions - /// - /// This feature looses up burst transmissions coming from a single node and it protects against - /// "babbling idiot" scenarios where the application program erroneously requests too many - /// transmissions. - pub transmit_pause: bool, - /// Enabled or disables the pausing between transmissions - /// - /// This feature looses up burst transmissions coming from a single node and it protects against - /// "babbling idiot" scenarios where the application program erroneously requests too many - /// transmissions. - pub frame_transmit: FrameTransmissionConfig, - /// Non Isoe Mode - /// If this is set, the FDCAN uses the CAN FD frame format as specified by the Bosch CAN - /// FD Specification V1.0. - pub non_iso_mode: bool, - /// Edge Filtering: Two consecutive dominant tq required to detect an edge for hard synchronization - pub edge_filtering: bool, - /// Enables protocol exception handling - pub protocol_exception_handling: bool, - /// Sets the general clock divider for this FdCAN instance - pub clock_divider: ClockDivider, - /// This sets the interrupts for each interrupt line of the FdCan (FDCAN_INT0/1) - /// Each interrupt set to 0 is set to line_0, each set to 1 is set to line_1. - /// NOTE: This does not enable or disable the interrupt, but merely configure - /// them to which interrupt the WOULD trigger if they are enabled. - pub interrupt_line_config: Interrupts, - /// Sets the timestamp source - pub timestamp_source: TimestampSource, - /// Configures the Global Filter - pub global_filter: GlobalFilter, -} - -impl FdCanConfig { - /// Configures the bit timings. - #[inline] - pub const fn set_nominal_bit_timing(mut self, btr: NominalBitTiming) -> Self { - self.nbtr = btr; - self - } - - /// Configures the bit timings. - #[inline] - pub const fn set_data_bit_timing(mut self, btr: DataBitTiming) -> Self { - self.dbtr = btr; - self - } - - /// Enables or disables automatic retransmission of messages - /// - /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame - /// util it can be sent. Otherwise, it will try only once to send each frame. - /// - /// Automatic retransmission is enabled by default. - #[inline] - pub const fn set_automatic_retransmit(mut self, enabled: bool) -> Self { - self.automatic_retransmit = enabled; - self - } - - /// Enabled or disables the pausing between transmissions - /// - /// This feature looses up burst transmissions coming from a single node and it protects against - /// "babbling idiot" scenarios where the application program erroneously requests too many - /// transmissions. - #[inline] - pub const fn set_transmit_pause(mut self, enabled: bool) -> Self { - self.transmit_pause = enabled; - self - } - - /// If this is set, the FDCAN uses the CAN FD frame format as specified by the Bosch CAN - /// FD Specification V1.0. - #[inline] - pub const fn set_non_iso_mode(mut self, enabled: bool) -> Self { - self.non_iso_mode = enabled; - self - } - - /// Two consecutive dominant tq required to detect an edge for hard synchronization - #[inline] - pub const fn set_edge_filtering(mut self, enabled: bool) -> Self { - self.edge_filtering = enabled; - self - } - - /// Sets the allowed transmission types for messages. - #[inline] - pub const fn set_frame_transmit(mut self, fts: FrameTransmissionConfig) -> Self { - self.frame_transmit = fts; - self - } - - /// Enables protocol exception handling - #[inline] - pub const fn set_protocol_exception_handling(mut self, peh: bool) -> Self { - self.protocol_exception_handling = peh; - self - } - - /// Configures which interrupt go to which interrupt lines - #[inline] - pub const fn set_interrupt_line_config(mut self, l0int: Interrupts) -> Self { - self.interrupt_line_config = l0int; - self - } - - /// Sets the general clock divider for this FdCAN instance - #[inline] - pub const fn set_clock_divider(mut self, div: ClockDivider) -> Self { - self.clock_divider = div; - self - } - - /// Sets the timestamp source - #[inline] - pub const fn set_timestamp_source(mut self, tss: TimestampSource) -> Self { - self.timestamp_source = tss; - self - } - - /// Sets the global filter settings - #[inline] - pub const fn set_global_filter(mut self, filter: GlobalFilter) -> Self { - self.global_filter = filter; - self - } -} - -impl Default for FdCanConfig { - #[inline] - fn default() -> Self { - Self { - nbtr: NominalBitTiming::default(), - dbtr: DataBitTiming::default(), - automatic_retransmit: true, - transmit_pause: false, - frame_transmit: FrameTransmissionConfig::ClassicCanOnly, - non_iso_mode: false, - edge_filtering: false, - interrupt_line_config: Interrupts::none(), - protocol_exception_handling: true, - clock_divider: ClockDivider::_1, - timestamp_source: TimestampSource::None, - global_filter: GlobalFilter::default(), - } - } -} diff --git a/src/fdcan/embedded_can.rs b/src/fdcan/embedded_can.rs deleted file mode 100644 index 667b85e1..00000000 --- a/src/fdcan/embedded_can.rs +++ /dev/null @@ -1,106 +0,0 @@ -//! `embedded_can` trait impls. - -use crate::{Can, Data, ExtendedId, Frame, Id, Instance, StandardId}; -use embedded_can_03 as embedded_can; - -impl embedded_can::Can for Can -where - I: Instance, -{ - type Frame = Frame; - - type Error = (); - - fn try_transmit( - &mut self, - frame: &Self::Frame, - ) -> nb::Result, Self::Error> { - match self.transmit(frame) { - Ok(status) => Ok(status.dequeued_frame().cloned()), - Err(nb::Error::WouldBlock) => Err(nb::Error::WouldBlock), - Err(nb::Error::Other(e)) => match e {}, - } - } - - fn try_receive(&mut self) -> nb::Result { - self.receive() - } -} - -impl embedded_can::Frame for Frame { - fn new(id: impl Into, data: &[u8]) -> Result { - let id = match id.into() { - embedded_can::Id::Standard(id) => unsafe { - Id::Standard(StandardId::new_unchecked(id.as_raw())) - }, - embedded_can::Id::Extended(id) => unsafe { - Id::Extended(ExtendedId::new_unchecked(id.as_raw())) - }, - }; - - let data = Data::new(data).ok_or(())?; - Ok(Frame::new_data(id, data)) - } - - fn new_remote(id: impl Into, dlc: usize) -> Result { - let id = match id.into() { - embedded_can::Id::Standard(id) => unsafe { - Id::Standard(StandardId::new_unchecked(id.as_raw())) - }, - embedded_can::Id::Extended(id) => unsafe { - Id::Extended(ExtendedId::new_unchecked(id.as_raw())) - }, - }; - - if dlc <= 8 { - Ok(Frame::new_remote(id, dlc as u8)) - } else { - Err(()) - } - } - - #[inline] - fn is_extended(&self) -> bool { - self.is_extended() - } - - #[inline] - fn is_standard(&self) -> bool { - self.is_standard() - } - - #[inline] - fn is_remote_frame(&self) -> bool { - self.is_remote_frame() - } - - #[inline] - fn is_data_frame(&self) -> bool { - self.is_data_frame() - } - - #[inline] - fn id(&self) -> embedded_can::Id { - match self.id() { - Id::Standard(id) => unsafe { - embedded_can::Id::Standard(embedded_can::StandardId::new_unchecked(id.as_raw())) - }, - Id::Extended(id) => unsafe { - embedded_can::Id::Extended(embedded_can::ExtendedId::new_unchecked(id.as_raw())) - }, - } - } - - #[inline] - fn dlc(&self) -> usize { - self.dlc() as usize - } - - fn data(&self) -> &[u8] { - if let Some(data) = self.data() { - data - } else { - &[] - } - } -} diff --git a/src/fdcan/frame.rs b/src/fdcan/frame.rs deleted file mode 100644 index 01fe13e7..00000000 --- a/src/fdcan/frame.rs +++ /dev/null @@ -1,203 +0,0 @@ -use core::cmp::Ordering; - -use super::Id; -use super::IdReg; - -use super::filter::FilterId; - -use super::message_ram::enums::FrameFormat as PacFrameFormat; -use super::message_ram::{RxFifoElementHeader, TxBufferElementHeader}; - -use super::message_ram::enums::RemoteTransmissionRequest; -use super::message_ram::enums::{DataLength, FilterFrameMatch}; - -/// Type of Frame -#[derive(Clone, Copy, Debug, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum FrameFormat { - /// Frame used by Classic CAN - Standard = 0, - /// New frame format used by FdCan - Fdcan = 1, -} -impl From for PacFrameFormat { - fn from(ff: FrameFormat) -> Self { - match ff { - FrameFormat::Standard => PacFrameFormat::Standard, - FrameFormat::Fdcan => PacFrameFormat::Fdcan, - } - } -} -impl From for FrameFormat { - fn from(ff: PacFrameFormat) -> Self { - match ff { - PacFrameFormat::Standard => FrameFormat::Standard, - PacFrameFormat::Fdcan => FrameFormat::Fdcan, - } - } -} - -/// Priority of a CAN frame. -/// -/// The priority of a frame is determined by the bits that are part of the *arbitration field*. -/// These consist of the frame identifier bits (including the *IDE* bit, which is 0 for extended -/// frames and 1 for standard frames), as well as the *RTR* bit, which determines whether a frame -/// is a data or remote frame. Lower values of the *arbitration field* have higher priority. -/// -/// This struct wraps the *arbitration field* and implements `PartialOrd` and `Ord` accordingly, -/// ordering higher priorities greater than lower ones. -#[derive(Debug, Copy, Clone)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub struct FramePriority(pub(crate) IdReg); - -/// Ordering is based on the Identifier and frame type (data vs. remote) and can be used to sort -/// frames by priority. -impl Ord for FramePriority { - fn cmp(&self, other: &Self) -> Ordering { - self.0.cmp(&other.0) - } -} - -impl PartialOrd for FramePriority { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl PartialEq for FramePriority { - fn eq(&self, other: &Self) -> bool { - self.cmp(other) == Ordering::Equal - } -} - -impl Eq for FramePriority {} - -/// Header of a transmit request -#[derive(Debug, Copy, Clone)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub struct TxFrameHeader { - /// Length of the data in bytes - pub len: u8, - /// Type of message - pub frame_format: FrameFormat, - /// Id - pub id: Id, - /// Should we use bit rate switching - /// - /// Not that this is a request and if the global frame_transmit is set to ClassicCanOnly - /// this is ignored. - pub bit_rate_switching: bool, - //pub error_state: Option<()>, //TODO - /// - pub marker: Option, -} -impl From for IdReg { - fn from(header: TxFrameHeader) -> IdReg { - let id: IdReg = header.id.into(); - id.with_rtr(header.len == 0) - } -} - -pub(crate) trait MergeTxFrameHeader { - fn merge(&self, header: TxFrameHeader); -} -impl MergeTxFrameHeader for TxBufferElementHeader { - fn merge(&self, header: TxFrameHeader) { - let id: IdReg = header.id.into(); - self.write(|w| { - unsafe { w.id().bits(id.as_raw_id()) } - .rtr() - .bit(header.len == 0) - .xtd() - .set_id_type(header.id.into()) - .set_len(DataLength::new(header.len, header.frame_format.into())) - .set_event(header.marker.into()) - .fdf() - .set_format(header.frame_format.into()) - .brs() - .bit(header.bit_rate_switching) - //esi.set_error_indicator(//TODO//) - }); - } -} - -impl From<&TxBufferElementHeader> for TxFrameHeader { - fn from(reg: &TxBufferElementHeader) -> Self { - let reader = reg.read(); - let id = reader.id().bits(); - let rtr = reader.rtr().rtr(); - let xtd = reader.xtd().id_type(); - let len = reader.to_data_length(); - let ff: PacFrameFormat = len.into(); - TxFrameHeader { - len: len.len(), - frame_format: ff.into(), - id: IdReg::from_register(id, rtr, xtd).into(), - bit_rate_switching: reader.brs().is_with_brs(), - //error_state: Option<()>, //TODO - marker: reader.to_event().into(), - } - } -} - -/// Header of a Received Frame -#[derive(Debug, Copy, Clone)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub struct RxFrameInfo { - /// Length in bytes - pub len: u8, - /// Frame Format - pub frame_format: FrameFormat, - /// Id - pub id: Id, - /// Is this an Remote Transmit Request - pub rtr: bool, - /// Did this message match any filters - pub filter_match: Option, - /// was this received with bit rate switching - pub bit_rate_switching: bool, - //pub error_state: (), //TODO - /// Time stamp counter - pub time_stamp: u16, -} -impl RxFrameInfo { - /// Transforms an RxFrameInfo into an TxFrameHeader - pub fn to_tx_header(self, marker: Option) -> TxFrameHeader { - TxFrameHeader { - len: self.len, - frame_format: self.frame_format, - id: self.id, - bit_rate_switching: self.bit_rate_switching, - marker, - } - } -} -impl From<&RxFifoElementHeader> for RxFrameInfo { - fn from(reg: &RxFifoElementHeader) -> Self { - let reader = reg.read(); - let len = reader.to_data_length(); - let ff: PacFrameFormat = len.into(); - let id = reader.id().bits(); - let rtr = reader.rtr().rtr(); - let xtd = reader.xtd().id_type(); - let id = IdReg::from_register(id, rtr, xtd).to_id(); - let filter = reader.to_filter_match(); - let filter = match filter { - FilterFrameMatch::DidNotMatch => None, - FilterFrameMatch::DidMatch(filter) => Some(match id { - Id::Standard(_) => FilterId::Standard(filter.into()), - Id::Extended(_) => FilterId::Extended(filter.into()), - }), - }; - RxFrameInfo { - len: len.len(), - frame_format: ff.into(), - id, - rtr: rtr == RemoteTransmissionRequest::TransmitRemoteFrame, - filter_match: filter, - bit_rate_switching: reader.brs().is_with_brs(), - time_stamp: reader.txts().bits(), - //error_state //TODO - } - } -} diff --git a/src/fdcan/frame/tests.rs b/src/fdcan/frame/tests.rs deleted file mode 100644 index ebcdd961..00000000 --- a/src/fdcan/frame/tests.rs +++ /dev/null @@ -1,84 +0,0 @@ -use crate::{ExtendedId, Frame, StandardId}; - -#[test] -fn data_greater_remote() { - let id = StandardId::new(0).unwrap(); - - let data_frame = Frame::new_data(id, []); - let remote_frame = Frame::new_remote(id, 0); - assert!(data_frame.is_data_frame()); - assert!(remote_frame.is_remote_frame()); - - assert!(data_frame.priority() > remote_frame.priority()); -} - -#[test] -fn lower_ids_win_arbitration() { - let zero = Frame::new_data(StandardId::new(0).unwrap(), []); - let one = Frame::new_data(StandardId::new(1).unwrap(), []); - assert!(zero.is_standard()); - assert!(!zero.is_extended()); - assert!(one.is_standard()); - assert!(!one.is_extended()); - assert!(zero.priority() > one.priority()); - - // Standard IDs have priority over Extended IDs if the Base ID matches. - let ext_one = Frame::new_data( - ExtendedId::new(0b00000000001_000000000000000000).unwrap(), - [], - ); - assert!(!ext_one.is_standard()); - assert!(ext_one.is_extended()); - assert!(one.priority() > ext_one.priority()); - assert!(zero.priority() > ext_one.priority()); - - // Ext. ID with Base ID 0 has priority over Standard ID 1. - let ext_zero = Frame::new_data( - ExtendedId::new(0b00000000000_100000000000000000).unwrap(), - [], - ); - assert!(!ext_zero.is_standard()); - assert!(ext_zero.is_extended()); - assert!(one.priority() < ext_zero.priority()); - // ...but not over Standard ID 0. - assert!(zero.priority() > ext_zero.priority()); -} - -#[test] -fn highest_standard_higher_prio_than_highest_ext() { - let std = Frame::new_data(StandardId::MAX, []); - let ext = Frame::new_data(ExtendedId::MAX, []); - - assert!(std.is_standard()); - assert!(!std.is_extended()); - assert!(!ext.is_standard()); - assert!(ext.is_extended()); - assert!(std.priority() > ext.priority()); -} - -#[test] -fn data_neq_remote() { - let id = StandardId::new(0).unwrap(); - - let data_frame = Frame::new_data(id, []); - let remote_frame = Frame::new_remote(id, 0); - - assert_ne!(data_frame, remote_frame); -} - -#[test] -fn remote_eq_remote_ignores_data() { - let mut remote1 = Frame::new_remote(StandardId::MAX, 7); - let mut remote2 = Frame::new_remote(StandardId::MAX, 7); - - remote1.data.bytes = [0xAA; 8]; - remote2.data.bytes = [0x55; 8]; - - assert_eq!(remote1, remote2); -} - -#[test] -fn max_len() { - Frame::new_data(StandardId::MAX, [0; 8]); - Frame::new_remote(StandardId::MAX, 8); -} diff --git a/src/fdcan/message_ram.rs b/src/fdcan/message_ram.rs deleted file mode 100644 index 9fbdcc34..00000000 --- a/src/fdcan/message_ram.rs +++ /dev/null @@ -1,153 +0,0 @@ -pub(crate) mod common; -pub(crate) mod enums; -pub(crate) mod generic; - -/// Number of Receive Fifos configured by this module -pub const RX_FIFOS_MAX: u8 = 2; -/// Number of Receive Messages per RxFifo configured by this module -pub const RX_FIFO_MAX: u8 = 3; -/// Number of Transmit Messages configured by this module -pub const TX_FIFO_MAX: u8 = 3; -/// Number of Transmit Events configured by this module -pub const TX_EVENT_MAX: u8 = 3; -/// Number of Standard Filters configured by this module -pub const STANDARD_FILTER_MAX: u8 = 28; -/// Number of Extended Filters configured by this module -pub const EXTENDED_FILTER_MAX: u8 = 8; - -/// MessageRam Overlay -#[repr(C)] -pub struct RegisterBlock { - pub(crate) filters: Filters, - pub(crate) receive: [Receive; RX_FIFOS_MAX as usize], - pub(crate) transmit: Transmit, -} -impl RegisterBlock { - pub fn reset(&mut self) { - self.filters.reset(); - self.receive[0].reset(); - self.receive[1].reset(); - self.transmit.reset(); - } -} - -#[repr(C)] -pub(crate) struct Filters { - pub(crate) flssa: [StandardFilter; STANDARD_FILTER_MAX as usize], - pub(crate) flesa: [ExtendedFilter; EXTENDED_FILTER_MAX as usize], -} -impl Filters { - pub fn reset(&mut self) { - for sf in &mut self.flssa { - sf.reset(); - } - for ef in &mut self.flesa { - ef.reset(); - } - } -} - -#[repr(C)] -pub(crate) struct Receive { - pub(crate) fxsa: [RxFifoElement; RX_FIFO_MAX as usize], -} -impl Receive { - pub fn reset(&mut self) { - for fe in &mut self.fxsa { - fe.reset(); - } - } -} - -#[repr(C)] -pub(crate) struct Transmit { - pub(crate) efsa: [TxEventElement; TX_EVENT_MAX as usize], - pub(crate) tbsa: [TxBufferElement; TX_FIFO_MAX as usize], -} -impl Transmit { - pub fn reset(&mut self) { - for ee in &mut self.efsa { - ee.reset(); - } - for be in &mut self.tbsa { - be.reset(); - } - } -} - -pub(crate) mod standard_filter; -pub(crate) type StandardFilterType = u32; -pub(crate) type StandardFilter = generic::Reg; -pub(crate) struct _StandardFilter; -impl generic::Readable for StandardFilter {} -impl generic::Writable for StandardFilter {} - -pub(crate) mod extended_filter; -pub(crate) type ExtendedFilterType = [u32; 2]; -pub(crate) type ExtendedFilter = generic::Reg; -pub(crate) struct _ExtendedFilter; -impl generic::Readable for ExtendedFilter {} -impl generic::Writable for ExtendedFilter {} - -pub(crate) mod txevent_element; -pub(crate) type TxEventElementType = [u32; 2]; -pub(crate) type TxEventElement = generic::Reg; -pub(crate) struct _TxEventElement; -impl generic::Readable for TxEventElement {} -impl generic::Writable for TxEventElement {} - -pub(crate) mod rxfifo_element; -#[repr(C)] -pub(crate) struct RxFifoElement { - pub(crate) header: RxFifoElementHeader, - pub(crate) data: [u32; 16], // TODO: Does this need to be volatile? -} -impl RxFifoElement { - pub(crate) fn reset(&mut self) { - self.header.reset(); - self.data = [0; 16]; - } -} -pub(crate) type RxFifoElementHeaderType = [u32; 2]; -pub(crate) type RxFifoElementHeader = generic::Reg; -pub(crate) struct _RxFifoElement; -impl generic::Readable for RxFifoElementHeader {} -impl generic::Writable for RxFifoElementHeader {} - -pub(crate) mod txbuffer_element; -#[repr(C)] -pub(crate) struct TxBufferElement { - pub(crate) header: TxBufferElementHeader, - pub(crate) data: [u32; 16], // TODO: Does this need to be volatile? -} -impl TxBufferElement { - pub(crate) fn reset(&mut self) { - self.header.reset(); - self.data = [0; 16]; - } -} -pub(crate) type TxBufferElementHeader = generic::Reg; -pub(crate) type TxBufferElementHeaderType = [u32; 2]; -pub(crate) struct _TxBufferElement; -impl generic::Readable for TxBufferElementHeader {} -impl generic::Writable for TxBufferElementHeader {} - -/// Accessor for the FdCan Message Ram Area -pub unsafe trait MsgRamExt { - const MSG_RAM: *mut RegisterBlock; - fn msg_ram(&self) -> &RegisterBlock { - unsafe { &*Self::MSG_RAM } - } - fn msg_ram_mut(&mut self) -> &mut RegisterBlock { - unsafe { &mut *Self::MSG_RAM } - } -} - -// Ensure the RegisterBlock is the same size as on pg 1957 of RM0440. -static_assertions::assert_eq_size!(Filters, [u32; 28 + 16]); -static_assertions::assert_eq_size!(Receive, [u32; 54]); -static_assertions::assert_eq_size!(Transmit, [u32; 6 + 54]); -static_assertions::assert_eq_size!( - RegisterBlock, - [u32; 28 /*Standard Filters*/ +16 /*Extended Filters*/ +54 /*RxFifo0*/ +54 /*RxFifo1*/ +6 /*TxEvent*/ +54 /*TxFifo */] -); diff --git a/src/fdcan/message_ram/common.rs b/src/fdcan/message_ram/common.rs deleted file mode 100644 index 027211c5..00000000 --- a/src/fdcan/message_ram/common.rs +++ /dev/null @@ -1,129 +0,0 @@ -use super::enums::{ - BitRateSwitching, ErrorStateIndicator, FilterElementConfig, FilterType, FrameFormat, IdType, - RemoteTransmissionRequest, -}; -use super::generic; - -#[doc = "Reader of field `ID`"] -pub type ID_R = generic::R; - -#[doc = "Reader of field `RTR`"] -pub type RTR_R = generic::R; -impl RTR_R { - pub fn rtr(&self) -> RemoteTransmissionRequest { - match self.bits { - false => RemoteTransmissionRequest::TransmitDataFrame, - true => RemoteTransmissionRequest::TransmitRemoteFrame, - } - } - pub fn is_transmit_remote_frame(&self) -> bool { - *self == RemoteTransmissionRequest::TransmitRemoteFrame - } - pub fn is_transmit_data_frame(&self) -> bool { - *self == RemoteTransmissionRequest::TransmitDataFrame - } -} - -#[doc = "Reader of field `XTD`"] -pub type XTD_R = generic::R; -impl XTD_R { - pub fn id_type(&self) -> IdType { - match self.bits() { - false => IdType::StandardId, - true => IdType::ExtendedId, - } - } - pub fn is_standard_id(&self) -> bool { - *self == IdType::StandardId - } - pub fn is_exteded_id(&self) -> bool { - *self == IdType::ExtendedId - } -} - -#[doc = "Reader of field `ESI`"] -pub type ESI_R = generic::R; -impl ESI_R { - pub fn error_state(&self) -> ErrorStateIndicator { - match self.bits() { - false => ErrorStateIndicator::ErrorActive, - true => ErrorStateIndicator::ErrorPassive, - } - } - pub fn is_error_active(&self) -> bool { - *self == ErrorStateIndicator::ErrorActive - } - pub fn is_error_passive(&self) -> bool { - *self == ErrorStateIndicator::ErrorPassive - } -} - -#[doc = "Reader of field `DLC`"] -pub type DLC_R = generic::R; - -#[doc = "Reader of field `BRS`"] -pub type BRS_R = generic::R; -impl BRS_R { - pub fn bit_rate_switching(&self) -> BitRateSwitching { - match self.bits() { - true => BitRateSwitching::WithBRS, - false => BitRateSwitching::WithoutBRS, - } - } - pub fn is_with_brs(&self) -> bool { - *self == BitRateSwitching::WithBRS - } - pub fn is_without_brs(&self) -> bool { - *self == BitRateSwitching::WithoutBRS - } -} - -#[doc = "Reader of field `FDF`"] -pub type FDF_R = generic::R; -impl FDF_R { - pub fn frame_format(&self) -> FrameFormat { - match self.bits() { - false => FrameFormat::Standard, - true => FrameFormat::Fdcan, - } - } - pub fn is_standard_format(&self) -> bool { - *self == FrameFormat::Standard - } - pub fn is_fdcan_format(&self) -> bool { - *self == FrameFormat::Fdcan - } -} - -#[doc = "Reader of field `(X|S)FT`"] -pub type ESFT_R = generic::R; -impl ESFT_R { - #[doc = r"Gets the Filtertype"] - #[inline(always)] - pub fn to_filter_type(&self) -> FilterType { - match self.bits() { - 0b00 => FilterType::RangeFilter, - 0b01 => FilterType::DualIdFilter, - 0b10 => FilterType::ClassicFilter, - 0b11 => FilterType::FilterDisabled, - _ => unreachable!(), - } - } -} - -#[doc = "Reader of field `(E|S)FEC`"] -pub type ESFEC_R = generic::R; -impl ESFEC_R { - pub fn to_filter_element_config(&self) -> FilterElementConfig { - match self.bits() { - 0b000 => FilterElementConfig::DisableFilterElement, - 0b001 => FilterElementConfig::StoreInFifo0, - 0b010 => FilterElementConfig::StoreInFifo1, - 0b011 => FilterElementConfig::Reject, - 0b100 => FilterElementConfig::SetPriority, - 0b101 => FilterElementConfig::SetPriorityAndStoreInFifo0, - 0b110 => FilterElementConfig::SetPriorityAndStoreInFifo1, - _ => unimplemented!(), - } - } -} diff --git a/src/fdcan/message_ram/enums.rs b/src/fdcan/message_ram/enums.rs deleted file mode 100644 index 33f3f5d2..00000000 --- a/src/fdcan/message_ram/enums.rs +++ /dev/null @@ -1,240 +0,0 @@ -/// Datalength is the message length generalised over -/// the Standard (Classic) and FDCAN message types -#[derive(Clone, Copy, Debug, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum DataLength { - Standard(u8), - Fdcan(u8), -} -impl DataLength { - /// Creates a DataLength type - /// - /// Uses the byte length and Type of frame as input - pub fn new(len: u8, ff: FrameFormat) -> DataLength { - match ff { - FrameFormat::Standard => match len { - 0..=8 => DataLength::Standard(len), - _ => panic!("DataLength > 8"), - }, - FrameFormat::Fdcan => match len { - 0..=64 => DataLength::Fdcan(len), - _ => panic!("DataLength > 64"), - }, - } - } - /// Specialised function to create standard frames - pub fn new_standard(len: u8) -> DataLength { - Self::new(len, FrameFormat::Standard) - } - /// Specialised function to create FDCAN frames - pub fn new_fdcan(len: u8) -> DataLength { - Self::new(len, FrameFormat::Fdcan) - } - - /// returns the length in bytes - pub fn len(&self) -> u8 { - match self { - DataLength::Standard(l) | DataLength::Fdcan(l) => *l, - } - } - - pub(crate) fn dlc(&self) -> u8 { - match self { - DataLength::Standard(l) => *l, - DataLength::Fdcan(l) => match l { - 0..=8 => *l, - 9..=12 => 12, - 13..=16 => 16, - 17..=20 => 20, - 21..=24 => 24, - 25..=32 => 32, - 33..=48 => 48, - 49..=64 => 64, - _ => panic!("DataLength > 64"), - }, - } - } -} -impl From for FrameFormat { - fn from(dl: DataLength) -> FrameFormat { - match dl { - DataLength::Standard(_) => FrameFormat::Standard, - DataLength::Fdcan(_) => FrameFormat::Fdcan, - } - } -} - -/// Wheter or not to generate an Tx Event -#[derive(Clone, Copy, Debug, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum Event { - /// Do not generate an Tx Event - NoEvent, - /// Generate an Tx Event with a specified ID - Event(u8), -} - -impl From for EventControl { - fn from(e: Event) -> Self { - match e { - Event::NoEvent => EventControl::DoNotStore, - Event::Event(_) => EventControl::Store, - } - } -} - -impl From> for Event { - fn from(mm: Option) -> Self { - match mm { - None => Event::NoEvent, - Some(mm) => Event::Event(mm), - } - } -} - -impl From for Option { - fn from(e: Event) -> Option { - match e { - Event::NoEvent => None, - Event::Event(mm) => Some(mm), - } - } -} - -/// TODO -#[derive(Clone, Copy, Debug, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum ErrorStateIndicator { - /// TODO - ErrorActive = 0, - /// TODO - ErrorPassive = 1, -} -impl From for bool { - #[inline(always)] - fn from(e: ErrorStateIndicator) -> Self { - e as u8 != 0 - } -} - -/// Type of frame, standard (classic) or FdCAN -#[derive(Clone, Copy, Debug, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum FrameFormat { - Standard = 0, - Fdcan = 1, -} -impl From for bool { - #[inline(always)] - fn from(e: FrameFormat) -> Self { - e as u8 != 0 - } -} - -/// Type of Id, Standard or Extended -#[derive(Clone, Copy, Debug, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum IdType { - /// Standard ID - StandardId = 0, - /// Extended ID - ExtendedId = 1, -} -impl From for bool { - #[inline(always)] - fn from(e: IdType) -> Self { - e as u8 != 0 - } -} - -/// Whether the frame contains data or requests data -#[derive(Clone, Copy, Debug, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum RemoteTransmissionRequest { - /// Frame contains data - TransmitDataFrame = 0, - /// frame does not contain data - TransmitRemoteFrame = 1, -} -impl From for bool { - #[inline(always)] - fn from(e: RemoteTransmissionRequest) -> Self { - e as u8 != 0 - } -} - -/// Whether BitRateSwitching should be or was enabled -#[derive(Clone, Copy, Debug, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum BitRateSwitching { - /// disable bit rate switching - WithoutBRS = 0, - /// enable bit rate switching - WithBRS = 1, -} -impl From for bool { - #[inline(always)] - fn from(e: BitRateSwitching) -> Self { - e as u8 != 0 - } -} - -/// Whether to store transmit Events -#[derive(Clone, Copy, Debug, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum EventControl { - /// do not store an tx event - DoNotStore, - /// store transmit events - Store, -} -impl From for bool { - #[inline(always)] - fn from(e: EventControl) -> Self { - e as u8 != 0 - } -} - -/// If an received message matched any filters -#[derive(Clone, Copy, Debug, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum FilterFrameMatch { - /// This did match filter - DidMatch(u8), - /// This received frame did not match any specific filters - DidNotMatch, -} - -/// Type of filter to be used -#[derive(Clone, Copy, Debug, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum FilterType { - /// Filter uses the range between two id's - RangeFilter = 0b00, - /// The filter matches on two specific id's (or one ID checked twice) - DualIdFilter = 0b01, - /// Filter is using a bitmask - ClassicFilter = 0b10, - /// Filter is disabled - FilterDisabled = 0b11, -} - -#[derive(Clone, Copy, Debug, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum FilterElementConfig { - /// Filter is disabled - DisableFilterElement = 0b000, - /// Store a matching message in FIFO 0 - StoreInFifo0 = 0b001, - /// Store a matching message in FIFO 1 - StoreInFifo1 = 0b010, - /// Reject a matching message - Reject = 0b011, - /// Flag that a priority message has been received, *But do note store!*?? - SetPriority = 0b100, - /// Flag and store message in FIFO 0 - SetPriorityAndStoreInFifo0 = 0b101, - /// Flag and store message in FIFO 1 - SetPriorityAndStoreInFifo1 = 0b110, - //_Unused = 0b111, -} diff --git a/src/fdcan/message_ram/extended_filter.rs b/src/fdcan/message_ram/extended_filter.rs deleted file mode 100644 index 5f66468c..00000000 --- a/src/fdcan/message_ram/extended_filter.rs +++ /dev/null @@ -1,130 +0,0 @@ -use super::common::{ESFEC_R, ESFT_R}; -use super::enums::{FilterElementConfig, FilterType}; -use super::generic; - -#[doc = "Reader of register ExtendedFilter"] -pub(crate) type R = generic::R; -#[doc = "Writer for register ExtendedFilter"] -pub(crate) type W = generic::W; -#[doc = "Register ExtendedFilter `reset()`'s"] -impl generic::ResetValue for super::ExtendedFilter { - type Type = super::ExtendedFilterType; - #[inline(always)] - fn reset_value() -> Self::Type { - // Sets filter element to Disabled - [0x0, 0x0] - } -} - -#[doc = "Reader of field `EFID2`"] -pub(crate) type EFID2_R = generic::R; -#[doc = "Write proxy for field `EFID2`"] -pub(crate) struct EFID2_W<'a> { - w: &'a mut W, -} -impl<'a> EFID2_W<'a> { - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - pub unsafe fn bits(self, value: u32) -> &'a mut W { - self.w.bits[1] = (self.w.bits[1] & !(0x1FFFFFFF)) | ((value as u32) & 0x1FFFFFFF); - self.w - } -} - -#[doc = "Reader of field `EFID1`"] -pub(crate) type EFID1_R = generic::R; -#[doc = "Write proxy for field `EFID1`"] -pub(crate) struct EFID1_W<'a> { - w: &'a mut W, -} -impl<'a> EFID1_W<'a> { - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - pub unsafe fn bits(self, value: u32) -> &'a mut W { - self.w.bits[0] = (self.w.bits[0] & !(0x1FFFFFFF)) | ((value as u32) & 0x1FFFFFFF); - self.w - } -} - -#[doc = "Write proxy for field `EFEC`"] -pub(crate) struct EFEC_W<'a> { - w: &'a mut W, -} -impl<'a> EFEC_W<'a> { - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - pub unsafe fn bits(self, value: u8) -> &'a mut W { - self.w.bits[0] = (self.w.bits[0] & !(0x07 << 29)) | (((value as u32) & 0x07) << 29); - self.w - } - #[doc = r"Sets the field according to FilterElementConfig"] - #[inline(always)] - pub fn set_filter_element_config(self, fec: FilterElementConfig) -> &'a mut W { - //SAFETY: FilterElementConfig only be valid options - unsafe { self.bits(fec as u8) } - } -} - -#[doc = "Write proxy for field `EFT`"] -pub(crate) struct EFT_W<'a> { - w: &'a mut W, -} -impl<'a> EFT_W<'a> { - #[doc = r"Sets the field according the FilterType"] - #[inline(always)] - pub fn set_filter_type(self, filter: FilterType) -> &'a mut W { - //SAFETY: FilterType only be valid options - unsafe { self.bits(filter as u8) } - } - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - pub unsafe fn bits(self, value: u8) -> &'a mut W { - self.w.bits[1] = (self.w.bits[1] & !(0x03 << 30)) | (((value as u32) & 0x03) << 30); - self.w - } -} - -impl R { - #[doc = "Byte 0 - Bits 0:28 - EFID1"] - #[inline(always)] - pub fn sfid1(&self) -> EFID1_R { - EFID1_R::new(((self.bits[0]) & 0x1FFFFFFF) as u32) - } - #[doc = "Byte 0 - Bits 29:31 - EFEC"] - #[inline(always)] - pub fn efec(&self) -> ESFEC_R { - ESFEC_R::new(((self.bits[0] >> 29) & 0x07) as u8) - } - #[doc = "Byte 1 - Bits 0:28 - EFID2"] - #[inline(always)] - pub fn sfid2(&self) -> EFID2_R { - EFID2_R::new(((self.bits[1]) & 0x1FFFFFFF) as u32) - } - #[doc = "Byte 1 - Bits 30:31 - EFT"] - #[inline(always)] - pub fn eft(&self) -> ESFT_R { - ESFT_R::new(((self.bits[1] >> 30) & 0x03) as u8) - } -} -impl W { - #[doc = "Byte 0 - Bits 0:28 - EFID1"] - #[inline(always)] - pub fn efid1(&mut self) -> EFID1_W { - EFID1_W { w: self } - } - #[doc = "Byte 0 - Bits 29:31 - EFEC"] - #[inline(always)] - pub fn efec(&mut self) -> EFEC_W { - EFEC_W { w: self } - } - #[doc = "Byte 1 - Bits 0:28 - EFID2"] - #[inline(always)] - pub fn efid2(&mut self) -> EFID2_W { - EFID2_W { w: self } - } - #[doc = "Byte 1 - Bits 30:31 - EFT"] - #[inline(always)] - pub fn eft(&mut self) -> EFT_W { - EFT_W { w: self } - } -} diff --git a/src/fdcan/message_ram/generic.rs b/src/fdcan/message_ram/generic.rs deleted file mode 100644 index 7f232ca5..00000000 --- a/src/fdcan/message_ram/generic.rs +++ /dev/null @@ -1,256 +0,0 @@ -use core::marker; - -///This trait shows that register has `read` method -/// -///Registers marked with `Writable` can be also `modify`'ed -pub trait Readable {} - -///This trait shows that register has `write`, `write_with_zero` and `reset` method -/// -///Registers marked with `Readable` can be also `modify`'ed -pub trait Writable {} - -///Reset value of the register -/// -///This value is initial value for `write` method. -///It can be also directly writed to register by `reset` method. -pub trait ResetValue { - ///Register size - type Type; - ///Reset value of the register - fn reset_value() -> Self::Type; -} - -///This structure provides volatile access to register -pub struct Reg { - register: vcell::VolatileCell, - _marker: marker::PhantomData, -} - -unsafe impl Send for Reg {} - -impl Reg -where - Self: Readable, - U: Copy, -{ - ///Reads the contents of `Readable` register - /// - ///You can read the contents of a register in such way: - ///```ignore - ///let bits = periph.reg.read().bits(); - ///``` - ///or get the content of a particular field of a register. - ///```ignore - ///let reader = periph.reg.read(); - ///let bits = reader.field1().bits(); - ///let flag = reader.field2().bit_is_set(); - ///``` - #[inline(always)] - pub fn read(&self) -> R { - R { - bits: self.register.get(), - _reg: marker::PhantomData, - } - } -} - -impl Reg -where - Self: ResetValue + Writable, - U: Copy, -{ - ///Writes the reset value to `Writable` register - /// - ///Resets the register to its initial state - #[inline(always)] - pub fn reset(&self) { - self.register.set(Self::reset_value()) - } -} - -impl Reg -where - Self: ResetValue + Writable, - U: Copy, -{ - ///Writes bits to `Writable` register - /// - ///You can write raw bits into a register: - ///```ignore - ///periph.reg.write(|w| unsafe { w.bits(rawbits) }); - ///``` - ///or write only the fields you need: - ///```ignore - ///periph.reg.write(|w| w - /// .field1().bits(newfield1bits) - /// .field2().set_bit() - /// .field3().variant(VARIANT) - ///); - ///``` - ///Other fields will have reset value. - #[inline(always)] - pub fn write(&self, f: F) - where - F: FnOnce(&mut W) -> &mut W, - { - self.register.set( - f(&mut W { - bits: Self::reset_value(), - _reg: marker::PhantomData, - }) - .bits, - ); - } -} - -impl Reg -where - Self: Writable, - U: Copy + Default, -{ - ///Writes Zero to `Writable` register - /// - ///Similar to `write`, but unused bits will contain 0. - #[inline(always)] - pub fn write_with_zero(&self, f: F) - where - F: FnOnce(&mut W) -> &mut W, - { - self.register.set( - f(&mut W { - bits: U::default(), - _reg: marker::PhantomData, - }) - .bits, - ); - } -} - -impl Reg -where - Self: Readable + Writable, - U: Copy, -{ - ///Modifies the contents of the register - /// - ///E.g. to do a read-modify-write sequence to change parts of a register: - ///```ignore - ///periph.reg.modify(|r, w| unsafe { w.bits( - /// r.bits() | 3 - ///) }); - ///``` - ///or - ///```ignore - ///periph.reg.modify(|_, w| w - /// .field1().bits(newfield1bits) - /// .field2().set_bit() - /// .field3().variant(VARIANT) - ///); - ///``` - ///Other fields will have value they had before call `modify`. - #[inline(always)] - pub fn modify(&self, f: F) - where - for<'w> F: FnOnce(&R, &'w mut W) -> &'w mut W, - { - let bits = self.register.get(); - self.register.set( - f( - &R { - bits, - _reg: marker::PhantomData, - }, - &mut W { - bits, - _reg: marker::PhantomData, - }, - ) - .bits, - ); - } -} - -///Register/field reader -/// -///Result of the [`read`](Reg::read) method of a register. -///Also it can be used in the [`modify`](Reg::read) method -pub struct R { - pub(crate) bits: U, - _reg: marker::PhantomData, -} - -impl R -where - U: Copy, -{ - ///Create new instance of reader - #[inline(always)] - pub(crate) fn new(bits: U) -> Self { - Self { - bits, - _reg: marker::PhantomData, - } - } - ///Read raw bits from register/field - #[inline(always)] - pub fn bits(&self) -> U { - self.bits - } -} - -impl PartialEq for R -where - U: PartialEq, - FI: Copy + Into, -{ - #[inline(always)] - fn eq(&self, other: &FI) -> bool { - self.bits.eq(&(*other).into()) - } -} - -impl R { - ///Value of the field as raw bits - #[inline(always)] - pub fn bit(&self) -> bool { - self.bits - } - ///Returns `true` if the bit is clear (0) - #[inline(always)] - pub fn bit_is_clear(&self) -> bool { - !self.bit() - } - ///Returns `true` if the bit is set (1) - #[inline(always)] - pub fn bit_is_set(&self) -> bool { - self.bit() - } -} - -///Register writer -/// -///Used as an argument to the closures in the [`write`](Reg::write) and [`modify`](Reg::modify) methods of the register -pub struct W { - ///Writable bits - pub(crate) bits: U, - _reg: marker::PhantomData, -} - -impl W { - ///Writes raw bits to the register - #[inline(always)] - pub unsafe fn bits(&mut self, bits: U) -> &mut Self { - self.bits = bits; - self - } -} - -// ///Used if enumerated values cover not the whole range -// #[derive(Clone,Copy,PartialEq)] -// pub enum Variant { -// ///Expected variant -// Val(T), -// ///Raw bits -// Res(U), -// } diff --git a/src/fdcan/message_ram/rxfifo_element.rs b/src/fdcan/message_ram/rxfifo_element.rs deleted file mode 100644 index 4158afd0..00000000 --- a/src/fdcan/message_ram/rxfifo_element.rs +++ /dev/null @@ -1,96 +0,0 @@ -use super::common::{BRS_R, DLC_R, ESI_R, FDF_R, ID_R, RTR_R, XTD_R}; -use super::enums::{DataLength, FilterFrameMatch}; -use super::generic; - -#[doc = "Reader of register RxFifoElement"] -pub(crate) type R = generic::R; -// #[doc = "Writer for register ExtendedFilter"] -// pub(crate) type W = generic::W; -#[doc = "Register ExtendedFilter `reset()`'s"] -impl generic::ResetValue for super::RxFifoElementHeader { - type Type = super::RxFifoElementHeaderType; - #[inline(always)] - fn reset_value() -> Self::Type { - [0x0, 0x0] - } -} - -#[doc = "Reader of field `RXTS`"] -pub(crate) type RXTS_R = generic::R; - -#[doc = "Reader of field `FIDX`"] -pub(crate) type FIDX_R = generic::R; - -pub(crate) struct _ANMF; -#[doc = "Reader of field `ANMF`"] -pub(crate) type ANMF_R = generic::R; -impl ANMF_R { - pub fn is_matching_frame(&self) -> bool { - self.bit_is_clear() - } -} - -impl R { - #[doc = "Byte 0 - Bits 0:28 - ID"] - #[inline(always)] - pub fn id(&self) -> ID_R { - ID_R::new(((self.bits[0]) & 0x1FFFFFFF) as u32) - } - #[doc = "Byte 0 - Bit 29 - RTR"] - #[inline(always)] - pub fn rtr(&self) -> RTR_R { - RTR_R::new(((self.bits[0] >> 29) & 0x01) != 0) - } - #[doc = "Byte 0 - Bit 30 - XTD"] - #[inline(always)] - pub fn xtd(&self) -> XTD_R { - XTD_R::new(((self.bits[0] >> 30) & 0x01) != 0) - } - #[doc = "Byte 0 - Bit 30 - ESI"] - #[inline(always)] - pub fn esi(&self) -> ESI_R { - ESI_R::new(((self.bits[0] >> 31) & 0x01) != 0) - } - #[doc = "Byte 1 - Bits 0:15 - RXTS"] - #[inline(always)] - pub fn txts(&self) -> RXTS_R { - RXTS_R::new(((self.bits[1]) & 0xFFFF) as u16) - } - #[doc = "Byte 1 - Bits 16:19 - DLC"] - #[inline(always)] - pub fn dlc(&self) -> DLC_R { - DLC_R::new(((self.bits[1] >> 16) & 0x0F) as u8) - } - #[doc = "Byte 1 - Bits 20 - BRS"] - #[inline(always)] - pub fn brs(&self) -> BRS_R { - BRS_R::new(((self.bits[1] >> 20) & 0x01) != 0) - } - #[doc = "Byte 1 - Bits 20 - FDF"] - #[inline(always)] - pub fn fdf(&self) -> FDF_R { - FDF_R::new(((self.bits[1] >> 21) & 0x01) != 0) - } - #[doc = "Byte 1 - Bits 24:30 - FIDX"] - #[inline(always)] - pub fn fidx(&self) -> FIDX_R { - FIDX_R::new(((self.bits[1] >> 24) & 0xFF) as u8) - } - #[doc = "Byte 1 - Bits 31 - ANMF"] - #[inline(always)] - pub fn anmf(&self) -> ANMF_R { - ANMF_R::new(((self.bits[1] >> 31) & 0x01) != 0) - } - pub fn to_data_length(&self) -> DataLength { - let dlc = self.dlc().bits(); - let ff = self.fdf().frame_format(); - DataLength::new(dlc, ff) - } - pub fn to_filter_match(&self) -> FilterFrameMatch { - if self.anmf().is_matching_frame() { - FilterFrameMatch::DidMatch(self.fidx().bits()) - } else { - FilterFrameMatch::DidNotMatch - } - } -} diff --git a/src/fdcan/message_ram/standard_filter.rs b/src/fdcan/message_ram/standard_filter.rs deleted file mode 100644 index 2e35a9ef..00000000 --- a/src/fdcan/message_ram/standard_filter.rs +++ /dev/null @@ -1,130 +0,0 @@ -use super::common::{ESFEC_R, ESFT_R}; -use super::enums::{FilterElementConfig, FilterType}; -use super::generic; - -#[doc = "Reader of register StandardFilter"] -pub(crate) type R = generic::R; -#[doc = "Writer for register StandardFilter"] -pub(crate) type W = generic::W; -#[doc = "Register StandardFilter `reset()`'s with value 0xC0000"] -impl generic::ResetValue for super::StandardFilter { - type Type = super::StandardFilterType; - #[inline(always)] - fn reset_value() -> Self::Type { - // Sets filter element to Disabled - 0xC000 - } -} - -#[doc = "Reader of field `SFID2`"] -pub(crate) type SFID2_R = generic::R; -#[doc = "Write proxy for field `SFID2`"] -pub(crate) struct SFID2_W<'a> { - w: &'a mut W, -} -impl<'a> SFID2_W<'a> { - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - pub unsafe fn bits(self, value: u16) -> &'a mut W { - self.w.bits = (self.w.bits & !(0x03ff)) | ((value as u32) & 0x03ff); - self.w - } -} - -#[doc = "Reader of field `SFID1`"] -pub(crate) type SFID1_R = generic::R; -#[doc = "Write proxy for field `SFID1`"] -pub(crate) struct SFID1_W<'a> { - w: &'a mut W, -} -impl<'a> SFID1_W<'a> { - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - pub unsafe fn bits(self, value: u16) -> &'a mut W { - self.w.bits = (self.w.bits & !(0x03ff << 16)) | (((value as u32) & 0x03ff) << 16); - self.w - } -} - -#[doc = "Write proxy for field `SFEC`"] -pub(crate) struct SFEC_W<'a> { - w: &'a mut W, -} -impl<'a> SFEC_W<'a> { - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - pub unsafe fn bits(self, value: u8) -> &'a mut W { - self.w.bits = (self.w.bits & !(0x07 << 27)) | (((value as u32) & 0x07) << 27); - self.w - } - #[doc = r"Sets the field according to FilterElementConfig"] - #[inline(always)] - pub fn set_filter_element_config(self, fec: FilterElementConfig) -> &'a mut W { - //SAFETY: FilterElementConfig only be valid options - unsafe { self.bits(fec as u8) } - } -} - -#[doc = "Write proxy for field `SFT`"] -pub(crate) struct SFT_W<'a> { - w: &'a mut W, -} -impl<'a> SFT_W<'a> { - #[doc = r"Sets the field according the FilterType"] - #[inline(always)] - pub fn set_filter_type(self, filter: FilterType) -> &'a mut W { - //SAFETY: FilterType only be valid options - unsafe { self.bits(filter as u8) } - } - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - pub unsafe fn bits(self, value: u8) -> &'a mut W { - self.w.bits = (self.w.bits & !(0x03 << 30)) | (((value as u32) & 0x03) << 30); - self.w - } -} - -impl R { - #[doc = "Bits 0:10 - SFID2"] - #[inline(always)] - pub fn sfid2(&self) -> SFID2_R { - SFID2_R::new((self.bits & 0x03ff) as u16) - } - #[doc = "Bits 16:26 - SFID1"] - #[inline(always)] - pub fn sfid1(&self) -> SFID1_R { - SFID1_R::new(((self.bits >> 16) & 0x03ff) as u16) - } - #[doc = "Bits 27:29 - SFEC"] - #[inline(always)] - pub fn sfec(&self) -> ESFEC_R { - ESFEC_R::new(((self.bits >> 27) & 0x07) as u8) - } - #[doc = "Bits 30:31 - SFT"] - #[inline(always)] - pub fn sft(&self) -> ESFT_R { - ESFT_R::new(((self.bits >> 30) & 0x03) as u8) - } -} -impl W { - #[doc = "Bits 0:10 - SFID2"] - #[inline(always)] - pub fn sfid2(&mut self) -> SFID2_W { - SFID2_W { w: self } - } - #[doc = "Bits 16:26 - SFID1"] - #[inline(always)] - pub fn sfid1(&mut self) -> SFID1_W { - SFID1_W { w: self } - } - #[doc = "Bits 27:29 - SFEC"] - #[inline(always)] - pub fn sfec(&mut self) -> SFEC_W { - SFEC_W { w: self } - } - #[doc = "Bits 30:31 - SFT"] - #[inline(always)] - pub fn sft(&mut self) -> SFT_W { - SFT_W { w: self } - } -} diff --git a/src/fdcan/message_ram/txevent_element.rs b/src/fdcan/message_ram/txevent_element.rs deleted file mode 100644 index d202b858..00000000 --- a/src/fdcan/message_ram/txevent_element.rs +++ /dev/null @@ -1,135 +0,0 @@ -use super::common::{BRS_R, DLC_R, ESI_R, RTR_R, XTD_R}; -// use super::enums::{ -// BitRateSwitching, ErrorStateIndicator, FrameFormat, IdType, RemoteTransmissionRequest, -// }; -use super::generic; - -#[doc = "Reader of register TxEventElement"] -pub(crate) type R = generic::R; -// #[doc = "Writer for register TxEventElement"] -// pub(crate) type W = generic::W; -#[doc = "Register TxEventElement `reset()`'s"] -impl generic::ResetValue for super::TxEventElement { - type Type = super::TxEventElementType; - #[inline(always)] - fn reset_value() -> Self::Type { - [0, 0] - } -} - -#[doc = "Reader of field `ID`"] -pub(crate) type ID_R = generic::R; - -#[doc = "Reader of field `TXTS`"] -pub(crate) type TXTS_R = generic::R; - -#[derive(Clone, Copy, Debug, PartialEq)] -pub(crate) enum DataLengthFormat { - StandardLength = 0, - FDCANLength = 1, -} -impl From for bool { - #[inline(always)] - fn from(dlf: DataLengthFormat) -> Self { - dlf as u8 != 0 - } -} - -#[doc = "Reader of field `EDL`"] -pub(crate) type EDL_R = generic::R; -impl EDL_R { - pub fn data_length_format(&self) -> DataLengthFormat { - match self.bits() { - false => DataLengthFormat::StandardLength, - true => DataLengthFormat::FDCANLength, - } - } - pub fn is_standard_length(&self) -> bool { - *self == DataLengthFormat::StandardLength - } - pub fn is_fdcan_length(&self) -> bool { - *self == DataLengthFormat::FDCANLength - } -} - -#[derive(Clone, Copy, Debug, PartialEq)] -pub(crate) enum EventType { - //_Reserved = 0b00, - TxEvent = 0b01, - TxDespiteAbort = 0b10, - //_Reserved = 0b10, -} - -#[doc = "Reader of field `EFC`"] -pub(crate) type EFC_R = generic::R; -impl EFC_R { - pub fn event_type(&self) -> EventType { - match self.bits() { - 0b01 => EventType::TxEvent, - 0b10 => EventType::TxDespiteAbort, - _ => unimplemented!(), - } - } - pub fn is_tx_event(&self) -> bool { - self.event_type() == EventType::TxEvent - } - pub fn is_despite_abort(&self) -> bool { - self.event_type() == EventType::TxDespiteAbort - } -} - -#[doc = "Reader of field `MM`"] -pub(crate) type MM_R = generic::R; - -impl R { - #[doc = "Byte 0 - Bits 0:28 - ID"] - #[inline(always)] - pub fn id(&self) -> ID_R { - ID_R::new(((self.bits[0]) & 0x1FFFFFFF) as u32) - } - #[doc = "Byte 0 - Bit 29 - RTR"] - #[inline(always)] - pub fn rtr(&self) -> RTR_R { - RTR_R::new(((self.bits[0] >> 29) & 0x01) != 0) - } - #[doc = "Byte 0 - Bit 30 - XTD"] - #[inline(always)] - pub fn xtd(&self) -> XTD_R { - XTD_R::new(((self.bits[0] >> 30) & 0x01) != 0) - } - #[doc = "Byte 0 - Bit 30 - ESI"] - #[inline(always)] - pub fn esi(&self) -> ESI_R { - ESI_R::new(((self.bits[0] >> 31) & 0x01) != 0) - } - #[doc = "Byte 1 - Bits 0:15 - TXTS"] - #[inline(always)] - pub fn txts(&self) -> TXTS_R { - TXTS_R::new(((self.bits[1]) & 0xFFFF) as u16) - } - #[doc = "Byte 1 - Bits 16:19 - DLC"] - #[inline(always)] - pub fn dlc(&self) -> DLC_R { - DLC_R::new(((self.bits[1] >> 16) & 0x0F) as u8) - } - #[doc = "Byte 1 - Bits 20 - BRS"] - #[inline(always)] - pub fn brs(&self) -> BRS_R { - BRS_R::new(((self.bits[1] >> 20) & 0x01) != 0) - } - #[doc = "Byte 1 - Bits 21 - EDL"] - #[inline(always)] - pub fn edl(&self) -> EDL_R { - EDL_R::new(((self.bits[1] >> 21) & 0x01) != 0) - } - #[doc = "Byte 1 - Bits 22:23 - EFC"] - #[inline(always)] - pub fn efc(&self) -> EFC_R { - EFC_R::new(((self.bits[1] >> 22) & 0x03) as u8) - } - #[doc = "Byte 1 - Bits 24:31 - MM"] - #[inline(always)] - pub fn mm(&self) -> MM_R { - MM_R::new(((self.bits[1] >> 24) & 0xFF) as u8) - } -} diff --git a/src/lib.rs b/src/lib.rs index 8b890afe..0b7d3ee4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,8 +62,7 @@ pub use crate::stm32::interrupt; pub mod adc; pub mod bb; -// pub mod can; -pub mod fdcan; +pub mod can; // pub mod crc; // pub mod dac; pub mod delay;