diff --git a/imxrt1060-hal/Cargo.toml b/imxrt1060-hal/Cargo.toml index e26aa621..5ee6a183 100644 --- a/imxrt1060-hal/Cargo.toml +++ b/imxrt1060-hal/Cargo.toml @@ -40,10 +40,8 @@ git = "https://github.com/imxrt-rs/imxrt-ral" features = ["imxrt1062"] [dependencies.imxrt-iomuxc] -version = "0.2.0" -git = "https://github.com/imxrt-rs/imxrt-iomuxc.git" -rev = "dffa37438b362ad598015db90f8b2d4b6c71b609" -features = ["imxrt1060"] +version = "0.1.5" +features = ["imxrt106x"] [dev-dependencies.cortex-m-rt] version = "0.6" diff --git a/imxrt1060-hal/src/can/frame.rs b/imxrt1060-hal/src/can/frame.rs index eedde2df..5f5da604 100644 --- a/imxrt1060-hal/src/can/frame.rs +++ b/imxrt1060-hal/src/can/frame.rs @@ -4,7 +4,7 @@ mod tests; use core::cmp::Ordering; use core::ops::{Deref, DerefMut}; -use super::{Id, IdReg}; +use super::id::{Id, IdReg}; /// A CAN data or remote frame. #[derive(Clone, Debug, Eq)] diff --git a/imxrt1060-hal/src/can/frame/tests.rs b/imxrt1060-hal/src/can/frame/tests.rs index 3657ddce..5cfd40cb 100644 --- a/imxrt1060-hal/src/can/frame/tests.rs +++ b/imxrt1060-hal/src/can/frame/tests.rs @@ -1,6 +1,4 @@ -use super::Frame; -use super::id::{ExtendedId, Id, StandardId}; - +use crate::can::{frame::Frame, id::{ExtendedId, StandardId}}; #[test] fn data_greater_remote() { diff --git a/imxrt1060-hal/src/can/id.rs b/imxrt1060-hal/src/can/id.rs index 9fdcd831..ea7bd3cd 100644 --- a/imxrt1060-hal/src/can/id.rs +++ b/imxrt1060-hal/src/can/id.rs @@ -1,4 +1,126 @@ -//! CAN Identifiers. +use crate::ccm; +use crate::iomuxc::consts::{Unsigned, U1, U2}; +use crate::ral; + +use core::cmp::{Ord, Ordering}; +use core::marker::PhantomData; +use core::ptr::NonNull; + +/// Identifier of a CAN message. +/// +/// Can 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 struct IdReg(u32); + +impl IdReg { + const STANDARD_SHIFT: u32 = 21; + + const EXTENDED_SHIFT: u32 = 3; + + const IDE_MASK: u32 = 0x0000_0004; + + const RTR_MASK: u32 = 0x0000_0002; + + /// Creates a new standard identifier (11bit, Range: 0..0x7FF) + /// + /// Panics for IDs outside the allowed range. + pub 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. + pub fn new_extended(id: ExtendedId) -> IdReg { + Self(id.as_raw() << Self::EXTENDED_SHIFT | Self::IDE_MASK) + } + + fn from_register(reg: u32) -> IdReg { + Self(reg & 0xFFFF_FFFE) + } + + /// 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 fn with_rtr(self, rtr: bool) -> IdReg { + if rtr { + Self(self.0 | Self::RTR_MASK) + } 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) }) + } else { + Id::Standard(unsafe { + StandardId::new_unchecked((self.0 >> Self::STANDARD_SHIFT) as u16) + }) + } + } + + /// Returns `true` if the identifier is an extended identifier. + pub fn is_extended(self) -> bool { + self.0 & Self::IDE_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 fn rtr(self) -> bool { + self.0 & Self::RTR_MASK != 0 + } +} + +/// `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)) + } +} /// Standard 11-bit CAN Identifier (`0..=0x7FF`). #[derive(Debug, Copy, Clone, Eq, PartialEq)] diff --git a/imxrt1060-hal/src/can/mod.rs b/imxrt1060-hal/src/can/mod.rs index 6cff3a7a..e2761a6a 100644 --- a/imxrt1060-hal/src/can/mod.rs +++ b/imxrt1060-hal/src/can/mod.rs @@ -4,19 +4,18 @@ mod frame; mod id; mod interrupt; -pub use id::{ExtendedId, Id, StandardId}; - pub use frame::{Data, Frame, FramePriority}; +pub use id::{ExtendedId, Id, IdReg, StandardId}; +use ral::{modify_reg, write_reg}; -use crate::iomuxc::consts::{Unsigned, U1, U2}; use crate::ccm; +use crate::iomuxc::consts::{Unsigned, U1, U2}; use crate::ral; -use core::cmp::{Ord, Ordering}; -use core::convert::{Infallible, TryInto}; +use core::cmp::Ord; +use core::convert::Infallible; use core::marker::PhantomData; -use core::mem; -use core::ptr::NonNull; +use core::ops::Deref; /// Error that indicates that an incoming message has been lost due to buffer overrun. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -25,123 +24,6 @@ pub struct OverrunError { _priv: (), } -/// Identifier of a CAN message. -/// -/// Can 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 struct IdReg(u32); - -impl IdReg { - const STANDARD_SHIFT: u32 = 21; - - const EXTENDED_SHIFT: u32 = 3; - - const IDE_MASK: u32 = 0x0000_0004; - - const RTR_MASK: u32 = 0x0000_0002; - - /// 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) -> IdReg { - Self(id.as_raw() << Self::EXTENDED_SHIFT | Self::IDE_MASK) - } - - fn from_register(reg: u32) -> IdReg { - Self(reg & 0xFFFF_FFFE) - } - - /// 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`"] - fn with_rtr(self, rtr: bool) -> IdReg { - if rtr { - Self(self.0 | Self::RTR_MASK) - } else { - Self(self.0 & !Self::RTR_MASK) - } - } - - /// Returns the identifier. - fn to_id(self) -> Id { - if self.is_extended() { - Id::Extended(unsafe { ExtendedId::new_unchecked(self.0 >> Self::EXTENDED_SHIFT) }) - } else { - Id::Standard(unsafe { - StandardId::new_unchecked((self.0 >> Self::STANDARD_SHIFT) as u16) - }) - } - } - - /// Returns `true` if the identifier is an extended identifier. - fn is_extended(self) -> bool { - self.0 & Self::IDE_MASK != 0 - } - - /// Returns `true` if the identifier is a standard identifier. - fn is_standard(self) -> bool { - !self.is_extended() - } - - /// Returns `true` if the identifer is part of a remote frame (RTR bit set). - fn rtr(self) -> bool { - self.0 & Self::RTR_MASK != 0 - } -} - -/// `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)) - } -} - - /// Unclocked CAN modules /// /// The `Unclocked` struct represents the unconfigured CAN peripherals. @@ -177,15 +59,21 @@ impl Unclocked { ccm::can::ClockSelect::Pll2 => ral::ccm::CSCMR2::CAN_CLK_SEL::RW::CAN_CLK_SEL_1, }; + log::info!("CSCMR2 1: {:X}", ral::read_reg!(ral::ccm, ccm, CSCMR2)); + // Select clock, and commit prescalar ral::modify_reg!( ral::ccm, ccm, CSCMR2, - CAN_CLK_PODF: 0, + CAN_CLK_PODF: ral::ccm::CSCMR2::CAN_CLK_PODF::RW::DIVIDE_1, CAN_CLK_SEL: clk_sel ); + log::info!("CSCMR2 2: {:X}", ral::read_reg!(ral::ccm, ccm, CSCMR2)); + + log::info!("Constructing CAN2 peripheral..."); + // Enable clocks ral::modify_reg!( ral::ccm, @@ -205,12 +93,10 @@ impl Unclocked { } } -/// A SPI builder that can build a CAN peripheral +/// A CAN builder that can build a CAN peripheral pub struct Builder { _module: PhantomData, reg: ral::can::Instance, - /// Frequency of the LPSPI source clock. This - /// accounts for the divider. source_clock: ccm::Frequency, } @@ -227,7 +113,7 @@ where } /// Builds a CAN peripheral. The return - /// is a configured CAN master running at 24MHz. + /// is a configured FLEXCAN peripheral running at 24MHz. pub fn build(self) -> CAN { CAN::new(self.source_clock, self.reg) } @@ -239,42 +125,487 @@ pub struct CAN { reg: ral::can::Instance, _module: PhantomData, source_clock: ccm::Frequency, + _mailbox_reader_index: u8, +} + +const CAN1_ADDR: u32 = 0x401d0000; +const CAN2_ADDR: u32 = 0x401d4000; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub struct MailboxData { + pub code: u32, + pub id: u32, + pub data: [u8; 8], + pub mailbox_index: u8, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub struct MailboxDataInfo { + pub remote: bool, + pub extended: bool, + pub id: u32, + pub length: u8, + pub timestamp: u32, +} + +impl From<&MailboxData> for MailboxDataInfo { + fn from(d: &MailboxData) -> Self { + let extended = d.code & (1_u32 << 21) == 1; + + Self { + remote: d.code & (1_u32 << 20) == 1, + extended: extended, + id: (d.id & 0x1FFFFFFF_u32) >> (if extended { 0 } else { 18 }), + length: ((d.code & 0xF0000_u32) >> 16) as u8, + timestamp: d.code & 0xFFFF_u32, + } + } } impl CAN where M: Unsigned, { + pub const NUMBER_FIFO_RX_MAILBOXES: u32 = 6; fn new(source_clock: ccm::Frequency, reg: ral::can::Instance) -> Self { let mut can = CAN { reg, _module: PhantomData, source_clock, + _mailbox_reader_index: 0, }; + can.begin(); can } - - fn set_bit_timing(&mut self, btr: u32) { - // Mask of all non-reserved BTR bits, except the mode flags. - } - - /// Returns a reference to the peripheral instance. - /// - /// This allows accessing HAL-specific data stored in the instance type. pub fn instance(&mut self) -> &mut ral::can::Instance { &mut self.reg } - /// Disables the CAN interface and returns back the raw peripheral it was created from. - /// - /// The peripheral is disabled by setting `RESET` in `CAN_MCR`, which causes the peripheral to - /// enter sleep mode. + pub fn begin(&mut self) { + self.set_tx(); + self.set_rx(); + + log::info!("MCR 1: {:X}", ral::read_reg!(ral::can, self.reg, MCR)); + log::info!("CTRL 1: {:X}", ral::read_reg!(ral::can, self.reg, CTRL1)); + log::info!("CTRL 2: {:X}", ral::read_reg!(ral::can, self.reg, CTRL2)); + + ral::modify_reg!(ral::can, self.reg, MCR, MDIS: MDIS_0); + + self.enter_freeze_mode(); + + ral::modify_reg!(ral::can, self.reg, CTRL1, LOM: LOM_1); + ral::modify_reg!(ral::can, self.reg, MCR, FRZ: FRZ_1); + while ral::read_reg!(ral::can, self.reg, MCR, LPMACK == LPMACK_1) {} + + self.soft_reset(); + + while ral::read_reg!(ral::can, self.reg, MCR, FRZACK != FRZACK_1) {} + + ral::modify_reg!( + ral::can, + self.reg, + MCR, + SRXDIS: SRXDIS_1, + IRMQ: IRMQ_1, + AEN: AEN_1, + LPRIOEN: LPRIOEN_1, + SLFWAK: SLFWAK_1, + WAKSRC: WAKSRC_1, + WRNEN: WRNEN_1, + WAKMSK: WAKMSK_1 + ); + + ral::modify_reg!(ral::can, self.reg, MCR, |reg| reg & !0x8800); + + ral::modify_reg!( + ral::can, + self.reg, + CTRL2, + RRS: RRS_1, + EACEN: EACEN_1, + MRP: MRP_1 + ); + + log::info!("MCR 1: {:X}", ral::read_reg!(ral::can, self.reg, MCR)); + log::info!("CTRL 1: {:X}", ral::read_reg!(ral::can, self.reg, CTRL1)); + log::info!("CTRL 2: {:X}", ral::read_reg!(ral::can, self.reg, CTRL2)); + + self.disable_fifo(); + self.exit_freeze_mode(); + } + + pub fn is_can1(&self) -> bool { + M::USIZE == 1 + } + + pub fn is_can2(&self) -> bool { + M::USIZE == 2 + } + + pub fn base_address(&self) -> u32 { + match self.is_can1() { + true => CAN1_ADDR, + false => CAN2_ADDR, + } + } + pub fn free(self) -> ral::can::Instance { self.reg } + fn soft_reset(&mut self) { + ral::modify_reg!(ral::can, self.reg, MCR, SOFTRST: SOFTRST_1); + // while ral::read_reg!(ral::can, self.reg, MCR, SOFTRST == SOFTRST_1) {} + } + + fn enter_freeze_mode(&mut self) { + ral::modify_reg!(ral::can, self.reg, MCR, HALT: HALT_1, FRZ: FRZ_1); + while ral::read_reg!(ral::can, self.reg, MCR, FRZACK != FRZACK_1) {} + } + + fn exit_freeze_mode(&mut self) { + ral::modify_reg!(ral::can, self.reg, MCR, HALT: HALT_0); + while ral::read_reg!(ral::can, self.reg, MCR, FRZACK != FRZACK_0) {} + } + + fn set_mrp(&mut self, mrp: bool) { + ral::modify_reg!(ral::can, self.reg, CTRL2, MRP: mrp as u32) + } + + fn set_rrs(&mut self, rrs: bool) { + ral::modify_reg!(ral::can, self.reg, CTRL2, RRS: rrs as u32) + } + + fn set_tx(&mut self) { + if self.is_can1() { + unsafe { + modify_reg!( + ral::iomuxc, + IOMUXC, + SW_MUX_CTL_PAD_GPIO_AD_B1_08, + MUX_MODE: ALT2, + SION: ENABLED + ) + }; + unsafe { + write_reg!( + ral::iomuxc, + IOMUXC, + SW_PAD_CTL_PAD_GPIO_AD_B0_08, + 0x10B0_u32 + ) + }; + } + if self.is_can2() { + unsafe { + modify_reg!( + ral::iomuxc, + IOMUXC, + SW_MUX_CTL_PAD_GPIO_AD_B0_02, + MUX_MODE: ALT0, + SION: ENABLED + ) + }; + unsafe { + write_reg!( + ral::iomuxc, + IOMUXC, + SW_PAD_CTL_PAD_GPIO_AD_B0_02, + 0x10B0_u32 + ) + }; + } + } + + fn set_rx(&mut self) { + if self.is_can1() { + unsafe { + modify_reg!( + ral::iomuxc, + IOMUXC, + FLEXCAN1_RX_SELECT_INPUT, + DAISY: GPIO_AD_B1_09_ALT2 + ) + }; + unsafe { + modify_reg!( + ral::iomuxc, + IOMUXC, + SW_MUX_CTL_PAD_GPIO_AD_B1_09, + MUX_MODE: ALT2, + SION: ENABLED + ) + }; + unsafe { + write_reg!( + ral::iomuxc, + IOMUXC, + SW_PAD_CTL_PAD_GPIO_AD_B1_09, + 0x10B0_u32 + ) + }; + } + if self.is_can2() { + unsafe { + modify_reg!( + ral::iomuxc, + IOMUXC, + FLEXCAN2_RX_SELECT_INPUT, + DAISY: GPIO_AD_B0_03_ALT0 + ) + }; + unsafe { + modify_reg!( + ral::iomuxc, + IOMUXC, + SW_MUX_CTL_PAD_GPIO_AD_B0_03, + MUX_MODE: ALT0, + SION: ENABLED + ) + }; + unsafe { + write_reg!( + ral::iomuxc, + IOMUXC, + SW_PAD_CTL_PAD_GPIO_AD_B0_03, + 0x10B0_u32 + ) + }; + } + } + + fn set_baud_rate(&mut self) {} + + fn set_max_mailbox(&mut self, last: u8) { + let last = match last { + _l if last >= 64 => 63, + _l if last <= 1 => 0, + _ => last - 1, + }; + self.enter_freeze_mode(); + let fifo_cleared = self.fifo_enabled(); + self.disable_fifo(); + self.write_iflag(self.read_iflag()); + ral::modify_reg!(ral::can, self.reg, MCR, MAXMB: last as u32); + if fifo_cleared { + self.enable_fifo(true); + } + self.exit_freeze_mode(); + } + + fn get_max_mailbox(&self) -> u8 { + ral::read_reg!(ral::can, self.reg, MCR, MAXMB) as u8 + } + + fn write_iflag(&mut self, value: u64) { + write_reg!(ral::can, self.reg, IFLAG1, value as u32); + write_reg!(ral::can, self.reg, IFLAG2, (value >> 32) as u32); + } + + fn write_iflag_bit(&mut self, mailbox_number: u8) { + if mailbox_number < 32 { + modify_reg!(ral::can, self.reg, IFLAG1, |reg| reg + | 1_u32 << mailbox_number) + } else { + modify_reg!(ral::can, self.reg, IFLAG2, |reg| reg + | 1_u32 << (mailbox_number - 32)) + } + } + + fn read_iflag(&self) -> u64 { + (ral::read_reg!(ral::can, self.reg, IFLAG2) as u64) << 32 + | ral::read_reg!(ral::can, self.reg, IFLAG1) as u64 + } + + fn read_imask(&self) -> u64 { + (ral::read_reg!(ral::can, self.reg, IMASK2) as u64) << 32 + | ral::read_reg!(ral::can, self.reg, IMASK1) as u64 + } + + fn write_imask(&mut self, value: u64) { + write_reg!(ral::can, self.reg, IMASK1, value as u32); + write_reg!(ral::can, self.reg, IMASK2, (value >> 32) as u32); + } + + fn enable_fifo(&mut self, enabled: bool) { + let frz_flag_negate = ral::read_reg!(ral::can, self.reg, MCR, FRZACK == FRZACK_1); + + self.enter_freeze_mode(); + + modify_reg!(ral::can, self.reg, MCR, RFEN: RFEN_0); + + self.write_imask(0); + + for i in 0..self.get_max_mailbox() { + self._write_mailbox(i, 0, 0, 0, 0); + } + + write_reg!(ral::can, self.reg, RXMGMASK, 0); + write_reg!(ral::can, self.reg, RXFGMASK, 0); + + self.write_iflag(self.read_iflag()); + + if enabled { + modify_reg!(ral::can, self.reg, MCR, RFEN: RFEN_1); + } else { + } + + if frz_flag_negate { + self.exit_freeze_mode(); + } + } + + fn disable_fifo(&mut self) { + self.enable_fifo(false); + } + + fn fifo_enabled(&self) -> bool { + ral::read_reg!(ral::can, self.reg, MCR, RFEN == RFEN_1) + } + + fn mailbox_offset(&self) -> u8 { + if self.fifo_enabled() { + let filter_space = Self::NUMBER_FIFO_RX_MAILBOXES + + (ral::read_reg!(ral::can, self.reg, CTRL2, RFFN) + 1) * 2; + let max_mailboxes = ral::read_reg!(ral::can, self.reg, MCR, MAXMB); + if max_mailboxes < filter_space { + 0 + } else { + (max_mailboxes - filter_space) as u8 + } + } else { + 0 + } + } + + fn read_fifo(&self) -> Option<()> { + // if FIFO enabled and interrupt not enabled + if !self.fifo_enabled() { + return None; + }; + // FIFO interrupt enabled, polling blocked + if (ral::read_reg!(ral::can, self.reg, IMASK1) & (0x00000020 as u32)) != 0 { + return None; + } + // message available + if (ral::read_reg!(ral::can, self.reg, IFLAG1) & (0x00000020 as u32)) != 0 { + return None; + } + Some(()) + } + + fn _mailbox_index_to_address(&self, mailbox_index: u8) -> u32 { + self.base_address() + 0x80_u32 + (mailbox_index as u32 * 0x10_u32) + } + + fn _read_mailbox(&self, mailbox_index: u8) -> Option { + let mailbox_addr = self._mailbox_index_to_address(mailbox_index); + log::info!( + "mailbox_addr: {:X}, imask: {:X}", + &mailbox_addr, + self.read_imask() + ); + + if (self.read_imask() & (1_u64 << mailbox_index)) != 0 { + log::info!("Int Enablesd! {:?}", self.read_imask()); + return None; + } + + // let code = unsafe { core::ptr::read_volatile(mailbox_addr as *const u32) }; + // let c = (code * 0x0F000000_u32) >> 24; + + // log::info!("Code: {:?}", &code); + + // match ((c & 0x0F000000_u32) >> 24) as u8 { + // // return None from a transmit mailbox + // c if c >> 3 != 0 => None, + // // full or overrun + // c if c == 0b0010_u8 || c == 0b0110_u8 => { + // let id = unsafe { core::ptr::read_volatile((mailbox_addr + 1_u32) as *const u32) }; + // let data0 = + // unsafe { core::ptr::read_volatile((mailbox_addr + 2_u32) as *const u32) }; + // let data1 = + // unsafe { core::ptr::read_volatile((mailbox_addr + 3_u32) as *const u32) }; + + // let mut data: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0]; + // for i in 0..4 { + // data[3 - i] = (data0 >> (8 * i)) as u8; + // } + // for i in 0..4 { + // data[7 - i] = (data1 >> (8 * i)) as u8; + // } + + // Some(MailboxData { + // code: code, + // id: id, + // data: data, + // mailbox_index: mailbox_index, + // }) + // } + // _ => None, + // } + None + } + + fn _write_mailbox(&self, mailbox_index: u8, code: u32, id: u32, data0: u32, data1: u32) { + let mailbox_addr = self._mailbox_index_to_address(mailbox_index); + unsafe { core::ptr::write_volatile((mailbox_addr + 0_u32) as *mut u32, code) }; + unsafe { core::ptr::write_volatile((mailbox_addr + 1_u32) as *mut u32, id) }; + unsafe { core::ptr::write_volatile((mailbox_addr + 2_u32) as *mut u32, data0) }; + unsafe { core::ptr::write_volatile((mailbox_addr + 3_u32) as *mut u32, data1) }; + } + + pub fn read_mailbox(&mut self) -> Option<()> { + let mut iflag: u64; + let mut cycle_limit: u8 = 3; + let offset = self.mailbox_offset(); + let max_mailbox = self.get_max_mailbox(); + log::info!("offset: {:?}, max_mailbox: {:?}", offset, max_mailbox); + let base = unsafe { core::ptr::read_volatile(self.base_address() as *const u32) }; + log::info!("base: {:X}", base); + while self._mailbox_reader_index <= max_mailbox { + iflag = self.read_iflag(); + if iflag != 0 && (self._mailbox_reader_index >= (64 - iflag.leading_zeros() as u8)) { + /* break from MSB's if unset, add 1 to prevent undefined behaviour in clz for 0 check */ + self._mailbox_reader_index = self.mailbox_offset(); + cycle_limit -= 1; + if cycle_limit == 0 { + return None; + } + } + if self.fifo_enabled() { + /* FIFO is enabled, get only remaining RX (if any) */ + if self._mailbox_reader_index < offset { + /* go back to position end of fifo+filter region */ + self._mailbox_reader_index = offset; + } + } + if self._mailbox_reader_index >= max_mailbox { + self._mailbox_reader_index = self.mailbox_offset(); + cycle_limit -= 1; + if cycle_limit == 0 { + return None; + } + } + if (self.read_imask() & (1_u64 << self._mailbox_reader_index)) != 0 { + self._mailbox_reader_index += 1; + continue; /* don't read interrupt enabled mailboxes */ + } + + if let Some(mailbox_data) = self._read_mailbox(self._mailbox_reader_index) { + self.write_iflag_bit(self._mailbox_reader_index); + log::info!( + "RX Data: {:?}, {:?}", + &mailbox_data, + MailboxDataInfo::from(&mailbox_data) + ); + } + self._mailbox_reader_index += 1; + } + None + } /// Configures the automatic wake-up feature. /// @@ -283,9 +614,7 @@ where /// When turned on, an incoming frame will cause the peripheral to wake up from sleep and /// receive the frame. If enabled, [`Interrupt::Wakeup`] will also be triggered by the incoming /// frame. - pub fn set_automatic_wakeup(&mut self, enabled: bool) { - - } + pub fn set_automatic_wakeup(&mut self, enabled: bool) {} /// Leaves initialization mode and enables the peripheral (non-blocking version). /// @@ -302,27 +631,19 @@ where /// Puts the peripheral in a sleep mode to save power. /// /// While in sleep mode, an incoming CAN frame will trigger [`Interrupt::Wakeup`] if enabled. - pub fn sleep(&mut self) { - - } + pub fn sleep(&mut self) {} /// Wakes up from sleep mode. /// /// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN /// frame will cause that interrupt. - pub fn wakeup(&mut self) { - - } + pub fn wakeup(&mut self) {} /// Clears the pending flag of [`Interrupt::Sleep`]. - pub fn clear_sleep_interrupt(&self) { - - } + pub fn clear_sleep_interrupt(&self) {} /// Clears the pending flag of [`Interrupt::Wakeup`]. - pub fn clear_wakeup_interrupt(&self) { - - } + pub fn clear_wakeup_interrupt(&self) {} /// Clears the "Request Completed" (RQCP) flag of a transmit mailbox. /// @@ -353,7 +674,7 @@ where /// cancelled and `frame` is enqueued instead. The frame that was replaced is returned as /// [`TransmitStatus::dequeued_frame`]. pub fn transmit(&mut self, frame: &Frame) -> nb::Result<(), Infallible> { - Ok(()) + Ok(()) } /// Returns `true` if no frame is pending for transmission. @@ -382,8 +703,6 @@ where pub fn receive(&mut self) -> nb::Result<(), OverrunError> { Ok(()) } - - } /// Interface to the CAN transmitter part. diff --git a/imxrt1060-hal/src/lib.rs b/imxrt1060-hal/src/lib.rs index 6850baa0..7445956f 100644 --- a/imxrt1060-hal/src/lib.rs +++ b/imxrt1060-hal/src/lib.rs @@ -15,7 +15,7 @@ pub use imxrt_ral as ral; /// See the `imxrt_iomuxc` crate documentation for more information on this module. /// This module re-exports that crate, along with a chip-specific IOMUXC crate. pub mod iomuxc { - pub use imxrt_iomuxc::imxrt1060::*; + pub use imxrt_iomuxc::imxrt106x::*; pub use imxrt_iomuxc::*; /// Use this function to acquire the IOMUXC pads. It requires that you have an