aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/stm32/Cargo.toml2
-rw-r--r--tests/stm32/src/bin/usart_rx_ringbuffered.rs188
-rw-r--r--tests/utils/Cargo.toml10
-rw-r--r--tests/utils/src/bin/saturate_serial.rs52
4 files changed, 252 insertions, 0 deletions
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index d10d01e29..240fad522 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -33,6 +33,8 @@ embedded-hal = "0.2.6"
33embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } 33embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" }
34embedded-hal-async = { version = "=0.2.0-alpha.1" } 34embedded-hal-async = { version = "=0.2.0-alpha.1" }
35panic-probe = { version = "0.3.0", features = ["print-defmt"] } 35panic-probe = { version = "0.3.0", features = ["print-defmt"] }
36rand_core = { version = "0.6", default-features = false }
37rand_chacha = { version = "0.3", default-features = false }
36 38
37chrono = { version = "^0.4", default-features = false, optional = true} 39chrono = { version = "^0.4", default-features = false, optional = true}
38 40
diff --git a/tests/stm32/src/bin/usart_rx_ringbuffered.rs b/tests/stm32/src/bin/usart_rx_ringbuffered.rs
new file mode 100644
index 000000000..3ea8bfb7b
--- /dev/null
+++ b/tests/stm32/src/bin/usart_rx_ringbuffered.rs
@@ -0,0 +1,188 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5#[path = "../example_common.rs"]
6mod example_common;
7use embassy_executor::Spawner;
8use embassy_stm32::interrupt;
9use embassy_stm32::usart::{Config, DataBits, Parity, RingBufferedUartRx, StopBits, Uart, UartTx};
10use embassy_time::{Duration, Timer};
11use example_common::*;
12use rand_chacha::ChaCha8Rng;
13use rand_core::{RngCore, SeedableRng};
14
15#[cfg(feature = "stm32f103c8")]
16mod board {
17 pub type Uart = embassy_stm32::peripherals::USART1;
18 pub type TxDma = embassy_stm32::peripherals::DMA1_CH4;
19 pub type RxDma = embassy_stm32::peripherals::DMA1_CH5;
20}
21#[cfg(feature = "stm32g491re")]
22mod board {
23 pub type Uart = embassy_stm32::peripherals::USART1;
24 pub type TxDma = embassy_stm32::peripherals::DMA1_CH1;
25 pub type RxDma = embassy_stm32::peripherals::DMA1_CH2;
26}
27#[cfg(feature = "stm32g071rb")]
28mod board {
29 pub type Uart = embassy_stm32::peripherals::USART1;
30 pub type TxDma = embassy_stm32::peripherals::DMA1_CH1;
31 pub type RxDma = embassy_stm32::peripherals::DMA1_CH2;
32}
33#[cfg(feature = "stm32f429zi")]
34mod board {
35 pub type Uart = embassy_stm32::peripherals::USART2;
36 pub type TxDma = embassy_stm32::peripherals::DMA1_CH6;
37 pub type RxDma = embassy_stm32::peripherals::DMA1_CH5;
38}
39#[cfg(feature = "stm32wb55rg")]
40mod board {
41 pub type Uart = embassy_stm32::peripherals::LPUART1;
42 pub type TxDma = embassy_stm32::peripherals::DMA1_CH1;
43 pub type RxDma = embassy_stm32::peripherals::DMA1_CH2;
44}
45#[cfg(feature = "stm32h755zi")]
46mod board {
47 pub type Uart = embassy_stm32::peripherals::USART1;
48 pub type TxDma = embassy_stm32::peripherals::DMA1_CH0;
49 pub type RxDma = embassy_stm32::peripherals::DMA1_CH1;
50}
51#[cfg(feature = "stm32u585ai")]
52mod board {
53 pub type Uart = embassy_stm32::peripherals::USART3;
54 pub type TxDma = embassy_stm32::peripherals::GPDMA1_CH0;
55 pub type RxDma = embassy_stm32::peripherals::GPDMA1_CH1;
56}
57
58const ONE_BYTE_DURATION_US: u32 = 9_000_000 / 115200;
59
60#[embassy_executor::main]
61async fn main(spawner: Spawner) {
62 let p = embassy_stm32::init(config());
63 info!("Hello World!");
64
65 // Arduino pins D0 and D1
66 // They're connected together with a 1K resistor.
67 #[cfg(feature = "stm32f103c8")]
68 let (tx, rx, usart, irq, tx_dma, rx_dma) = (
69 p.PA9,
70 p.PA10,
71 p.USART1,
72 interrupt::take!(USART1),
73 p.DMA1_CH4,
74 p.DMA1_CH5,
75 );
76 #[cfg(feature = "stm32g491re")]
77 let (tx, rx, usart, irq, tx_dma, rx_dma) =
78 (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
79 #[cfg(feature = "stm32g071rb")]
80 let (tx, rx, usart, irq, tx_dma, rx_dma) =
81 (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
82 #[cfg(feature = "stm32f429zi")]
83 let (tx, rx, usart, irq, tx_dma, rx_dma) =
84 (p.PA2, p.PA3, p.USART2, interrupt::take!(USART2), p.DMA1_CH6, p.DMA1_CH5);
85 #[cfg(feature = "stm32wb55rg")]
86 let (tx, rx, usart, irq, tx_dma, rx_dma) = (
87 p.PA2,
88 p.PA3,
89 p.LPUART1,
90 interrupt::take!(LPUART1),
91 p.DMA1_CH1,
92 p.DMA1_CH2,
93 );
94 #[cfg(feature = "stm32h755zi")]
95 let (tx, rx, usart, irq, tx_dma, rx_dma) =
96 (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1), p.DMA1_CH0, p.DMA1_CH1);
97 #[cfg(feature = "stm32u585ai")]
98 let (tx, rx, usart, irq, tx_dma, rx_dma) = (
99 p.PD8,
100 p.PD9,
101 p.USART3,
102 interrupt::take!(USART3),
103 p.GPDMA1_CH0,
104 p.GPDMA1_CH1,
105 );
106
107 // To run this test, use the saturating_serial test utility to saturate the serial port
108
109 let mut config = Config::default();
110 config.baudrate = 115200;
111 config.data_bits = DataBits::DataBits8;
112 config.stop_bits = StopBits::STOP1;
113 config.parity = Parity::ParityNone;
114
115 let usart = Uart::new(usart, rx, tx, irq, tx_dma, rx_dma, config);
116 let (tx, rx) = usart.split();
117 static mut DMA_BUF: [u8; 64] = [0; 64];
118 let dma_buf = unsafe { DMA_BUF.as_mut() };
119 let rx = rx.into_ring_buffered(dma_buf);
120
121 info!("Spawning tasks");
122 spawner.spawn(transmit_task(tx)).unwrap();
123 spawner.spawn(receive_task(rx)).unwrap();
124}
125
126#[embassy_executor::task]
127async fn transmit_task(mut tx: UartTx<'static, board::Uart, board::TxDma>) {
128 let mut rng = ChaCha8Rng::seed_from_u64(1337);
129
130 info!("Starting random transmissions into void...");
131
132 let mut i: u8 = 0;
133 loop {
134 let mut buf = [0; 32];
135 let len = 1 + (rng.next_u32() as usize % (buf.len() - 1));
136 for b in &mut buf[..len] {
137 *b = i;
138 i = i.wrapping_add(1);
139 }
140
141 tx.write(&buf[..len]).await.unwrap();
142 Timer::after(Duration::from_micros((rng.next_u32() % 10000) as _)).await;
143
144 //i += 1;
145 //if i % 1000 == 0 {
146 // trace!("Wrote {} times", i);
147 //}
148 }
149}
150
151#[embassy_executor::task]
152async fn receive_task(mut rx: RingBufferedUartRx<'static, board::Uart, board::RxDma>) {
153 info!("Ready to receive...");
154
155 let mut rng = ChaCha8Rng::seed_from_u64(1337);
156
157 let mut i = 0;
158 let mut expected: Option<u8> = None;
159 loop {
160 let mut buf = [0; 100];
161 let max_len = 1 + (rng.next_u32() as usize % (buf.len() - 1));
162 let received = rx.read(&mut buf[..max_len]).await.unwrap();
163
164 if expected.is_none() {
165 info!("Test started");
166 expected = Some(buf[0]);
167 }
168
169 for byte in &buf[..received] {
170 if byte != &expected.unwrap() {
171 error!("Test fail! received {}, expected {}", *byte, expected.unwrap());
172 cortex_m::asm::bkpt();
173 return;
174 }
175 expected = Some(expected.unwrap().wrapping_add(1));
176 }
177
178 if received < max_len {
179 let byte_count = rng.next_u32() % 64;
180 Timer::after(Duration::from_micros((byte_count * ONE_BYTE_DURATION_US) as _)).await;
181 }
182
183 i += 1;
184 if i % 1000 == 0 {
185 trace!("Read {} times", i);
186 }
187 }
188}
diff --git a/tests/utils/Cargo.toml b/tests/utils/Cargo.toml
new file mode 100644
index 000000000..7d66fd586
--- /dev/null
+++ b/tests/utils/Cargo.toml
@@ -0,0 +1,10 @@
1[package]
2name = "test-utils"
3version = "0.1.0"
4edition = "2021"
5
6# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7
8[dependencies]
9rand = "0.8"
10serial = "0.4"
diff --git a/tests/utils/src/bin/saturate_serial.rs b/tests/utils/src/bin/saturate_serial.rs
new file mode 100644
index 000000000..28480516d
--- /dev/null
+++ b/tests/utils/src/bin/saturate_serial.rs
@@ -0,0 +1,52 @@
1use std::path::Path;
2use std::time::Duration;
3use std::{env, io, thread};
4
5use rand::random;
6use serial::SerialPort;
7
8pub fn main() {
9 if let Some(port_name) = env::args().nth(1) {
10 let sleep = env::args().position(|x| x == "--sleep").is_some();
11
12 println!("Saturating port {:?} with 115200 8N1", port_name);
13 println!("Sleep: {}", sleep);
14 let mut port = serial::open(&port_name).unwrap();
15 if saturate(&mut port, sleep).is_err() {
16 eprintln!("Unable to saturate port");
17 }
18 } else {
19 let path = env::args().next().unwrap();
20 let basepath = Path::new(&path).with_extension("");
21 let basename = basepath.file_name().unwrap();
22 eprintln!("USAGE: {} <port-name>", basename.to_string_lossy());
23 }
24}
25
26fn saturate<T: SerialPort>(port: &mut T, sleep: bool) -> io::Result<()> {
27 port.reconfigure(&|settings| {
28 settings.set_baud_rate(serial::Baud115200)?;
29 settings.set_char_size(serial::Bits8);
30 settings.set_parity(serial::ParityNone);
31 settings.set_stop_bits(serial::Stop1);
32 Ok(())
33 })?;
34
35 let mut written = 0;
36 loop {
37 let len = random::<usize>() % 0x1000;
38 let buf: Vec<u8> = (written..written + len).map(|x| x as u8).collect();
39
40 port.write_all(&buf)?;
41
42 if sleep {
43 let micros = (random::<usize>() % 1000) as u64;
44 println!("Sleeping {}us", micros);
45 port.flush().unwrap();
46 thread::sleep(Duration::from_micros(micros));
47 }
48
49 written += len;
50 println!("Written: {}", written);
51 }
52} \ No newline at end of file