Added set_fifos/set_rx_watermark/set_tx_watermark

that permit to enable/disable the Rx/Tx FIFOs and to set
the watermarks for the DMA/interrupts triggering
This commit is contained in:
Olivier 2022-09-12 17:06:27 +02:00
parent e681b67d9c
commit b29cc2630c
4 changed files with 89 additions and 11 deletions

View file

@ -62,7 +62,7 @@ impl<D: UartDevice, P: ValidUartPinout<D>> UartPeripheral<Disabled, D, P> {
device.uartlcr_h.write(|w| { device.uartlcr_h.write(|w| {
// FIFOs are enabled // FIFOs are enabled
w.fen().set_bit(); w.fen().set_bit(); // Leaved here for backward compatibility
set_format(w, &config.data_bits, &config.stop_bits, &config.parity); set_format(w, &config.data_bits, &config.stop_bits, &config.parity);
w w
}); });
@ -108,6 +108,29 @@ impl<D: UartDevice, P: ValidUartPinout<D>> UartPeripheral<Enabled, D, P> {
self.transition(Disabled) self.transition(Disabled)
} }
/// Enable/disable the rx/tx FIFO
///
/// Unfortunately, it's not possible to enable/disable rx/tx
/// independently on this chip
/// Default is false
pub fn set_fifos(&mut self, enable: bool) {
super::reader::set_fifos(&self.device, enable)
}
/// Set rx FIFO watermark
///
/// See DS: Table 423
pub fn set_rx_watermark(&mut self, watermark: FifoWatermark) {
super::reader::set_rx_watermark(&self.device, watermark)
}
/// Set tx FIFO watermark
///
/// See DS: Table 423
pub fn set_tx_watermark(&mut self, watermark: FifoWatermark) {
super::writer::set_tx_watermark(&self.device, watermark)
}
/// Enables the Receive Interrupt. /// Enables the Receive Interrupt.
/// ///
/// The relevant UARTx IRQ will fire when there is data in the receive register. /// The relevant UARTx IRQ will fire when there is data in the receive register.

View file

@ -2,7 +2,7 @@
//! //!
//! This module is for receiving data with a UART. //! This module is for receiving data with a UART.
use super::{UartDevice, ValidUartPinout}; use super::{FifoWatermark, UartDevice, ValidUartPinout};
use rp2040_pac::uart0::RegisterBlock; use rp2040_pac::uart0::RegisterBlock;
use embedded_hal::serial::Read; use embedded_hal::serial::Read;
@ -52,16 +52,37 @@ pub(crate) fn is_readable<D: UartDevice>(device: &D) -> bool {
device.uartfr.read().rxfe().bit_is_clear() device.uartfr.read().rxfe().bit_is_clear()
} }
/// Enable/disable the rx/tx FIFO
///
/// Unfortunately, it's not possible to enable/disable rx/tx
/// independently on this chip
/// Default is false
pub fn set_fifos(rb: &RegisterBlock, enable: bool) {
if enable {
rb.uartlcr_h.modify(|_r, w| w.fen().set_bit())
} else {
rb.uartlcr_h.modify(|_r, w| w.fen().clear_bit())
}
}
/// Set rx FIFO watermark
///
/// See DS: Table 423
pub fn set_rx_watermark(rb: &RegisterBlock, watermark: FifoWatermark) {
let wm = match watermark {
FifoWatermark::Bytes4 => 0,
FifoWatermark::Bytes8 => 1,
FifoWatermark::Bytes16 => 2,
FifoWatermark::Bytes24 => 3,
FifoWatermark::Bytes28 => 4,
};
rb.uartifls.modify(|_r, w| unsafe { w.rxiflsel().bits(wm) });
}
/// Enables the Receive Interrupt. /// Enables the Receive Interrupt.
/// ///
/// The relevant UARTx IRQ will fire when there is data in the receive register. /// The relevant UARTx IRQ will fire when there is data in the receive register.
pub(crate) fn enable_rx_interrupt(rb: &RegisterBlock) { pub(crate) fn enable_rx_interrupt(rb: &RegisterBlock) {
// Access the UART FIFO Level Select. We set the RX FIFO trip level
// to be half-full.
// 2 means '>= 1/2 full'.
rb.uartifls.modify(|_r, w| unsafe { w.rxiflsel().bits(2) });
// Access the UART Interrupt Mask Set/Clear register. Setting a bit // Access the UART Interrupt Mask Set/Clear register. Setting a bit
// high enables the interrupt. // high enables the interrupt.

View file

@ -44,7 +44,6 @@ pub enum DataBits {
pub enum StopBits { pub enum StopBits {
/// 1 bit /// 1 bit
One, One,
/// 2 bits /// 2 bits
Two, Two,
} }
@ -54,7 +53,6 @@ pub enum StopBits {
pub enum Parity { pub enum Parity {
/// Odd parity /// Odd parity
Odd, Odd,
/// Even parity /// Even parity
Even, Even,
} }
@ -86,6 +84,28 @@ pub struct UartConfig {
pub parity: Option<Parity>, pub parity: Option<Parity>,
} }
/// Rx/Tx FIFO Watermark
///
/// Determine the FIFO level that trigger DMA/Interrupt
/// Default is Bytes16, see DS Table 423 and UARTIFLS Register
/// Example of use:
/// uart0.set_fifos(true); // Default is false
/// uart0.set_rx_watermark(hal::uart::FifoWatermark::Bytes8);
/// uart0.enable_rx_interrupt();
///
pub enum FifoWatermark {
/// Trigger when 4 bytes are (Rx: filled / Tx: available)
Bytes4,
/// Trigger when 8 bytes are (Rx: filled / Tx: available)
Bytes8,
/// Trigger when 16 bytes are (Rx: filled / Tx: available)
Bytes16,
/// Trigger when 24 bytes are (Rx: filled / Tx: available)
Bytes24,
/// Trigger when 28 bytes are (Rx: filled / Tx: available)
Bytes28,
}
impl Default for UartConfig { impl Default for UartConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {

View file

@ -2,7 +2,7 @@
//! //!
//! This module is for transmitting data with a UART. //! This module is for transmitting data with a UART.
use super::{UartDevice, ValidUartPinout}; use super::{FifoWatermark, UartDevice, ValidUartPinout};
use core::fmt; use core::fmt;
use core::{convert::Infallible, marker::PhantomData}; use core::{convert::Infallible, marker::PhantomData};
use embedded_hal::serial::Write; use embedded_hal::serial::Write;
@ -12,6 +12,20 @@ use rp2040_pac::uart0::RegisterBlock;
#[cfg(feature = "eh1_0_alpha")] #[cfg(feature = "eh1_0_alpha")]
use eh1_0_alpha::serial as eh1; use eh1_0_alpha::serial as eh1;
/// Set tx FIFO watermark
///
/// See DS: Table 423
pub fn set_tx_watermark(rb: &RegisterBlock, watermark: FifoWatermark) {
let wm = match watermark {
FifoWatermark::Bytes4 => 4,
FifoWatermark::Bytes8 => 3,
FifoWatermark::Bytes16 => 2,
FifoWatermark::Bytes24 => 1,
FifoWatermark::Bytes28 => 0,
};
rb.uartifls.modify(|_r, w| unsafe { w.txiflsel().bits(wm) });
}
/// Returns `Err(WouldBlock)` if the UART TX FIFO still has data in it or /// Returns `Err(WouldBlock)` if the UART TX FIFO still has data in it or
/// `Ok(())` if the FIFO is empty. /// `Ok(())` if the FIFO is empty.
pub(crate) fn transmit_flushed(rb: &RegisterBlock) -> nb::Result<(), Infallible> { pub(crate) fn transmit_flushed(rb: &RegisterBlock) -> nb::Result<(), Infallible> {