diff --git a/Cargo.toml b/Cargo.toml index 84d4bc39..7df962ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ paste = "1.0" bitflags = "1.2" vcell = "0.1" static_assertions = "1.1" -fugit = "0.3.5" +fugit = "0.3.7" stm32-usbd = { version = "0.7.0", optional = true } fixed = { version = "1.28.0", optional = true } @@ -94,7 +94,7 @@ stm32g4a1 = ["stm32g4/stm32g4a1"] log-itm = ["cortex-m-log/itm"] log-rtt = [] log-semihost = ["cortex-m-log/semihosting"] -defmt-logging = ["defmt"] +defmt = ["dep:defmt", "fugit/defmt"] cordic = ["dep:fixed"] [profile.dev] diff --git a/src/fdcan/filter.rs b/src/fdcan/filter.rs deleted file mode 100644 index a770ab23..00000000 --- a/src/fdcan/filter.rs +++ /dev/null @@ -1,401 +0,0 @@ -use super::id::{ExtendedId, StandardId}; - -pub use message_ram::{EXTENDED_FILTER_MAX, STANDARD_FILTER_MAX}; - -/// A Standard Filter -pub type StandardFilter = Filter; -/// An Extended Filter -pub type ExtendedFilter = Filter; - -impl Default for StandardFilter { - fn default() -> Self { - StandardFilter::disable() - } -} -impl Default for ExtendedFilter { - fn default() -> Self { - ExtendedFilter::disable() - } -} - -impl StandardFilter { - /// Accept all messages in FIFO 0 - pub fn accept_all_into_fifo0() -> StandardFilter { - StandardFilter { - filter: FilterType::BitMask { - filter: 0x0, - mask: 0x0, - }, - action: Action::StoreInFifo0, - } - } - - /// Accept all messages in FIFO 1 - pub fn accept_all_into_fifo1() -> StandardFilter { - StandardFilter { - filter: FilterType::BitMask { - filter: 0x0, - mask: 0x0, - }, - action: Action::StoreInFifo1, - } - } - - /// Reject all messages - pub fn reject_all() -> StandardFilter { - StandardFilter { - filter: FilterType::BitMask { - filter: 0x0, - mask: 0x0, - }, - action: Action::Reject, - } - } - - /// Disable the filter - pub fn disable() -> StandardFilter { - StandardFilter { - filter: FilterType::Disabled, - action: Action::Disable, - } - } -} - -impl ExtendedFilter { - /// Accept all messages in FIFO 0 - pub fn accept_all_into_fifo0() -> ExtendedFilter { - ExtendedFilter { - filter: FilterType::BitMask { - filter: 0x0, - mask: 0x0, - }, - action: Action::StoreInFifo0, - } - } - - /// Accept all messages in FIFO 1 - pub fn accept_all_into_fifo1() -> ExtendedFilter { - ExtendedFilter { - filter: FilterType::BitMask { - filter: 0x0, - mask: 0x0, - }, - action: Action::StoreInFifo1, - } - } - - /// Reject all messages - pub fn reject_all() -> ExtendedFilter { - ExtendedFilter { - filter: FilterType::BitMask { - filter: 0x0, - mask: 0x0, - }, - action: Action::Reject, - } - } - - /// Disable the filter - pub fn disable() -> ExtendedFilter { - ExtendedFilter { - filter: FilterType::Disabled, - action: Action::Disable, - } - } -} - -/// Filter Type -//#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -#[derive(Clone, Copy, Debug)] -pub enum FilterType -where - ID: Copy + Clone + core::fmt::Debug, - UNIT: Copy + Clone + core::fmt::Debug, -{ - /// Match with a range between two messages - Range { - /// First Id of the range - from: ID, - /// Last Id of the range - to: ID, - }, - /// Match with a bitmask - BitMask { - /// Filter of the bitmask - filter: UNIT, - /// Mask of the bitmask - mask: UNIT, - }, - /// Match with a single ID - DedicatedSingle(ID), - /// Match with one of two ID's - DedicatedDual(ID, ID), - /// Filter is disabled - Disabled, -} -impl From> for super::message_ram::enums::FilterType -where - ID: Copy + Clone + core::fmt::Debug, - UNIT: Copy + Clone + core::fmt::Debug, -{ - fn from(f: FilterType) -> Self { - match f { - FilterType::Range { to: _, from: _ } => Self::RangeFilter, - FilterType::BitMask { filter: _, mask: _ } => Self::ClassicFilter, - FilterType::DedicatedSingle(_) => Self::DualIdFilter, - FilterType::DedicatedDual(_, _) => Self::DualIdFilter, - FilterType::Disabled => Self::FilterDisabled, - } - } -} - -/// Filter Action -#[derive(Clone, Copy, Debug)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum Action { - /// No Action - Disable = 0b000, - /// Store an matching message in FIFO 0 - StoreInFifo0 = 0b001, - /// Store an matching message in FIFO 1 - StoreInFifo1 = 0b010, - /// Reject an matching message - Reject = 0b011, - /// Flag a matching message (But not store?!?) - FlagHighPrio = 0b100, - /// Flag a matching message as a High Priority message and store it in FIFO 0 - FlagHighPrioAndStoreInFifo0 = 0b101, - /// Flag a matching message as a High Priority message and store it in FIFO 1 - FlagHighPrioAndStoreInFifo1 = 0b110, -} -impl From for super::message_ram::enums::FilterElementConfig { - fn from(a: Action) -> Self { - match a { - Action::Disable => Self::DisableFilterElement, - Action::StoreInFifo0 => Self::StoreInFifo0, - Action::StoreInFifo1 => Self::StoreInFifo1, - Action::Reject => Self::Reject, - Action::FlagHighPrio => Self::SetPriority, - Action::FlagHighPrioAndStoreInFifo0 => Self::SetPriorityAndStoreInFifo0, - Action::FlagHighPrioAndStoreInFifo1 => Self::SetPriorityAndStoreInFifo1, - } - } -} - -/// Filter -#[derive(Clone, Copy, Debug)] -//#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub struct Filter -where - ID: Copy + Clone + core::fmt::Debug, - UNIT: Copy + Clone + core::fmt::Debug, -{ - /// How to match an incoming message - pub filter: FilterType, - /// What to do with a matching message - pub action: Action, -} - -/// Standard Filter Slot -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum StandardFilterSlot { - /// 0 - _0 = 0, - /// 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, - /// 17 - _17 = 17, - /// 18 - _18 = 18, - /// 19 - _19 = 19, - /// 20 - _20 = 20, - /// 21 - _21 = 21, - /// 22 - _22 = 22, - /// 23 - _23 = 23, - /// 24 - _24 = 24, - /// 25 - _25 = 25, - /// 26 - _26 = 26, - /// 27 - _27 = 27, -} -impl From for StandardFilterSlot { - fn from(u: u8) -> Self { - match u { - 0 => StandardFilterSlot::_0, - 1 => StandardFilterSlot::_1, - 2 => StandardFilterSlot::_2, - 3 => StandardFilterSlot::_3, - 4 => StandardFilterSlot::_4, - 5 => StandardFilterSlot::_5, - 6 => StandardFilterSlot::_6, - 7 => StandardFilterSlot::_7, - 8 => StandardFilterSlot::_8, - 9 => StandardFilterSlot::_9, - 10 => StandardFilterSlot::_10, - 11 => StandardFilterSlot::_11, - 12 => StandardFilterSlot::_12, - 13 => StandardFilterSlot::_13, - 14 => StandardFilterSlot::_14, - 15 => StandardFilterSlot::_15, - 16 => StandardFilterSlot::_16, - 17 => StandardFilterSlot::_17, - 18 => StandardFilterSlot::_18, - 19 => StandardFilterSlot::_19, - 20 => StandardFilterSlot::_20, - 21 => StandardFilterSlot::_21, - 22 => StandardFilterSlot::_22, - 23 => StandardFilterSlot::_23, - 24 => StandardFilterSlot::_24, - 25 => StandardFilterSlot::_25, - 26 => StandardFilterSlot::_26, - 27 => StandardFilterSlot::_27, - _ => panic!("Standard Filter Slot Too High!"), - } - } -} - -/// Extended Filter Slot -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum ExtendedFilterSlot { - /// 0 - _0 = 0, - /// 1 - _1 = 1, - /// 2 - _2 = 2, - /// 3 - _3 = 3, - /// 4 - _4 = 4, - /// 5 - _5 = 5, - /// 6 - _6 = 6, - /// 7 - _7 = 7, -} -impl From for ExtendedFilterSlot { - fn from(u: u8) -> Self { - match u { - 0 => ExtendedFilterSlot::_0, - 1 => ExtendedFilterSlot::_1, - 2 => ExtendedFilterSlot::_2, - 3 => ExtendedFilterSlot::_3, - 4 => ExtendedFilterSlot::_4, - 5 => ExtendedFilterSlot::_5, - 6 => ExtendedFilterSlot::_6, - 7 => ExtendedFilterSlot::_7, - _ => panic!("Extended Filter Slot Too High!"), // Should be unreachable - } - } -} - -/// Enum over both Standard and Extended Filter ID's -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum FilterId { - /// Standard Filter Slots - Standard(StandardFilterSlot), - /// Extended Filter Slots - Extended(ExtendedFilterSlot), -} - -pub(crate) trait ActivateFilter -where - ID: Copy + Clone + core::fmt::Debug, - UNIT: Copy + Clone + core::fmt::Debug, -{ - fn activate(&mut self, f: Filter); - // fn read(&self) -> Filter; -} - -use super::message_ram; - -impl ActivateFilter for message_ram::StandardFilter { - fn activate(&mut self, f: Filter) { - let sft = f.filter.into(); - - let (sfid1, sfid2) = match f.filter { - FilterType::Range { to, from } => (to.as_raw(), from.as_raw()), - FilterType::DedicatedSingle(id) => (id.as_raw(), id.as_raw()), - FilterType::DedicatedDual(id1, id2) => (id1.as_raw(), id2.as_raw()), - FilterType::BitMask { filter, mask } => (filter, mask), - FilterType::Disabled => (0x0, 0x0), - }; - let sfec = f.action.into(); - self.write(|w| { - unsafe { w.sfid1().bits(sfid1).sfid2().bits(sfid2) } - .sft() - .set_filter_type(sft) - .sfec() - .set_filter_element_config(sfec) - }); - } - // fn read(&self) -> Filter { - // todo!() - // } -} -impl ActivateFilter for message_ram::ExtendedFilter { - fn activate(&mut self, f: Filter) { - let eft = f.filter.into(); - - let (efid1, efid2) = match f.filter { - FilterType::Range { to, from } => (to.as_raw(), from.as_raw()), - FilterType::DedicatedSingle(id) => (id.as_raw(), id.as_raw()), - FilterType::DedicatedDual(id1, id2) => (id1.as_raw(), id2.as_raw()), - FilterType::BitMask { filter, mask } => (filter, mask), - FilterType::Disabled => (0x0, 0x0), - }; - let efec = f.action.into(); - self.write(|w| { - unsafe { w.efid1().bits(efid1).efid2().bits(efid2) } - .eft() - .set_filter_type(eft) - .efec() - .set_filter_element_config(efec) - }); - } - // fn read(&self) -> Filter { - // todo!() - // } -} diff --git a/src/fdcan/id.rs b/src/fdcan/id.rs deleted file mode 100644 index 20f77598..00000000 --- a/src/fdcan/id.rs +++ /dev/null @@ -1,311 +0,0 @@ -//! CAN Identifiers. - -use core::cmp::{Ord, Ordering}; - -use super::message_ram::enums::{IdType, RemoteTransmissionRequest}; - -/// Standard 11-bit CAN Identifier (`0..=0x7FF`). -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub struct StandardId(u16); - -impl StandardId { - /// CAN ID `0`, the highest priority. - pub const ZERO: Self = Self(0); - - /// CAN ID `0x7FF`, the lowest priority. - pub const MAX: Self = Self(0x7FF); - - /// Tries to create a `StandardId` from a raw 16-bit integer. - /// - /// This will return `None` if `raw` is out of range of an 11-bit integer (`> 0x7FF`). - #[inline] - pub const fn new(raw: u16) -> Option { - if raw <= 0x7FF { - Some(Self(raw)) - } else { - None - } - } - - /// Creates a new `StandardId` without checking if it is inside the valid range. - /// - /// # Safety - /// - /// The caller must ensure that `raw` is in the valid range, otherwise the behavior is - /// undefined. - #[inline] - pub const unsafe fn new_unchecked(raw: u16) -> Self { - Self(raw) - } - - /// Returns this CAN Identifier as a raw 16-bit integer. - #[inline] - pub fn as_raw(&self) -> u16 { - self.0 - } -} -impl From for IdType { - fn from(_id: StandardId) -> Self { - IdType::StandardId - } -} - -/// Extended 29-bit CAN Identifier (`0..=1FFF_FFFF`). -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub struct ExtendedId(u32); - -impl ExtendedId { - /// CAN ID `0`, the highest priority. - pub const ZERO: Self = Self(0); - - /// CAN ID `0x1FFFFFFF`, the lowest priority. - pub const MAX: Self = Self(0x1FFF_FFFF); - - /// Tries to create a `ExtendedId` from a raw 32-bit integer. - /// - /// This will return `None` if `raw` is out of range of an 29-bit integer (`> 0x1FFF_FFFF`). - #[inline] - pub const fn new(raw: u32) -> Option { - if raw <= 0x1FFF_FFFF { - Some(Self(raw)) - } else { - None - } - } - - /// Creates a new `ExtendedId` without checking if it is inside the valid range. - /// - /// # Safety - /// - /// The caller must ensure that `raw` is in the valid range, otherwise the behavior is - /// undefined. - #[inline] - pub const unsafe fn new_unchecked(raw: u32) -> Self { - Self(raw) - } - - /// Returns this CAN Identifier as a raw 32-bit integer. - #[inline] - pub fn as_raw(&self) -> u32 { - self.0 - } - - /// Returns the Base ID part of this extended identifier. - pub fn standard_id(&self) -> StandardId { - // ID-28 to ID-18 - StandardId((self.0 >> 18) as u16) - } -} - -impl From for IdType { - fn from(_id: ExtendedId) -> Self { - IdType::ExtendedId - } -} - -/// A CAN Identifier (standard or extended). -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum Id { - /// Standard 11-bit Identifier (`0..=0x7FF`). - Standard(StandardId), - - /// Extended 29-bit Identifier (`0..=0x1FFF_FFFF`). - Extended(ExtendedId), -} - -impl From for Id { - #[inline] - fn from(id: StandardId) -> Self { - Id::Standard(id) - } -} - -impl From for Id { - #[inline] - fn from(id: ExtendedId) -> Self { - Id::Extended(id) - } -} - -impl From for IdType { - #[inline] - fn from(id: Id) -> Self { - match id { - Id::Standard(id) => id.into(), - Id::Extended(id) => id.into(), - } - } -} - -/// Identifier of a CAN message. -/// -/// FdCan be either a standard identifier (11bit, Range: 0..0x3FF) or a -/// extendended identifier (29bit , Range: 0..0x1FFFFFFF). -/// -/// The `Ord` trait can be used to determine the frame’s priority this ID -/// belongs to. -/// Lower identifier values have a higher priority. Additionally standard frames -/// have a higher priority than extended frames and data frames have a higher -/// priority than remote frames. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub(crate) struct IdReg(u32); - -impl IdReg { - const STANDARD_SHIFT: u32 = 18; - #[allow(dead_code)] - const STANDARD_MASK: u32 = 0x1FFC0000; - - const EXTENDED_SHIFT: u32 = 0; - const EXTENDED_MASK: u32 = 0x1FFFFFFF; - - const XTD_SHIFT: u32 = 30; - const XTD_MASK: u32 = 1 << Self::XTD_SHIFT; - - const RTR_SHIFT: u32 = 29; - const RTR_MASK: u32 = 1 << Self::RTR_SHIFT; - - /// Creates a new standard identifier (11bit, Range: 0..0x7FF) - /// - /// Panics for IDs outside the allowed range. - fn new_standard(id: StandardId) -> Self { - Self(u32::from(id.as_raw()) << Self::STANDARD_SHIFT) - } - - /// Creates a new extendended identifier (29bit , Range: 0..0x1FFFFFFF). - /// - /// Panics for IDs outside the allowed range. - fn new_extended(id: ExtendedId) -> Self { - Self(id.as_raw() << Self::EXTENDED_SHIFT | (1 << Self::XTD_SHIFT)) - } - - pub(crate) fn as_raw_id(&self) -> u32 { - self.0 & Self::EXTENDED_MASK - } - - pub(crate) fn from_register(id: u32, rtr: RemoteTransmissionRequest, xtd: IdType) -> Self { - let rtr: u32 = match rtr { - RemoteTransmissionRequest::TransmitDataFrame => 0, - RemoteTransmissionRequest::TransmitRemoteFrame => 1 << Self::RTR_SHIFT, - }; - let xtd: u32 = match xtd { - IdType::StandardId => 0, - IdType::ExtendedId => 1 << Self::XTD_SHIFT, - }; - Self(id | rtr | xtd) - } - - /// Sets the remote transmission (RTR) flag. This marks the identifier as - /// being part of a remote frame. - #[must_use = "returns a new IdReg without modifying `self`"] - pub(crate) fn with_rtr(self, rtr: bool) -> Self { - if rtr { - Self(self.0 | (1 << Self::RTR_SHIFT)) - } else { - Self(self.0 & !Self::RTR_MASK) - } - } - - /// Returns the identifier. - pub fn to_id(self) -> Id { - if self.is_extended() { - Id::Extended(unsafe { - ExtendedId::new_unchecked((self.0 >> Self::EXTENDED_SHIFT) & Self::EXTENDED_MASK) - }) - } else { - Id::Standard(unsafe { - StandardId::new_unchecked( - ((self.0 >> Self::STANDARD_SHIFT) & Self::STANDARD_MASK) as u16, - ) - }) - } - } - - /// Returns `true` if the identifier is an extended identifier. - pub fn is_extended(self) -> bool { - (self.0 & Self::XTD_MASK) != 0 - } - - /// Returns `true` if the identifier is a standard identifier. - pub fn is_standard(self) -> bool { - !self.is_extended() - } - - /// Returns `true` if the identifer is part of a remote frame (RTR bit set). - pub(crate) fn rtr(self) -> bool { - self.0 & Self::RTR_MASK != 0 - } -} -impl From for IdReg { - fn from(id: Id) -> Self { - match id { - Id::Standard(s) => IdReg::new_standard(s), - Id::Extended(e) => IdReg::new_extended(e), - } - } -} -impl From for Id { - fn from(idr: IdReg) -> Self { - idr.to_id() - } -} -impl From for IdType { - #[inline] - fn from(id: IdReg) -> Self { - if id.is_standard() { - IdType::StandardId - } else { - IdType::ExtendedId - } - } -} -impl From for RemoteTransmissionRequest { - #[inline] - fn from(id: IdReg) -> Self { - if id.rtr() { - RemoteTransmissionRequest::TransmitRemoteFrame - } else { - RemoteTransmissionRequest::TransmitDataFrame - } - } -} - -/// `IdReg` is ordered by priority. -impl Ord for IdReg { - fn cmp(&self, other: &Self) -> Ordering { - // When the IDs match, data frames have priority over remote frames. - let rtr = self.rtr().cmp(&other.rtr()).reverse(); - - let id_a = self.to_id(); - let id_b = other.to_id(); - match (id_a, id_b) { - (Id::Standard(a), Id::Standard(b)) => { - // Lower IDs have priority over higher IDs. - a.as_raw().cmp(&b.as_raw()).reverse().then(rtr) - } - (Id::Extended(a), Id::Extended(b)) => a.as_raw().cmp(&b.as_raw()).reverse().then(rtr), - (Id::Standard(a), Id::Extended(b)) => { - // Standard frames have priority over extended frames if their Base IDs match. - a.as_raw() - .cmp(&b.standard_id().as_raw()) - .reverse() - .then(Ordering::Greater) - } - (Id::Extended(a), Id::Standard(b)) => a - .standard_id() - .as_raw() - .cmp(&b.as_raw()) - .reverse() - .then(Ordering::Less), - } - } -} - -impl PartialOrd for IdReg { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} diff --git a/src/fdcan/interrupt.rs b/src/fdcan/interrupt.rs deleted file mode 100644 index a9525e8e..00000000 --- a/src/fdcan/interrupt.rs +++ /dev/null @@ -1,205 +0,0 @@ -//! Interrupt types. - -use core::ops; - -#[allow(unused_imports)] // for intra-doc links only -use crate::fdcan::{FdCan, Rx}; - -/// FdCAN interrupt sources. -/// -/// These can be individually enabled and disabled in the FdCAN peripheral. Note that each FdCAN -/// peripheral only exposes 2 interrupts to the microcontroller: -/// -/// FDCANx_INTR0, -/// FDCANx_INTR1, -/// -/// The interrupts available on each line can be configured using the [`config::FdCanConfig`] struct. -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -#[non_exhaustive] -pub enum Interrupt { - /// Rx FIFO 0 has a new message - RxFifo0NewMsg = 1 << 0, - /// Rx FIFO 0 is full - RxFifo0Full = 1 << 1, - /// Rx FIFO 0 has lost a message - RxFifo0MsgLost = 1 << 2, - /// Rx FIFO 1 has a new message - RxFifo1NewMsg = 1 << 3, - /// Rx FIFO 1 is full - RxFifo1Full = 1 << 4, - /// Rx FIFO 1 has lost a message - RxFifo1MsgLost = 1 << 5, - /// A High Priority Message has been flagged by a filter - RxHighPrio = 1 << 6, - /// Transmit has been completed - TxComplete = 1 << 7, - /// Tx message has been cancelled - TxCancel = 1 << 8, - /// Tx Fifo is empty - TxEmpty = 1 << 9, - /// An new Event has been received in the Tx Event Fifo - TxEventNew = 1 << 10, - /// The TxEvent Fifo is full - TxEventFull = 1 << 11, - /// An Tx Event has been lost - TxEventLost = 1 << 12, - /// Timestamp wrap around has occurred - TsWrapAround = 1 << 13, - /// Message RAM access failure - /// - /// The flag is set when the Rx handler: - /// has not completed acceptance filtering or storage of an accepted message until the - /// arbitration field of the following message has been received. In this case acceptance - /// filtering or message storage is aborted and the Rx handler starts processing of the - /// following message. was unable to write a message to the message RAM. In this case - /// message storage is aborted. - /// In both cases the FIFO put index is not updated. The partly stored message is overwritten - /// when the next message is stored to this location. - /// The flag is also set when the Tx Handler was not able to read a message from the Message - /// RAM in time. In this case message transmission is aborted. In case of a Tx Handler access - /// failure the FDCAN is switched into Restricted operation Mode (see Restricted operation - /// mode). - MsgRamAccessFailure = 1 << 14, - /// Timeout Occurred - TimeoutOccurred = 1 << 15, - /// Overflow of CAN error logging counter occurred - ErrLogOverflow = 1 << 16, - /// Errr Passive - ErrPassive = 1 << 17, - /// Warning Status - WarningStatus = 1 << 18, - /// Bus_Off status - BusOff = 1 << 19, - /// Watchdog interrupt - WatchdogInt = 1 << 20, - /// Protocol error in arbitration phase (nominal bit time is used) - ProtErrArbritation = 1 << 21, - /// Protocol error in data phase (data bit time is used) - ProtErrData = 1 << 22, - /// Access to reserved address - ReservedAccess = 1 << 23, -} - -bitflags::bitflags! { - /// A set of FdCAN interrupts. - #[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] - pub struct Interrupts: u32 { - /// Rx FIFO 0 has a new message - const RX_FIFO_0_NEW_MESSAGE = 1 << 0; - /// Rx FIFO 0 is full - const RX_FIFO_0_FULL = 1 << 1; - /// Rx FIFO 0 has lost a message - const RX_FIFO_0_MSG_LOST = 1 << 2; - /// Rx FIFO 1 has a new message - const RX_FIFO_1_NEW_MESSAGE = 1 << 3; - /// Rx FIFO 1 is full - const RX_FIFO_1_FULL = 1 << 4; - /// Rx FIFO 1 has lost a message - const RX_FIFO_1_MSG_LOST = 1 << 5; - /// A High Priority Message has been flagged by a filter - const RX_HIGH_PRIO_MSG = 1<<6; - /// Transmit has been completed - const TX_COMPLETE = 1<<7; - /// Tx message has been cancelled - const TX_CANCEL = 1<<8; - /// Tx Fifo is empty - const TX_EMPTY = 1<<9; - /// An new Event has been received in the Tx Event Fifo - const TX_EVENT_NEW = 1<<10; - /// The TxEvent Fifo is full - const TX_EVENT_FULL = 1<<11; - /// An Tx Event has been lost - const TX_EVENT_LOST = 1<<12; - /// Timestamp wrap around has occurred - const TS_WRAP_AROUND = 1<<13; - /// Message RAM access failure - /// - /// The flag is set when the Rx handler: - /// has not completed acceptance filtering or storage of an accepted message until the - /// arbitration field of the following message has been received. In this case acceptance - /// filtering or message storage is aborted and the Rx handler starts processing of the - /// following message. was unable to write a message to the message RAM. In this case - /// message storage is aborted. - /// In both cases the FIFO put index is not updated. The partly stored message is overwritten - /// when the next message is stored to this location. - /// The flag is also set when the Tx Handler was not able to read a message from the Message - /// RAM in time. In this case message transmission is aborted. In case of a Tx Handler access - /// failure the FDCAN is switched into Restricted operation Mode (see Restricted operation - /// mode). - const MSG_RAM_ACCESS_FAILURE = 1<<14; - /// Timeout Occurred - const TIMEOUT_OCCURRED = 1<<15; - /// Overflow of CAN error logging counter occurred - const ERR_LOG_OVERFLOW = 1<<16; - /// Err Passive - const ERR_PASSIVE = 1<<17; - /// Warning Status - const WARNING_STATUS = 1<<18; - /// Bus_Off status - const BUS_OFF = 1<<19; - /// Watchdog interrupt - const WATCHDOG_INT = 1<<20; - /// Protocol error in arbitration phase (nominal bit time is used) - const PROT_ERR_ARBRITATION = 1<<21; - /// Protocol error in data phase (data bit time is used) - const PROT_ERR_DATA = 1<<22; - /// Access to reserved address - const RESERVED_ACCESS = 1<<23; - } -} - -impl Interrupts { - /// No Interrupt masks selected - pub fn none() -> Self { - Self::from_bits_truncate(0) - } -} - -impl From for Interrupts { - #[inline] - fn from(i: Interrupt) -> Self { - Self::from_bits_truncate(i as u32) - } -} - -/// Adds an interrupt to the interrupt set. -impl ops::BitOrAssign for Interrupts { - #[inline] - fn bitor_assign(&mut self, rhs: Interrupt) { - *self |= Self::from(rhs); - } -} - -/// There are two interrupt lines for the FdCan -/// The events linked to these can be configured -/// see `[config::FdCanConfig]` -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] -pub enum InterruptLine { - /// Interrupt Line 0 - _0 = 0, - /// Interrupt Line 1 - _1 = 1, -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn interrupt_flags() { - assert_eq!( - Interrupts::from(Interrupt::TxComplete), - Interrupts::TX_COMPLETE - ); - assert_eq!(Interrupts::from(Interrupt::TxEmpty), Interrupts::TX_EMPTY); - - let mut ints = Interrupts::RX_FIFO_0_FULL; - ints |= Interrupt::RxFifo1Full; - assert_eq!( - ints, - Interrupts::RX_FIFO_0_FULL | Interrupts::RX_FIFO_1_FULL - ); - } -} diff --git a/src/fdcan/message_ram/txbuffer_element.rs b/src/fdcan/message_ram/txbuffer_element.rs deleted file mode 100644 index 7afc74e2..00000000 --- a/src/fdcan/message_ram/txbuffer_element.rs +++ /dev/null @@ -1,407 +0,0 @@ -use super::common::{BRS_R, DLC_R, ESI_R, FDF_R, ID_R, RTR_R, XTD_R}; -use super::enums::{ - BitRateSwitching, DataLength, ErrorStateIndicator, Event, EventControl, FrameFormat, IdType, - RemoteTransmissionRequest, -}; -use super::generic; - -#[doc = "Reader of register TxBufferElement"] -pub(crate) type R = generic::R; -#[doc = "Writer for register TxBufferElement"] -pub(crate) type W = generic::W; -impl generic::ResetValue for super::TxBufferElementHeader { - type Type = super::TxBufferElementHeaderType; - - #[allow(dead_code)] - #[inline(always)] - fn reset_value() -> Self::Type { - [0; 2] - } -} - -#[doc = "Write proxy for field `ESI`"] -pub(crate) struct ESI_W<'a> { - w: &'a mut W, -} -impl<'a> ESI_W<'a> { - #[doc = r"Writes `variant` to the field"] - #[inline(always)] - #[allow(dead_code)] - pub fn set_error_indicator(self, esi: ErrorStateIndicator) -> &'a mut W { - self.bit(esi as u8 != 0) - } - - #[doc = r"Sets the field bit"] - #[inline(always)] - #[allow(dead_code)] - pub fn set_bit(self) -> &'a mut W { - self.bit(true) - } - #[doc = r"Clears the field bit"] - #[inline(always)] - #[allow(dead_code)] - pub fn clear_bit(self) -> &'a mut W { - self.bit(false) - } - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - #[allow(dead_code)] - pub fn bit(self, value: bool) -> &'a mut W { - self.w.bits[0] = (self.w.bits[0] & !(0x01 << 31)) | (((value as u32) & 0x01) << 31); - self.w - } -} - -#[doc = "Write proxy for field `XTD`"] -pub(crate) struct XTD_W<'a> { - w: &'a mut W, -} -impl<'a> XTD_W<'a> { - #[doc = r"Writes `variant` to the field"] - #[inline(always)] - #[allow(dead_code)] - pub fn set_id_type(self, idt: IdType) -> &'a mut W { - self.bit(idt as u8 != 0) - } - - #[doc = r"Sets the field bit"] - #[inline(always)] - #[allow(dead_code)] - pub fn set_bit(self) -> &'a mut W { - self.bit(true) - } - #[doc = r"Clears the field bit"] - #[inline(always)] - #[allow(dead_code)] - pub fn clear_bit(self) -> &'a mut W { - self.bit(false) - } - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - #[allow(dead_code)] - pub fn bit(self, value: bool) -> &'a mut W { - self.w.bits[0] = (self.w.bits[0] & !(0x01 << 30)) | (((value as u32) & 0x01) << 30); - self.w - } -} - -#[doc = "Write proxy for field `RTR`"] -pub(crate) struct RTR_W<'a> { - w: &'a mut W, -} -impl<'a> RTR_W<'a> { - #[doc = r"Writes `variant` to the field"] - #[inline(always)] - #[allow(dead_code)] - pub fn set_rtr(self, rtr: RemoteTransmissionRequest) -> &'a mut W { - self.bit(rtr as u8 != 0) - } - - #[doc = r"Sets the field bit"] - #[inline(always)] - #[allow(dead_code)] - pub fn set_bit(self) -> &'a mut W { - self.bit(true) - } - #[doc = r"Clears the field bit"] - #[inline(always)] - #[allow(dead_code)] - pub fn clear_bit(self) -> &'a mut W { - self.bit(false) - } - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - #[allow(dead_code)] - pub fn bit(self, value: bool) -> &'a mut W { - self.w.bits[0] = (self.w.bits[0] & !(0x01 << 29)) | (((value as u32) & 0x01) << 29); - self.w - } -} - -#[doc = "Write proxy for field `ID`"] -pub(crate) struct ID_W<'a> { - w: &'a mut W, -} -impl<'a> ID_W<'a> { - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - #[allow(dead_code)] - 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 `DLC`"] -pub(crate) struct DLC_W<'a> { - w: &'a mut W, -} -impl<'a> DLC_W<'a> { - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - #[allow(dead_code)] - pub unsafe fn bits(self, value: u8) -> &'a mut W { - self.w.bits[1] = (self.w.bits[1] & !(0x0F << 16)) | (((value as u32) & 0x0F) << 16); - self.w - } -} - -#[doc = "Write proxy for field `BRS`"] -pub(crate) struct BRS_W<'a> { - w: &'a mut W, -} -impl<'a> BRS_W<'a> { - #[doc = r"Writes `variant` to the field"] - #[inline(always)] - #[allow(dead_code)] - pub fn set_brs(self, brs: BitRateSwitching) -> &'a mut W { - self.bit(brs as u8 != 0) - } - - #[doc = r"Sets the field bit"] - #[inline(always)] - #[allow(dead_code)] - pub fn set_bit(self) -> &'a mut W { - self.bit(true) - } - #[doc = r"Clears the field bit"] - #[inline(always)] - #[allow(dead_code)] - pub fn clear_bit(self) -> &'a mut W { - self.bit(false) - } - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - #[allow(dead_code)] - pub fn bit(self, value: bool) -> &'a mut W { - self.w.bits[1] = (self.w.bits[1] & !(0x01 << 20)) | (((value as u32) & 0x01) << 20); - self.w - } -} - -#[doc = "Write proxy for field `FDF`"] -pub(crate) struct FDF_W<'a> { - w: &'a mut W, -} -impl<'a> FDF_W<'a> { - #[doc = r"Writes `variant` to the field"] - #[inline(always)] - #[allow(dead_code)] - pub fn set_format(self, fdf: FrameFormat) -> &'a mut W { - self.bit(fdf as u8 != 0) - } - - #[doc = r"Sets the field bit"] - #[inline(always)] - #[allow(dead_code)] - pub fn set_bit(self) -> &'a mut W { - self.bit(true) - } - #[doc = r"Clears the field bit"] - #[inline(always)] - #[allow(dead_code)] - pub fn clear_bit(self) -> &'a mut W { - self.bit(false) - } - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - #[allow(dead_code)] - pub fn bit(self, value: bool) -> &'a mut W { - self.w.bits[1] = (self.w.bits[1] & !(0x01 << 21)) | (((value as u32) & 0x01) << 21); - self.w - } -} - -#[doc = "Reader of field `EFC`"] -pub(crate) type EFC_R = generic::R; -impl EFC_R { - pub fn to_event_control(&self) -> EventControl { - match self.bit() { - false => EventControl::DoNotStore, - true => EventControl::Store, - } - } -} -#[doc = "Write proxy for field `EFC`"] -pub(crate) struct EFC_W<'a> { - w: &'a mut W, -} -impl<'a> EFC_W<'a> { - #[doc = r"Writes `variant` to the field"] - #[inline(always)] - #[allow(dead_code)] - pub fn set_event_control(self, efc: EventControl) -> &'a mut W { - self.bit(match efc { - EventControl::DoNotStore => false, - EventControl::Store => true, - }) - } - - #[doc = r"Sets the field bit"] - #[inline(always)] - #[allow(dead_code)] - pub fn set_bit(self) -> &'a mut W { - self.bit(true) - } - #[doc = r"Clears the field bit"] - #[inline(always)] - #[allow(dead_code)] - pub fn clear_bit(self) -> &'a mut W { - self.bit(false) - } - #[doc = r"Writes raw bits to the field"] - #[inline(always)] - #[allow(dead_code)] - pub fn bit(self, value: bool) -> &'a mut W { - self.w.bits[1] = (self.w.bits[1] & !(0x01 << 23)) | (((value as u32) & 0x01) << 23); - self.w - } -} - -struct Marker(u8); -impl From for Marker { - fn from(e: Event) -> Marker { - match e { - Event::NoEvent => Marker(0), - Event::Event(mm) => Marker(mm), - } - } -} - -#[doc = "Reader of field `MM`"] -pub(crate) type MM_R = generic::R; -#[doc = "Write proxy for field `MM`"] -pub(crate) struct MM_W<'a> { - w: &'a mut W, -} -impl<'a> MM_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[1] = (self.w.bits[1] & !(0x7F << 24)) | (((value as u32) & 0x7F) << 24); - self.w - } - - fn set_message_marker(self, mm: Marker) -> &'a mut W { - unsafe { self.bits(mm.0) } - } -} - -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 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 23 - EFC"] - #[inline(always)] - pub fn efc(&self) -> EFC_R { - EFC_R::new(((self.bits[1] >> 23) & 0x01) != 0) - } - #[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) - } - 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_event(&self) -> Event { - let mm = self.mm().bits(); - let efc = self.efc().to_event_control(); - match efc { - EventControl::DoNotStore => Event::NoEvent, - EventControl::Store => Event::Event(mm), - } - } -} -impl W { - #[doc = "Byte 0 - Bits 0:28 - ID"] - #[inline(always)] - pub fn id(&mut self) -> ID_W { - ID_W { w: self } - } - #[doc = "Byte 0 - Bit 29 - RTR"] - #[inline(always)] - pub fn rtr(&mut self) -> RTR_W { - RTR_W { w: self } - } - #[doc = "Byte 0 - Bit 30 - XTD"] - #[inline(always)] - pub fn xtd(&mut self) -> XTD_W { - XTD_W { w: self } - } - #[doc = "Byte 0 - Bit 31 - ESI"] - #[inline(always)] - pub fn esi(&mut self) -> ESI_W { - ESI_W { w: self } - } - #[doc = "Byte 1 - Bit 16:19 - DLC"] - #[inline(always)] - pub fn dlc(&mut self) -> DLC_W { - DLC_W { w: self } - } - #[doc = "Byte 1 - Bit 20 - BRS"] - #[inline(always)] - pub fn brs(&mut self) -> BRS_W { - BRS_W { w: self } - } - #[doc = "Byte 1 - Bit 21 - FDF"] - #[inline(always)] - pub fn fdf(&mut self) -> FDF_W { - FDF_W { w: self } - } - #[doc = "Byte 1 - Bit 23 - EFC"] - #[inline(always)] - pub fn efc(&mut self) -> EFC_W { - EFC_W { w: self } - } - #[doc = "Byte 1 - Bit 24:31 - MM"] - #[inline(always)] - pub fn mm(&mut self) -> MM_W { - MM_W { w: self } - } - #[doc = "Convenience function for setting the data length and frame format"] - #[inline(always)] - pub fn set_len(&mut self, dl: impl Into) -> &mut Self { - let dl: DataLength = dl.into(); - self.fdf().set_format(dl.into()); - unsafe { self.dlc().bits(dl.dlc()) } - } - pub fn set_event(&mut self, event: Event) -> &mut Self { - self.mm().set_message_marker(event.into()); - self.efc().set_event_control(event.into()) - } -} diff --git a/src/lib.rs b/src/lib.rs index 93c12d07..d274d5ae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,6 +67,8 @@ pub use stm32g4::stm32g491 as stm32; #[cfg(feature = "stm32g4a1")] pub use stm32g4::stm32g4a1 as stm32; +pub use stm32 as pac; + #[cfg(feature = "rt")] pub use crate::stm32::interrupt; diff --git a/src/rcc/mod.rs b/src/rcc/mod.rs index 9030093e..4e32dd63 100644 --- a/src/rcc/mod.rs +++ b/src/rcc/mod.rs @@ -16,6 +16,7 @@ pub const HSI_FREQ: u32 = 16_000_000; /// Clock frequencies #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Clocks { /// System frequency pub sys_clk: Hertz, @@ -37,6 +38,7 @@ pub struct Clocks { /// PLL Clock frequencies #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PLLClocks { /// R frequency pub r: Option,