diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2023-05-01 15:35:39 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-05-01 15:35:39 +0000 |
| commit | 05c36e05f9f6b1a0a36982239b2e7c697f0d3734 (patch) | |
| tree | 68852621ce845a7e5a6e15ee07bbcb54b49ef9a8 /tests | |
| parent | ac0ea406f91a5b630811accd0c97a622a020c700 (diff) | |
| parent | b58b9ff390fb885f0cca2ad15fc89d537f3a9818 (diff) | |
Merge #1414
1414: rp: report errors from buffered and dma uart receives r=Dirbaio a=pennae
neither of these reported errors so far, which is not ideal. add error reporting to both of them that matches the blocking error reporting as closely as is feasible, even allowing partial receives from buffered uarts before errors are reported where they would have been by the blocking code. dma transfers don't do this, if an errors applies to any byte in a transfer the entire transfer is nuked (though we probably could report how many bytes have been transferred).
Co-authored-by: pennae <[email protected]>
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/rp/src/bin/uart.rs | 159 | ||||
| -rw-r--r-- | tests/rp/src/bin/uart_buffered.rs | 249 | ||||
| -rw-r--r-- | tests/rp/src/bin/uart_dma.rs | 238 |
3 files changed, 605 insertions, 41 deletions
diff --git a/tests/rp/src/bin/uart.rs b/tests/rp/src/bin/uart.rs index 92f61464e..80c18c02e 100644 --- a/tests/rp/src/bin/uart.rs +++ b/tests/rp/src/bin/uart.rs | |||
| @@ -4,28 +4,165 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::{assert_eq, *}; | 5 | use defmt::{assert_eq, *}; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_rp::uart::{Config, Uart}; | 7 | use embassy_rp::gpio::{Level, Output}; |
| 8 | use embassy_rp::uart::{Blocking, Config, Error, Instance, Parity, Uart, UartRx}; | ||
| 9 | use embassy_time::{Duration, Timer}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 11 | ||
| 12 | fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Blocking>) -> Result<[u8; N], Error> { | ||
| 13 | let mut buf = [255; N]; | ||
| 14 | uart.blocking_read(&mut buf)?; | ||
| 15 | Ok(buf) | ||
| 16 | } | ||
| 17 | |||
| 18 | fn read1<const N: usize>(uart: &mut UartRx<'_, impl Instance, Blocking>) -> Result<[u8; N], Error> { | ||
| 19 | let mut buf = [255; N]; | ||
| 20 | uart.blocking_read(&mut buf)?; | ||
| 21 | Ok(buf) | ||
| 22 | } | ||
| 23 | |||
| 24 | async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) { | ||
| 25 | pin.set_low(); | ||
| 26 | Timer::after(Duration::from_millis(1)).await; | ||
| 27 | for i in 0..8 { | ||
| 28 | if v & (1 << i) == 0 { | ||
| 29 | pin.set_low(); | ||
| 30 | } else { | ||
| 31 | pin.set_high(); | ||
| 32 | } | ||
| 33 | Timer::after(Duration::from_millis(1)).await; | ||
| 34 | } | ||
| 35 | if let Some(b) = parity { | ||
| 36 | if b { | ||
| 37 | pin.set_high(); | ||
| 38 | } else { | ||
| 39 | pin.set_low(); | ||
| 40 | } | ||
| 41 | Timer::after(Duration::from_millis(1)).await; | ||
| 42 | } | ||
| 43 | pin.set_high(); | ||
| 44 | Timer::after(Duration::from_millis(1)).await; | ||
| 45 | } | ||
| 46 | |||
| 10 | #[embassy_executor::main] | 47 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 48 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_rp::init(Default::default()); | 49 | let p = embassy_rp::init(Default::default()); |
| 13 | info!("Hello World!"); | 50 | info!("Hello World!"); |
| 14 | 51 | ||
| 15 | let (tx, rx, uart) = (p.PIN_0, p.PIN_1, p.UART0); | 52 | let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0); |
| 53 | |||
| 54 | { | ||
| 55 | let config = Config::default(); | ||
| 56 | let mut uart = Uart::new_blocking(&mut uart, &mut tx, &mut rx, config); | ||
| 57 | |||
| 58 | // We can't send too many bytes, they have to fit in the FIFO. | ||
| 59 | // This is because we aren't sending+receiving at the same time. | ||
| 60 | |||
| 61 | let data = [0xC0, 0xDE]; | ||
| 62 | uart.blocking_write(&data).unwrap(); | ||
| 63 | assert_eq!(read(&mut uart).unwrap(), data); | ||
| 64 | } | ||
| 65 | |||
| 66 | info!("test overflow detection"); | ||
| 67 | { | ||
| 68 | let config = Config::default(); | ||
| 69 | let mut uart = Uart::new_blocking(&mut uart, &mut tx, &mut rx, config); | ||
| 70 | |||
| 71 | let data = [ | ||
| 72 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, | ||
| 73 | 30, 31, 32, | ||
| 74 | ]; | ||
| 75 | let overflow = [ | ||
| 76 | 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, | ||
| 77 | ]; | ||
| 78 | uart.blocking_write(&data).unwrap(); | ||
| 79 | uart.blocking_write(&overflow).unwrap(); | ||
| 80 | while uart.busy() {} | ||
| 81 | |||
| 82 | // prefix in fifo is valid | ||
| 83 | assert_eq!(read(&mut uart).unwrap(), data); | ||
| 84 | // next received character causes overrun error and is discarded | ||
| 85 | uart.blocking_write(&[1, 2, 3]).unwrap(); | ||
| 86 | assert_eq!(read::<1>(&mut uart).unwrap_err(), Error::Overrun); | ||
| 87 | assert_eq!(read(&mut uart).unwrap(), [2, 3]); | ||
| 88 | } | ||
| 89 | |||
| 90 | info!("test break detection"); | ||
| 91 | { | ||
| 92 | let config = Config::default(); | ||
| 93 | let mut uart = Uart::new_blocking(&mut uart, &mut tx, &mut rx, config); | ||
| 94 | |||
| 95 | // break on empty fifo | ||
| 96 | uart.send_break(20).await; | ||
| 97 | uart.blocking_write(&[64]).unwrap(); | ||
| 98 | assert_eq!(read::<1>(&mut uart).unwrap_err(), Error::Break); | ||
| 99 | assert_eq!(read(&mut uart).unwrap(), [64]); | ||
| 100 | |||
| 101 | // break on partially filled fifo | ||
| 102 | uart.blocking_write(&[65; 2]).unwrap(); | ||
| 103 | uart.send_break(20).await; | ||
| 104 | uart.blocking_write(&[66]).unwrap(); | ||
| 105 | assert_eq!(read(&mut uart).unwrap(), [65; 2]); | ||
| 106 | assert_eq!(read::<1>(&mut uart).unwrap_err(), Error::Break); | ||
| 107 | assert_eq!(read(&mut uart).unwrap(), [66]); | ||
| 108 | } | ||
| 109 | |||
| 110 | // parity detection. here we bitbang to not require two uarts. | ||
| 111 | info!("test parity error detection"); | ||
| 112 | { | ||
| 113 | let mut pin = Output::new(&mut tx, Level::High); | ||
| 114 | let mut config = Config::default(); | ||
| 115 | config.baudrate = 1000; | ||
| 116 | config.parity = Parity::ParityEven; | ||
| 117 | let mut uart = UartRx::new_blocking(&mut uart, &mut rx, config); | ||
| 118 | |||
| 119 | async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u8) { | ||
| 120 | send(pin, v, Some(parity != 0)).await; | ||
| 121 | } | ||
| 122 | |||
| 123 | // first check that we can send correctly | ||
| 124 | chr(&mut pin, 64, 1).await; | ||
| 125 | assert_eq!(read1(&mut uart).unwrap(), [64]); | ||
| 126 | |||
| 127 | // all good, check real errors | ||
| 128 | chr(&mut pin, 2, 1).await; | ||
| 129 | chr(&mut pin, 3, 0).await; | ||
| 130 | chr(&mut pin, 4, 0).await; | ||
| 131 | chr(&mut pin, 5, 0).await; | ||
| 132 | assert_eq!(read1(&mut uart).unwrap(), [2, 3]); | ||
| 133 | assert_eq!(read1::<1>(&mut uart).unwrap_err(), Error::Parity); | ||
| 134 | assert_eq!(read1(&mut uart).unwrap(), [5]); | ||
| 135 | } | ||
| 16 | 136 | ||
| 17 | let config = Config::default(); | 137 | // framing error detection. here we bitbang because there's no other way. |
| 18 | let mut uart = Uart::new_blocking(uart, tx, rx, config); | 138 | info!("test framing error detection"); |
| 139 | { | ||
| 140 | let mut pin = Output::new(&mut tx, Level::High); | ||
| 141 | let mut config = Config::default(); | ||
| 142 | config.baudrate = 1000; | ||
| 143 | let mut uart = UartRx::new_blocking(&mut uart, &mut rx, config); | ||
| 19 | 144 | ||
| 20 | // We can't send too many bytes, they have to fit in the FIFO. | 145 | async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) { |
| 21 | // This is because we aren't sending+receiving at the same time. | 146 | if good { |
| 147 | send(pin, v, None).await; | ||
| 148 | } else { | ||
| 149 | send(pin, v, Some(false)).await; | ||
| 150 | } | ||
| 151 | } | ||
| 22 | 152 | ||
| 23 | let data = [0xC0, 0xDE]; | 153 | // first check that we can send correctly |
| 24 | uart.blocking_write(&data).unwrap(); | 154 | chr(&mut pin, 64, true).await; |
| 155 | assert_eq!(read1(&mut uart).unwrap(), [64]); | ||
| 25 | 156 | ||
| 26 | let mut buf = [0; 2]; | 157 | // all good, check real errors |
| 27 | uart.blocking_read(&mut buf).unwrap(); | 158 | chr(&mut pin, 2, true).await; |
| 28 | assert_eq!(buf, data); | 159 | chr(&mut pin, 3, true).await; |
| 160 | chr(&mut pin, 4, false).await; | ||
| 161 | chr(&mut pin, 5, true).await; | ||
| 162 | assert_eq!(read1(&mut uart).unwrap(), [2, 3]); | ||
| 163 | assert_eq!(read1::<1>(&mut uart).unwrap_err(), Error::Framing); | ||
| 164 | assert_eq!(read1(&mut uart).unwrap(), [5]); | ||
| 165 | } | ||
| 29 | 166 | ||
| 30 | info!("Test OK"); | 167 | info!("Test OK"); |
| 31 | cortex_m::asm::bkpt(); | 168 | cortex_m::asm::bkpt(); |
diff --git a/tests/rp/src/bin/uart_buffered.rs b/tests/rp/src/bin/uart_buffered.rs index bea9283e7..1deb22ce6 100644 --- a/tests/rp/src/bin/uart_buffered.rs +++ b/tests/rp/src/bin/uart_buffered.rs | |||
| @@ -2,39 +2,248 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 4 | 4 | ||
| 5 | use defmt::{assert_eq, *}; | 5 | use defmt::{assert_eq, panic, *}; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_rp::gpio::{Level, Output}; | ||
| 7 | use embassy_rp::interrupt; | 8 | use embassy_rp::interrupt; |
| 8 | use embassy_rp::uart::{BufferedUart, Config}; | 9 | use embassy_rp::uart::{BufferedUart, BufferedUartRx, Config, Error, Instance, Parity}; |
| 9 | use embedded_io::asynch::{Read, Write}; | 10 | use embassy_time::{Duration, Timer}; |
| 11 | use embedded_io::asynch::{Read, ReadExactError, Write}; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 13 | ||
| 14 | async fn read<const N: usize>(uart: &mut BufferedUart<'_, impl Instance>) -> Result<[u8; N], Error> { | ||
| 15 | let mut buf = [255; N]; | ||
| 16 | match uart.read_exact(&mut buf).await { | ||
| 17 | Ok(()) => Ok(buf), | ||
| 18 | // we should not ever produce an Eof condition | ||
| 19 | Err(ReadExactError::UnexpectedEof) => panic!(), | ||
| 20 | Err(ReadExactError::Other(e)) => Err(e), | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | async fn read1<const N: usize>(uart: &mut BufferedUartRx<'_, impl Instance>) -> Result<[u8; N], Error> { | ||
| 25 | let mut buf = [255; N]; | ||
| 26 | match uart.read_exact(&mut buf).await { | ||
| 27 | Ok(()) => Ok(buf), | ||
| 28 | // we should not ever produce an Eof condition | ||
| 29 | Err(ReadExactError::UnexpectedEof) => panic!(), | ||
| 30 | Err(ReadExactError::Other(e)) => Err(e), | ||
| 31 | } | ||
| 32 | } | ||
| 33 | |||
| 34 | async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) { | ||
| 35 | pin.set_low(); | ||
| 36 | Timer::after(Duration::from_millis(1)).await; | ||
| 37 | for i in 0..8 { | ||
| 38 | if v & (1 << i) == 0 { | ||
| 39 | pin.set_low(); | ||
| 40 | } else { | ||
| 41 | pin.set_high(); | ||
| 42 | } | ||
| 43 | Timer::after(Duration::from_millis(1)).await; | ||
| 44 | } | ||
| 45 | if let Some(b) = parity { | ||
| 46 | if b { | ||
| 47 | pin.set_high(); | ||
| 48 | } else { | ||
| 49 | pin.set_low(); | ||
| 50 | } | ||
| 51 | Timer::after(Duration::from_millis(1)).await; | ||
| 52 | } | ||
| 53 | pin.set_high(); | ||
| 54 | Timer::after(Duration::from_millis(1)).await; | ||
| 55 | } | ||
| 56 | |||
| 12 | #[embassy_executor::main] | 57 | #[embassy_executor::main] |
| 13 | async fn main(_spawner: Spawner) { | 58 | async fn main(_spawner: Spawner) { |
| 14 | let p = embassy_rp::init(Default::default()); | 59 | let p = embassy_rp::init(Default::default()); |
| 15 | info!("Hello World!"); | 60 | info!("Hello World!"); |
| 16 | 61 | ||
| 17 | let (tx, rx, uart) = (p.PIN_0, p.PIN_1, p.UART0); | 62 | let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0); |
| 63 | let mut irq = interrupt::take!(UART0_IRQ); | ||
| 64 | |||
| 65 | { | ||
| 66 | let config = Config::default(); | ||
| 67 | let tx_buf = &mut [0u8; 16]; | ||
| 68 | let rx_buf = &mut [0u8; 16]; | ||
| 69 | let mut uart = BufferedUart::new(&mut uart, &mut irq, &mut tx, &mut rx, tx_buf, rx_buf, config); | ||
| 70 | |||
| 71 | // Make sure we send more bytes than fits in the FIFO, to test the actual | ||
| 72 | // bufferedUart. | ||
| 73 | |||
| 74 | let data = [ | ||
| 75 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, | ||
| 76 | 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, | ||
| 77 | ]; | ||
| 78 | uart.write_all(&data).await.unwrap(); | ||
| 79 | info!("Done writing"); | ||
| 80 | |||
| 81 | assert_eq!(read(&mut uart).await.unwrap(), data); | ||
| 82 | } | ||
| 83 | |||
| 84 | info!("test overflow detection"); | ||
| 85 | { | ||
| 86 | let config = Config::default(); | ||
| 87 | let tx_buf = &mut [0u8; 16]; | ||
| 88 | let rx_buf = &mut [0u8; 16]; | ||
| 89 | let mut uart = BufferedUart::new(&mut uart, &mut irq, &mut tx, &mut rx, tx_buf, rx_buf, config); | ||
| 90 | |||
| 91 | // Make sure we send more bytes than fits in the FIFO, to test the actual | ||
| 92 | // bufferedUart. | ||
| 93 | |||
| 94 | let data = [ | ||
| 95 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, | ||
| 96 | 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, | ||
| 97 | ]; | ||
| 98 | let overflow = [ | ||
| 99 | 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, | ||
| 100 | ]; | ||
| 101 | // give each block time to settle into the fifo. we want the overrun to occur at a well-defined point. | ||
| 102 | uart.write_all(&data).await.unwrap(); | ||
| 103 | uart.blocking_flush().unwrap(); | ||
| 104 | while uart.busy() {} | ||
| 105 | uart.write_all(&overflow).await.unwrap(); | ||
| 106 | uart.blocking_flush().unwrap(); | ||
| 107 | while uart.busy() {} | ||
| 108 | |||
| 109 | // already buffered/fifod prefix is valid | ||
| 110 | assert_eq!(read(&mut uart).await.unwrap(), data); | ||
| 111 | // next received character causes overrun error and is discarded | ||
| 112 | uart.write_all(&[1, 2, 3]).await.unwrap(); | ||
| 113 | uart.blocking_flush().unwrap(); | ||
| 114 | assert_eq!(read::<1>(&mut uart).await.unwrap_err(), Error::Overrun); | ||
| 115 | assert_eq!(read(&mut uart).await.unwrap(), [2, 3]); | ||
| 116 | } | ||
| 117 | |||
| 118 | info!("test break detection"); | ||
| 119 | { | ||
| 120 | let mut config = Config::default(); | ||
| 121 | config.baudrate = 1000; | ||
| 122 | let tx_buf = &mut [0u8; 16]; | ||
| 123 | let rx_buf = &mut [0u8; 16]; | ||
| 124 | let mut uart = BufferedUart::new(&mut uart, &mut irq, &mut tx, &mut rx, tx_buf, rx_buf, config); | ||
| 125 | |||
| 126 | // break on empty buffer | ||
| 127 | uart.send_break(20).await; | ||
| 128 | assert_eq!(read::<1>(&mut uart).await.unwrap_err(), Error::Break); | ||
| 129 | uart.write_all(&[64]).await.unwrap(); | ||
| 130 | assert_eq!(read(&mut uart).await.unwrap(), [64]); | ||
| 131 | |||
| 132 | // break on partially filled buffer | ||
| 133 | uart.write_all(&[65; 2]).await.unwrap(); | ||
| 134 | uart.send_break(20).await; | ||
| 135 | uart.write_all(&[66]).await.unwrap(); | ||
| 136 | assert_eq!(read(&mut uart).await.unwrap(), [65; 2]); | ||
| 137 | assert_eq!(read::<1>(&mut uart).await.unwrap_err(), Error::Break); | ||
| 138 | assert_eq!(read(&mut uart).await.unwrap(), [66]); | ||
| 139 | |||
| 140 | // break on full buffer | ||
| 141 | uart.write_all(&[64; 16]).await.unwrap(); | ||
| 142 | uart.send_break(20).await; | ||
| 143 | uart.write_all(&[65]).await.unwrap(); | ||
| 144 | assert_eq!(read(&mut uart).await.unwrap(), [64; 16]); | ||
| 145 | assert_eq!(read::<1>(&mut uart).await.unwrap_err(), Error::Break); | ||
| 146 | assert_eq!(read(&mut uart).await.unwrap(), [65]); | ||
| 147 | } | ||
| 148 | |||
| 149 | // parity detection. here we bitbang to not require two uarts. | ||
| 150 | info!("test parity error detection"); | ||
| 151 | { | ||
| 152 | let mut pin = Output::new(&mut tx, Level::High); | ||
| 153 | // choose a very slow baud rate to make tests reliable even with O0 | ||
| 154 | let mut config = Config::default(); | ||
| 155 | config.baudrate = 1000; | ||
| 156 | config.parity = Parity::ParityEven; | ||
| 157 | let rx_buf = &mut [0u8; 16]; | ||
| 158 | let mut uart = BufferedUartRx::new(&mut uart, &mut irq, &mut rx, rx_buf, config); | ||
| 159 | |||
| 160 | async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u32) { | ||
| 161 | send(pin, v, Some(parity != 0)).await; | ||
| 162 | } | ||
| 163 | |||
| 164 | // first check that we can send correctly | ||
| 165 | chr(&mut pin, 64, 1).await; | ||
| 166 | assert_eq!(read1(&mut uart).await.unwrap(), [64]); | ||
| 167 | |||
| 168 | // parity on empty buffer | ||
| 169 | chr(&mut pin, 64, 0).await; | ||
| 170 | chr(&mut pin, 4, 1).await; | ||
| 171 | assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity); | ||
| 172 | assert_eq!(read1(&mut uart).await.unwrap(), [4]); | ||
| 173 | |||
| 174 | // parity on partially filled buffer | ||
| 175 | chr(&mut pin, 64, 1).await; | ||
| 176 | chr(&mut pin, 32, 1).await; | ||
| 177 | chr(&mut pin, 64, 0).await; | ||
| 178 | chr(&mut pin, 65, 0).await; | ||
| 179 | assert_eq!(read1(&mut uart).await.unwrap(), [64, 32]); | ||
| 180 | assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity); | ||
| 181 | assert_eq!(read1(&mut uart).await.unwrap(), [65]); | ||
| 182 | |||
| 183 | // parity on full buffer | ||
| 184 | for i in 0..16 { | ||
| 185 | chr(&mut pin, i, i.count_ones() % 2).await; | ||
| 186 | } | ||
| 187 | chr(&mut pin, 64, 0).await; | ||
| 188 | chr(&mut pin, 65, 0).await; | ||
| 189 | assert_eq!( | ||
| 190 | read1(&mut uart).await.unwrap(), | ||
| 191 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] | ||
| 192 | ); | ||
| 193 | assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity); | ||
| 194 | assert_eq!(read1(&mut uart).await.unwrap(), [65]); | ||
| 195 | } | ||
| 196 | |||
| 197 | // framing error detection. here we bitbang because there's no other way. | ||
| 198 | info!("test framing error detection"); | ||
| 199 | { | ||
| 200 | let mut pin = Output::new(&mut tx, Level::High); | ||
| 201 | // choose a very slow baud rate to make tests reliable even with O0 | ||
| 202 | let mut config = Config::default(); | ||
| 203 | config.baudrate = 1000; | ||
| 204 | let rx_buf = &mut [0u8; 16]; | ||
| 205 | let mut uart = BufferedUartRx::new(&mut uart, &mut irq, &mut rx, rx_buf, config); | ||
| 206 | |||
| 207 | async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) { | ||
| 208 | if good { | ||
| 209 | send(pin, v, None).await; | ||
| 210 | } else { | ||
| 211 | send(pin, v, Some(false)).await; | ||
| 212 | } | ||
| 213 | } | ||
| 18 | 214 | ||
| 19 | let config = Config::default(); | 215 | // first check that we can send correctly |
| 20 | let irq = interrupt::take!(UART0_IRQ); | 216 | chr(&mut pin, 64, true).await; |
| 21 | let tx_buf = &mut [0u8; 16]; | 217 | assert_eq!(read1(&mut uart).await.unwrap(), [64]); |
| 22 | let rx_buf = &mut [0u8; 16]; | ||
| 23 | let mut uart = BufferedUart::new(uart, irq, tx, rx, tx_buf, rx_buf, config); | ||
| 24 | 218 | ||
| 25 | // Make sure we send more bytes than fits in the FIFO, to test the actual | 219 | // framing on empty buffer |
| 26 | // bufferedUart. | 220 | chr(&mut pin, 64, false).await; |
| 221 | assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing); | ||
| 222 | chr(&mut pin, 65, true).await; | ||
| 223 | assert_eq!(read1(&mut uart).await.unwrap(), [65]); | ||
| 27 | 224 | ||
| 28 | let data = [ | 225 | // framing on partially filled buffer |
| 29 | 1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, | 226 | chr(&mut pin, 64, true).await; |
| 30 | 30, 31, | 227 | chr(&mut pin, 32, true).await; |
| 31 | ]; | 228 | chr(&mut pin, 64, false).await; |
| 32 | uart.write_all(&data).await.unwrap(); | 229 | chr(&mut pin, 65, true).await; |
| 33 | info!("Done writing"); | 230 | assert_eq!(read1(&mut uart).await.unwrap(), [64, 32]); |
| 231 | assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing); | ||
| 232 | assert_eq!(read1(&mut uart).await.unwrap(), [65]); | ||
| 34 | 233 | ||
| 35 | let mut buf = [0; 31]; | 234 | // framing on full buffer |
| 36 | uart.read_exact(&mut buf).await.unwrap(); | 235 | for i in 0..16 { |
| 37 | assert_eq!(buf, data); | 236 | chr(&mut pin, i, true).await; |
| 237 | } | ||
| 238 | chr(&mut pin, 64, false).await; | ||
| 239 | chr(&mut pin, 65, true).await; | ||
| 240 | assert_eq!( | ||
| 241 | read1(&mut uart).await.unwrap(), | ||
| 242 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] | ||
| 243 | ); | ||
| 244 | assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing); | ||
| 245 | assert_eq!(read1(&mut uart).await.unwrap(), [65]); | ||
| 246 | } | ||
| 38 | 247 | ||
| 39 | info!("Test OK"); | 248 | info!("Test OK"); |
| 40 | cortex_m::asm::bkpt(); | 249 | cortex_m::asm::bkpt(); |
diff --git a/tests/rp/src/bin/uart_dma.rs b/tests/rp/src/bin/uart_dma.rs index 963c22707..92aa205c9 100644 --- a/tests/rp/src/bin/uart_dma.rs +++ b/tests/rp/src/bin/uart_dma.rs | |||
| @@ -4,28 +4,246 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::{assert_eq, *}; | 5 | use defmt::{assert_eq, *}; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_rp::uart::{Config, Uart}; | 7 | use embassy_rp::gpio::{Level, Output}; |
| 8 | use embassy_rp::interrupt; | ||
| 9 | use embassy_rp::uart::{Async, Config, Error, Instance, Parity, Uart, UartRx}; | ||
| 10 | use embassy_time::{Duration, Timer}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 12 | ||
| 13 | async fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Async>) -> Result<[u8; N], Error> { | ||
| 14 | let mut buf = [255; N]; | ||
| 15 | uart.read(&mut buf).await?; | ||
| 16 | Ok(buf) | ||
| 17 | } | ||
| 18 | |||
| 19 | async fn read1<const N: usize>(uart: &mut UartRx<'_, impl Instance, Async>) -> Result<[u8; N], Error> { | ||
| 20 | let mut buf = [255; N]; | ||
| 21 | uart.read(&mut buf).await?; | ||
| 22 | Ok(buf) | ||
| 23 | } | ||
| 24 | |||
| 25 | async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) { | ||
| 26 | pin.set_low(); | ||
| 27 | Timer::after(Duration::from_millis(1)).await; | ||
| 28 | for i in 0..8 { | ||
| 29 | if v & (1 << i) == 0 { | ||
| 30 | pin.set_low(); | ||
| 31 | } else { | ||
| 32 | pin.set_high(); | ||
| 33 | } | ||
| 34 | Timer::after(Duration::from_millis(1)).await; | ||
| 35 | } | ||
| 36 | if let Some(b) = parity { | ||
| 37 | if b { | ||
| 38 | pin.set_high(); | ||
| 39 | } else { | ||
| 40 | pin.set_low(); | ||
| 41 | } | ||
| 42 | Timer::after(Duration::from_millis(1)).await; | ||
| 43 | } | ||
| 44 | pin.set_high(); | ||
| 45 | Timer::after(Duration::from_millis(1)).await; | ||
| 46 | } | ||
| 47 | |||
| 10 | #[embassy_executor::main] | 48 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 49 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_rp::init(Default::default()); | 50 | let mut p = embassy_rp::init(Default::default()); |
| 13 | info!("Hello World!"); | 51 | info!("Hello World!"); |
| 14 | 52 | ||
| 15 | let (tx, rx, uart) = (p.PIN_0, p.PIN_1, p.UART0); | 53 | let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0); |
| 54 | let mut irq = interrupt::take!(UART0_IRQ); | ||
| 16 | 55 | ||
| 17 | let config = Config::default(); | 56 | // TODO |
| 18 | let mut uart = Uart::new(uart, tx, rx, p.DMA_CH0, p.DMA_CH1, config); | 57 | // nuclear error reporting. just abort the entire transfer and invalidate the |
| 58 | // dma buffer, buffered buffer, fifo etc. | ||
| 19 | 59 | ||
| 20 | // We can't send too many bytes, they have to fit in the FIFO. | 60 | // We can't send too many bytes, they have to fit in the FIFO. |
| 21 | // This is because we aren't sending+receiving at the same time. | 61 | // This is because we aren't sending+receiving at the same time. |
| 62 | { | ||
| 63 | let config = Config::default(); | ||
| 64 | let mut uart = Uart::new( | ||
| 65 | &mut uart, | ||
| 66 | &mut tx, | ||
| 67 | &mut rx, | ||
| 68 | &mut irq, | ||
| 69 | &mut p.DMA_CH0, | ||
| 70 | &mut p.DMA_CH1, | ||
| 71 | config, | ||
| 72 | ); | ||
| 73 | |||
| 74 | let data = [0xC0, 0xDE]; | ||
| 75 | uart.write(&data).await.unwrap(); | ||
| 76 | |||
| 77 | let mut buf = [0; 2]; | ||
| 78 | uart.read(&mut buf).await.unwrap(); | ||
| 79 | assert_eq!(buf, data); | ||
| 80 | } | ||
| 81 | |||
| 82 | info!("test overflow detection"); | ||
| 83 | { | ||
| 84 | let config = Config::default(); | ||
| 85 | let mut uart = Uart::new( | ||
| 86 | &mut uart, | ||
| 87 | &mut tx, | ||
| 88 | &mut rx, | ||
| 89 | &mut irq, | ||
| 90 | &mut p.DMA_CH0, | ||
| 91 | &mut p.DMA_CH1, | ||
| 92 | config, | ||
| 93 | ); | ||
| 94 | |||
| 95 | uart.blocking_write(&[42; 32]).unwrap(); | ||
| 96 | uart.blocking_write(&[1, 2, 3]).unwrap(); | ||
| 97 | uart.blocking_flush().unwrap(); | ||
| 98 | |||
| 99 | // can receive regular fifo contents | ||
| 100 | assert_eq!(read(&mut uart).await, Ok([42; 16])); | ||
| 101 | assert_eq!(read(&mut uart).await, Ok([42; 16])); | ||
| 102 | // receiving the rest fails with overrun | ||
| 103 | assert_eq!(read::<16>(&mut uart).await, Err(Error::Overrun)); | ||
| 104 | // new data is accepted, latest overrunning byte first | ||
| 105 | assert_eq!(read(&mut uart).await, Ok([3])); | ||
| 106 | uart.blocking_write(&[8, 9]).unwrap(); | ||
| 107 | Timer::after(Duration::from_millis(1)).await; | ||
| 108 | assert_eq!(read(&mut uart).await, Ok([8, 9])); | ||
| 109 | } | ||
| 110 | |||
| 111 | info!("test break detection"); | ||
| 112 | { | ||
| 113 | let config = Config::default(); | ||
| 114 | let (mut tx, mut rx) = Uart::new( | ||
| 115 | &mut uart, | ||
| 116 | &mut tx, | ||
| 117 | &mut rx, | ||
| 118 | &mut irq, | ||
| 119 | &mut p.DMA_CH0, | ||
| 120 | &mut p.DMA_CH1, | ||
| 121 | config, | ||
| 122 | ) | ||
| 123 | .split(); | ||
| 124 | |||
| 125 | // break before read | ||
| 126 | tx.send_break(20).await; | ||
| 127 | tx.write(&[64]).await.unwrap(); | ||
| 128 | assert_eq!(read1::<1>(&mut rx).await.unwrap_err(), Error::Break); | ||
| 129 | assert_eq!(read1(&mut rx).await.unwrap(), [64]); | ||
| 130 | |||
| 131 | // break during read | ||
| 132 | { | ||
| 133 | let r = read1::<2>(&mut rx); | ||
| 134 | tx.write(&[2]).await.unwrap(); | ||
| 135 | tx.send_break(20).await; | ||
| 136 | tx.write(&[3]).await.unwrap(); | ||
| 137 | assert_eq!(r.await.unwrap_err(), Error::Break); | ||
| 138 | assert_eq!(read1(&mut rx).await.unwrap(), [3]); | ||
| 139 | } | ||
| 140 | |||
| 141 | // break after read | ||
| 142 | { | ||
| 143 | let r = read1(&mut rx); | ||
| 144 | tx.write(&[2]).await.unwrap(); | ||
| 145 | tx.send_break(20).await; | ||
| 146 | tx.write(&[3]).await.unwrap(); | ||
| 147 | assert_eq!(r.await.unwrap(), [2]); | ||
| 148 | assert_eq!(read1::<1>(&mut rx).await.unwrap_err(), Error::Break); | ||
| 149 | assert_eq!(read1(&mut rx).await.unwrap(), [3]); | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | // parity detection. here we bitbang to not require two uarts. | ||
| 154 | info!("test parity error detection"); | ||
| 155 | { | ||
| 156 | let mut pin = Output::new(&mut tx, Level::High); | ||
| 157 | // choose a very slow baud rate to make tests reliable even with O0 | ||
| 158 | let mut config = Config::default(); | ||
| 159 | config.baudrate = 1000; | ||
| 160 | config.parity = Parity::ParityEven; | ||
| 161 | let mut uart = UartRx::new(&mut uart, &mut rx, &mut irq, &mut p.DMA_CH0, config); | ||
| 162 | |||
| 163 | async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u32) { | ||
| 164 | send(pin, v, Some(parity != 0)).await; | ||
| 165 | } | ||
| 166 | |||
| 167 | // first check that we can send correctly | ||
| 168 | chr(&mut pin, 32, 1).await; | ||
| 169 | assert_eq!(read1(&mut uart).await.unwrap(), [32]); | ||
| 170 | |||
| 171 | // parity error before read | ||
| 172 | chr(&mut pin, 32, 0).await; | ||
| 173 | chr(&mut pin, 31, 1).await; | ||
| 174 | assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity); | ||
| 175 | assert_eq!(read1(&mut uart).await.unwrap(), [31]); | ||
| 176 | |||
| 177 | // parity error during read | ||
| 178 | { | ||
| 179 | let r = read1::<2>(&mut uart); | ||
| 180 | chr(&mut pin, 2, 1).await; | ||
| 181 | chr(&mut pin, 32, 0).await; | ||
| 182 | chr(&mut pin, 3, 0).await; | ||
| 183 | assert_eq!(r.await.unwrap_err(), Error::Parity); | ||
| 184 | assert_eq!(read1(&mut uart).await.unwrap(), [3]); | ||
| 185 | } | ||
| 186 | |||
| 187 | // parity error after read | ||
| 188 | { | ||
| 189 | let r = read1(&mut uart); | ||
| 190 | chr(&mut pin, 2, 1).await; | ||
| 191 | chr(&mut pin, 32, 0).await; | ||
| 192 | chr(&mut pin, 3, 0).await; | ||
| 193 | assert_eq!(r.await.unwrap(), [2]); | ||
| 194 | assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity); | ||
| 195 | assert_eq!(read1(&mut uart).await.unwrap(), [3]); | ||
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | // framing error detection. here we bitbang because there's no other way. | ||
| 200 | info!("test framing error detection"); | ||
| 201 | { | ||
| 202 | let mut pin = Output::new(&mut tx, Level::High); | ||
| 203 | // choose a very slow baud rate to make tests reliable even with O0 | ||
| 204 | let mut config = Config::default(); | ||
| 205 | config.baudrate = 1000; | ||
| 206 | let mut uart = UartRx::new(&mut uart, &mut rx, &mut irq, &mut p.DMA_CH0, config); | ||
| 207 | |||
| 208 | async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) { | ||
| 209 | if good { | ||
| 210 | send(pin, v, None).await; | ||
| 211 | } else { | ||
| 212 | send(pin, v, Some(false)).await; | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | // first check that we can send correctly | ||
| 217 | chr(&mut pin, 32, true).await; | ||
| 218 | assert_eq!(read1(&mut uart).await.unwrap(), [32]); | ||
| 219 | |||
| 220 | // parity error before read | ||
| 221 | chr(&mut pin, 32, false).await; | ||
| 222 | chr(&mut pin, 31, true).await; | ||
| 223 | assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing); | ||
| 224 | assert_eq!(read1(&mut uart).await.unwrap(), [31]); | ||
| 22 | 225 | ||
| 23 | let data = [0xC0, 0xDE]; | 226 | // parity error during read |
| 24 | uart.write(&data).await.unwrap(); | 227 | { |
| 228 | let r = read1::<2>(&mut uart); | ||
| 229 | chr(&mut pin, 2, true).await; | ||
| 230 | chr(&mut pin, 32, false).await; | ||
| 231 | chr(&mut pin, 3, true).await; | ||
| 232 | assert_eq!(r.await.unwrap_err(), Error::Framing); | ||
| 233 | assert_eq!(read1(&mut uart).await.unwrap(), [3]); | ||
| 234 | } | ||
| 25 | 235 | ||
| 26 | let mut buf = [0; 2]; | 236 | // parity error after read |
| 27 | uart.read(&mut buf).await.unwrap(); | 237 | { |
| 28 | assert_eq!(buf, data); | 238 | let r = read1(&mut uart); |
| 239 | chr(&mut pin, 2, true).await; | ||
| 240 | chr(&mut pin, 32, false).await; | ||
| 241 | chr(&mut pin, 3, true).await; | ||
| 242 | assert_eq!(r.await.unwrap(), [2]); | ||
| 243 | assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing); | ||
| 244 | assert_eq!(read1(&mut uart).await.unwrap(), [3]); | ||
| 245 | } | ||
| 246 | } | ||
| 29 | 247 | ||
| 30 | info!("Test OK"); | 248 | info!("Test OK"); |
| 31 | cortex_m::asm::bkpt(); | 249 | cortex_m::asm::bkpt(); |
