From ae8467a6dd5b1cebeeb75e9556e23e40162b67ab Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 14 Feb 2025 15:23:04 +0100 Subject: [PATCH] HAL update --- board-tests/src/main.rs | 15 +- va108xx-hal/CHANGELOG.md | 10 ++ va108xx-hal/Cargo.toml | 2 +- va108xx-hal/src/gpio/pin.rs | 9 +- va108xx-hal/src/i2c.rs | 281 +----------------------------------- va108xx-hal/src/lib.rs | 3 +- va108xx-hal/src/spi.rs | 7 + 7 files changed, 31 insertions(+), 296 deletions(-) diff --git a/board-tests/src/main.rs b/board-tests/src/main.rs index 3b91589..7f9d71c 100644 --- a/board-tests/src/main.rs +++ b/board-tests/src/main.rs @@ -137,15 +137,12 @@ fn main() -> ! { } } TestCase::DelayGpio => { - let mut out_0 = pinsa - .pa0 - .into_readable_push_pull_output() - .configure_delay(true, false); - let mut out_1 = pinsa - .pa1 - .into_readable_push_pull_output() - .configure_delay(false, true); - let mut out_2 = pinsa.pa3.into_readable_push_pull_output().configure_delay(true, true); + let mut out_0 = pinsa.pa0.into_readable_push_pull_output(); + out_0.configure_delay(true, false); + let mut out_1 = pinsa.pa1.into_readable_push_pull_output(); + out_1.configure_delay(false, true); + let mut out_2 = pinsa.pa3.into_readable_push_pull_output(); + out_2.configure_delay(true, true); for _ in 0..20 { out_0.toggle().unwrap(); out_1.toggle().unwrap(); diff --git a/va108xx-hal/CHANGELOG.md b/va108xx-hal/CHANGELOG.md index d8f35fb..cd01c09 100644 --- a/va108xx-hal/CHANGELOG.md +++ b/va108xx-hal/CHANGELOG.md @@ -8,6 +8,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [unreleased] +## [v0.10.0] + +## Added + +- A lot of missing `defmt::Format` implementations. + +## Changed + +- Missing GPIO API replacements from `x` to `configure_x` + ## [v0.9.0] ## Fixed diff --git a/va108xx-hal/Cargo.toml b/va108xx-hal/Cargo.toml index 26ea489..6209983 100644 --- a/va108xx-hal/Cargo.toml +++ b/va108xx-hal/Cargo.toml @@ -42,7 +42,7 @@ portable-atomic = "1" [features] default = ["rt"] rt = ["va108xx/rt"] -defmt = ["dep:defmt", "fugit/defmt"] +defmt = ["dep:defmt", "fugit/defmt", "embedded-hal/defmt-03"] [package.metadata.docs.rs] all-features = true diff --git a/va108xx-hal/src/gpio/pin.rs b/va108xx-hal/src/gpio/pin.rs index b8b1842..14ab13b 100644 --- a/va108xx-hal/src/gpio/pin.rs +++ b/va108xx-hal/src/gpio/pin.rs @@ -486,11 +486,6 @@ impl Pin { self.inner.regs.write_pin(false) } - #[inline] - pub(crate) fn _toggle_with_toggle_reg(&mut self) { - self.inner.regs.toggle(); - } - #[inline] pub(crate) fn _is_low(&self) -> bool { !self.inner.regs.read_pin() @@ -626,13 +621,13 @@ impl Pin> { /// - Delay 2: 2 /// - Delay 1 + Delay 2: 3 #[inline] - pub fn configure_delay(&mut self, delay_1: bool, delay_2: bool) { + pub fn configure_delay(&mut self, delay_1: bool, delay_2: bool) { self.inner.regs.configure_delay(delay_1, delay_2); } #[inline] pub fn toggle_with_toggle_reg(&mut self) { - self._toggle_with_toggle_reg() + self.inner.regs.toggle() } #[deprecated( diff --git a/va108xx-hal/src/i2c.rs b/va108xx-hal/src/i2c.rs index e33e93f..4ed9373 100644 --- a/va108xx-hal/src/i2c.rs +++ b/va108xx-hal/src/i2c.rs @@ -36,8 +36,6 @@ pub struct InvalidTimingParamsError; #[derive(Debug, PartialEq, Eq, thiserror::Error)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { - //#[error("Invalid timing parameters")] - //InvalidTimingParams, #[error("arbitration lost")] ArbitrationLost, #[error("nack address")] @@ -82,6 +80,7 @@ impl embedded_hal::i2c::Error for Error { } #[derive(Debug, PartialEq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] enum I2cCmd { Start = 0b00, Stop = 0b10, @@ -252,6 +251,8 @@ impl Default for MasterConfig { impl Sealed for MasterConfig {} +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SlaveConfig { pub tx_fe_mode: FifoEmptyMode, pub rx_fe_mode: FifoEmptyMode, @@ -455,13 +456,6 @@ impl I2cBase { } } -// Unique mode to use the loopback functionality -// pub struct I2cLoopback { -// i2c_base: I2cBase, -// master_cfg: MasterConfig, -// slave_cfg: SlaveConfig, -// } - //================================================================================================== // I2C Master //================================================================================================== @@ -673,275 +667,6 @@ impl I2cMaster { } } -/* -macro_rules! i2c_master { - ($($I2CX:path: ($i2cx:ident, $clk_enb:path),)+) => { - $( - impl I2cMaster<$I2CX, ADDR> { - pub fn $i2cx( - i2c: $I2CX, - cfg: MasterConfig, - sys_clk: impl Into + Copy, - speed_mode: I2cSpeed, - sys_cfg: Option<&mut pac::Sysconfig>, - ) -> Self { - I2cMaster { - i2c_base: I2cBase::$i2cx( - i2c, - sys_clk, - speed_mode, - Some(&cfg), - None, - sys_cfg - ), - _addr: PhantomData, - } - .enable_master() - } - - #[inline] - pub fn cancel_transfer(&self) { - self.i2c_base - .i2c - .cmd() - .write(|w| unsafe { w.bits(I2cCmd::Cancel as u32) }); - } - - #[inline] - pub fn clear_tx_fifo(&self) { - self.i2c_base.i2c.fifo_clr().write(|w| w.txfifo().set_bit()); - } - - #[inline] - pub fn clear_rx_fifo(&self) { - self.i2c_base.i2c.fifo_clr().write(|w| w.rxfifo().set_bit()); - } - - #[inline] - pub fn enable_master(self) -> Self { - self.i2c_base.i2c.ctrl().modify(|_, w| w.enable().set_bit()); - self - } - - #[inline] - pub fn disable_master(self) -> Self { - self.i2c_base.i2c.ctrl().modify(|_, w| w.enable().clear_bit()); - self - } - - #[inline(always)] - fn load_fifo(&self, word: u8) { - self.i2c_base - .i2c - .data() - .write(|w| unsafe { w.bits(word as u32) }); - } - - #[inline(always)] - fn read_fifo(&self) -> u8 { - self.i2c_base.i2c.data().read().bits() as u8 - } - - fn error_handler_write(&mut self, init_cmd: &I2cCmd) { - self.clear_tx_fifo(); - if *init_cmd == I2cCmd::Start { - self.i2c_base.stop_cmd() - } - } - - fn write_base( - &mut self, - addr: I2cAddress, - init_cmd: I2cCmd, - bytes: impl IntoIterator, - ) -> Result<(), Error> { - let mut iter = bytes.into_iter(); - // Load address - let (addr, addr_mode_bit) = I2cBase::<$I2CX>::unwrap_addr(addr); - self.i2c_base.i2c.address().write(|w| unsafe { - w.bits(I2cDirection::Send as u32 | (addr << 1) as u32 | addr_mode_bit) - }); - - self.i2c_base - .i2c - .cmd() - .write(|w| unsafe { w.bits(init_cmd as u32) }); - let mut load_if_next_available = || { - if let Some(next_byte) = iter.next() { - self.load_fifo(next_byte); - } - }; - loop { - let status_reader = self.i2c_base.i2c.status().read(); - if status_reader.arblost().bit_is_set() { - self.error_handler_write(&init_cmd); - return Err(Error::ArbitrationLost); - } else if status_reader.nackaddr().bit_is_set() { - self.error_handler_write(&init_cmd); - return Err(Error::NackAddr); - } else if status_reader.nackdata().bit_is_set() { - self.error_handler_write(&init_cmd); - return Err(Error::NackData); - } else if status_reader.idle().bit_is_set() { - return Ok(()); - } else { - while !status_reader.txnfull().bit_is_set() { - load_if_next_available(); - } - } - } - } - - fn write_from_buffer( - &mut self, - init_cmd: I2cCmd, - addr: I2cAddress, - output: &[u8], - ) -> Result<(), Error> { - let len = output.len(); - // It should theoretically possible to transfer larger data sizes by tracking - // the number of sent words and setting it to 0x7fe as soon as only that many - // bytes are remaining. However, large transfer like this are not common. This - // feature will therefore not be supported for now. - if len > 0x7fe { - return Err(Error::DataTooLarge); - } - // Load number of words - self.i2c_base - .i2c - .words() - .write(|w| unsafe { w.bits(len as u32) }); - let mut bytes = output.iter(); - // FIFO has a depth of 16. We load slightly above the trigger level - // but not all of it because the transaction might fail immediately - const FILL_DEPTH: usize = 12; - - // load the FIFO - for _ in 0..core::cmp::min(FILL_DEPTH, len) { - self.load_fifo(*bytes.next().unwrap()); - } - - self.write_base(addr, init_cmd, output.iter().cloned()) - } - - fn read_internal(&mut self, addr: I2cAddress, buffer: &mut [u8]) -> Result<(), Error> { - let len = buffer.len(); - // It should theoretically possible to transfer larger data sizes by tracking - // the number of sent words and setting it to 0x7fe as soon as only that many - // bytes are remaining. However, large transfer like this are not common. This - // feature will therefore not be supported for now. - if len > 0x7fe { - return Err(Error::DataTooLarge); - } - // Clear the receive FIFO - self.clear_rx_fifo(); - - // Load number of words - self.i2c_base - .i2c - .words() - .write(|w| unsafe { w.bits(len as u32) }); - let (addr, addr_mode_bit) = match addr { - I2cAddress::Regular(addr) => (addr as u16, 0 << 15), - I2cAddress::TenBit(addr) => (addr, 1 << 15), - }; - // Load address - self.i2c_base.i2c.address().write(|w| unsafe { - w.bits(I2cDirection::Read as u32 | (addr << 1) as u32 | addr_mode_bit) - }); - - let mut buf_iter = buffer.iter_mut(); - let mut read_bytes = 0; - // Start receive transfer - self.i2c_base - .i2c - .cmd() - .write(|w| unsafe { w.bits(I2cCmd::StartWithStop as u32) }); - let mut read_if_next_available = || { - if let Some(next_byte) = buf_iter.next() { - *next_byte = self.read_fifo(); - } - }; - loop { - let status_reader = self.i2c_base.i2c.status().read(); - if status_reader.arblost().bit_is_set() { - self.clear_rx_fifo(); - return Err(Error::ArbitrationLost); - } else if status_reader.nackaddr().bit_is_set() { - self.clear_rx_fifo(); - return Err(Error::NackAddr); - } else if status_reader.idle().bit_is_set() { - if read_bytes != len { - return Err(Error::InsufficientDataReceived); - } - return Ok(()); - } else if status_reader.rxnempty().bit_is_set() { - read_if_next_available(); - read_bytes += 1; - } - } - } - } - - //====================================================================================== - // Embedded HAL I2C implementations - //====================================================================================== - - impl embedded_hal::i2c::ErrorType for I2cMaster<$I2CX, SevenBitAddress> { - type Error = Error; - } - impl embedded_hal::i2c::I2c for I2cMaster<$I2CX, SevenBitAddress> { - fn transaction( - &mut self, - address: SevenBitAddress, - operations: &mut [Operation<'_>], - ) -> Result<(), Self::Error> { - for operation in operations { - match operation { - Operation::Read(buf) => self.read_internal(I2cAddress::Regular(address), buf)?, - Operation::Write(buf) => self.write_from_buffer( - I2cCmd::StartWithStop, - I2cAddress::Regular(address), - buf, - )?, - } - } - Ok(()) - } - } - - impl embedded_hal::i2c::ErrorType for I2cMaster<$I2CX, TenBitAddress> { - type Error = Error; - } - impl embedded_hal::i2c::I2c for I2cMaster<$I2CX, TenBitAddress> { - fn transaction( - &mut self, - address: TenBitAddress, - operations: &mut [Operation<'_>], - ) -> Result<(), Self::Error> { - for operation in operations { - match operation { - Operation::Read(buf) => self.read_internal(I2cAddress::TenBit(address), buf)?, - Operation::Write(buf) => self.write_from_buffer( - I2cCmd::StartWithStop, - I2cAddress::TenBit(address), - buf, - )?, - } - } - Ok(()) - } - } - )+ - } -} - -i2c_master!( - pac::I2ca: (i2ca, PeripheralClocks::I2c0), - pac::I2cb: (i2cb, PeripheralClocks::I2c1), -); -*/ - //====================================================================================== // Embedded HAL I2C implementations //====================================================================================== diff --git a/va108xx-hal/src/lib.rs b/va108xx-hal/src/lib.rs index 9da8768..b146c77 100644 --- a/va108xx-hal/src/lib.rs +++ b/va108xx-hal/src/lib.rs @@ -31,7 +31,7 @@ pub enum PortSel { PortB, } -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum PeripheralSelect { PortA = 0, @@ -54,6 +54,7 @@ pub enum PeripheralSelect { /// Cortex-M0 NVIC. Both are generally necessary for IRQs to work, but the user might want to /// perform those steps themselves. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct InterruptConfig { /// Interrupt target vector. Should always be set, might be required for disabling IRQs pub id: pac::Interrupt, diff --git a/va108xx-hal/src/spi.rs b/va108xx-hal/src/spi.rs index 48052ef..b213a7f 100644 --- a/va108xx-hal/src/spi.rs +++ b/va108xx-hal/src/spi.rs @@ -33,6 +33,7 @@ use embedded_hal::spi::{Mode, MODE_0}; const FILL_DEPTH: usize = 12; pub const BMSTART_BMSTOP_MASK: u32 = 1 << 31; +pub const BMSKIPDATA_MASK: u32 = 1 << 30; pub const DEFAULT_CLK_DIV: u16 = 2; @@ -288,6 +289,7 @@ pub trait TransferConfigProvider { /// This struct contains all configuration parameter which are transfer specific /// and might change for transfers to different SPI slaves #[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct TransferConfigWithHwcs { pub hw_cs: Option, pub cfg: TransferConfig, @@ -296,6 +298,7 @@ pub struct TransferConfigWithHwcs { /// Type erased variant of the transfer configuration. This is required to avoid generics in /// the SPI constructor. #[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct TransferConfig { pub clk_cfg: Option, pub mode: Option, @@ -383,6 +386,8 @@ impl TransferConfigProvider for TransferConfigWithHwcs } /// Configuration options for the whole SPI bus. See Programmer Guide p.92 for more details +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SpiConfig { clk: SpiClkConfig, // SPI mode configuration @@ -532,6 +537,7 @@ pub struct Spi { pins: Pins, } +#[inline(always)] pub fn mode_to_cpo_cph_bit(mode: embedded_hal::spi::Mode) -> (bool, bool) { match mode { embedded_hal::spi::MODE_0 => (false, false), @@ -575,6 +581,7 @@ impl SpiClkConfig { } #[derive(Debug, thiserror::Error)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SpiClkConfigError { #[error("division by zero")] DivIsZero,