1 Commits

Author SHA1 Message Date
28fba19eac completed async RX support as well 2025-02-13 11:11:19 +01:00
14 changed files with 28 additions and 70 deletions

View File

@@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Fixed
- Important bugfix for UART driver which causes UART B drivers not to work.
- Error in UART driver which caused UART B to not work properly.
## Removed

View File

@@ -25,6 +25,12 @@ rustup target add thumbv6m-none-eabi
After that, you can use `cargo build` to build the development version of the crate.
If you have not done this yet, it is recommended to read some of the excellent resources
available to learn Rust:
- [Rust Embedded Book](https://docs.rust-embedded.org/book/)
- [Rust Discovery Book](https://docs.rust-embedded.org/discovery/)
## Setting up your own binary crate
If you have a custom board, you might be interested in setting up a new binary crate for your
@@ -59,11 +65,3 @@ is contained within the
7. Flashing the board might work differently for different boards and there is usually
more than one way. You can find example instructions in primary README.
## Embedded Rust
If you have not done this yet, it is recommended to read some of the excellent resources available
to learn Rust:
- [Rust Embedded Book](https://docs.rust-embedded.org/book/)
- [Rust Discovery Book](https://docs.rust-embedded.org/discovery/)

View File

@@ -11,7 +11,6 @@ static SYS_CLOCK: Mutex<OnceCell<Hertz>> = Mutex::new(OnceCell::new());
pub type PeripheralClocks = PeripheralSelect;
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum FilterClkSel {
SysClk = 0,
Clk1 = 1,

View File

@@ -4,7 +4,7 @@
//! the [embedded_hal_async::digital::Wait] trait. These types allow for asynchronous waiting
//! on GPIO pins. Please note that this module does not specify/declare the interrupt handlers
//! which must be provided for async support to work. However, it provides one generic
//! [handler][on_interrupt_for_asynch_gpio] which should be called in ALL user interrupt handlers
//! [handler][handle_interrupt_for_async_gpio] which should be called in ALL user interrupt handlers
//! which handle GPIO interrupts.
//!
//! # Example
@@ -90,7 +90,7 @@ pub struct InputPinFuture {
impl InputPinFuture {
/// # Safety
///
/// This calls [Self::new_with_dyn_pin] but uses [pac::Peripherals::steal] to get the system configuration
/// This calls [Self::new] but uses [pac::Peripherals::steal] to get the system configuration
/// and IRQ selection peripherals. Users must ensure that the registers and configuration
/// related to this input pin are not being used elsewhere concurrently.
pub unsafe fn new_unchecked_with_dyn_pin(
@@ -127,7 +127,7 @@ impl InputPinFuture {
/// # Safety
///
/// This calls [Self::new_with_pin] but uses [pac::Peripherals::steal] to get the system configuration
/// This calls [Self::new] but uses [pac::Peripherals::steal] to get the system configuration
/// and IRQ selection peripherals. Users must ensure that the registers and configuration
/// related to this input pin are not being used elsewhere concurrently.
pub unsafe fn new_unchecked_with_pin<I: PinId, C: InputConfig>(
@@ -200,7 +200,7 @@ impl InputDynPinAsync {
/// passed as well and is used to route and enable the interrupt.
///
/// Please note that the interrupt handler itself must be provided by the user and the
/// generic [on_interrupt_for_asynch_gpio] function must be called inside that function for
/// generic [handle_interrupt_for_async_gpio] function must be called inside that function for
/// the asynchronous functionality to work.
pub fn new(pin: DynPin, irq: pac::Interrupt) -> Result<Self, InvalidPinTypeError> {
if !pin.is_input_pin() {
@@ -335,7 +335,7 @@ impl<I: PinId, C: InputConfig> InputPinAsync<I, C> {
/// passed as well and is used to route and enable the interrupt.
///
/// Please note that the interrupt handler itself must be provided by the user and the
/// generic [on_interrupt_for_asynch_gpio] function must be called inside that function for
/// generic [handle_interrupt_for_async_gpio] function must be called inside that function for
/// the asynchronous functionality to work.
pub fn new(pin: Pin<I, pin::Input<C>>, irq: pac::Interrupt) -> Self {
Self { pin, irq }

View File

@@ -69,7 +69,6 @@ use crate::{clock::FilterClkSel, enable_nvic_interrupt, pac, FunSel, InterruptCo
/// Value-level `enum` for disabled configurations
#[derive(PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum DynDisabled {
Floating,
PullDown,
@@ -157,16 +156,14 @@ 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))]
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum DynGroup {
A,
B,
}
/// Value-level `struct` representing pin IDs
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(PartialEq, Eq, Clone, Copy)]
pub struct DynPinId {
pub group: DynGroup,
pub num: u8,
@@ -180,7 +177,6 @@ pub struct DynPinId {
///
/// This `struct` takes ownership of a [`DynPinId`] and provides an API to
/// access the corresponding regsiters.
#[derive(Debug)]
pub(crate) struct DynRegisters(DynPinId);
// [`DynRegisters`] takes ownership of the [`DynPinId`], and [`DynPin`]
@@ -213,7 +209,6 @@ 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)]
pub struct DynPin {
pub(crate) regs: DynRegisters,
mode: DynPinMode,

View File

@@ -119,11 +119,8 @@ pub trait InputConfig: Sealed {
const DYN: DynInput;
}
#[derive(Debug)]
pub enum Floating {}
#[derive(Debug)]
pub enum PullDown {}
#[derive(Debug)]
pub enum PullUp {}
impl InputConfig for Floating {
@@ -151,7 +148,6 @@ pub type InputPullUp = Input<PullUp>;
///
/// Type `C` is one of three input configurations: [`Floating`], [`PullDown`] or
/// [`PullUp`]
#[derive(Debug)]
pub struct Input<C: InputConfig> {
cfg: PhantomData<C>,
}
@@ -181,17 +177,13 @@ pub trait OutputConfig: Sealed {
pub trait ReadableOutput: Sealed {}
/// Type-level variant of [`OutputConfig`] for a push-pull configuration
#[derive(Debug)]
pub enum PushPull {}
/// Type-level variant of [`OutputConfig`] for an open drain configuration
#[derive(Debug)]
pub enum OpenDrain {}
/// Type-level variant of [`OutputConfig`] for a readable push-pull configuration
#[derive(Debug)]
pub enum ReadablePushPull {}
/// Type-level variant of [`OutputConfig`] for a readable open-drain configuration
#[derive(Debug)]
pub enum ReadableOpenDrain {}
impl Sealed for PushPull {}
@@ -218,7 +210,6 @@ impl OutputConfig for ReadableOpenDrain {
///
/// Type `C` is one of four output configurations: [`PushPull`], [`OpenDrain`] or
/// their respective readable versions
#[derive(Debug)]
pub struct Output<C: OutputConfig> {
cfg: PhantomData<C>,
}
@@ -313,7 +304,6 @@ macro_rules! pin_id {
// Need paste macro to use ident in doc attribute
paste! {
#[doc = "Pin ID representing pin " $Id]
#[derive(Debug)]
pub enum $Id {}
impl Sealed for $Id {}
impl PinId for $Id {
@@ -331,7 +321,6 @@ macro_rules! pin_id {
//==================================================================================================
/// A type-level GPIO pin, parameterized by [PinId] and [PinMode] types
#[derive(Debug)]
pub struct Pin<I: PinId, M: PinMode> {
inner: DynPin,
phantom: PhantomData<(I, M)>,
@@ -752,7 +741,6 @@ macro_rules! pins {
) => {
paste!(
/// Collection of all the individual [`Pin`]s for a given port (PORTA or PORTB)
#[derive(Debug)]
pub struct $PinsName {
port: $Port,
$(

View File

@@ -18,7 +18,6 @@ const CLK_400K: Hertz = Hertz::from_raw(400_000);
const MIN_CLK_400K: Hertz = Hertz::from_raw(8_000_000);
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum FifoEmptyMode {
Stall = 0,
EndTransaction = 1,
@@ -90,21 +89,18 @@ enum I2cCmd {
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum I2cSpeed {
Regular100khz = 0,
Fast400khz = 1,
}
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum I2cDirection {
Send = 0,
Read = 1,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum I2cAddress {
Regular(u8),
TenBit(u16),
@@ -145,12 +141,9 @@ impl Instance for pac::I2cb {
// 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,
@@ -225,7 +218,6 @@ impl Default for TimingCfg {
}
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct MasterConfig {
pub tx_fe_mode: FifoEmptyMode,
pub rx_fe_mode: FifoEmptyMode,

View File

@@ -51,8 +51,8 @@ pub enum PeripheralSelect {
/// Generic interrupt config which can be used to specify whether the HAL driver will
/// use the IRQSEL register to route an interrupt, and whether the IRQ will be unmasked in the
/// Cortex-M0 NVIC. Both are generally necessary for IRQs to work, but the user might want to
/// perform those steps themselves.
/// Cortex-M0 NVIC. Both are generally necessary for IRQs to work, but the user might perform
/// this steps themselves
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct InterruptConfig {
/// Interrupt target vector. Should always be set, might be required for disabling IRQs
@@ -77,7 +77,6 @@ impl InterruptConfig {
pub type IrqCfg = InterruptConfig;
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct InvalidPin(pub(crate) ());
/// Can be used to manually manipulate the function select of port pins

View File

@@ -15,9 +15,7 @@ use crate::{clock::enable_peripheral_clock, gpio::DynPinId};
const DUTY_MAX: u16 = u16::MAX;
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub(crate) struct PwmCommon {
pub struct PwmCommon {
sys_clk: Hertz,
/// For PWMB, this is the upper limit
current_duty: u16,

View File

@@ -37,7 +37,6 @@ pub const BMSTART_BMSTOP_MASK: u32 = 1 << 31;
pub const DEFAULT_CLK_DIV: u16 = 2;
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum HwChipSelectId {
Id0 = 0,
Id1 = 1,
@@ -51,7 +50,6 @@ pub enum HwChipSelectId {
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum SpiPort {
Porta = 0,
Portb = 1,
@@ -60,7 +58,6 @@ pub enum SpiPort {
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum WordSize {
OneBit = 0x00,
FourBits = 0x03,

View File

@@ -79,7 +79,6 @@ pub enum Event {
}
#[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,
@@ -109,7 +108,6 @@ pub struct CascadeCtrl {
}
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum CascadeSel {
Csd0 = 0,
Csd1 = 1,

View File

@@ -23,7 +23,6 @@ use crate::{
use embedded_hal_nb::serial::Read;
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Bank {
A = 0,
B = 1,
@@ -238,7 +237,6 @@ impl From<Hertz> for Config {
//==================================================================================================
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct IrqContextTimeoutOrMaxSize {
rx_idx: usize,
mode: IrqReceptionMode,
@@ -264,7 +262,6 @@ 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>,
@@ -272,7 +269,6 @@ 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,
@@ -323,7 +319,6 @@ impl IrqResultMaxSizeOrTimeout {
}
#[derive(Debug, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
enum IrqReceptionMode {
Idle,
Pending,
@@ -412,7 +407,7 @@ impl Instance for pac::Uarta {
}
#[inline(always)]
fn ptr() -> *const uart_base::RegisterBlock {
Self::ptr() as *const _
pac::Uarta::ptr() as *const _
}
}
@@ -427,7 +422,7 @@ impl Instance for pac::Uartb {
}
#[inline(always)]
fn ptr() -> *const uart_base::RegisterBlock {
Self::ptr() as *const _
pac::Uartb::ptr() as *const _
}
}
@@ -1113,10 +1108,10 @@ impl<Uart: Instance> embedded_io::Write for Tx<Uart> {
///
/// 1. The first way simply empties the FIFO on an interrupt into a user provided buffer. You
/// can simply use [Self::start] to prepare the peripheral and then call the
/// [Self::on_interrupt] in the interrupt service routine.
/// [Self::irq_handler] in the interrupt service routine.
/// 2. The second way reads packets bounded by a maximum size or a baudtick based timeout. You
/// can use [Self::read_fixed_len_or_timeout_based_using_irq] to prepare the peripheral and
/// then call the [Self::on_interrupt_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
/// start reading the next packet.
pub struct RxWithInterrupt<Uart>(Rx<Uart>);
@@ -1127,7 +1122,7 @@ impl<Uart: Instance> RxWithInterrupt<Uart> {
}
/// This function should be called once at initialization time if the regular
/// [Self::on_interrupt] 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) {
self.0.enable();
self.enable_rx_irq_sources(true);
@@ -1138,13 +1133,13 @@ impl<Uart: Instance> RxWithInterrupt<Uart> {
&self.0.uart
}
/// This function is used together with the [Self::on_interrupt_max_size_or_timeout_based]
/// This function is used together with the [Self::irq_handler_max_size_or_timeout_based]
/// function to read packets with a maximum size or variable sized packets by using the
/// receive timeout of the hardware.
///
/// This function should be called once at initialization to initiate the context state
/// and to [Self::start] the receiver. After that, it should be called after each
/// completed [Self::on_interrupt_max_size_or_timeout_based] call to restart the reception
/// completed [Self::irq_handler_max_size_or_timeout_based] call to restart the reception
/// of a packet.
pub fn read_fixed_len_or_timeout_based_using_irq(
&mut self,

View File

@@ -286,7 +286,7 @@ impl Drop for ActiveReadGuard {
}
}
/// Core data structure to allow asynchronous UART reception.
/// Core data structure to allow asynchrnous UART reception.
///
/// If the ring buffer becomes full, data will be lost.
pub struct RxAsync<Uart: Instance, const N: usize> {
@@ -295,7 +295,7 @@ pub struct RxAsync<Uart: Instance, const N: usize> {
}
impl<Uart: Instance, const N: usize> ErrorType for RxAsync<Uart, N> {
/// Error reporting is done using the result of the interrupt functions.
/// Error reporting is done using atomic booleans and the [get_and_clear_errors] function.
type Error = Infallible;
}
@@ -345,7 +345,7 @@ impl<Uart: Instance, const N: usize> embedded_io_async::Read for RxAsync<Uart, N
}
}
/// Core data structure to allow asynchronous UART reception.
/// Core data structure to allow asynchrnous UART reception.
///
/// If the ring buffer becomes full, the oldest data will be overwritten when using the
/// [on_interrupt_uart_a_overwriting] and [on_interrupt_uart_b_overwriting] interrupt handlers.
@@ -355,7 +355,7 @@ pub struct RxAsyncSharedConsumer<Uart: Instance, const N: usize> {
}
impl<Uart: Instance, const N: usize> ErrorType for RxAsyncSharedConsumer<Uart, N> {
/// Error reporting is done using the result of the interrupt functions.
/// Error reporting is done using atomic booleans and the [get_and_clear_errors] function.
type Error = Infallible;
}

View File

@@ -10,7 +10,6 @@ use va108xx_hal::{
pac, InterruptConfig,
};
#[derive(Debug)]
pub struct Button {
button: Pin<PA11, InputFloating>,
}