HAL update #51
@ -32,7 +32,8 @@ use va416xx_hal::{
|
|||||||
uart,
|
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));
|
static RX: SharedUart = Mutex::new(RefCell::new(None));
|
||||||
|
|
||||||
const BAUDRATE: u32 = 115200;
|
const BAUDRATE: u32 = 115200;
|
||||||
|
@ -127,7 +127,7 @@ mod app {
|
|||||||
|
|
||||||
#[local]
|
#[local]
|
||||||
struct Local {
|
struct Local {
|
||||||
uart_rx: uart::RxWithIrq<pac::Uart0>,
|
uart_rx: uart::RxWithInterrupt<pac::Uart0>,
|
||||||
uart_tx: uart::Tx<pac::Uart0>,
|
uart_tx: uart::Tx<pac::Uart0>,
|
||||||
rx_context: IrqContextTimeoutOrMaxSize,
|
rx_context: IrqContextTimeoutOrMaxSize,
|
||||||
rom_spi: Option<pac::Spi3>,
|
rom_spi: Option<pac::Spi3>,
|
||||||
|
@ -8,6 +8,33 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
# [unreleased]
|
# [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
|
# [v0.3.0] 2024-30-09
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
@ -36,7 +36,7 @@ features = ["critical-section"]
|
|||||||
[features]
|
[features]
|
||||||
default = ["rt", "revb"]
|
default = ["rt", "revb"]
|
||||||
rt = ["va416xx/rt"]
|
rt = ["va416xx/rt"]
|
||||||
defmt = ["dep:defmt", "fugit/defmt"]
|
defmt = ["dep:defmt", "fugit/defmt", "embedded-hal/defmt-03"]
|
||||||
|
|
||||||
va41630 = ["device-selected"]
|
va41630 = ["device-selected"]
|
||||||
va41620 = ["device-selected"]
|
va41620 = ["device-selected"]
|
||||||
|
@ -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))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[error("ADC empty error")]
|
||||||
pub struct AdcEmptyError;
|
pub struct AdcEmptyError;
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Copy, Clone, thiserror::Error)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[error("invalid channel range error")]
|
||||||
pub struct InvalidChannelRangeError;
|
pub struct InvalidChannelRangeError;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone, thiserror::Error)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[error("buffer too small")]
|
||||||
pub struct BufferTooSmallError;
|
pub struct BufferTooSmallError;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone, thiserror::Error)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum AdcRangeReadError {
|
pub enum AdcRangeReadError {
|
||||||
InvalidChannelRange(InvalidChannelRangeError),
|
#[error("invalid channel range: {0}")]
|
||||||
BufferTooSmall(BufferTooSmallError),
|
InvalidChannelRange(#[from] InvalidChannelRangeError),
|
||||||
}
|
#[error("buffer too small: {0}")]
|
||||||
|
BufferTooSmall(#[from] 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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
|
@ -19,7 +19,8 @@ use crate::time::Hertz;
|
|||||||
pub const HBO_FREQ: Hertz = Hertz::from_raw(20_000_000);
|
pub const HBO_FREQ: Hertz = Hertz::from_raw(20_000_000);
|
||||||
pub const XTAL_OSC_TSTART_MS: u32 = 15;
|
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 {
|
pub enum PeripheralSelect {
|
||||||
Spi0 = 0,
|
Spi0 = 0,
|
||||||
Spi1 = 1,
|
Spi1 = 1,
|
||||||
@ -57,6 +58,7 @@ pub enum PeripheralSelect {
|
|||||||
pub type PeripheralClock = PeripheralSelect;
|
pub type PeripheralClock = PeripheralSelect;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum FilterClkSel {
|
pub enum FilterClkSel {
|
||||||
SysClk = 0,
|
SysClk = 0,
|
||||||
Clk1 = 1,
|
Clk1 = 1,
|
||||||
|
@ -77,12 +77,15 @@ pub enum RPower {
|
|||||||
Every1024 = 0b1111,
|
Every1024 = 0b1111,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
|
||||||
pub struct InvalidCtrlBlockAddr;
|
#[error("Invalid DMA control block address")]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub struct InvalidCtrlBlockAddrError;
|
||||||
|
|
||||||
bitfield::bitfield! {
|
bitfield::bitfield! {
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct ChannelConfig(u32);
|
pub struct ChannelConfig(u32);
|
||||||
impl Debug;
|
impl Debug;
|
||||||
u32;
|
u32;
|
||||||
@ -111,6 +114,7 @@ bitfield::bitfield! {
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DmaChannelControl {
|
pub struct DmaChannelControl {
|
||||||
pub src_end_ptr: u32,
|
pub src_end_ptr: u32,
|
||||||
pub dest_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
|
/// 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.
|
/// 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.
|
/// 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 {
|
if addr & BASE_PTR_ADDR_MASK > 0 {
|
||||||
return Err(InvalidCtrlBlockAddr);
|
return Err(InvalidCtrlBlockAddrError);
|
||||||
}
|
}
|
||||||
let ctrl_block_ptr = addr as *mut DmaCtrlBlock;
|
let ctrl_block_ptr = addr as *mut DmaCtrlBlock;
|
||||||
unsafe { core::ptr::write(ctrl_block_ptr, DmaCtrlBlock::default()) }
|
unsafe { core::ptr::write(ctrl_block_ptr, DmaCtrlBlock::default()) }
|
||||||
@ -175,19 +179,21 @@ pub struct Dma {
|
|||||||
ctrl_block: *mut DmaCtrlBlock,
|
ctrl_block: *mut DmaCtrlBlock,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, thiserror::Error)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum DmaTransferInitError {
|
pub enum DmaTransferInitError {
|
||||||
SourceDestLenMissmatch {
|
#[error("source and destination buffer length mismatch: {src_len} != {dest_len}")]
|
||||||
src_len: usize,
|
SourceDestLenMissmatch { src_len: usize, dest_len: usize },
|
||||||
dest_len: usize,
|
|
||||||
},
|
|
||||||
/// Overflow when calculating the source or destination end address.
|
/// Overflow when calculating the source or destination end address.
|
||||||
|
#[error("address overflow")]
|
||||||
AddrOverflow,
|
AddrOverflow,
|
||||||
/// Transfer size larger than 1024 units.
|
/// Transfer size larger than 1024 units.
|
||||||
|
#[error("transfer size too large: {0}, 1024 is the allowed maximum")]
|
||||||
TransferSizeTooLarge(usize),
|
TransferSizeTooLarge(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DmaCfg {
|
pub struct DmaCfg {
|
||||||
pub bufferable: bool,
|
pub bufferable: bool,
|
||||||
pub cacheable: bool,
|
pub cacheable: bool,
|
||||||
@ -493,11 +499,11 @@ impl Dma {
|
|||||||
dma: pac::Dma,
|
dma: pac::Dma,
|
||||||
cfg: DmaCfg,
|
cfg: DmaCfg,
|
||||||
ctrl_block: *mut DmaCtrlBlock,
|
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.
|
// The conversion to u32 is safe here because we are on a 32-bit system.
|
||||||
let raw_addr = ctrl_block as u32;
|
let raw_addr = ctrl_block as u32;
|
||||||
if raw_addr & BASE_PTR_ADDR_MASK > 0 {
|
if raw_addr & BASE_PTR_ADDR_MASK > 0 {
|
||||||
return Err(InvalidCtrlBlockAddr);
|
return Err(InvalidCtrlBlockAddrError);
|
||||||
}
|
}
|
||||||
syscfg.enable_peripheral_clock(PeripheralClock::Dma);
|
syscfg.enable_peripheral_clock(PeripheralClock::Dma);
|
||||||
syscfg.assert_periph_reset_for_two_cycles(PeripheralSelect::Dma);
|
syscfg.assert_periph_reset_for_two_cycles(PeripheralSelect::Dma);
|
||||||
|
@ -68,7 +68,7 @@ use super::{
|
|||||||
|
|
||||||
/// Value-level `enum` for disabled configurations
|
/// Value-level `enum` for disabled configurations
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum DynDisabled {
|
pub enum DynDisabled {
|
||||||
Floating,
|
Floating,
|
||||||
PullDown,
|
PullDown,
|
||||||
@ -77,7 +77,7 @@ pub enum DynDisabled {
|
|||||||
|
|
||||||
/// Value-level `enum` for input configurations
|
/// Value-level `enum` for input configurations
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum DynInput {
|
pub enum DynInput {
|
||||||
Floating,
|
Floating,
|
||||||
PullDown,
|
PullDown,
|
||||||
@ -86,7 +86,7 @@ pub enum DynInput {
|
|||||||
|
|
||||||
/// Value-level `enum` for output configurations
|
/// Value-level `enum` for output configurations
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum DynOutput {
|
pub enum DynOutput {
|
||||||
PushPull,
|
PushPull,
|
||||||
OpenDrain,
|
OpenDrain,
|
||||||
@ -121,7 +121,7 @@ impl embedded_hal::digital::Error for InvalidPinTypeError {
|
|||||||
|
|
||||||
/// Value-level `enum` representing pin modes
|
/// Value-level `enum` representing pin modes
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum DynPinMode {
|
pub enum DynPinMode {
|
||||||
Input(DynInput),
|
Input(DynInput),
|
||||||
Output(DynOutput),
|
Output(DynOutput),
|
||||||
@ -157,7 +157,7 @@ pub const DYN_ALT_FUNC_3: DynPinMode = DynPinMode::Alternate(DynAlternate::Sel3)
|
|||||||
|
|
||||||
/// Value-level `enum` for pin groups
|
/// Value-level `enum` for pin groups
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum DynGroup {
|
pub enum DynGroup {
|
||||||
A,
|
A,
|
||||||
B,
|
B,
|
||||||
@ -170,7 +170,7 @@ pub enum DynGroup {
|
|||||||
|
|
||||||
/// Value-level `struct` representing pin IDs
|
/// Value-level `struct` representing pin IDs
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DynPinId {
|
pub struct DynPinId {
|
||||||
pub group: DynGroup,
|
pub group: DynGroup,
|
||||||
pub num: u8,
|
pub num: u8,
|
||||||
@ -185,7 +185,7 @@ pub struct DynPinId {
|
|||||||
/// This `struct` takes ownership of a [`DynPinId`] and provides an API to
|
/// This `struct` takes ownership of a [`DynPinId`] and provides an API to
|
||||||
/// access the corresponding regsiters.
|
/// access the corresponding regsiters.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct DynRegisters(DynPinId);
|
pub(crate) struct DynRegisters(DynPinId);
|
||||||
|
|
||||||
// [`DynRegisters`] takes ownership of the [`DynPinId`], and [`DynPin`]
|
// [`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
|
/// 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.
|
/// by the same type, and pins are tracked and distinguished at run-time.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DynPin {
|
pub struct DynPin {
|
||||||
pub(crate) regs: DynRegisters,
|
pub(crate) regs: DynRegisters,
|
||||||
mode: DynPinMode,
|
mode: DynPinMode,
|
||||||
|
@ -28,37 +28,42 @@ pub enum FifoEmptyMode {
|
|||||||
EndTransaction = 1,
|
EndTransaction = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[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))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
InvalidTimingParams,
|
#[error("arbitration lost")]
|
||||||
ArbitrationLost,
|
ArbitrationLost,
|
||||||
|
#[error("nack address")]
|
||||||
NackAddr,
|
NackAddr,
|
||||||
/// Data not acknowledged in write operation
|
/// Data not acknowledged in write operation
|
||||||
|
#[error("data not acknowledged in write operation")]
|
||||||
NackData,
|
NackData,
|
||||||
/// Not enough data received in read operation
|
/// Not enough data received in read operation
|
||||||
|
#[error("insufficient data received")]
|
||||||
InsufficientDataReceived,
|
InsufficientDataReceived,
|
||||||
/// Number of bytes in transfer too large (larger than 0x7fe)
|
/// Number of bytes in transfer too large (larger than 0x7fe)
|
||||||
|
#[error("data too large (larger than 0x7fe)")]
|
||||||
DataTooLarge,
|
DataTooLarge,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum InitError {
|
pub enum InitError {
|
||||||
/// Wrong address used in constructor
|
/// Wrong address used in constructor
|
||||||
|
#[error("wrong address mode")]
|
||||||
WrongAddrMode,
|
WrongAddrMode,
|
||||||
/// APB1 clock is too slow for fast I2C mode.
|
/// APB1 clock is too slow for fast I2C mode.
|
||||||
ClkTooSlow(ClockTooSlowForFastI2c),
|
#[error("clock too slow for fast I2C mode: {0}")]
|
||||||
}
|
ClkTooSlow(#[from] ClockTooSlowForFastI2cError),
|
||||||
|
|
||||||
impl From<ClockTooSlowForFastI2c> for InitError {
|
|
||||||
fn from(value: ClockTooSlowForFastI2c) -> Self {
|
|
||||||
Self::ClkTooSlow(value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl embedded_hal::i2c::Error for Error {
|
impl embedded_hal::i2c::Error for Error {
|
||||||
@ -71,7 +76,7 @@ impl embedded_hal::i2c::Error for Error {
|
|||||||
Error::NackData => {
|
Error::NackData => {
|
||||||
embedded_hal::i2c::ErrorKind::NoAcknowledge(i2c::NoAcknowledgeSource::Data)
|
embedded_hal::i2c::ErrorKind::NoAcknowledge(i2c::NoAcknowledgeSource::Data)
|
||||||
}
|
}
|
||||||
Error::DataTooLarge | Error::InsufficientDataReceived | Error::InvalidTimingParams => {
|
Error::DataTooLarge | Error::InsufficientDataReceived => {
|
||||||
embedded_hal::i2c::ErrorKind::Other
|
embedded_hal::i2c::ErrorKind::Other
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,9 +158,12 @@ impl Instance for pac::I2c2 {
|
|||||||
// Config
|
// Config
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct TrTfThighTlow(u8, u8, u8, u8);
|
pub struct TrTfThighTlow(u8, u8, u8, u8);
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct TsuStoTsuStaThdStaTBuf(u8, u8, u8, u8);
|
pub struct TsuStoTsuStaThdStaTBuf(u8, u8, u8, u8);
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct TimingCfg {
|
pub struct TimingCfg {
|
||||||
// 4 bit max width
|
// 4 bit max width
|
||||||
tr: u8,
|
tr: u8,
|
||||||
@ -179,7 +187,7 @@ impl TimingCfg {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
first_16_bits: TrTfThighTlow,
|
first_16_bits: TrTfThighTlow,
|
||||||
second_16_bits: TsuStoTsuStaThdStaTBuf,
|
second_16_bits: TsuStoTsuStaThdStaTBuf,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, InvalidTimingParamsError> {
|
||||||
if first_16_bits.0 > 0xf
|
if first_16_bits.0 > 0xf
|
||||||
|| first_16_bits.1 > 0xf
|
|| first_16_bits.1 > 0xf
|
||||||
|| first_16_bits.2 > 0xf
|
|| first_16_bits.2 > 0xf
|
||||||
@ -189,7 +197,7 @@ impl TimingCfg {
|
|||||||
|| second_16_bits.2 > 0xf
|
|| second_16_bits.2 > 0xf
|
||||||
|| second_16_bits.3 > 0xf
|
|| second_16_bits.3 > 0xf
|
||||||
{
|
{
|
||||||
return Err(Error::InvalidTimingParams);
|
return Err(InvalidTimingParamsError);
|
||||||
}
|
}
|
||||||
Ok(TimingCfg {
|
Ok(TimingCfg {
|
||||||
tr: first_16_bits.0,
|
tr: first_16_bits.0,
|
||||||
@ -230,6 +238,7 @@ impl Default for TimingCfg {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct MasterConfig {
|
pub struct MasterConfig {
|
||||||
pub tx_fe_mode: FifoEmptyMode,
|
pub tx_fe_mode: FifoEmptyMode,
|
||||||
pub rx_fe_mode: FifoEmptyMode,
|
pub rx_fe_mode: FifoEmptyMode,
|
||||||
@ -256,6 +265,8 @@ impl Default for MasterConfig {
|
|||||||
|
|
||||||
impl Sealed for MasterConfig {}
|
impl Sealed for MasterConfig {}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct SlaveConfig {
|
pub struct SlaveConfig {
|
||||||
pub tx_fe_mode: FifoEmptyMode,
|
pub tx_fe_mode: FifoEmptyMode,
|
||||||
pub rx_fe_mode: FifoEmptyMode,
|
pub rx_fe_mode: FifoEmptyMode,
|
||||||
@ -318,7 +329,7 @@ impl<I2c: Instance> I2cBase<I2c> {
|
|||||||
speed_mode: I2cSpeed,
|
speed_mode: I2cSpeed,
|
||||||
ms_cfg: Option<&MasterConfig>,
|
ms_cfg: Option<&MasterConfig>,
|
||||||
sl_cfg: Option<&SlaveConfig>,
|
sl_cfg: Option<&SlaveConfig>,
|
||||||
) -> Result<Self, ClockTooSlowForFastI2c> {
|
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
||||||
syscfg.enable_peripheral_clock(I2c::PERIPH_SEL);
|
syscfg.enable_peripheral_clock(I2c::PERIPH_SEL);
|
||||||
|
|
||||||
let mut i2c_base = I2cBase {
|
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 {
|
if speed_mode == I2cSpeed::Regular100khz {
|
||||||
Ok(((self.clock.raw() / CLK_100K.raw() / 20) - 1) as u8)
|
Ok(((self.clock.raw() / CLK_100K.raw() / 20) - 1) as u8)
|
||||||
} else {
|
} else {
|
||||||
if self.clock.raw() < MIN_CLK_400K.raw() {
|
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)
|
Ok(((self.clock.raw() / CLK_400K.raw() / 25) - 1) as u8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configures the clock scale for a given speed mode setting
|
/// 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)?;
|
let clk_div = self.calc_clk_div(speed_mode)?;
|
||||||
self.i2c
|
self.i2c
|
||||||
.clkscale()
|
.clkscale()
|
||||||
@ -472,7 +486,7 @@ impl<I2c: Instance, Addr> I2cMaster<I2c, Addr> {
|
|||||||
cfg: MasterConfig,
|
cfg: MasterConfig,
|
||||||
clocks: &Clocks,
|
clocks: &Clocks,
|
||||||
speed_mode: I2cSpeed,
|
speed_mode: I2cSpeed,
|
||||||
) -> Result<Self, ClockTooSlowForFastI2c> {
|
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
||||||
Ok(I2cMaster {
|
Ok(I2cMaster {
|
||||||
i2c_base: I2cBase::new(i2c, sys_cfg, clocks, speed_mode, Some(&cfg), None)?,
|
i2c_base: I2cBase::new(i2c, sys_cfg, clocks, speed_mode, Some(&cfg), None)?,
|
||||||
addr: PhantomData,
|
addr: PhantomData,
|
||||||
@ -733,7 +747,7 @@ impl<I2c: Instance, Addr> I2cSlave<I2c, Addr> {
|
|||||||
cfg: SlaveConfig,
|
cfg: SlaveConfig,
|
||||||
clocks: &Clocks,
|
clocks: &Clocks,
|
||||||
speed_mode: I2cSpeed,
|
speed_mode: I2cSpeed,
|
||||||
) -> Result<Self, ClockTooSlowForFastI2c> {
|
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
||||||
Ok(I2cSlave {
|
Ok(I2cSlave {
|
||||||
i2c_base: I2cBase::new(i2c, sys_cfg, clocks, speed_mode, None, Some(&cfg))?,
|
i2c_base: I2cBase::new(i2c, sys_cfg, clocks, speed_mode, None, Some(&cfg))?,
|
||||||
addr: PhantomData,
|
addr: PhantomData,
|
||||||
@ -895,7 +909,7 @@ impl<I2c: Instance> I2cSlave<I2c, TenBitAddress> {
|
|||||||
cfg: SlaveConfig,
|
cfg: SlaveConfig,
|
||||||
clocks: &Clocks,
|
clocks: &Clocks,
|
||||||
speed_mode: I2cSpeed,
|
speed_mode: I2cSpeed,
|
||||||
) -> Result<Self, ClockTooSlowForFastI2c> {
|
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
||||||
Self::new_generic(i2c, sys_cfg, cfg, clocks, speed_mode)
|
Self::new_generic(i2c, sys_cfg, cfg, clocks, speed_mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ pub mod adc;
|
|||||||
pub mod dac;
|
pub mod dac;
|
||||||
|
|
||||||
#[derive(Debug, Eq, Copy, Clone, PartialEq)]
|
#[derive(Debug, Eq, Copy, Clone, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum FunSel {
|
pub enum FunSel {
|
||||||
Sel0 = 0b00,
|
Sel0 = 0b00,
|
||||||
Sel1 = 0b01,
|
Sel1 = 0b01,
|
||||||
|
@ -39,6 +39,7 @@ pub const BMSTART_BMSTOP_MASK: u32 = 1 << 31;
|
|||||||
pub const BMSKIPDATA_MASK: u32 = 1 << 30;
|
pub const BMSKIPDATA_MASK: u32 = 1 << 30;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum HwChipSelectId {
|
pub enum HwChipSelectId {
|
||||||
Id0 = 0,
|
Id0 = 0,
|
||||||
Id1 = 1,
|
Id1 = 1,
|
||||||
@ -52,6 +53,7 @@ pub enum HwChipSelectId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum SpiId {
|
pub enum SpiId {
|
||||||
Spi0,
|
Spi0,
|
||||||
Spi1,
|
Spi1,
|
||||||
@ -61,6 +63,7 @@ pub enum SpiId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum WordSize {
|
pub enum WordSize {
|
||||||
OneBit = 0x00,
|
OneBit = 0x00,
|
||||||
FourBits = 0x03,
|
FourBits = 0x03,
|
||||||
@ -68,6 +71,57 @@ pub enum WordSize {
|
|||||||
SixteenBits = 0x0f,
|
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
|
// Pin type definitions
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
@ -239,6 +293,7 @@ pub trait TransferConfigProvider {
|
|||||||
/// This struct contains all configuration parameter which are transfer specific
|
/// This struct contains all configuration parameter which are transfer specific
|
||||||
/// and might change for transfers to different SPI slaves
|
/// and might change for transfers to different SPI slaves
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct TransferConfigWithHwcs<HwCs> {
|
pub struct TransferConfigWithHwcs<HwCs> {
|
||||||
pub hw_cs: Option<HwCs>,
|
pub hw_cs: Option<HwCs>,
|
||||||
pub cfg: TransferConfig,
|
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
|
/// Type erased variant of the transfer configuration. This is required to avoid generics in
|
||||||
/// the SPI constructor.
|
/// the SPI constructor.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct TransferConfig {
|
pub struct TransferConfig {
|
||||||
pub clk_cfg: Option<SpiClkConfig>,
|
pub clk_cfg: Option<SpiClkConfig>,
|
||||||
pub mode: Option<Mode>,
|
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
|
/// 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 {
|
pub struct SpiConfig {
|
||||||
clk: SpiClkConfig,
|
clk: SpiClkConfig,
|
||||||
// SPI mode configuration
|
// 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
|
// Spi
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
@ -533,6 +540,7 @@ pub struct Spi<SpiInstance, Pins, Word = u8> {
|
|||||||
pins: Pins,
|
pins: Pins,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
pub fn mode_to_cpo_cph_bit(mode: embedded_hal::spi::Mode) -> (bool, bool) {
|
pub fn mode_to_cpo_cph_bit(mode: embedded_hal::spi::Mode) -> (bool, bool) {
|
||||||
match mode {
|
match mode {
|
||||||
embedded_hal::spi::MODE_0 => (false, false),
|
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 {
|
pub enum SpiClkConfigError {
|
||||||
|
#[error("division by zero")]
|
||||||
DivIsZero,
|
DivIsZero,
|
||||||
|
#[error("divide value is not even")]
|
||||||
DivideValueNotEven,
|
DivideValueNotEven,
|
||||||
|
#[error("scrdv value is too large")]
|
||||||
ScrdvValueTooLarge,
|
ScrdvValueTooLarge,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)]
|
#[derive(Default, Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct CascadeCtrl {
|
pub struct CascadeCtrl {
|
||||||
/// Enable Cascade 0 signal active as a requirement for counting
|
/// Enable Cascade 0 signal active as a requirement for counting
|
||||||
pub enb_start_src_csd0: bool,
|
pub enb_start_src_csd0: bool,
|
||||||
|
@ -248,6 +248,7 @@ impl From<Hertz> for Config {
|
|||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct IrqContextTimeoutOrMaxSize {
|
pub struct IrqContextTimeoutOrMaxSize {
|
||||||
rx_idx: usize,
|
rx_idx: usize,
|
||||||
mode: IrqReceptionMode,
|
mode: IrqReceptionMode,
|
||||||
@ -273,6 +274,7 @@ impl IrqContextTimeoutOrMaxSize {
|
|||||||
|
|
||||||
/// This struct is used to return the default IRQ handler result to the user
|
/// This struct is used to return the default IRQ handler result to the user
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct IrqResult {
|
pub struct IrqResult {
|
||||||
pub bytes_read: usize,
|
pub bytes_read: usize,
|
||||||
pub errors: Option<UartErrors>,
|
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
|
/// This struct is used to return the default IRQ handler result to the user
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct IrqResultMaxSizeOrTimeout {
|
pub struct IrqResultMaxSizeOrTimeout {
|
||||||
complete: bool,
|
complete: bool,
|
||||||
timeout: bool,
|
timeout: bool,
|
||||||
@ -330,12 +333,14 @@ impl IrqResultMaxSizeOrTimeout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
enum IrqReceptionMode {
|
enum IrqReceptionMode {
|
||||||
Idle,
|
Idle,
|
||||||
Pending,
|
Pending,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Copy, Clone)]
|
#[derive(Default, Debug, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct UartErrors {
|
pub struct UartErrors {
|
||||||
overflow: bool,
|
overflow: bool,
|
||||||
framing: bool,
|
framing: bool,
|
||||||
@ -780,8 +785,8 @@ impl<Uart: Instance> Rx<Uart> {
|
|||||||
self.0.data().read().bits()
|
self.0.data().read().bits()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_rx_with_irq(self) -> RxWithIrq<Uart> {
|
pub fn into_rx_with_irq(self) -> RxWithInterrupt<Uart> {
|
||||||
RxWithIrq(self)
|
RxWithInterrupt(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release(self) -> Uart {
|
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
|
/// 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
|
/// routine. You have to call [Self::read_fixed_len_or_timeout_based_using_irq] in the ISR to
|
||||||
/// start reading the next packet.
|
/// 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
|
/// 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.
|
/// [Self::irq_handler] is used to read the UART receiver to enable and start the receiver.
|
||||||
pub fn start(&mut self) {
|
pub fn start(&mut self) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user