HAL update + CHANGELOG

This commit is contained in:
Robin Müller 2025-02-14 15:23:14 +01:00
parent f9d94a9d7e
commit 14ad647773
13 changed files with 182 additions and 119 deletions

View File

@ -32,7 +32,8 @@ use va416xx_hal::{
uart,
};
pub type SharedUart = Mutex<CriticalSectionRawMutex, RefCell<Option<uart::RxWithIrq<pac::Uart0>>>>;
pub type SharedUart =
Mutex<CriticalSectionRawMutex, RefCell<Option<uart::RxWithInterrupt<pac::Uart0>>>>;
static RX: SharedUart = Mutex::new(RefCell::new(None));
const BAUDRATE: u32 = 115200;

View File

@ -127,7 +127,7 @@ mod app {
#[local]
struct Local {
uart_rx: uart::RxWithIrq<pac::Uart0>,
uart_rx: uart::RxWithInterrupt<pac::Uart0>,
uart_tx: uart::Tx<pac::Uart0>,
rx_context: IrqContextTimeoutOrMaxSize,
rom_spi: Option<pac::Spi3>,

View File

@ -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

View File

@ -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"]

View File

@ -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<InvalidChannelRangeError> for AdcRangeReadError {
fn from(value: InvalidChannelRangeError) -> Self {
AdcRangeReadError::InvalidChannelRange(value)
}
}
impl From<BufferTooSmallError> 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)]

View File

@ -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,

View File

@ -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<Self, InvalidCtrlBlockAddr> {
) -> Result<Self, InvalidCtrlBlockAddrError> {
// 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);

View File

@ -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,

View File

@ -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<ClockTooSlowForFastI2c> 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<Self, Error> {
) -> Result<Self, InvalidTimingParamsError> {
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<I2c: Instance> I2cBase<I2c> {
speed_mode: I2cSpeed,
ms_cfg: Option<&MasterConfig>,
sl_cfg: Option<&SlaveConfig>,
) -> Result<Self, ClockTooSlowForFastI2c> {
) -> Result<Self, ClockTooSlowForFastI2cError> {
syscfg.enable_peripheral_clock(I2c::PERIPH_SEL);
let mut i2c_base = I2cBase {
@ -421,19 +432,22 @@ impl<I2c: Instance> I2cBase<I2c> {
});
}
fn calc_clk_div(&self, speed_mode: I2cSpeed) -> Result<u8, ClockTooSlowForFastI2c> {
fn calc_clk_div(&self, speed_mode: I2cSpeed) -> Result<u8, ClockTooSlowForFastI2cError> {
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<I2c: Instance, Addr> I2cMaster<I2c, Addr> {
cfg: MasterConfig,
clocks: &Clocks,
speed_mode: I2cSpeed,
) -> Result<Self, ClockTooSlowForFastI2c> {
) -> Result<Self, ClockTooSlowForFastI2cError> {
Ok(I2cMaster {
i2c_base: I2cBase::new(i2c, sys_cfg, clocks, speed_mode, Some(&cfg), None)?,
addr: PhantomData,
@ -733,7 +747,7 @@ impl<I2c: Instance, Addr> I2cSlave<I2c, Addr> {
cfg: SlaveConfig,
clocks: &Clocks,
speed_mode: I2cSpeed,
) -> Result<Self, ClockTooSlowForFastI2c> {
) -> Result<Self, ClockTooSlowForFastI2cError> {
Ok(I2cSlave {
i2c_base: I2cBase::new(i2c, sys_cfg, clocks, speed_mode, None, Some(&cfg))?,
addr: PhantomData,
@ -895,7 +909,7 @@ impl<I2c: Instance> I2cSlave<I2c, TenBitAddress> {
cfg: SlaveConfig,
clocks: &Clocks,
speed_mode: I2cSpeed,
) -> Result<Self, ClockTooSlowForFastI2c> {
) -> Result<Self, ClockTooSlowForFastI2cError> {
Self::new_generic(i2c, sys_cfg, cfg, clocks, speed_mode)
}
}

View File

@ -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,

View File

@ -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<Target = SpiRegBlock> {
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<HwCs> {
pub hw_cs: Option<HwCs>,
pub cfg: TransferConfig,
@ -247,6 +302,7 @@ pub struct TransferConfigWithHwcs<HwCs> {
/// 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<SpiClkConfig>,
pub mode: Option<Mode>,
@ -334,6 +390,8 @@ impl<HwCs: HwCsProvider> TransferConfigProvider for TransferConfigWithHwcs<HwCs>
}
/// 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<Target = SpiRegBlock> {
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<SpiInstance, Pins, Word = u8> {
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,
}

View File

@ -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,

View File

@ -248,6 +248,7 @@ impl From<Hertz> 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<UartErrors>,
@ -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<Uart: Instance> Rx<Uart> {
self.0.data().read().bits()
}
pub fn into_rx_with_irq(self) -> RxWithIrq<Uart> {
RxWithIrq(self)
pub fn into_rx_with_irq(self) -> RxWithInterrupt<Uart> {
RxWithInterrupt(self)
}
pub fn release(self) -> Uart {
@ -962,9 +967,9 @@ impl<Uart: Instance> embedded_io::Write for Tx<Uart> {
/// 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<Uart>(Rx<Uart>);
pub struct RxWithInterrupt<Uart>(Rx<Uart>);
impl<Uart: Instance> RxWithIrq<Uart> {
impl<Uart: Instance> RxWithInterrupt<Uart> {
/// 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) {