From 14ad647773bdbd60eaada469824034d2c1e7271f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 14 Feb 2025 15:23:14 +0100 Subject: [PATCH] HAL update + CHANGELOG --- .../embassy/src/bin/uart-echo-with-irq.rs | 3 +- flashloader/src/main.rs | 2 +- va416xx-hal/CHANGELOG.md | 27 ++++ va416xx-hal/Cargo.toml | 2 +- va416xx-hal/src/adc.rs | 30 ++--- va416xx-hal/src/clock.rs | 4 +- va416xx-hal/src/dma.rs | 28 +++-- va416xx-hal/src/gpio/dynpin.rs | 16 +-- va416xx-hal/src/i2c.rs | 58 +++++---- va416xx-hal/src/lib.rs | 1 + va416xx-hal/src/spi.rs | 116 ++++++++++-------- va416xx-hal/src/timer.rs | 1 + va416xx-hal/src/uart.rs | 13 +- 13 files changed, 182 insertions(+), 119 deletions(-) diff --git a/examples/embassy/src/bin/uart-echo-with-irq.rs b/examples/embassy/src/bin/uart-echo-with-irq.rs index 66d1623..79018e7 100644 --- a/examples/embassy/src/bin/uart-echo-with-irq.rs +++ b/examples/embassy/src/bin/uart-echo-with-irq.rs @@ -32,7 +32,8 @@ use va416xx_hal::{ uart, }; -pub type SharedUart = Mutex>>>; +pub type SharedUart = + Mutex>>>; static RX: SharedUart = Mutex::new(RefCell::new(None)); const BAUDRATE: u32 = 115200; diff --git a/flashloader/src/main.rs b/flashloader/src/main.rs index 4b28bcf..e0d4040 100644 --- a/flashloader/src/main.rs +++ b/flashloader/src/main.rs @@ -127,7 +127,7 @@ mod app { #[local] struct Local { - uart_rx: uart::RxWithIrq, + uart_rx: uart::RxWithInterrupt, uart_tx: uart::Tx, rx_context: IrqContextTimeoutOrMaxSize, rom_spi: Option, diff --git a/va416xx-hal/CHANGELOG.md b/va416xx-hal/CHANGELOG.md index bb9fffe..8dd6ebd 100644 --- a/va416xx-hal/CHANGELOG.md +++ b/va416xx-hal/CHANGELOG.md @@ -8,6 +8,33 @@ and this project adheres to [Semantic Versioning](http://semver.org/). # [unreleased] +# [v0.4.0] 2025-02-14 + +## Changed + +- GPIO API: Interrupt, pulse and filter and `set_datamask` and `clear_datamask` APIs are now + methods which mutable modify the pin instead of consuming and returning it. +- Simplified PWM module implementation. +- All error types now implement `core::error::Error` by using the `thiserror::Error` derive. +- `InvalidPinTypeError` now wraps the pin mode. +- I2C `TimingCfg` constructor now returns explicit error instead of generic Error. + Removed the timing configuration error type from the generic I2C error enumeration. +- `PinsA` and `PinsB` constructor do not expect an optional `pac::Ioconfig` argument anymore. +- `IrqCfg` renamed to `InterruptConfig`, kept alias for old name. +- All library provided interrupt handlers now start with common prefix `on_interrupt_*` +- `RxWithIrq` renamed to `RxWithInterrupt` +- `Rx::into_rx_with_irq` does not expect any arguments any more. +- `filter_type` renamed to `configure_filter_type`. +- `level_irq` renamed to `configure_level_interrupt`. +- `edge_irq` renamed to `configure_edge_interrupt`. +- UART interrupt management is now handled by the main constructor instead of later stages to + statically ensure one interrupt vector for the UART peripheral. `Uart::new` expects an + optional `InterruptConfig` argument. +- `enable_interrupt` and `disable_interrupt` renamed to `enable_nvic_interrupt` and + `disable_nvic_interrupt` to distinguish them from peripheral interrupts more clearly. +- `port_mux` renamed to `port_function_select` +- Renamed `IrqUartErrors` to `UartErrors`. + # [v0.3.0] 2024-30-09 ## Changed diff --git a/va416xx-hal/Cargo.toml b/va416xx-hal/Cargo.toml index 5ca6983..df81791 100644 --- a/va416xx-hal/Cargo.toml +++ b/va416xx-hal/Cargo.toml @@ -36,7 +36,7 @@ features = ["critical-section"] [features] default = ["rt", "revb"] rt = ["va416xx/rt"] -defmt = ["dep:defmt", "fugit/defmt"] +defmt = ["dep:defmt", "fugit/defmt", "embedded-hal/defmt-03"] va41630 = ["device-selected"] va41620 = ["device-selected"] diff --git a/va416xx-hal/src/adc.rs b/va416xx-hal/src/adc.rs index da2ce49..2eec515 100644 --- a/va416xx-hal/src/adc.rs +++ b/va416xx-hal/src/adc.rs @@ -74,34 +74,28 @@ bitflags::bitflags! { } } -#[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Copy, Clone, thiserror::Error)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[error("ADC empty error")] pub struct AdcEmptyError; -#[derive(Debug, PartialEq, Eq, Copy, Clone)] + +#[derive(Debug, PartialEq, Eq, Copy, Clone, thiserror::Error)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[error("invalid channel range error")] pub struct InvalidChannelRangeError; -#[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Copy, Clone, thiserror::Error)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[error("buffer too small")] pub struct BufferTooSmallError; -#[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Copy, Clone, thiserror::Error)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum AdcRangeReadError { - InvalidChannelRange(InvalidChannelRangeError), - BufferTooSmall(BufferTooSmallError), -} - -impl From for AdcRangeReadError { - fn from(value: InvalidChannelRangeError) -> Self { - AdcRangeReadError::InvalidChannelRange(value) - } -} - -impl From for AdcRangeReadError { - fn from(value: BufferTooSmallError) -> Self { - AdcRangeReadError::BufferTooSmall(value) - } + #[error("invalid channel range: {0}")] + InvalidChannelRange(#[from] InvalidChannelRangeError), + #[error("buffer too small: {0}")] + BufferTooSmall(#[from] BufferTooSmallError), } #[derive(Debug, PartialEq, Eq, Copy, Clone)] diff --git a/va416xx-hal/src/clock.rs b/va416xx-hal/src/clock.rs index baa6510..6bdd7ee 100644 --- a/va416xx-hal/src/clock.rs +++ b/va416xx-hal/src/clock.rs @@ -19,7 +19,8 @@ use crate::time::Hertz; pub const HBO_FREQ: Hertz = Hertz::from_raw(20_000_000); pub const XTAL_OSC_TSTART_MS: u32 = 15; -#[derive(Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum PeripheralSelect { Spi0 = 0, Spi1 = 1, @@ -57,6 +58,7 @@ pub enum PeripheralSelect { pub type PeripheralClock = PeripheralSelect; #[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum FilterClkSel { SysClk = 0, Clk1 = 1, diff --git a/va416xx-hal/src/dma.rs b/va416xx-hal/src/dma.rs index e26bfe3..ab4b904 100644 --- a/va416xx-hal/src/dma.rs +++ b/va416xx-hal/src/dma.rs @@ -77,12 +77,15 @@ pub enum RPower { Every1024 = 0b1111, } -#[derive(Debug, PartialEq, Eq)] -pub struct InvalidCtrlBlockAddr; +#[derive(Debug, PartialEq, Eq, thiserror::Error)] +#[error("Invalid DMA control block address")] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct InvalidCtrlBlockAddrError; bitfield::bitfield! { #[repr(transparent)] #[derive(Clone, Copy)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ChannelConfig(u32); impl Debug; u32; @@ -111,6 +114,7 @@ bitfield::bitfield! { #[repr(C)] #[derive(Debug, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DmaChannelControl { pub src_end_ptr: u32, pub dest_end_ptr: u32, @@ -160,9 +164,9 @@ impl DmaCtrlBlock { /// The passed address must be 128-byte aligned. The user must also take care of specifying /// a valid memory address for the DMA control block which is accessible by the system as well. /// For example, the control block can be placed in the SRAM1. - pub fn new_at_addr(addr: u32) -> Result<*mut DmaCtrlBlock, InvalidCtrlBlockAddr> { + pub fn new_at_addr(addr: u32) -> Result<*mut DmaCtrlBlock, InvalidCtrlBlockAddrError> { if addr & BASE_PTR_ADDR_MASK > 0 { - return Err(InvalidCtrlBlockAddr); + return Err(InvalidCtrlBlockAddrError); } let ctrl_block_ptr = addr as *mut DmaCtrlBlock; unsafe { core::ptr::write(ctrl_block_ptr, DmaCtrlBlock::default()) } @@ -175,19 +179,21 @@ pub struct Dma { ctrl_block: *mut DmaCtrlBlock, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, thiserror::Error)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum DmaTransferInitError { - SourceDestLenMissmatch { - src_len: usize, - dest_len: usize, - }, + #[error("source and destination buffer length mismatch: {src_len} != {dest_len}")] + SourceDestLenMissmatch { src_len: usize, dest_len: usize }, /// Overflow when calculating the source or destination end address. + #[error("address overflow")] AddrOverflow, /// Transfer size larger than 1024 units. + #[error("transfer size too large: {0}, 1024 is the allowed maximum")] TransferSizeTooLarge(usize), } #[derive(Debug, Clone, Copy, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DmaCfg { pub bufferable: bool, pub cacheable: bool, @@ -493,11 +499,11 @@ impl Dma { dma: pac::Dma, cfg: DmaCfg, ctrl_block: *mut DmaCtrlBlock, - ) -> Result { + ) -> Result { // The conversion to u32 is safe here because we are on a 32-bit system. let raw_addr = ctrl_block as u32; if raw_addr & BASE_PTR_ADDR_MASK > 0 { - return Err(InvalidCtrlBlockAddr); + return Err(InvalidCtrlBlockAddrError); } syscfg.enable_peripheral_clock(PeripheralClock::Dma); syscfg.assert_periph_reset_for_two_cycles(PeripheralSelect::Dma); diff --git a/va416xx-hal/src/gpio/dynpin.rs b/va416xx-hal/src/gpio/dynpin.rs index 1281f2d..335493e 100644 --- a/va416xx-hal/src/gpio/dynpin.rs +++ b/va416xx-hal/src/gpio/dynpin.rs @@ -68,7 +68,7 @@ use super::{ /// Value-level `enum` for disabled configurations #[derive(Debug, PartialEq, Eq, Clone, Copy)] -#[cfg_attr(feature = "defmt", derive(defmt::format))] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum DynDisabled { Floating, PullDown, @@ -77,7 +77,7 @@ pub enum DynDisabled { /// Value-level `enum` for input configurations #[derive(Debug, PartialEq, Eq, Clone, Copy)] -#[cfg_attr(feature = "defmt", derive(defmt::format))] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum DynInput { Floating, PullDown, @@ -86,7 +86,7 @@ pub enum DynInput { /// Value-level `enum` for output configurations #[derive(Debug, PartialEq, Eq, Clone, Copy)] -#[cfg_attr(feature = "defmt", derive(defmt::format))] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum DynOutput { PushPull, OpenDrain, @@ -121,7 +121,7 @@ impl embedded_hal::digital::Error for InvalidPinTypeError { /// Value-level `enum` representing pin modes #[derive(Debug, PartialEq, Eq, Clone, Copy)] -#[cfg_attr(feature = "defmt", derive(defmt::format))] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum DynPinMode { Input(DynInput), Output(DynOutput), @@ -157,7 +157,7 @@ pub const DYN_ALT_FUNC_3: DynPinMode = DynPinMode::Alternate(DynAlternate::Sel3) /// Value-level `enum` for pin groups #[derive(Debug, PartialEq, Eq, Clone, Copy)] -#[cfg_attr(feature = "defmt", derive(defmt::format))] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum DynGroup { A, B, @@ -170,7 +170,7 @@ pub enum DynGroup { /// Value-level `struct` representing pin IDs #[derive(Debug, PartialEq, Eq, Clone, Copy)] -#[cfg_attr(feature = "defmt", derive(defmt::format))] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DynPinId { pub group: DynGroup, pub num: u8, @@ -185,7 +185,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))] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) struct DynRegisters(DynPinId); // [`DynRegisters`] takes ownership of the [`DynPinId`], and [`DynPin`] @@ -219,7 +219,7 @@ impl DynRegisters { /// This type acts as a type-erased version of [`Pin`]. Every pin is represented /// by the same type, and pins are tracked and distinguished at run-time. #[derive(Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::format))] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DynPin { pub(crate) regs: DynRegisters, mode: DynPinMode, diff --git a/va416xx-hal/src/i2c.rs b/va416xx-hal/src/i2c.rs index b7f9dec..383758a 100644 --- a/va416xx-hal/src/i2c.rs +++ b/va416xx-hal/src/i2c.rs @@ -28,37 +28,42 @@ pub enum FifoEmptyMode { EndTransaction = 1, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, thiserror::Error)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct ClockTooSlowForFastI2c; +#[error("clock too slow for fast I2C mode")] +pub struct ClockTooSlowForFastI2cError; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, thiserror::Error)] +#[error("invalid timing parameters")] +pub struct InvalidTimingParamsError; + +#[derive(Debug, PartialEq, Eq, thiserror::Error)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { - InvalidTimingParams, + #[error("arbitration lost")] ArbitrationLost, + #[error("nack address")] NackAddr, /// Data not acknowledged in write operation + #[error("data not acknowledged in write operation")] NackData, /// Not enough data received in read operation + #[error("insufficient data received")] InsufficientDataReceived, /// Number of bytes in transfer too large (larger than 0x7fe) + #[error("data too large (larger than 0x7fe)")] DataTooLarge, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, thiserror::Error)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum InitError { /// Wrong address used in constructor + #[error("wrong address mode")] WrongAddrMode, /// APB1 clock is too slow for fast I2C mode. - ClkTooSlow(ClockTooSlowForFastI2c), -} - -impl From for InitError { - fn from(value: ClockTooSlowForFastI2c) -> Self { - Self::ClkTooSlow(value) - } + #[error("clock too slow for fast I2C mode: {0}")] + ClkTooSlow(#[from] ClockTooSlowForFastI2cError), } impl embedded_hal::i2c::Error for Error { @@ -71,7 +76,7 @@ impl embedded_hal::i2c::Error for Error { Error::NackData => { embedded_hal::i2c::ErrorKind::NoAcknowledge(i2c::NoAcknowledgeSource::Data) } - Error::DataTooLarge | Error::InsufficientDataReceived | Error::InvalidTimingParams => { + Error::DataTooLarge | Error::InsufficientDataReceived => { embedded_hal::i2c::ErrorKind::Other } } @@ -153,9 +158,12 @@ impl Instance for pac::I2c2 { // Config //================================================================================================== +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct TrTfThighTlow(u8, u8, u8, u8); +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct TsuStoTsuStaThdStaTBuf(u8, u8, u8, u8); +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct TimingCfg { // 4 bit max width tr: u8, @@ -179,7 +187,7 @@ impl TimingCfg { pub fn new( first_16_bits: TrTfThighTlow, second_16_bits: TsuStoTsuStaThdStaTBuf, - ) -> Result { + ) -> Result { if first_16_bits.0 > 0xf || first_16_bits.1 > 0xf || first_16_bits.2 > 0xf @@ -189,7 +197,7 @@ impl TimingCfg { || second_16_bits.2 > 0xf || second_16_bits.3 > 0xf { - return Err(Error::InvalidTimingParams); + return Err(InvalidTimingParamsError); } Ok(TimingCfg { tr: first_16_bits.0, @@ -230,6 +238,7 @@ impl Default for TimingCfg { } } +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct MasterConfig { pub tx_fe_mode: FifoEmptyMode, pub rx_fe_mode: FifoEmptyMode, @@ -256,6 +265,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, @@ -318,7 +329,7 @@ impl I2cBase { speed_mode: I2cSpeed, ms_cfg: Option<&MasterConfig>, sl_cfg: Option<&SlaveConfig>, - ) -> Result { + ) -> Result { syscfg.enable_peripheral_clock(I2c::PERIPH_SEL); let mut i2c_base = I2cBase { @@ -421,19 +432,22 @@ impl I2cBase { }); } - fn calc_clk_div(&self, speed_mode: I2cSpeed) -> Result { + fn calc_clk_div(&self, speed_mode: I2cSpeed) -> Result { if speed_mode == I2cSpeed::Regular100khz { Ok(((self.clock.raw() / CLK_100K.raw() / 20) - 1) as u8) } else { if self.clock.raw() < MIN_CLK_400K.raw() { - return Err(ClockTooSlowForFastI2c); + return Err(ClockTooSlowForFastI2cError); } Ok(((self.clock.raw() / CLK_400K.raw() / 25) - 1) as u8) } } /// Configures the clock scale for a given speed mode setting - pub fn cfg_clk_scale(&mut self, speed_mode: I2cSpeed) -> Result<(), ClockTooSlowForFastI2c> { + pub fn cfg_clk_scale( + &mut self, + speed_mode: I2cSpeed, + ) -> Result<(), ClockTooSlowForFastI2cError> { let clk_div = self.calc_clk_div(speed_mode)?; self.i2c .clkscale() @@ -472,7 +486,7 @@ impl I2cMaster { cfg: MasterConfig, clocks: &Clocks, speed_mode: I2cSpeed, - ) -> Result { + ) -> Result { Ok(I2cMaster { i2c_base: I2cBase::new(i2c, sys_cfg, clocks, speed_mode, Some(&cfg), None)?, addr: PhantomData, @@ -733,7 +747,7 @@ impl I2cSlave { cfg: SlaveConfig, clocks: &Clocks, speed_mode: I2cSpeed, - ) -> Result { + ) -> Result { Ok(I2cSlave { i2c_base: I2cBase::new(i2c, sys_cfg, clocks, speed_mode, None, Some(&cfg))?, addr: PhantomData, @@ -895,7 +909,7 @@ impl I2cSlave { cfg: SlaveConfig, clocks: &Clocks, speed_mode: I2cSpeed, - ) -> Result { + ) -> Result { Self::new_generic(i2c, sys_cfg, cfg, clocks, speed_mode) } } diff --git a/va416xx-hal/src/lib.rs b/va416xx-hal/src/lib.rs index 265c089..ab22eee 100644 --- a/va416xx-hal/src/lib.rs +++ b/va416xx-hal/src/lib.rs @@ -63,6 +63,7 @@ pub mod adc; pub mod dac; #[derive(Debug, Eq, Copy, Clone, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum FunSel { Sel0 = 0b00, Sel1 = 0b01, diff --git a/va416xx-hal/src/spi.rs b/va416xx-hal/src/spi.rs index 61a4e62..2681b83 100644 --- a/va416xx-hal/src/spi.rs +++ b/va416xx-hal/src/spi.rs @@ -39,6 +39,7 @@ pub const BMSTART_BMSTOP_MASK: u32 = 1 << 31; pub const BMSKIPDATA_MASK: u32 = 1 << 30; #[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum HwChipSelectId { Id0 = 0, Id1 = 1, @@ -52,6 +53,7 @@ pub enum HwChipSelectId { } #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SpiId { Spi0, Spi1, @@ -61,6 +63,7 @@ pub enum SpiId { } #[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum WordSize { OneBit = 0x00, FourBits = 0x03, @@ -68,6 +71,57 @@ pub enum WordSize { SixteenBits = 0x0f, } +pub type SpiRegBlock = pac::spi0::RegisterBlock; + +/// Common trait implemented by all PAC peripheral access structures. The register block +/// format is the same for all SPI blocks. +pub trait Instance: Deref { + const IDX: u8; + const PERIPH_SEL: PeripheralSelect; + + fn ptr() -> *const SpiRegBlock; +} + +impl Instance for pac::Spi0 { + const IDX: u8 = 0; + const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Spi0; + + #[inline(always)] + fn ptr() -> *const SpiRegBlock { + Self::ptr() + } +} + +impl Instance for pac::Spi1 { + const IDX: u8 = 1; + const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Spi1; + + #[inline(always)] + fn ptr() -> *const SpiRegBlock { + Self::ptr() + } +} + +impl Instance for pac::Spi2 { + const IDX: u8 = 2; + const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Spi2; + + #[inline(always)] + fn ptr() -> *const SpiRegBlock { + Self::ptr() + } +} + +impl Instance for pac::Spi3 { + const IDX: u8 = 3; + const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Spi3; + + #[inline(always)] + fn ptr() -> *const SpiRegBlock { + Self::ptr() + } +} + //================================================================================================== // Pin type definitions //================================================================================================== @@ -239,6 +293,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, @@ -247,6 +302,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, @@ -334,6 +390,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 @@ -432,57 +490,6 @@ impl WordProvider for u16 { } } -pub type SpiRegBlock = pac::spi0::RegisterBlock; - -/// Common trait implemented by all PAC peripheral access structures. The register block -/// format is the same for all SPI blocks. -pub trait Instance: Deref { - const IDX: u8; - const PERIPH_SEL: PeripheralSelect; - - fn ptr() -> *const SpiRegBlock; -} - -impl Instance for pac::Spi0 { - const IDX: u8 = 0; - const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Spi0; - - #[inline(always)] - fn ptr() -> *const SpiRegBlock { - Self::ptr() - } -} - -impl Instance for pac::Spi1 { - const IDX: u8 = 1; - const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Spi1; - - #[inline(always)] - fn ptr() -> *const SpiRegBlock { - Self::ptr() - } -} - -impl Instance for pac::Spi2 { - const IDX: u8 = 2; - const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Spi2; - - #[inline(always)] - fn ptr() -> *const SpiRegBlock { - Self::ptr() - } -} - -impl Instance for pac::Spi3 { - const IDX: u8 = 3; - const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Spi3; - - #[inline(always)] - fn ptr() -> *const SpiRegBlock { - Self::ptr() - } -} - //================================================================================================== // Spi //================================================================================================== @@ -533,6 +540,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,10 +583,14 @@ impl SpiClkConfig { } } -#[derive(Debug)] +#[derive(Debug, thiserror::Error)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SpiClkConfigError { + #[error("division by zero")] DivIsZero, + #[error("divide value is not even")] DivideValueNotEven, + #[error("scrdv value is too large")] ScrdvValueTooLarge, } diff --git a/va416xx-hal/src/timer.rs b/va416xx-hal/src/timer.rs index ba1e823..2e7d10e 100644 --- a/va416xx-hal/src/timer.rs +++ b/va416xx-hal/src/timer.rs @@ -78,6 +78,7 @@ pub const unsafe fn get_tim_raw(tim_idx: usize) -> &'static pac::tim0::RegisterB //================================================================================================== #[derive(Default, Debug, PartialEq, Eq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CascadeCtrl { /// Enable Cascade 0 signal active as a requirement for counting pub enb_start_src_csd0: bool, diff --git a/va416xx-hal/src/uart.rs b/va416xx-hal/src/uart.rs index 49dbe9e..4f1ea2a 100644 --- a/va416xx-hal/src/uart.rs +++ b/va416xx-hal/src/uart.rs @@ -248,6 +248,7 @@ impl From for Config { //================================================================================================== #[derive(Debug, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct IrqContextTimeoutOrMaxSize { rx_idx: usize, mode: IrqReceptionMode, @@ -273,6 +274,7 @@ impl IrqContextTimeoutOrMaxSize { /// This struct is used to return the default IRQ handler result to the user #[derive(Debug, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct IrqResult { pub bytes_read: usize, pub errors: Option, @@ -280,6 +282,7 @@ pub struct IrqResult { /// This struct is used to return the default IRQ handler result to the user #[derive(Debug, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct IrqResultMaxSizeOrTimeout { complete: bool, timeout: bool, @@ -330,12 +333,14 @@ impl IrqResultMaxSizeOrTimeout { } #[derive(Debug, PartialEq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] enum IrqReceptionMode { Idle, Pending, } #[derive(Default, Debug, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct UartErrors { overflow: bool, framing: bool, @@ -780,8 +785,8 @@ impl Rx { self.0.data().read().bits() } - pub fn into_rx_with_irq(self) -> RxWithIrq { - RxWithIrq(self) + pub fn into_rx_with_irq(self) -> RxWithInterrupt { + RxWithInterrupt(self) } pub fn release(self) -> Uart { @@ -962,9 +967,9 @@ impl embedded_io::Write for Tx { /// then call the [Self::irq_handler_max_size_or_timeout_based] in the interrupt service /// routine. You have to call [Self::read_fixed_len_or_timeout_based_using_irq] in the ISR to /// start reading the next packet. -pub struct RxWithIrq(Rx); +pub struct RxWithInterrupt(Rx); -impl RxWithIrq { +impl RxWithInterrupt { /// This function should be called once at initialization time if the regular /// [Self::irq_handler] is used to read the UART receiver to enable and start the receiver. pub fn start(&mut self) {