diff options
| author | Kevin P. Fleming <[email protected]> | 2025-05-24 19:34:07 -0400 |
|---|---|---|
| committer | Kevin P. Fleming <[email protected]> | 2025-05-24 19:34:07 -0400 |
| commit | ca5fe2645dd5a969052081ab855aa88520198e12 (patch) | |
| tree | 95528700a5dabbe6f33840a9e1b83c564870a7e7 | |
| parent | 2ed5e04fd0fa216502c20ec4571a4b553bb86f1f (diff) | |
Move new documentation to RingBufferedUartRx struct.
| -rw-r--r-- | embassy-stm32/src/usart/ringbuffered.rs | 118 |
1 files changed, 62 insertions, 56 deletions
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index 9280dbd18..1d4a44896 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs | |||
| @@ -18,6 +18,65 @@ use crate::Peri; | |||
| 18 | /// Rx-only Ring-buffered UART Driver | 18 | /// Rx-only Ring-buffered UART Driver |
| 19 | /// | 19 | /// |
| 20 | /// Created with [UartRx::into_ring_buffered] | 20 | /// Created with [UartRx::into_ring_buffered] |
| 21 | /// | ||
| 22 | /// ### Notes on 'waiting for bytes' | ||
| 23 | /// | ||
| 24 | /// The `read(buf)` (but not `read()`) and `read_exact(buf)` functions | ||
| 25 | /// may need to wait for bytes to arrive, if the ring buffer does not | ||
| 26 | /// contain enough bytes to fill the buffer passed by the caller of | ||
| 27 | /// the function, or is empty. | ||
| 28 | /// | ||
| 29 | /// Waiting for bytes operates in one of two modes, depending on | ||
| 30 | /// the behavior of the sender and the size of the buffer passed | ||
| 31 | /// to the function: | ||
| 32 | /// | ||
| 33 | /// - If the sender sends intermittently, the 'idle line' | ||
| 34 | /// condition will be detected when the sender stops, and any | ||
| 35 | /// bytes in the ring buffer will be returned. If there are no | ||
| 36 | /// bytes in the buffer, the check will be repeated each time the | ||
| 37 | /// 'idle line' condition is detected, so if the sender sends just | ||
| 38 | /// a single byte, it will be returned once the 'idle line' | ||
| 39 | /// condition is detected. | ||
| 40 | /// | ||
| 41 | /// - If the sender sends continuously, the call will wait until | ||
| 42 | /// the DMA controller indicates that it has written to either the | ||
| 43 | /// middle byte or last byte of the ring buffer ('half transfer' | ||
| 44 | /// or 'transfer complete', respectively). This does not indicate | ||
| 45 | /// the buffer is half-full or full, though, because the DMA | ||
| 46 | /// controller does not detect those conditions; it sends an | ||
| 47 | /// interrupt when those specific buffer addresses have been | ||
| 48 | /// written. | ||
| 49 | /// | ||
| 50 | /// In both cases this will result in variable latency due to the | ||
| 51 | /// buffering effect. For example, if the baudrate is 2400 bps, and | ||
| 52 | /// the configuration is 8 data bits, no parity bit, and one stop bit, | ||
| 53 | /// then a byte will be received every ~4.16ms. If the ring buffer is | ||
| 54 | /// 32 bytes, then a 'wait for bytes' delay may have to wait for 16 | ||
| 55 | /// bytes in the worst case, resulting in a delay (latency) of | ||
| 56 | /// ~62.46ms for the first byte in the ring buffer. If the sender | ||
| 57 | /// sends only 6 bytes and then stops, but the buffer was empty when | ||
| 58 | /// the read function was called, then those bytes may not be returned | ||
| 59 | /// until ~24.96ms after the first byte was received (time for 5 | ||
| 60 | /// additional bytes plus the 'idle frame' which triggers the 'idle | ||
| 61 | /// line' condition). | ||
| 62 | /// | ||
| 63 | /// Applications subject to this latency must be careful if they | ||
| 64 | /// also apply timeouts during reception, as it may appear (to | ||
| 65 | /// them) that the sender has stopped sending when it did not. In | ||
| 66 | /// the example above, a 50ms timeout (12 bytes at 2400bps) might | ||
| 67 | /// seem to be reasonable to detect that the sender has stopped | ||
| 68 | /// sending, but would be falsely triggered in the worst-case | ||
| 69 | /// buffer delay scenario. | ||
| 70 | /// | ||
| 71 | /// Note: This latency is caused by the limited capabilities of the | ||
| 72 | /// STM32 DMA controller; since it cannot generate an interrupt when | ||
| 73 | /// it stores a byte into an empty ring buffer, or in any other | ||
| 74 | /// configurable conditions, it is not possible to take notice of the | ||
| 75 | /// contents of the ring buffer more quickly without introducing | ||
| 76 | /// polling. As a result the latency can be reduced by calling the | ||
| 77 | /// read functions repeatedly with smaller buffers to receive the | ||
| 78 | /// available bytes, as each call to a read function will explicitly | ||
| 79 | /// check the ring buffer for available bytes. | ||
| 21 | pub struct RingBufferedUartRx<'d> { | 80 | pub struct RingBufferedUartRx<'d> { |
| 22 | info: &'static Info, | 81 | info: &'static Info, |
| 23 | state: &'static State, | 82 | state: &'static State, |
| @@ -79,7 +138,8 @@ impl<'d> RingBufferedUartRx<'d> { | |||
| 79 | 138 | ||
| 80 | /// Configure and start the DMA backed UART receiver | 139 | /// Configure and start the DMA backed UART receiver |
| 81 | /// | 140 | /// |
| 82 | /// Note: This is also done automatically by `read()` if required. | 141 | /// Note: This is also done automatically by the read functions if |
| 142 | /// required. | ||
| 83 | pub fn start_uart(&mut self) { | 143 | pub fn start_uart(&mut self) { |
| 84 | // Clear the buffer so that it is ready to receive data | 144 | // Clear the buffer so that it is ready to receive data |
| 85 | compiler_fence(Ordering::SeqCst); | 145 | compiler_fence(Ordering::SeqCst); |
| @@ -148,61 +208,7 @@ impl<'d> RingBufferedUartRx<'d> { | |||
| 148 | /// | 208 | /// |
| 149 | /// Background reception is terminated when an error is returned. | 209 | /// Background reception is terminated when an error is returned. |
| 150 | /// It must be started again by calling `start_uart()` or by | 210 | /// It must be started again by calling `start_uart()` or by |
| 151 | /// calling `read()` again. | 211 | /// calling a read function again. |
| 152 | /// | ||
| 153 | /// ### Notes on 'waiting for bytes' | ||
| 154 | /// | ||
| 155 | /// Waiting for bytes operates in one of two modes, depending on | ||
| 156 | /// the behavior of the sender and the size of the buffer passed | ||
| 157 | /// to `read()`: | ||
| 158 | /// | ||
| 159 | /// - If the sender sends intermittently, the 'idle line' | ||
| 160 | /// condition will be detected when the sender stops, and any | ||
| 161 | /// bytes in the ring buffer will be returned. If there are no | ||
| 162 | /// bytes in the buffer, the check will be repeated each time the | ||
| 163 | /// 'idle line' condition is detected, so if the sender sends just | ||
| 164 | /// a single byte, it will be returned once the 'idle line' | ||
| 165 | /// condition is detected. | ||
| 166 | /// | ||
| 167 | /// - If the sender sends continuously, the call will wait until | ||
| 168 | /// the DMA controller indicates that it has written to either the | ||
| 169 | /// middle byte or last byte of the ring buffer ('half transfer' | ||
| 170 | /// or 'transfer complete', respectively). This does not indicate | ||
| 171 | /// the buffer is half-full or full, though, because the DMA | ||
| 172 | /// controller does not detect those conditions; it sends an | ||
| 173 | /// interrupt when those specific buffer addresses have been | ||
| 174 | /// written. | ||
| 175 | /// | ||
| 176 | /// In both cases this will result in variable latency due to the | ||
| 177 | /// buffering effect. For example, if the baudrate is 2400 bps, | ||
| 178 | /// and the configuration is 8 data bits, no parity bit, and one | ||
| 179 | /// stop bit, then a byte will be received every ~4.16ms. If the | ||
| 180 | /// ring buffer is 32 bytes, then a 'wait for bytes' delay may | ||
| 181 | /// have to wait for 16 bytes in the worst case, resulting in a | ||
| 182 | /// delay (latency) of ~62.46ms for the first byte in the ring | ||
| 183 | /// buffer. If the sender sends only 6 bytes and then stops, but | ||
| 184 | /// the buffer was empty when `read()` was called, then those | ||
| 185 | /// bytes may not be returned until ~24.96ms after the first byte | ||
| 186 | /// was received (time for 5 additional bytes plus the 'idle | ||
| 187 | /// frame' which triggers the 'idle line' condition). | ||
| 188 | /// | ||
| 189 | /// Applications subject to this latency must be careful if they | ||
| 190 | /// also apply timeouts during reception, as it may appear (to | ||
| 191 | /// them) that the sender has stopped sending when it did not. In | ||
| 192 | /// the example above, a 50ms timeout (12 bytes at 2400bps) might | ||
| 193 | /// seem to be reasonable to detect that the sender has stopped | ||
| 194 | /// sending, but would be falsely triggered in the worst-case | ||
| 195 | /// buffer delay scenario. | ||
| 196 | /// | ||
| 197 | /// Note: This latency is caused by the limited capabilities of | ||
| 198 | /// the STM32 DMA controller; since it cannot generate an | ||
| 199 | /// interrupt when it stores a byte into an empty ring buffer, or | ||
| 200 | /// in any other configurable conditions, it is not possible to | ||
| 201 | /// take notice of the contents of the ring buffer more quickly | ||
| 202 | /// without introducing polling. As a result the latency can be | ||
| 203 | /// reduced by calling `read()` repeatedly with smaller buffers to | ||
| 204 | /// receive the available bytes, as each call to `read()` will | ||
| 205 | /// explicitly check the ring buffer for available bytes. | ||
| 206 | pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { | 212 | pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { |
| 207 | self.start_dma_or_check_errors()?; | 213 | self.start_dma_or_check_errors()?; |
| 208 | 214 | ||
