pub struct RingBufferedUartRx<'d> { /* private fields */ }
Expand description
Rx-only Ring-buffered UART Driver
Created with UartRx::into_ring_buffered
§Notes on ‘waiting for bytes’
The read(buf)
(but not read()
) and read_exact(buf)
functions
may need to wait for bytes to arrive, if the ring buffer does not
contain enough bytes to fill the buffer passed by the caller of
the function, or is empty.
Waiting for bytes operates in one of two modes, depending on the behavior of the sender and the size of the buffer passed to the function:
-
If the sender sends intermittently, the ‘idle line’ condition will be detected when the sender stops, and any bytes in the ring buffer will be returned. If there are no bytes in the buffer, the check will be repeated each time the ‘idle line’ condition is detected, so if the sender sends just a single byte, it will be returned once the ‘idle line’ condition is detected.
-
If the sender sends continuously, the call will wait until the DMA controller indicates that it has written to either the middle byte or last byte of the ring buffer (‘half transfer’ or ‘transfer complete’, respectively). This does not indicate the buffer is half-full or full, though, because the DMA controller does not detect those conditions; it sends an interrupt when those specific buffer addresses have been written.
In both cases this will result in variable latency due to the buffering effect. For example, if the baudrate is 2400 bps, and the configuration is 8 data bits, no parity bit, and one stop bit, then a byte will be received every ~4.16ms. If the ring buffer is 32 bytes, then a ‘wait for bytes’ delay may have to wait for 16 bytes in the worst case, resulting in a delay (latency) of ~62.46ms for the first byte in the ring buffer. If the sender sends only 6 bytes and then stops, but the buffer was empty when the read function was called, then those bytes may not be returned until ~24.96ms after the first byte was received (time for 5 additional bytes plus the ‘idle frame’ which triggers the ‘idle line’ condition).
Applications subject to this latency must be careful if they also apply timeouts during reception, as it may appear (to them) that the sender has stopped sending when it did not. In the example above, a 50ms timeout (12 bytes at 2400bps) might seem to be reasonable to detect that the sender has stopped sending, but would be falsely triggered in the worst-case buffer delay scenario.
Note: This latency is caused by the limited capabilities of the STM32 DMA controller; since it cannot generate an interrupt when it stores a byte into an empty ring buffer, or in any other configurable conditions, it is not possible to take notice of the contents of the ring buffer more quickly without introducing polling. As a result the latency can be reduced by calling the read functions repeatedly with smaller buffers to receive the available bytes, as each call to a read function will explicitly check the ring buffer for available bytes.
Implementations§
Source§impl<'d> RingBufferedUartRx<'d>
impl<'d> RingBufferedUartRx<'d>
Sourcepub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError>
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError>
Reconfigure the driver
Sourcepub fn start_uart(&mut self)
pub fn start_uart(&mut self)
Configure and start the DMA backed UART receiver
Note: This is also done automatically by the read functions if required.
Sourcepub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error>
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error>
Read bytes that are available in the ring buffer, or wait for bytes to become available and return them.
Background reception is started if necessary (if start_uart()
had
not previously been called, or if an error was detected which
caused background reception to be stopped).
Background reception is terminated when an error is returned.
It must be started again by calling start_uart()
or by
calling a read function again.
Sourcepub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError>
pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError>
Set baudrate
Trait Implementations§
Source§impl Drop for RingBufferedUartRx<'_>
impl Drop for RingBufferedUartRx<'_>
Source§impl ErrorType for RingBufferedUartRx<'_>
impl ErrorType for RingBufferedUartRx<'_>
Source§impl Read for RingBufferedUartRx<'_>
impl Read for RingBufferedUartRx<'_>
Source§async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>
Source§async fn read_exact(
&mut self,
buf: &mut [u8],
) -> Result<(), ReadExactError<Self::Error>>
async fn read_exact( &mut self, buf: &mut [u8], ) -> Result<(), ReadExactError<Self::Error>>
buf
. Read moreSource§impl Read for RingBufferedUartRx<'_>
impl Read for RingBufferedUartRx<'_>
Source§impl ReadReady for RingBufferedUartRx<'_>
impl ReadReady for RingBufferedUartRx<'_>
Source§impl<'d> SetConfig for RingBufferedUartRx<'d>
impl<'d> SetConfig for RingBufferedUartRx<'d>
Source§type ConfigError = ConfigError
type ConfigError = ConfigError
set_config
fails.