diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-03-27 14:47:19 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-03-27 14:47:19 +0000 |
| commit | a678b4850c6d5db449378ede28638b86fe2c0d39 (patch) | |
| tree | 3c917aa42d20c599423c85b135e5542094090747 | |
| parent | 289c5edb9b12e14cd3918a6580c5a63ed4a9333c (diff) | |
| parent | e3ef7cd99faf2fe46463882b35d00ef0f2a34481 (diff) | |
Merge pull request #2739 from adri326/adri326/nodma-embedded-io
Provide embedded_io impls for Uart with and without Dma
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 7ab33043a..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>, |
| @@ -1260,7 +1298,6 @@ where | |||
| 1260 | impl<T, TxDma, RxDma> embedded_io::Write for Uart<'_, T, TxDma, RxDma> | 1298 | impl<T, TxDma, RxDma> embedded_io::Write for Uart<'_, T, TxDma, RxDma> |
| 1261 | where | 1299 | where |
| 1262 | T: BasicInstance, | 1300 | T: BasicInstance, |
| 1263 | TxDma: crate::usart::TxDma<T>, | ||
| 1264 | { | 1301 | { |
| 1265 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 1302 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 1266 | self.blocking_write(buf)?; | 1303 | self.blocking_write(buf)?; |
| @@ -1275,7 +1312,6 @@ where | |||
| 1275 | impl<T, TxDma> embedded_io::Write for UartTx<'_, T, TxDma> | 1312 | impl<T, TxDma> embedded_io::Write for UartTx<'_, T, TxDma> |
| 1276 | where | 1313 | where |
| 1277 | T: BasicInstance, | 1314 | T: BasicInstance, |
| 1278 | TxDma: crate::usart::TxDma<T>, | ||
| 1279 | { | 1315 | { |
| 1280 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 1316 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 1281 | self.blocking_write(buf)?; | 1317 | self.blocking_write(buf)?; |
