diff --git a/board-tests/src/main.rs b/board-tests/src/main.rs index d59e3ac..7f9d71c 100644 --- a/board-tests/src/main.rs +++ b/board-tests/src/main.rs @@ -122,14 +122,14 @@ fn main() -> ! { } TestCase::Pulse => { let mut output_pulsed = pinsa.pa0.into_push_pull_output(); - output_pulsed.pulse_mode(true, PinState::Low); + output_pulsed.configure_pulse_mode(true, PinState::Low); rprintln!("Pulsing high 10 times.."); output_pulsed.set_low().unwrap(); for _ in 0..10 { output_pulsed.set_high().unwrap(); cortex_m::asm::delay(25_000_000); } - output_pulsed.pulse_mode(true, PinState::High); + output_pulsed.configure_pulse_mode(true, PinState::High); rprintln!("Pulsing low 10 times.."); for _ in 0..10 { output_pulsed.set_low().unwrap(); @@ -137,15 +137,12 @@ fn main() -> ! { } } TestCase::DelayGpio => { - let mut out_0 = pinsa - .pa0 - .into_readable_push_pull_output() - .delay(true, false); - let mut out_1 = pinsa - .pa1 - .into_readable_push_pull_output() - .delay(false, true); - let mut out_2 = pinsa.pa3.into_readable_push_pull_output().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..e74c8e0 100644 --- a/va108xx-hal/Cargo.toml +++ b/va108xx-hal/Cargo.toml @@ -29,7 +29,7 @@ static_cell = "2" thiserror = { version = "2", default-features = false } void = { version = "1", default-features = false } once_cell = {version = "1", default-features = false } -va108xx = { version = "0.4", default-features = false, features = ["critical-section"] } +va108xx = { version = "0.5", path = "../va108xx", default-features = false, features = ["critical-section", "defmt"] } embassy-sync = "0.6" defmt = { version = "0.3", optional = true } @@ -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/asynch.rs b/va108xx-hal/src/gpio/asynch.rs index 0e5a478..40ccd14 100644 --- a/va108xx-hal/src/gpio/asynch.rs +++ b/va108xx-hal/src/gpio/asynch.rs @@ -115,7 +115,7 @@ impl InputPinFuture { EDGE_DETECTION[pin_id_to_offset(pin.id())] .store(false, core::sync::atomic::Ordering::Relaxed); - pin.interrupt_edge( + pin.configure_edge_interrupt( edge, InterruptConfig::new(irq, true, true), Some(sys_cfg), diff --git a/va108xx-hal/src/gpio/dynpin.rs b/va108xx-hal/src/gpio/dynpin.rs index 20447da..4dc56ee 100644 --- a/va108xx-hal/src/gpio/dynpin.rs +++ b/va108xx-hal/src/gpio/dynpin.rs @@ -181,6 +181,7 @@ pub struct DynPinId { /// This `struct` takes ownership of a [`DynPinId`] and provides an API to /// access the corresponding regsiters. #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) struct DynRegisters(DynPinId); // [`DynRegisters`] takes ownership of the [`DynPinId`], and [`DynPin`] @@ -392,11 +393,15 @@ impl DynPin { /// - Delay 2: 2 /// - Delay 1 + Delay 2: 3 #[inline] - pub fn delay(self, delay_1: bool, delay_2: bool) -> Result { + pub fn configure_delay( + &mut self, + delay_1: bool, + delay_2: bool, + ) -> Result<(), InvalidPinTypeError> { match self.mode { DynPinMode::Output(_) => { - self.regs.delay(delay_1, delay_2); - Ok(self) + self.regs.configure_delay(delay_1, delay_2); + Ok(()) } _ => Err(InvalidPinTypeError(self.mode)), } @@ -406,7 +411,7 @@ impl DynPin { /// When configured for pulse mode, a given pin will set the non-default state for exactly /// one clock cycle before returning to the configured default state #[inline] - pub fn pulse_mode( + pub fn configure_pulse_mode( &mut self, enable: bool, default_state: PinState, @@ -422,14 +427,14 @@ impl DynPin { /// See p.37 and p.38 of the programmers guide for more information. #[inline] - pub fn filter_type( + pub fn configure_filter_type( &mut self, filter: FilterType, clksel: FilterClkSel, ) -> Result<(), InvalidPinTypeError> { match self.mode { DynPinMode::Input(_) => { - self.regs.filter_type(filter, clksel); + self.regs.configure_filter_type(filter, clksel); Ok(()) } _ => Err(InvalidPinTypeError(self.mode)), @@ -437,7 +442,7 @@ impl DynPin { } #[inline] - pub fn interrupt_edge( + pub fn configure_edge_interrupt( &mut self, edge_type: InterruptEdge, irq_cfg: InterruptConfig, @@ -446,7 +451,7 @@ impl DynPin { ) -> Result<(), InvalidPinTypeError> { match self.mode { DynPinMode::Input(_) | DynPinMode::Output(_) => { - self.regs.interrupt_edge(edge_type); + self.regs.configure_edge_interrupt(edge_type); self.irq_enb(irq_cfg, syscfg, irqsel); Ok(()) } @@ -455,7 +460,7 @@ impl DynPin { } #[inline] - pub fn interrupt_level( + pub fn configure_level_interrupt( &mut self, level_type: InterruptLevel, irq_cfg: InterruptConfig, @@ -464,7 +469,7 @@ impl DynPin { ) -> Result<(), InvalidPinTypeError> { match self.mode { DynPinMode::Input(_) | DynPinMode::Output(_) => { - self.regs.interrupt_level(level_type); + self.regs.configure_level_interrupt(level_type); self.irq_enb(irq_cfg, syscfg, irqsel); Ok(()) } diff --git a/va108xx-hal/src/gpio/pin.rs b/va108xx-hal/src/gpio/pin.rs index a02fd19..14ab13b 100644 --- a/va108xx-hal/src/gpio/pin.rs +++ b/va108xx-hal/src/gpio/pin.rs @@ -89,6 +89,7 @@ use paste::paste; //================================================================================================== #[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum InterruptEdge { HighToLow, LowToHigh, @@ -96,12 +97,14 @@ pub enum InterruptEdge { } #[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum InterruptLevel { Low = 0, High = 1, } #[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum PinState { Low = 0, High = 1, @@ -353,6 +356,7 @@ impl Pin { } } + #[inline] pub fn id(&self) -> DynPinId { self.inner.id() } @@ -482,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() @@ -599,7 +598,7 @@ impl Pin> { syscfg: Option<&mut Sysconfig>, irqsel: Option<&mut Irqsel>, ) { - self.inner.regs.interrupt_edge(edge_type); + self.inner.regs.configure_edge_interrupt(edge_type); self.irq_enb(irq_cfg, syscfg, irqsel); } @@ -610,7 +609,7 @@ impl Pin> { syscfg: Option<&mut Sysconfig>, irqsel: Option<&mut Irqsel>, ) { - self.inner.regs.interrupt_level(level_type); + self.inner.regs.configure_level_interrupt(level_type); self.irq_enb(irq_cfg, syscfg, irqsel); } } @@ -622,23 +621,34 @@ impl Pin> { /// - Delay 2: 2 /// - Delay 1 + Delay 2: 3 #[inline] - pub fn delay(self, delay_1: bool, delay_2: bool) -> Self { - self.inner.regs.delay(delay_1, delay_2); - self + 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( + since = "0.9.0", + note = "Please use the `configure_pulse_mode` method instead" + )] + pub fn pulse_mode(&mut self, enable: bool, default_state: PinState) { + self.configure_pulse_mode(enable, default_state); } /// See p.52 of the programmers guide for more information. /// When configured for pulse mode, a given pin will set the non-default state for exactly /// one clock cycle before returning to the configured default state - pub fn pulse_mode(&mut self, enable: bool, default_state: PinState) { + pub fn configure_pulse_mode(&mut self, enable: bool, default_state: PinState) { self.inner.regs.pulse_mode(enable, default_state); } + #[deprecated( + since = "0.9.0", + note = "Please use the `configure_edge_interrupt` method instead" + )] pub fn interrupt_edge( &mut self, edge_type: InterruptEdge, @@ -646,18 +656,43 @@ impl Pin> { syscfg: Option<&mut Sysconfig>, irqsel: Option<&mut Irqsel>, ) { - self.inner.regs.interrupt_edge(edge_type); + self.inner.regs.configure_edge_interrupt(edge_type); self.irq_enb(irq_cfg, syscfg, irqsel); } - pub fn interrupt_level( + pub fn configure_edge_interrupt( + &mut self, + edge_type: InterruptEdge, + irq_cfg: InterruptConfig, + syscfg: Option<&mut Sysconfig>, + irqsel: Option<&mut Irqsel>, + ) { + self.inner.regs.configure_edge_interrupt(edge_type); + self.irq_enb(irq_cfg, syscfg, irqsel); + } + + #[deprecated( + since = "0.9.0", + note = "Please use the `configure_level_interrupt` method instead" + )] + pub fn level_interrupt( &mut self, level_type: InterruptLevel, irq_cfg: InterruptConfig, syscfg: Option<&mut Sysconfig>, irqsel: Option<&mut Irqsel>, ) { - self.inner.regs.interrupt_level(level_type); + self.configure_level_interrupt(level_type, irq_cfg, syscfg, irqsel); + } + + pub fn configure_level_interrupt( + &mut self, + level_type: InterruptLevel, + irq_cfg: InterruptConfig, + syscfg: Option<&mut Sysconfig>, + irqsel: Option<&mut Irqsel>, + ) { + self.inner.regs.configure_level_interrupt(level_type); self.irq_enb(irq_cfg, syscfg, irqsel); } } @@ -666,7 +701,7 @@ impl Pin> { /// See p.37 and p.38 of the programmers guide for more information. #[inline] pub fn configure_filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) { - self.inner.regs.filter_type(filter, clksel); + self.inner.regs.configure_filter_type(filter, clksel); } } diff --git a/va108xx-hal/src/gpio/reg.rs b/va108xx-hal/src/gpio/reg.rs index 55ec595..d8d4993 100644 --- a/va108xx-hal/src/gpio/reg.rs +++ b/va108xx-hal/src/gpio/reg.rs @@ -240,7 +240,7 @@ pub(super) unsafe trait RegisterInterface { /// Only useful for interrupt pins. Configure whether to use edges or level as interrupt soure /// When using edge mode, it is possible to generate interrupts on both edges as well #[inline] - fn interrupt_edge(&mut self, edge_type: InterruptEdge) { + fn configure_edge_interrupt(&mut self, edge_type: InterruptEdge) { unsafe { self.port_reg() .irq_sen() @@ -267,7 +267,7 @@ pub(super) unsafe trait RegisterInterface { /// Configure which edge or level type triggers an interrupt #[inline] - fn interrupt_level(&mut self, level: InterruptLevel) { + fn configure_level_interrupt(&mut self, level: InterruptLevel) { unsafe { self.port_reg() .irq_sen() @@ -286,7 +286,7 @@ pub(super) unsafe trait RegisterInterface { /// Only useful for input pins #[inline] - fn filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) { + fn configure_filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) { self.iocfg_port().modify(|_, w| { // Safety: Only write to register for this Pin ID unsafe { @@ -349,7 +349,7 @@ pub(super) unsafe trait RegisterInterface { } /// Only useful for output pins - fn delay(&self, delay_1: bool, delay_2: bool) { + fn configure_delay(&mut self, delay_1: bool, delay_2: bool) { let portreg = self.port_reg(); unsafe { if delay_1 { 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, diff --git a/va108xx/README.md b/va108xx/README.md index ff37d3d..a5ec109 100644 --- a/va108xx/README.md +++ b/va108xx/README.md @@ -30,7 +30,7 @@ For full details on the autgenerated API, please see the - [`defmt`](https://defmt.ferrous-systems.com/): Add support for `defmt` by adding the [`defmt::Format`](https://defmt.ferrous-systems.com/format) derive on many types. -- [`debug`]: Add `Debug` derives for various structures +- `debug`: Add `Debug` derives for various structures ## Regenerating the PAC