From 5cbbb53094b57cefba05425ac51e2b737b398b4e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Dec 2021 00:14:08 +0100 Subject: [PATCH] some minor improvements - Docs updated, internal architecture improvements --- examples/uart-irq-rtic.rs | 2 +- src/uart.rs | 33 ++++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/examples/uart-irq-rtic.rs b/examples/uart-irq-rtic.rs index a67989c..0002a9a 100644 --- a/examples/uart-irq-rtic.rs +++ b/examples/uart-irq-rtic.rs @@ -6,7 +6,7 @@ //! //! This script was tested with an Arduino Due. You can find the test script in the //! [`/test/DueSerialTest`](https://egit.irs.uni-stuttgart.de/rust/va108xx-hal/src/branch/main/test/DueSerialTest) -//! folder, +//! folder. #![no_main] #![no_std] diff --git a/src/uart.rs b/src/uart.rs index 93fe712..1529b00 100644 --- a/src/uart.rs +++ b/src/uart.rs @@ -178,7 +178,7 @@ impl From for Config { // IRQ Definitions //================================================================================================== -pub struct IrqInfo { +struct IrqInfo { rx_len: usize, rx_idx: usize, irq_cfg: IrqCfg, @@ -197,6 +197,7 @@ pub enum IrqResultMask { Unknown = 7, } +/// This struct is used to return the default IRQ handler result to the user #[derive(Debug, Default)] pub struct IrqResult { raw_res: u32, @@ -277,32 +278,36 @@ impl IrqResult { } #[derive(Debug, PartialEq)] -pub enum IrqReceptionMode { +enum IrqReceptionMode { Idle, - FixedLen, - VarLen, + Pending } //================================================================================================== // UART implementation //================================================================================================== +/// Type erased variant of a UART. Can be created with the [`Uart::downgrade`] function. pub struct UartBase { uart: UART, tx: Tx, rx: Rx, } -/// Serial abstraction +/// Serial abstraction. Entry point to create a new UART pub struct Uart { uart_base: UartBase, pins: PINS, } +/// UART using the IRQ capabilities of the peripheral. Can be created with the +/// [`Uart::into_uart_with_irq`] function. pub struct UartWithIrq { irq_base: UartWithIrqBase, pins: PINS, } +/// Type-erased UART using the IRQ capabilities of the peripheral. Can be created with the +/// [`UartWithIrq::downgrade`] function. pub struct UartWithIrqBase { pub uart: UartBase, irq_info: IrqInfo, @@ -478,6 +483,8 @@ where self } + /// If the IRQ capabilities of the peripheral are used, the UART needs to be converted + /// with this function pub fn into_uart_with_irq( self, irq_cfg: IrqCfg, @@ -632,6 +639,14 @@ impl UartWithIrqBase { self } + /// This initializes a non-blocking read transfer using the IRQ capabilities of the UART + /// peripheral. + /// + /// The only required information is the maximum length for variable sized reception + /// or the expected length for fixed length reception. If variable sized packets are expected, + /// the timeout functionality of the IRQ should be enabled as well. After calling this function, + /// the [`irq_handler`](Self::irq_handler) function should be called in the user interrupt + /// handler to read the received packets and reinitiate another transfer if desired. pub fn read_fixed_len_using_irq( &mut self, max_len: usize, @@ -640,6 +655,7 @@ impl UartWithIrqBase { if self.irq_info.mode != IrqReceptionMode::Idle { return Err(Error::TransferPending); } + self.irq_info.mode = IrqReceptionMode::Pending; self.irq_info.rx_idx = 0; self.irq_info.rx_len = max_len; self.uart.enable_rx(); @@ -690,6 +706,10 @@ impl UartWithIrqBase { self.irq_info.rx_len = 0; } + /// Default IRQ handler which can be used to read the packets arriving on the UART peripheral. + /// + /// If passed buffer is equal to or larger than the specified maximum length, an + /// [`Error::BufferTooShort`] will be returned pub fn irq_handler(&mut self, res: &mut IrqResult, buf: &mut [u8]) -> Result<(), Error> { if buf.len() < self.irq_info.rx_len { return Err(Error::BufferTooShort); @@ -800,6 +820,7 @@ impl UartWithIrqBase { res.bytes_read = self.irq_info.rx_idx; res.clear_result(); res.set_result(IrqResultMask::Complete); + self.irq_info.mode = IrqReceptionMode::Idle; self.irq_info.rx_idx = 0; self.irq_info.rx_len = 0; } @@ -810,6 +831,7 @@ impl UartWithIrqBase { } impl UartWithIrq { + /// See [`UartWithIrqBase::read_fixed_len_using_irq`] doc pub fn read_fixed_len_using_irq( &mut self, max_len: usize, @@ -823,6 +845,7 @@ impl UartWithIrq { self.irq_base.cancel_transfer() } + /// See [`UartWithIrqBase::irq_handler`] doc pub fn irq_handler(&mut self, res: &mut IrqResult, buf: &mut [u8]) -> Result<(), Error> { self.irq_base.irq_handler(res, buf) }