diff options
| author | Emilie Burgun <[email protected]> | 2024-03-27 11:10:16 +0100 |
|---|---|---|
| committer | Emilie Burgun <[email protected]> | 2024-03-27 11:10:16 +0100 |
| commit | e3ef7cd99faf2fe46463882b35d00ef0f2a34481 (patch) | |
| tree | ebc88212468e88f7bb6ccc47b3b2e3de5527da37 | |
| parent | 1acc34bfaa43dfc3410396cb20e371128e693d1a (diff) | |
Document why embedded_io::Read cannot be implemented for the base Uart
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 62ea717b3..7c0523a25 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -209,7 +209,14 @@ enum ReadCompletionEvent { | |||
| 209 | Idle(usize), | 209 | Idle(usize), |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | /// Bidirectional UART Driver | 212 | /// Bidirectional UART Driver, which acts as a combination of [`UartTx`] and [`UartRx`]. |
| 213 | /// | ||
| 214 | /// ### Notes on [`embedded_io::Read`] | ||
| 215 | /// | ||
| 216 | /// `embedded_io::Read` requires guarantees that the base [`UartRx`] cannot provide. | ||
| 217 | /// | ||
| 218 | /// See [`UartRx`] for more details, and see [`BufferedUart`] and [`RingBufferedUartRx`] | ||
| 219 | /// as alternatives that do provide the necessary guarantees for `embedded_io::Read`. | ||
| 213 | pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> { | 220 | pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> { |
| 214 | tx: UartTx<'d, T, TxDma>, | 221 | tx: UartTx<'d, T, TxDma>, |
| 215 | rx: UartRx<'d, T, RxDma>, | 222 | rx: UartRx<'d, T, RxDma>, |
| @@ -225,7 +232,10 @@ impl<'d, T: BasicInstance, TxDma, RxDma> SetConfig for Uart<'d, T, TxDma, RxDma> | |||
| 225 | } | 232 | } |
| 226 | } | 233 | } |
| 227 | 234 | ||
| 228 | /// Tx-only UART Driver | 235 | /// Tx-only UART Driver. |
| 236 | /// | ||
| 237 | /// Can be obtained from [`Uart::split`], or can be constructed independently, | ||
| 238 | /// if you do not need the receiving half of the driver. | ||
| 229 | pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> { | 239 | pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> { |
| 230 | phantom: PhantomData<&'d mut T>, | 240 | phantom: PhantomData<&'d mut T>, |
| 231 | tx_dma: PeripheralRef<'d, TxDma>, | 241 | tx_dma: PeripheralRef<'d, TxDma>, |
| @@ -240,7 +250,35 @@ impl<'d, T: BasicInstance, TxDma> SetConfig for UartTx<'d, T, TxDma> { | |||
| 240 | } | 250 | } |
| 241 | } | 251 | } |
| 242 | 252 | ||
| 243 | /// Rx-only UART Driver | 253 | /// Rx-only UART Driver. |
| 254 | /// | ||
| 255 | /// Can be obtained from [`Uart::split`], or can be constructed independently, | ||
| 256 | /// if you do not need the transmitting half of the driver. | ||
| 257 | /// | ||
| 258 | /// ### Notes on [`embedded_io::Read`] | ||
| 259 | /// | ||
| 260 | /// `embedded_io::Read` requires guarantees that this struct cannot provide: | ||
| 261 | /// | ||
| 262 | /// - Any data received between calls to [`UartRx::read`] or [`UartRx::blocking_read`] | ||
| 263 | /// will be thrown away, as `UartRx` is unbuffered. | ||
| 264 | /// Users of `embedded_io::Read` are likely to not expect this behavior | ||
| 265 | /// (for instance if they read multiple small chunks in a row). | ||
| 266 | /// - [`UartRx::read`] and [`UartRx::blocking_read`] only return once the entire buffer has been | ||
| 267 | /// filled, whereas `embedded_io::Read` requires us to fill the buffer with what we already | ||
| 268 | /// received, and only block/wait until the first byte arrived. | ||
| 269 | /// <br /> | ||
| 270 | /// While [`UartRx::read_until_idle`] does return early, it will still eagerly wait for data until | ||
| 271 | /// the buffer is full or no data has been transmitted in a while, | ||
| 272 | /// which may not be what users of `embedded_io::Read` expect. | ||
| 273 | /// | ||
| 274 | /// [`UartRx::into_ring_buffered`] can be called to equip `UartRx` with a buffer, | ||
| 275 | /// that it can then use to store data received between calls to `read`, | ||
| 276 | /// provided you are using DMA already. | ||
| 277 | /// | ||
| 278 | /// Alternatively, you can use [`BufferedUartRx`], which is interrupt-based and which can also | ||
| 279 | /// store data received between calls. | ||
| 280 | /// | ||
| 281 | /// Also see [this github comment](https://github.com/embassy-rs/embassy/pull/2185#issuecomment-1810047043). | ||
| 244 | pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> { | 282 | pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> { |
| 245 | _peri: PeripheralRef<'d, T>, | 283 | _peri: PeripheralRef<'d, T>, |
| 246 | rx_dma: PeripheralRef<'d, RxDma>, | 284 | rx_dma: PeripheralRef<'d, RxDma>, |
