nrf: docs.

This commit is contained in:
Dario Nieuwenhuis
2023-02-01 00:48:33 +01:00
parent ca10fe7135
commit b5cf332cc0
40 changed files with 694 additions and 245 deletions

View File

@ -1,8 +1,6 @@
#![macro_use]
//! Async UART
//! Universal Asynchronous Receiver Transmitter (UART) driver.
//!
//! Async UART is provided in two flavors - this one and also [crate::buffered_uarte::BufferedUarte].
//! The UART driver is provided in two flavors - this one and also [crate::buffered_uarte::BufferedUarte].
//! The [Uarte] here is useful for those use-cases where reading the UARTE peripheral is
//! exclusively awaited on. If the [Uarte] is required to be awaited on with some other future,
//! for example when using `futures_util::future::select`, then you should consider
@ -13,6 +11,8 @@
//! memory may be used given that buffers are passed in directly to its read and write
//! methods.
#![macro_use]
use core::future::poll_fn;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
@ -32,10 +32,13 @@ use crate::timer::{Frequency, Instance as TimerInstance, Timer};
use crate::util::slice_in_ram_or;
use crate::{pac, Peripheral};
/// UARTE config.
#[derive(Clone)]
#[non_exhaustive]
pub struct Config {
/// Parity bit.
pub parity: Parity,
/// Baud rate.
pub baudrate: Baudrate,
}
@ -48,31 +51,33 @@ impl Default for Config {
}
}
/// UART error.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum Error {
/// Buffer was too long.
BufferTooLong,
DMABufferNotInDataMemory,
// TODO: add other error variants.
/// The buffer is not in data RAM. It's most likely in flash, and nRF's DMA cannot access flash.
BufferNotInRAM,
}
/// Interface to the UARTE peripheral using EasyDMA to offload the transmission and reception workload.
///
/// For more details about EasyDMA, consult the module documentation.
/// UARTE driver.
pub struct Uarte<'d, T: Instance> {
tx: UarteTx<'d, T>,
rx: UarteRx<'d, T>,
}
/// Transmitter interface to the UARTE peripheral obtained
/// via [Uarte]::split.
/// Transmitter part of the UARTE driver.
///
/// This can be obtained via [`Uarte::split`], or created directly.
pub struct UarteTx<'d, T: Instance> {
_p: PeripheralRef<'d, T>,
}
/// Receiver interface to the UARTE peripheral obtained
/// via [Uarte]::split.
/// Receiver part of the UARTE driver.
///
/// This can be obtained via [`Uarte::split`], or created directly.
pub struct UarteRx<'d, T: Instance> {
_p: PeripheralRef<'d, T>,
}
@ -165,16 +170,16 @@ impl<'d, T: Instance> Uarte<'d, T> {
}
}
/// Split the Uarte into a transmitter and receiver, which is
/// particularly useful when having two tasks correlating to
/// transmitting and receiving.
/// Split the Uarte into the transmitter and receiver parts.
///
/// This is useful to concurrently transmit and receive from independent tasks.
pub fn split(self) -> (UarteTx<'d, T>, UarteRx<'d, T>) {
(self.tx, self.rx)
}
/// Split the Uarte into a transmitter and receiver that will
/// return on idle, which is determined as the time it takes
/// for two bytes to be received.
/// Split the Uarte into the transmitter and receiver with idle support parts.
///
/// This is useful to concurrently transmit and receive from independent tasks.
pub fn split_with_idle<U: TimerInstance>(
self,
timer: impl Peripheral<P = U> + 'd,
@ -247,10 +252,12 @@ impl<'d, T: Instance> Uarte<'d, T> {
}
}
/// Read bytes until the buffer is filled.
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
self.rx.read(buffer).await
}
/// Write all bytes in the buffer.
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
self.tx.write(buffer).await
}
@ -260,10 +267,12 @@ impl<'d, T: Instance> Uarte<'d, T> {
self.tx.write_from_ram(buffer).await
}
/// Read bytes until the buffer is filled.
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
self.rx.blocking_read(buffer)
}
/// Write all bytes in the buffer.
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
self.tx.blocking_write(buffer)
}
@ -355,10 +364,11 @@ impl<'d, T: Instance> UarteTx<'d, T> {
Self { _p: uarte }
}
/// Write all bytes in the buffer.
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
match self.write_from_ram(buffer).await {
Ok(_) => Ok(()),
Err(Error::DMABufferNotInDataMemory) => {
Err(Error::BufferNotInRAM) => {
trace!("Copying UARTE tx buffer into RAM for DMA");
let ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..buffer.len()];
ram_buf.copy_from_slice(buffer);
@ -368,12 +378,13 @@ impl<'d, T: Instance> UarteTx<'d, T> {
}
}
/// Same as [`write`](Self::write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
pub async fn write_from_ram(&mut self, buffer: &[u8]) -> Result<(), Error> {
if buffer.len() == 0 {
return Ok(());
}
slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?;
slice_in_ram_or(buffer, Error::BufferNotInRAM)?;
if buffer.len() > EASY_DMA_SIZE {
return Err(Error::BufferTooLong);
}
@ -423,10 +434,11 @@ impl<'d, T: Instance> UarteTx<'d, T> {
Ok(())
}
/// Write all bytes in the buffer.
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
match self.blocking_write_from_ram(buffer) {
Ok(_) => Ok(()),
Err(Error::DMABufferNotInDataMemory) => {
Err(Error::BufferNotInRAM) => {
trace!("Copying UARTE tx buffer into RAM for DMA");
let ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..buffer.len()];
ram_buf.copy_from_slice(buffer);
@ -436,12 +448,13 @@ impl<'d, T: Instance> UarteTx<'d, T> {
}
}
/// Same as [`write_from_ram`](Self::write_from_ram) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
pub fn blocking_write_from_ram(&mut self, buffer: &[u8]) -> Result<(), Error> {
if buffer.len() == 0 {
return Ok(());
}
slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?;
slice_in_ram_or(buffer, Error::BufferNotInRAM)?;
if buffer.len() > EASY_DMA_SIZE {
return Err(Error::BufferTooLong);
}
@ -549,6 +562,7 @@ impl<'d, T: Instance> UarteRx<'d, T> {
Self { _p: uarte }
}
/// Read bytes until the buffer is filled.
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
if buffer.len() == 0 {
return Ok(());
@ -602,6 +616,7 @@ impl<'d, T: Instance> UarteRx<'d, T> {
Ok(())
}
/// Read bytes until the buffer is filled.
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
if buffer.len() == 0 {
return Ok(());
@ -653,6 +668,9 @@ impl<'a, T: Instance> Drop for UarteRx<'a, T> {
}
}
/// Receiver part of the UARTE driver, with `read_until_idle` support.
///
/// This can be obtained via [`Uarte::split_with_idle`].
pub struct UarteRxWithIdle<'d, T: Instance, U: TimerInstance> {
rx: UarteRx<'d, T>,
timer: Timer<'d, U>,
@ -661,16 +679,21 @@ pub struct UarteRxWithIdle<'d, T: Instance, U: TimerInstance> {
}
impl<'d, T: Instance, U: TimerInstance> UarteRxWithIdle<'d, T, U> {
/// Read bytes until the buffer is filled.
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
self.ppi_ch1.disable();
self.rx.read(buffer).await
}
/// Read bytes until the buffer is filled.
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
self.ppi_ch1.disable();
self.rx.blocking_read(buffer)
}
/// Read bytes until the buffer is filled, or the line becomes idle.
///
/// Returns the amount of bytes read.
pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
if buffer.len() == 0 {
return Ok(0);
@ -727,6 +750,9 @@ impl<'d, T: Instance, U: TimerInstance> UarteRxWithIdle<'d, T, U> {
Ok(n)
}
/// Read bytes until the buffer is filled, or the line becomes idle.
///
/// Returns the amount of bytes read.
pub fn blocking_read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
if buffer.len() == 0 {
return Ok(0);
@ -860,7 +886,9 @@ pub(crate) mod sealed {
}
}
/// UARTE peripheral instance.
pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
/// Interrupt for this peripheral.
type Interrupt: Interrupt;
}
@ -919,7 +947,7 @@ mod eh1 {
fn kind(&self) -> embedded_hal_1::serial::ErrorKind {
match *self {
Self::BufferTooLong => embedded_hal_1::serial::ErrorKind::Other,
Self::DMABufferNotInDataMemory => embedded_hal_1::serial::ErrorKind::Other,
Self::BufferNotInRAM => embedded_hal_1::serial::ErrorKind::Other,
}
}
}