diff options
| -rw-r--r-- | embassy-stm32/src/usart/ringbuffered.rs | 73 |
1 files changed, 65 insertions, 8 deletions
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index eaa9424c5..9280dbd18 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs | |||
| @@ -79,7 +79,7 @@ impl<'d> RingBufferedUartRx<'d> { | |||
| 79 | 79 | ||
| 80 | /// Configure and start the DMA backed UART receiver | 80 | /// Configure and start the DMA backed UART receiver |
| 81 | /// | 81 | /// |
| 82 | /// Note: This is also done automatically by [`read()`] if required. | 82 | /// Note: This is also done automatically by `read()` if required. |
| 83 | pub fn start_uart(&mut self) { | 83 | pub fn start_uart(&mut self) { |
| 84 | // Clear the buffer so that it is ready to receive data | 84 | // Clear the buffer so that it is ready to receive data |
| 85 | compiler_fence(Ordering::SeqCst); | 85 | compiler_fence(Ordering::SeqCst); |
| @@ -139,14 +139,70 @@ impl<'d> RingBufferedUartRx<'d> { | |||
| 139 | Ok(()) | 139 | Ok(()) |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | /// Read bytes that are readily available in the ring buffer. | 142 | /// Read bytes that are available in the ring buffer, or wait for |
| 143 | /// If no bytes are currently available in the buffer the call waits until the some | 143 | /// bytes to become available and return them. |
| 144 | /// bytes are available (at least one byte and at most half the buffer size) | ||
| 145 | /// | 144 | /// |
| 146 | /// Background receive is started if `start()` has not been previously called. | 145 | /// Background reception is started if necessary (if `start_uart()` had |
| 146 | /// not previously been called, or if an error was detected which | ||
| 147 | /// caused background reception to be stopped). | ||
| 147 | /// | 148 | /// |
| 148 | /// Receive in the background is terminated if an error is returned. | 149 | /// Background reception is terminated when an error is returned. |
| 149 | /// It must then manually be started again by calling `start()` or by re-calling `read()`. | 150 | /// It must be started again by calling `start_uart()` or by |
| 151 | /// calling `read()` 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. | ||
| 150 | pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { | 206 | pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { |
| 151 | self.start_dma_or_check_errors()?; | 207 | self.start_dma_or_check_errors()?; |
| 152 | 208 | ||
| @@ -202,7 +258,8 @@ impl<'d> RingBufferedUartRx<'d> { | |||
| 202 | }); | 258 | }); |
| 203 | 259 | ||
| 204 | let mut dma_init = false; | 260 | let mut dma_init = false; |
| 205 | // Future which completes when there is dma is half full or full | 261 | // Future which completes when the DMA controller indicates it |
| 262 | // has written to the ring buffer's middle byte, or last byte | ||
| 206 | let dma = poll_fn(|cx| { | 263 | let dma = poll_fn(|cx| { |
| 207 | self.ring_buf.set_waker(cx.waker()); | 264 | self.ring_buf.set_waker(cx.waker()); |
| 208 | 265 | ||
