Documented usart public API
This commit is contained in:
parent
5e76c8b41a
commit
f97ef61ef8
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@ -17,12 +17,12 @@
|
||||
//"rust-analyzer.cargo.target": "thumbv8m.main-none-eabihf",
|
||||
"rust-analyzer.cargo.features": [
|
||||
// Uncomment if the example has a "nightly" feature.
|
||||
"nightly",
|
||||
//"nightly",
|
||||
],
|
||||
"rust-analyzer.linkedProjects": [
|
||||
// Uncomment ONE line for the chip you want to work on.
|
||||
// This makes rust-analyzer work on the example crate and all its dependencies.
|
||||
"examples/nrf52840/Cargo.toml",
|
||||
//"examples/nrf52840/Cargo.toml",
|
||||
// "examples/nrf52840-rtic/Cargo.toml",
|
||||
// "examples/nrf5340/Cargo.toml",
|
||||
// "examples/nrf-rtos-trace/Cargo.toml",
|
||||
@ -39,7 +39,7 @@
|
||||
// "examples/stm32g0/Cargo.toml",
|
||||
// "examples/stm32g4/Cargo.toml",
|
||||
// "examples/stm32h5/Cargo.toml",
|
||||
// "examples/stm32h7/Cargo.toml",
|
||||
"examples/stm32h7/Cargo.toml",
|
||||
// "examples/stm32l0/Cargo.toml",
|
||||
// "examples/stm32l1/Cargo.toml",
|
||||
// "examples/stm32l4/Cargo.toml",
|
||||
|
@ -82,6 +82,7 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
|
||||
}
|
||||
}
|
||||
|
||||
/// Buffered UART State
|
||||
pub struct State {
|
||||
rx_waker: AtomicWaker,
|
||||
rx_buf: RingBuffer,
|
||||
@ -91,6 +92,7 @@ pub struct State {
|
||||
}
|
||||
|
||||
impl State {
|
||||
/// Create new state
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
rx_buf: RingBuffer::new(),
|
||||
@ -101,15 +103,18 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
/// Bidirectional buffered UART
|
||||
pub struct BufferedUart<'d, T: BasicInstance> {
|
||||
rx: BufferedUartRx<'d, T>,
|
||||
tx: BufferedUartTx<'d, T>,
|
||||
}
|
||||
|
||||
/// Tx-only buffered UART
|
||||
pub struct BufferedUartTx<'d, T: BasicInstance> {
|
||||
phantom: PhantomData<&'d mut T>,
|
||||
}
|
||||
|
||||
/// Rx-only buffered UART
|
||||
pub struct BufferedUartRx<'d, T: BasicInstance> {
|
||||
phantom: PhantomData<&'d mut T>,
|
||||
}
|
||||
@ -142,6 +147,7 @@ impl<'d, T: BasicInstance> SetConfig for BufferedUartTx<'d, T> {
|
||||
}
|
||||
|
||||
impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
||||
/// Create a new bidirectional buffered UART driver
|
||||
pub fn new(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||
@ -158,6 +164,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
||||
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
|
||||
}
|
||||
|
||||
/// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins
|
||||
pub fn new_with_rtscts(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||
@ -185,6 +192,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
||||
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
|
||||
}
|
||||
|
||||
/// Create a new bidirectional buffered UART driver with a driver-enable pin
|
||||
#[cfg(not(any(usart_v1, usart_v2)))]
|
||||
pub fn new_with_de(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
@ -246,10 +254,12 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Split the driver into a Tx and Rx part (useful for sending to separate tasks)
|
||||
pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) {
|
||||
(self.tx, self.rx)
|
||||
}
|
||||
|
||||
/// Reconfigure the driver
|
||||
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||
reconfigure::<T>(config)?;
|
||||
|
||||
@ -337,6 +347,7 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reconfigure the driver
|
||||
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||
reconfigure::<T>(config)?;
|
||||
|
||||
@ -418,6 +429,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reconfigure the driver
|
||||
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||
reconfigure::<T>(config)?;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! Universal Synchronous/Asynchronous Receiver Transmitter (USART, UART, LPUART)
|
||||
#![macro_use]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use core::future::poll_fn;
|
||||
use core::marker::PhantomData;
|
||||
@ -77,21 +78,29 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
/// Number of data bits
|
||||
pub enum DataBits {
|
||||
/// 8 Data Bits
|
||||
DataBits8,
|
||||
/// 9 Data Bits
|
||||
DataBits9,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
/// Parity
|
||||
pub enum Parity {
|
||||
/// No parity
|
||||
ParityNone,
|
||||
/// Even Parity
|
||||
ParityEven,
|
||||
/// Odd Parity
|
||||
ParityOdd,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
/// Number of stop bits
|
||||
pub enum StopBits {
|
||||
#[doc = "1 stop bit"]
|
||||
STOP1,
|
||||
@ -106,26 +115,37 @@ pub enum StopBits {
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
/// Config Error
|
||||
pub enum ConfigError {
|
||||
/// Baudrate too low
|
||||
BaudrateTooLow,
|
||||
/// Baudrate too high
|
||||
BaudrateTooHigh,
|
||||
/// Rx or Tx not enabled
|
||||
RxOrTxNotEnabled,
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
/// Config
|
||||
pub struct Config {
|
||||
/// Baud rate
|
||||
pub baudrate: u32,
|
||||
/// Number of data bits
|
||||
pub data_bits: DataBits,
|
||||
/// Number of stop bits
|
||||
pub stop_bits: StopBits,
|
||||
/// Parity type
|
||||
pub parity: Parity,
|
||||
/// if true, on read-like method, if there is a latent error pending,
|
||||
/// read will abort, the error reported and cleared
|
||||
/// if false, the error is ignored and cleared
|
||||
|
||||
/// If true: on a read-like method, if there is a latent error pending,
|
||||
/// the read will abort and the error will be reported and cleared
|
||||
///
|
||||
/// If false: the error is ignored and cleared
|
||||
pub detect_previous_overrun: bool,
|
||||
|
||||
/// Set this to true if the line is considered noise free.
|
||||
/// This will increase the receivers tolerance to clock deviations,
|
||||
/// This will increase the receiver’s tolerance to clock deviations,
|
||||
/// but will effectively disable noise detection.
|
||||
#[cfg(not(usart_v1))]
|
||||
pub assume_noise_free: bool,
|
||||
@ -188,6 +208,7 @@ enum ReadCompletionEvent {
|
||||
Idle(usize),
|
||||
}
|
||||
|
||||
/// Bidirectional UART Driver
|
||||
pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> {
|
||||
tx: UartTx<'d, T, TxDma>,
|
||||
rx: UartRx<'d, T, RxDma>,
|
||||
@ -203,6 +224,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> SetConfig for Uart<'d, T, TxDma, RxDma>
|
||||
}
|
||||
}
|
||||
|
||||
/// Tx-only UART Driver
|
||||
pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> {
|
||||
phantom: PhantomData<&'d mut T>,
|
||||
tx_dma: PeripheralRef<'d, TxDma>,
|
||||
@ -217,6 +239,7 @@ impl<'d, T: BasicInstance, TxDma> SetConfig for UartTx<'d, T, TxDma> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Rx-only UART Driver
|
||||
pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
|
||||
_peri: PeripheralRef<'d, T>,
|
||||
rx_dma: PeripheralRef<'d, RxDma>,
|
||||
@ -247,6 +270,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
||||
Self::new_inner(peri, tx, tx_dma, config)
|
||||
}
|
||||
|
||||
/// Create a new tx-only UART with a clear-to-send pin
|
||||
pub fn new_with_cts(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||
@ -288,10 +312,12 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Reconfigure the driver
|
||||
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||
reconfigure::<T>(config)
|
||||
}
|
||||
|
||||
/// Initiate an asynchronous UART write
|
||||
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
|
||||
where
|
||||
TxDma: crate::usart::TxDma<T>,
|
||||
@ -308,6 +334,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Perform a blocking UART write
|
||||
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||
let r = T::regs();
|
||||
for &b in buffer {
|
||||
@ -317,6 +344,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Block until transmission complete
|
||||
pub fn blocking_flush(&mut self) -> Result<(), Error> {
|
||||
let r = T::regs();
|
||||
while !sr(r).read().tc() {}
|
||||
@ -338,6 +366,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||
Self::new_inner(peri, rx, rx_dma, config)
|
||||
}
|
||||
|
||||
/// Create a new rx-only UART with a request-to-send pin
|
||||
pub fn new_with_rts(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||
@ -387,6 +416,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Reconfigure the driver
|
||||
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||
reconfigure::<T>(config)
|
||||
}
|
||||
@ -444,6 +474,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||
Ok(sr.rxne())
|
||||
}
|
||||
|
||||
/// Initiate an asynchronous UART read
|
||||
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
|
||||
where
|
||||
RxDma: crate::usart::RxDma<T>,
|
||||
@ -453,6 +484,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Read a single u8 if there is one available, otherwise return WouldBlock
|
||||
pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
|
||||
let r = T::regs();
|
||||
if self.check_rx_flags()? {
|
||||
@ -462,6 +494,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform a blocking read into `buffer`
|
||||
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||
let r = T::regs();
|
||||
for b in buffer {
|
||||
@ -471,6 +504,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Initiate an asynchronous read with idle line detection enabled
|
||||
pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
|
||||
where
|
||||
RxDma: crate::usart::RxDma<T>,
|
||||
@ -695,6 +729,7 @@ impl<'d, T: BasicInstance, TxDma> Drop for UartRx<'d, T, TxDma> {
|
||||
}
|
||||
|
||||
impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||
/// Create a new bidirectional UART
|
||||
pub fn new(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||
@ -711,6 +746,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||
Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
|
||||
}
|
||||
|
||||
/// Create a new bidirectional UART with request-to-send and clear-to-send pins
|
||||
pub fn new_with_rtscts(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||
@ -738,6 +774,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||
}
|
||||
|
||||
#[cfg(not(any(usart_v1, usart_v2)))]
|
||||
/// Create a new bidirectional UART with a driver-enable pin
|
||||
pub fn new_with_de(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||
@ -813,6 +850,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Initiate an asynchronous write
|
||||
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
|
||||
where
|
||||
TxDma: crate::usart::TxDma<T>,
|
||||
@ -820,14 +858,17 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||
self.tx.write(buffer).await
|
||||
}
|
||||
|
||||
/// Perform a blocking write
|
||||
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||
self.tx.blocking_write(buffer)
|
||||
}
|
||||
|
||||
/// Block until transmission complete
|
||||
pub fn blocking_flush(&mut self) -> Result<(), Error> {
|
||||
self.tx.blocking_flush()
|
||||
}
|
||||
|
||||
/// Initiate an asynchronous read into `buffer`
|
||||
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
|
||||
where
|
||||
RxDma: crate::usart::RxDma<T>,
|
||||
@ -835,14 +876,17 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||
self.rx.read(buffer).await
|
||||
}
|
||||
|
||||
/// Read a single `u8` or return `WouldBlock`
|
||||
pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
|
||||
self.rx.nb_read()
|
||||
}
|
||||
|
||||
/// Perform a blocking read into `buffer`
|
||||
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||
self.rx.blocking_read(buffer)
|
||||
}
|
||||
|
||||
/// Initiate an an asynchronous read with idle line detection enabled
|
||||
pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
|
||||
where
|
||||
RxDma: crate::usart::RxDma<T>,
|
||||
@ -1292,8 +1336,10 @@ pub(crate) mod sealed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Basic UART driver instance
|
||||
pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {}
|
||||
|
||||
/// Full UART driver instance
|
||||
pub trait FullInstance: sealed::FullInstance {}
|
||||
|
||||
pin_trait!(RxPin, BasicInstance);
|
||||
|
@ -11,6 +11,7 @@ use super::{clear_interrupt_flags, rdr, reconfigure, sr, BasicInstance, Config,
|
||||
use crate::dma::ReadableRingBuffer;
|
||||
use crate::usart::{Regs, Sr};
|
||||
|
||||
/// Rx-only Ring-buffered UART Driver
|
||||
pub struct RingBufferedUartRx<'d, T: BasicInstance, RxDma: super::RxDma<T>> {
|
||||
_peri: PeripheralRef<'d, T>,
|
||||
ring_buf: ReadableRingBuffer<'d, RxDma, u8>,
|
||||
@ -27,8 +28,8 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> SetConfig for RingBufferedUar
|
||||
|
||||
impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> {
|
||||
/// Turn the `UartRx` into a buffered uart which can continously receive in the background
|
||||
/// without the possibility of loosing bytes. The `dma_buf` is a buffer registered to the
|
||||
/// DMA controller, and must be sufficiently large, such that it will not overflow.
|
||||
/// without the possibility of losing bytes. The `dma_buf` is a buffer registered to the
|
||||
/// DMA controller, and must be large enough to prevent overflows.
|
||||
pub fn into_ring_buffered(self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d, T, RxDma> {
|
||||
assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
|
||||
|
||||
@ -49,6 +50,7 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> {
|
||||
}
|
||||
|
||||
impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxDma> {
|
||||
/// Clear the ring buffer and start receiving in the background
|
||||
pub fn start(&mut self) -> Result<(), Error> {
|
||||
// Clear the ring buffer so that it is ready to receive data
|
||||
self.ring_buf.clear();
|
||||
@ -64,6 +66,7 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD
|
||||
Err(err)
|
||||
}
|
||||
|
||||
/// Cleanly stop and reconfigure the driver
|
||||
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||
self.teardown_uart();
|
||||
reconfigure::<T>(config)
|
||||
|
Loading…
Reference in New Issue
Block a user