aboutsummaryrefslogtreecommitdiff
path: root/tests/rp/src
diff options
context:
space:
mode:
authorQuentin Smith <[email protected]>2023-07-17 21:31:43 -0400
committerQuentin Smith <[email protected]>2023-07-17 21:31:43 -0400
commit6f02403184eb7fb7990fb88fc9df9c4328a690a3 (patch)
tree748f510e190bb2724750507a6e69ed1a8e08cb20 /tests/rp/src
parentd896f80405aa8963877049ed999e4aba25d6e2bb (diff)
parent6b5df4523aa1c4902f02e803450ae4b418e0e3ca (diff)
Merge remote-tracking branch 'origin/main' into nrf-pdm
Diffstat (limited to 'tests/rp/src')
-rw-r--r--tests/rp/src/bin/adc.rs86
-rw-r--r--tests/rp/src/bin/cyw43-perf.rs264
-rw-r--r--tests/rp/src/bin/dma_copy_async.rs43
-rw-r--r--tests/rp/src/bin/flash.rs65
-rw-r--r--tests/rp/src/bin/float.rs53
-rw-r--r--tests/rp/src/bin/gpio.rs66
-rw-r--r--tests/rp/src/bin/gpio_async.rs4
-rw-r--r--tests/rp/src/bin/gpio_multicore.rs65
-rw-r--r--tests/rp/src/bin/multicore.rs49
-rw-r--r--tests/rp/src/bin/pio_irq.rs55
-rw-r--r--tests/rp/src/bin/pwm.rs144
-rw-r--r--tests/rp/src/bin/spi.rs30
-rw-r--r--tests/rp/src/bin/spi_async.rs86
-rw-r--r--tests/rp/src/bin/uart.rs171
-rw-r--r--tests/rp/src/bin/uart_buffered.rs256
-rw-r--r--tests/rp/src/bin/uart_dma.rs252
-rw-r--r--tests/rp/src/bin/uart_upgrade.rs60
-rw-r--r--tests/rp/src/common.rs1
18 files changed, 1744 insertions, 6 deletions
diff --git a/tests/rp/src/bin/adc.rs b/tests/rp/src/bin/adc.rs
new file mode 100644
index 000000000..e659844ae
--- /dev/null
+++ b/tests/rp/src/bin/adc.rs
@@ -0,0 +1,86 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use defmt::*;
8use embassy_executor::Spawner;
9use embassy_rp::adc::{Adc, Config, InterruptHandler, Pin};
10use embassy_rp::bind_interrupts;
11use embassy_rp::gpio::Pull;
12use {defmt_rtt as _, panic_probe as _};
13
14bind_interrupts!(struct Irqs {
15 ADC_IRQ_FIFO => InterruptHandler;
16});
17
18#[embassy_executor::main]
19async fn main(_spawner: Spawner) {
20 let mut p = embassy_rp::init(Default::default());
21 let mut adc = Adc::new(p.ADC, Irqs, Config::default());
22
23 {
24 {
25 let mut p = Pin::new(&mut p.PIN_26, Pull::Down);
26 defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000);
27 defmt::assert!(adc.read(&mut p).await.unwrap() < 0b01_0000_0000);
28 }
29 {
30 let mut p = Pin::new(&mut p.PIN_26, Pull::Up);
31 defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000);
32 defmt::assert!(adc.read(&mut p).await.unwrap() > 0b11_0000_0000);
33 }
34 }
35 // not bothering with async reads from now on
36 {
37 {
38 let mut p = Pin::new(&mut p.PIN_27, Pull::Down);
39 defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000);
40 }
41 {
42 let mut p = Pin::new(&mut p.PIN_27, Pull::Up);
43 defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000);
44 }
45 }
46 {
47 {
48 let mut p = Pin::new(&mut p.PIN_28, Pull::Down);
49 defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000);
50 }
51 {
52 let mut p = Pin::new(&mut p.PIN_28, Pull::Up);
53 defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000);
54 }
55 }
56 {
57 // gp29 is connected to vsys through a 200k/100k divider,
58 // adding pulls should change the value
59 let low = {
60 let mut p = Pin::new(&mut p.PIN_29, Pull::Down);
61 adc.blocking_read(&mut p).unwrap()
62 };
63 let none = {
64 let mut p = Pin::new(&mut p.PIN_29, Pull::None);
65 adc.blocking_read(&mut p).unwrap()
66 };
67 let up = {
68 let mut p = Pin::new(&mut p.PIN_29, Pull::Up);
69 adc.blocking_read(&mut p).unwrap()
70 };
71 defmt::assert!(low < none);
72 defmt::assert!(none < up);
73 }
74
75 let temp = convert_to_celsius(adc.read_temperature().await.unwrap());
76 defmt::assert!(temp > 0.0);
77 defmt::assert!(temp < 60.0);
78
79 info!("Test OK");
80 cortex_m::asm::bkpt();
81}
82
83fn convert_to_celsius(raw_temp: u16) -> f32 {
84 // According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet
85 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721 as f32
86}
diff --git a/tests/rp/src/bin/cyw43-perf.rs b/tests/rp/src/bin/cyw43-perf.rs
new file mode 100644
index 000000000..bc127e2e5
--- /dev/null
+++ b/tests/rp/src/bin/cyw43-perf.rs
@@ -0,0 +1,264 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use cyw43_pio::PioSpi;
8use defmt::{assert, panic, *};
9use embassy_executor::Spawner;
10use embassy_futures::join::join;
11use embassy_net::tcp::TcpSocket;
12use embassy_net::{Config, Ipv4Address, Stack, StackResources};
13use embassy_rp::gpio::{Level, Output};
14use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0};
15use embassy_rp::pio::{InterruptHandler, Pio};
16use embassy_rp::{bind_interrupts, rom_data};
17use embassy_time::{with_timeout, Duration, Timer};
18use static_cell::make_static;
19use {defmt_rtt as _, panic_probe as _};
20
21bind_interrupts!(struct Irqs {
22 PIO0_IRQ_0 => InterruptHandler<PIO0>;
23});
24
25teleprobe_meta::timeout!(120);
26
27#[embassy_executor::task]
28async fn wifi_task(
29 runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>,
30) -> ! {
31 runner.run().await
32}
33
34#[embassy_executor::task]
35async fn net_task(stack: &'static Stack<cyw43::NetDriver<'static>>) -> ! {
36 stack.run().await
37}
38
39#[embassy_executor::main]
40async fn main(spawner: Spawner) {
41 info!("Hello World!");
42 let p = embassy_rp::init(Default::default());
43
44 // needed for reading the firmware from flash via XIP.
45 unsafe {
46 rom_data::flash_exit_xip();
47 rom_data::flash_enter_cmd_xip();
48 }
49
50 // cyw43 firmware needs to be flashed manually:
51 // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x101c0000
52 // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x101f8000
53 let fw = unsafe { core::slice::from_raw_parts(0x101c0000 as *const u8, 224190) };
54 let clm = unsafe { core::slice::from_raw_parts(0x101f8000 as *const u8, 4752) };
55
56 let pwr = Output::new(p.PIN_23, Level::Low);
57 let cs = Output::new(p.PIN_25, Level::High);
58 let mut pio = Pio::new(p.PIO0, Irqs);
59 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0);
60
61 let state = make_static!(cyw43::State::new());
62 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
63 unwrap!(spawner.spawn(wifi_task(runner)));
64
65 control.init(clm).await;
66 control
67 .set_power_management(cyw43::PowerManagementMode::PowerSave)
68 .await;
69
70 // Generate random seed
71 let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random.
72
73 // Init network stack
74 let stack = &*make_static!(Stack::new(
75 net_device,
76 Config::dhcpv4(Default::default()),
77 make_static!(StackResources::<2>::new()),
78 seed
79 ));
80
81 unwrap!(spawner.spawn(net_task(stack)));
82
83 loop {
84 match control.join_wpa2(WIFI_NETWORK, WIFI_PASSWORD).await {
85 Ok(_) => break,
86 Err(err) => {
87 panic!("join failed with status={}", err.status);
88 }
89 }
90 }
91
92 info!("Waiting for DHCP up...");
93 while stack.config_v4().is_none() {
94 Timer::after(Duration::from_millis(100)).await;
95 }
96 info!("IP addressing up!");
97
98 let down = test_download(stack).await;
99 let up = test_upload(stack).await;
100 let updown = test_upload_download(stack).await;
101
102 assert!(down > TEST_EXPECTED_DOWNLOAD_KBPS);
103 assert!(up > TEST_EXPECTED_UPLOAD_KBPS);
104 assert!(updown > TEST_EXPECTED_UPLOAD_DOWNLOAD_KBPS);
105
106 info!("Test OK");
107 cortex_m::asm::bkpt();
108}
109
110// Test-only wifi network, no internet access!
111const WIFI_NETWORK: &str = "EmbassyTest";
112const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud";
113
114const TEST_DURATION: usize = 10;
115const TEST_EXPECTED_DOWNLOAD_KBPS: usize = 300;
116const TEST_EXPECTED_UPLOAD_KBPS: usize = 300;
117const TEST_EXPECTED_UPLOAD_DOWNLOAD_KBPS: usize = 300;
118const RX_BUFFER_SIZE: usize = 4096;
119const TX_BUFFER_SIZE: usize = 4096;
120const SERVER_ADDRESS: Ipv4Address = Ipv4Address::new(192, 168, 2, 2);
121const DOWNLOAD_PORT: u16 = 4321;
122const UPLOAD_PORT: u16 = 4322;
123const UPLOAD_DOWNLOAD_PORT: u16 = 4323;
124
125async fn test_download(stack: &'static Stack<cyw43::NetDriver<'static>>) -> usize {
126 info!("Testing download...");
127
128 let mut rx_buffer = [0; RX_BUFFER_SIZE];
129 let mut tx_buffer = [0; TX_BUFFER_SIZE];
130 let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
131 socket.set_timeout(Some(Duration::from_secs(10)));
132
133 info!("connecting to {:?}:{}...", SERVER_ADDRESS, DOWNLOAD_PORT);
134 if let Err(e) = socket.connect((SERVER_ADDRESS, DOWNLOAD_PORT)).await {
135 error!("connect error: {:?}", e);
136 return 0;
137 }
138 info!("connected, testing...");
139
140 let mut rx_buf = [0; 4096];
141 let mut total: usize = 0;
142 with_timeout(Duration::from_secs(TEST_DURATION as _), async {
143 loop {
144 match socket.read(&mut rx_buf).await {
145 Ok(0) => {
146 error!("read EOF");
147 return 0;
148 }
149 Ok(n) => total += n,
150 Err(e) => {
151 error!("read error: {:?}", e);
152 return 0;
153 }
154 }
155 }
156 })
157 .await
158 .ok();
159
160 let kbps = (total + 512) / 1024 / TEST_DURATION;
161 info!("download: {} kB/s", kbps);
162 kbps
163}
164
165async fn test_upload(stack: &'static Stack<cyw43::NetDriver<'static>>) -> usize {
166 info!("Testing upload...");
167
168 let mut rx_buffer = [0; RX_BUFFER_SIZE];
169 let mut tx_buffer = [0; TX_BUFFER_SIZE];
170 let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
171 socket.set_timeout(Some(Duration::from_secs(10)));
172
173 info!("connecting to {:?}:{}...", SERVER_ADDRESS, UPLOAD_PORT);
174 if let Err(e) = socket.connect((SERVER_ADDRESS, UPLOAD_PORT)).await {
175 error!("connect error: {:?}", e);
176 return 0;
177 }
178 info!("connected, testing...");
179
180 let buf = [0; 4096];
181 let mut total: usize = 0;
182 with_timeout(Duration::from_secs(TEST_DURATION as _), async {
183 loop {
184 match socket.write(&buf).await {
185 Ok(0) => {
186 error!("write zero?!??!?!");
187 return 0;
188 }
189 Ok(n) => total += n,
190 Err(e) => {
191 error!("write error: {:?}", e);
192 return 0;
193 }
194 }
195 }
196 })
197 .await
198 .ok();
199
200 let kbps = (total + 512) / 1024 / TEST_DURATION;
201 info!("upload: {} kB/s", kbps);
202 kbps
203}
204
205async fn test_upload_download(stack: &'static Stack<cyw43::NetDriver<'static>>) -> usize {
206 info!("Testing upload+download...");
207
208 let mut rx_buffer = [0; RX_BUFFER_SIZE];
209 let mut tx_buffer = [0; TX_BUFFER_SIZE];
210 let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
211 socket.set_timeout(Some(Duration::from_secs(10)));
212
213 info!("connecting to {:?}:{}...", SERVER_ADDRESS, UPLOAD_DOWNLOAD_PORT);
214 if let Err(e) = socket.connect((SERVER_ADDRESS, UPLOAD_DOWNLOAD_PORT)).await {
215 error!("connect error: {:?}", e);
216 return 0;
217 }
218 info!("connected, testing...");
219
220 let (mut reader, mut writer) = socket.split();
221
222 let tx_buf = [0; 4096];
223 let mut rx_buf = [0; 4096];
224 let mut total: usize = 0;
225 let tx_fut = async {
226 loop {
227 match writer.write(&tx_buf).await {
228 Ok(0) => {
229 error!("write zero?!??!?!");
230 return 0;
231 }
232 Ok(_) => {}
233 Err(e) => {
234 error!("write error: {:?}", e);
235 return 0;
236 }
237 }
238 }
239 };
240
241 let rx_fut = async {
242 loop {
243 match reader.read(&mut rx_buf).await {
244 Ok(0) => {
245 error!("read EOF");
246 return 0;
247 }
248 Ok(n) => total += n,
249 Err(e) => {
250 error!("read error: {:?}", e);
251 return 0;
252 }
253 }
254 }
255 };
256
257 with_timeout(Duration::from_secs(TEST_DURATION as _), join(tx_fut, rx_fut))
258 .await
259 .ok();
260
261 let kbps = (total + 512) / 1024 / TEST_DURATION;
262 info!("upload+download: {} kB/s", kbps);
263 kbps
264}
diff --git a/tests/rp/src/bin/dma_copy_async.rs b/tests/rp/src/bin/dma_copy_async.rs
new file mode 100644
index 000000000..2c0b559a9
--- /dev/null
+++ b/tests/rp/src/bin/dma_copy_async.rs
@@ -0,0 +1,43 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use defmt::{assert_eq, *};
8use embassy_executor::Spawner;
9use embassy_rp::dma::copy;
10use {defmt_rtt as _, panic_probe as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let p = embassy_rp::init(Default::default());
15 info!("Hello World!");
16
17 // Check `u8` copy
18 {
19 let data: [u8; 2] = [0xC0, 0xDE];
20 let mut buf = [0; 2];
21 unsafe { copy(p.DMA_CH0, &data, &mut buf).await };
22 assert_eq!(buf, data);
23 }
24
25 // Check `u16` copy
26 {
27 let data: [u16; 2] = [0xC0BE, 0xDEAD];
28 let mut buf = [0; 2];
29 unsafe { copy(p.DMA_CH1, &data, &mut buf).await };
30 assert_eq!(buf, data);
31 }
32
33 // Check `u32` copy
34 {
35 let data: [u32; 2] = [0xC0BEDEAD, 0xDEADAAFF];
36 let mut buf = [0; 2];
37 unsafe { copy(p.DMA_CH2, &data, &mut buf).await };
38 assert_eq!(buf, data);
39 }
40
41 info!("Test OK");
42 cortex_m::asm::bkpt();
43}
diff --git a/tests/rp/src/bin/flash.rs b/tests/rp/src/bin/flash.rs
new file mode 100644
index 000000000..cf9b86df5
--- /dev/null
+++ b/tests/rp/src/bin/flash.rs
@@ -0,0 +1,65 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use defmt::*;
8use embassy_executor::Spawner;
9use embassy_rp::flash::{ERASE_SIZE, FLASH_BASE};
10use embassy_time::{Duration, Timer};
11use {defmt_rtt as _, panic_probe as _};
12
13const ADDR_OFFSET: u32 = 0x4000;
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) {
17 let p = embassy_rp::init(Default::default());
18 info!("Hello World!");
19
20 // add some delay to give an attached debug probe time to parse the
21 // defmt RTT header. Reading that header might touch flash memory, which
22 // interferes with flash write operations.
23 // https://github.com/knurling-rs/defmt/pull/683
24 Timer::after(Duration::from_millis(10)).await;
25
26 let mut flash = embassy_rp::flash::Flash::<_, { 2 * 1024 * 1024 }>::new(p.FLASH);
27
28 // Get JEDEC id
29 let jedec = defmt::unwrap!(flash.jedec_id());
30 info!("jedec id: 0x{:x}", jedec);
31
32 // Get unique id
33 let mut uid = [0; 8];
34 defmt::unwrap!(flash.unique_id(&mut uid));
35 info!("unique id: {:?}", uid);
36
37 let mut buf = [0u8; ERASE_SIZE];
38 defmt::unwrap!(flash.read(ADDR_OFFSET, &mut buf));
39
40 info!("Addr of flash block is {:x}", ADDR_OFFSET + FLASH_BASE as u32);
41 info!("Contents start with {=[u8]}", buf[0..4]);
42
43 defmt::unwrap!(flash.erase(ADDR_OFFSET, ADDR_OFFSET + ERASE_SIZE as u32));
44
45 defmt::unwrap!(flash.read(ADDR_OFFSET, &mut buf));
46 info!("Contents after erase starts with {=[u8]}", buf[0..4]);
47 if buf.iter().any(|x| *x != 0xFF) {
48 defmt::panic!("unexpected");
49 }
50
51 for b in buf.iter_mut() {
52 *b = 0xDA;
53 }
54
55 defmt::unwrap!(flash.write(ADDR_OFFSET, &mut buf));
56
57 defmt::unwrap!(flash.read(ADDR_OFFSET, &mut buf));
58 info!("Contents after write starts with {=[u8]}", buf[0..4]);
59 if buf.iter().any(|x| *x != 0xDA) {
60 defmt::panic!("unexpected");
61 }
62
63 info!("Test OK");
64 cortex_m::asm::bkpt();
65}
diff --git a/tests/rp/src/bin/float.rs b/tests/rp/src/bin/float.rs
new file mode 100644
index 000000000..0e0de85fa
--- /dev/null
+++ b/tests/rp/src/bin/float.rs
@@ -0,0 +1,53 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use defmt::*;
8use embassy_executor::Spawner;
9use embassy_rp::pac;
10use embassy_time::{Duration, Timer};
11use {defmt_rtt as _, panic_probe as _};
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) {
15 embassy_rp::init(Default::default());
16 info!("Hello World!");
17
18 const PI_F: f32 = 3.1415926535f32;
19 const PI_D: f64 = 3.14159265358979323846f64;
20
21 pac::BUSCTRL
22 .perfsel(0)
23 .write(|r| r.set_perfsel(pac::busctrl::vals::Perfsel::ROM));
24
25 for i in 0..=360 {
26 let rad_f = (i as f32) * PI_F / 180.0;
27 info!(
28 "{}° float: {=f32} / {=f32} / {=f32} / {=f32}",
29 i,
30 rad_f,
31 rad_f - PI_F,
32 rad_f + PI_F,
33 rad_f % PI_F
34 );
35 let rad_d = (i as f64) * PI_D / 180.0;
36 info!(
37 "{}° double: {=f64} / {=f64} / {=f64} / {=f64}",
38 i,
39 rad_d,
40 rad_d - PI_D,
41 rad_d + PI_D,
42 rad_d % PI_D
43 );
44 Timer::after(Duration::from_millis(10)).await;
45 }
46
47 let rom_accesses = pac::BUSCTRL.perfctr(0).read().perfctr();
48 // every float operation used here uses at least 10 cycles
49 defmt::assert!(rom_accesses >= 360 * 12 * 10);
50
51 info!("Test OK");
52 cortex_m::asm::bkpt();
53}
diff --git a/tests/rp/src/bin/gpio.rs b/tests/rp/src/bin/gpio.rs
index af22fe27d..946b7dc88 100644
--- a/tests/rp/src/bin/gpio.rs
+++ b/tests/rp/src/bin/gpio.rs
@@ -1,6 +1,8 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)] 3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
4 6
5use defmt::{assert, *}; 7use defmt::{assert, *};
6use embassy_executor::Spawner; 8use embassy_executor::Spawner;
@@ -19,14 +21,46 @@ async fn main(_spawner: Spawner) {
19 let b = Input::new(&mut b, Pull::None); 21 let b = Input::new(&mut b, Pull::None);
20 22
21 { 23 {
22 let _a = Output::new(&mut a, Level::Low); 24 let a = Output::new(&mut a, Level::Low);
23 delay(); 25 delay();
24 assert!(b.is_low()); 26 assert!(b.is_low());
27 assert!(!b.is_high());
28 assert!(a.is_set_low());
29 assert!(!a.is_set_high());
25 } 30 }
26 { 31 {
27 let _a = Output::new(&mut a, Level::High); 32 let mut a = Output::new(&mut a, Level::High);
28 delay(); 33 delay();
34 assert!(!b.is_low());
29 assert!(b.is_high()); 35 assert!(b.is_high());
36 assert!(!a.is_set_low());
37 assert!(a.is_set_high());
38
39 // Test is_set_low / is_set_high
40 a.set_low();
41 delay();
42 assert!(b.is_low());
43 assert!(a.is_set_low());
44 assert!(!a.is_set_high());
45
46 a.set_high();
47 delay();
48 assert!(b.is_high());
49 assert!(!a.is_set_low());
50 assert!(a.is_set_high());
51
52 // Test toggle
53 a.toggle();
54 delay();
55 assert!(b.is_low());
56 assert!(a.is_set_low());
57 assert!(!a.is_set_high());
58
59 a.toggle();
60 delay();
61 assert!(b.is_high());
62 assert!(!a.is_set_low());
63 assert!(a.is_set_high());
30 } 64 }
31 } 65 }
32 66
@@ -78,6 +112,7 @@ async fn main(_spawner: Spawner) {
78 a.set_as_input(); 112 a.set_as_input();
79 113
80 // When an OutputOpenDrain is high, it doesn't drive the pin. 114 // When an OutputOpenDrain is high, it doesn't drive the pin.
115 b.set_high();
81 a.set_pull(Pull::Up); 116 a.set_pull(Pull::Up);
82 delay(); 117 delay();
83 assert!(a.is_high()); 118 assert!(a.is_high());
@@ -85,9 +120,8 @@ async fn main(_spawner: Spawner) {
85 delay(); 120 delay();
86 assert!(a.is_low()); 121 assert!(a.is_low());
87 122
88 b.set_low();
89
90 // When an OutputOpenDrain is low, it drives the pin low. 123 // When an OutputOpenDrain is low, it drives the pin low.
124 b.set_low();
91 a.set_pull(Pull::Up); 125 a.set_pull(Pull::Up);
92 delay(); 126 delay();
93 assert!(a.is_low()); 127 assert!(a.is_low());
@@ -95,14 +129,36 @@ async fn main(_spawner: Spawner) {
95 delay(); 129 delay();
96 assert!(a.is_low()); 130 assert!(a.is_low());
97 131
132 // Check high again
98 b.set_high(); 133 b.set_high();
99
100 a.set_pull(Pull::Up); 134 a.set_pull(Pull::Up);
101 delay(); 135 delay();
102 assert!(a.is_high()); 136 assert!(a.is_high());
103 a.set_pull(Pull::Down); 137 a.set_pull(Pull::Down);
104 delay(); 138 delay();
105 assert!(a.is_low()); 139 assert!(a.is_low());
140
141 // When an OutputOpenDrain is high, it reads the input value in the pin.
142 b.set_high();
143 a.set_as_input();
144 a.set_pull(Pull::Up);
145 delay();
146 assert!(b.is_high());
147 a.set_as_output();
148 a.set_low();
149 delay();
150 assert!(b.is_low());
151
152 // When an OutputOpenDrain is low, it always reads low.
153 b.set_low();
154 a.set_as_input();
155 a.set_pull(Pull::Up);
156 delay();
157 assert!(b.is_low());
158 a.set_as_output();
159 a.set_low();
160 delay();
161 assert!(b.is_low());
106 } 162 }
107 163
108 // FLEX 164 // FLEX
diff --git a/tests/rp/src/bin/gpio_async.rs b/tests/rp/src/bin/gpio_async.rs
index 1eeaac1f6..532494de5 100644
--- a/tests/rp/src/bin/gpio_async.rs
+++ b/tests/rp/src/bin/gpio_async.rs
@@ -1,12 +1,14 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)] 3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
4 6
5use defmt::{assert, *}; 7use defmt::{assert, *};
6use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_futures::join::join;
7use embassy_rp::gpio::{Input, Level, Output, Pull}; 10use embassy_rp::gpio::{Input, Level, Output, Pull};
8use embassy_time::{Duration, Instant, Timer}; 11use embassy_time::{Duration, Instant, Timer};
9use futures::future::join;
10use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
11 13
12#[embassy_executor::main] 14#[embassy_executor::main]
diff --git a/tests/rp/src/bin/gpio_multicore.rs b/tests/rp/src/bin/gpio_multicore.rs
new file mode 100644
index 000000000..780112bc1
--- /dev/null
+++ b/tests/rp/src/bin/gpio_multicore.rs
@@ -0,0 +1,65 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use defmt::{info, unwrap};
8use embassy_executor::Executor;
9use embassy_executor::_export::StaticCell;
10use embassy_rp::gpio::{Input, Level, Output, Pull};
11use embassy_rp::multicore::{spawn_core1, Stack};
12use embassy_rp::peripherals::{PIN_0, PIN_1};
13use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
14use embassy_sync::channel::Channel;
15use {defmt_rtt as _, panic_probe as _};
16
17static mut CORE1_STACK: Stack<1024> = Stack::new();
18static EXECUTOR0: StaticCell<Executor> = StaticCell::new();
19static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
20static CHANNEL0: Channel<CriticalSectionRawMutex, (), 1> = Channel::new();
21static CHANNEL1: Channel<CriticalSectionRawMutex, (), 1> = Channel::new();
22
23#[cortex_m_rt::entry]
24fn main() -> ! {
25 let p = embassy_rp::init(Default::default());
26 spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || {
27 let executor1 = EXECUTOR1.init(Executor::new());
28 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(p.PIN_1))));
29 });
30 let executor0 = EXECUTOR0.init(Executor::new());
31 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task(p.PIN_0))));
32}
33
34#[embassy_executor::task]
35async fn core0_task(p: PIN_0) {
36 info!("CORE0 is running");
37
38 let mut pin = Output::new(p, Level::Low);
39
40 CHANNEL0.send(()).await;
41 CHANNEL1.recv().await;
42
43 pin.set_high();
44
45 CHANNEL1.recv().await;
46
47 info!("Test OK");
48 cortex_m::asm::bkpt();
49}
50
51#[embassy_executor::task]
52async fn core1_task(p: PIN_1) {
53 info!("CORE1 is running");
54
55 CHANNEL0.recv().await;
56
57 let mut pin = Input::new(p, Pull::Down);
58 let wait = pin.wait_for_rising_edge();
59
60 CHANNEL1.send(()).await;
61
62 wait.await;
63
64 CHANNEL1.send(()).await;
65}
diff --git a/tests/rp/src/bin/multicore.rs b/tests/rp/src/bin/multicore.rs
new file mode 100644
index 000000000..114889dec
--- /dev/null
+++ b/tests/rp/src/bin/multicore.rs
@@ -0,0 +1,49 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use defmt::{info, unwrap};
8use embassy_executor::Executor;
9use embassy_executor::_export::StaticCell;
10use embassy_rp::multicore::{spawn_core1, Stack};
11use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
12use embassy_sync::channel::Channel;
13use {defmt_rtt as _, panic_probe as _};
14
15static mut CORE1_STACK: Stack<1024> = Stack::new();
16static EXECUTOR0: StaticCell<Executor> = StaticCell::new();
17static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
18static CHANNEL0: Channel<CriticalSectionRawMutex, bool, 1> = Channel::new();
19static CHANNEL1: Channel<CriticalSectionRawMutex, bool, 1> = Channel::new();
20
21#[cortex_m_rt::entry]
22fn main() -> ! {
23 let p = embassy_rp::init(Default::default());
24 spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || {
25 let executor1 = EXECUTOR1.init(Executor::new());
26 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task())));
27 });
28 let executor0 = EXECUTOR0.init(Executor::new());
29 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task())));
30}
31
32#[embassy_executor::task]
33async fn core0_task() {
34 info!("CORE0 is running");
35 let ping = true;
36 CHANNEL0.send(ping).await;
37 let pong = CHANNEL1.recv().await;
38 assert_eq!(ping, pong);
39
40 info!("Test OK");
41 cortex_m::asm::bkpt();
42}
43
44#[embassy_executor::task]
45async fn core1_task() {
46 info!("CORE1 is running");
47 let ping = CHANNEL0.recv().await;
48 CHANNEL1.send(ping).await;
49}
diff --git a/tests/rp/src/bin/pio_irq.rs b/tests/rp/src/bin/pio_irq.rs
new file mode 100644
index 000000000..45004424a
--- /dev/null
+++ b/tests/rp/src/bin/pio_irq.rs
@@ -0,0 +1,55 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use defmt::info;
8use embassy_executor::Spawner;
9use embassy_rp::bind_interrupts;
10use embassy_rp::peripherals::PIO0;
11use embassy_rp::pio::{Config, InterruptHandler, Pio};
12use embassy_rp::relocate::RelocatedProgram;
13use {defmt_rtt as _, panic_probe as _};
14
15bind_interrupts!(struct Irqs {
16 PIO0_IRQ_0 => InterruptHandler<PIO0>;
17});
18
19#[embassy_executor::main]
20async fn main(_spawner: Spawner) {
21 let p = embassy_rp::init(Default::default());
22 let pio = p.PIO0;
23 let Pio {
24 mut common,
25 sm0: mut sm,
26 irq_flags,
27 ..
28 } = Pio::new(pio, Irqs);
29
30 let prg = pio_proc::pio_asm!(
31 "irq set 0",
32 "irq wait 0",
33 "irq set 1",
34 // pause execution here
35 "irq wait 1",
36 );
37
38 let relocated = RelocatedProgram::new(&prg.program);
39 let mut cfg = Config::default();
40 cfg.use_program(&common.load_program(&relocated), &[]);
41 sm.set_config(&cfg);
42 sm.set_enable(true);
43
44 // not using the wait futures on purpose because they clear the irq bits,
45 // and we want to see in which order they are set.
46 while !irq_flags.check(0) {}
47 cortex_m::asm::nop();
48 assert!(!irq_flags.check(1));
49 irq_flags.clear(0);
50 cortex_m::asm::nop();
51 assert!(irq_flags.check(1));
52
53 info!("Test OK");
54 cortex_m::asm::bkpt();
55}
diff --git a/tests/rp/src/bin/pwm.rs b/tests/rp/src/bin/pwm.rs
new file mode 100644
index 000000000..c71d21ef9
--- /dev/null
+++ b/tests/rp/src/bin/pwm.rs
@@ -0,0 +1,144 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use defmt::{assert, assert_eq, assert_ne, *};
8use embassy_executor::Spawner;
9use embassy_rp::gpio::{Input, Level, Output, Pull};
10use embassy_rp::pwm::{Config, InputMode, Pwm};
11use embassy_time::{Duration, Timer};
12use {defmt_rtt as _, panic_probe as _};
13
14#[embassy_executor::main]
15async fn main(_spawner: Spawner) {
16 let mut p = embassy_rp::init(Default::default());
17 info!("Hello World!");
18
19 // Connections on CI device: 6 -> 9, 7 -> 11
20 let (mut p6, mut p7, mut p9, mut p11) = (p.PIN_6, p.PIN_7, p.PIN_9, p.PIN_11);
21
22 let cfg = {
23 let mut c = Config::default();
24 c.divider = 125.into();
25 c.top = 10000;
26 c.compare_a = 5000;
27 c.compare_b = 5000;
28 c
29 };
30
31 // Test free-running clock
32 {
33 let pwm = Pwm::new_free(&mut p.PWM_CH3, cfg.clone());
34 cortex_m::asm::delay(125);
35 let ctr = pwm.counter();
36 assert!(ctr > 0);
37 assert!(ctr < 100);
38 cortex_m::asm::delay(125);
39 assert!(ctr < pwm.counter());
40 }
41
42 for invert_a in [false, true] {
43 info!("free-running, invert A: {}", invert_a);
44 let mut cfg = cfg.clone();
45 cfg.invert_a = invert_a;
46 cfg.invert_b = !invert_a;
47
48 // Test output from A
49 {
50 let pin1 = Input::new(&mut p9, Pull::None);
51 let _pwm = Pwm::new_output_a(&mut p.PWM_CH3, &mut p6, cfg.clone());
52 Timer::after(Duration::from_millis(1)).await;
53 assert_eq!(pin1.is_low(), invert_a);
54 Timer::after(Duration::from_millis(5)).await;
55 assert_eq!(pin1.is_high(), invert_a);
56 Timer::after(Duration::from_millis(5)).await;
57 assert_eq!(pin1.is_low(), invert_a);
58 Timer::after(Duration::from_millis(5)).await;
59 assert_eq!(pin1.is_high(), invert_a);
60 }
61
62 // Test output from B
63 {
64 let pin2 = Input::new(&mut p11, Pull::None);
65 let _pwm = Pwm::new_output_b(&mut p.PWM_CH3, &mut p7, cfg.clone());
66 Timer::after(Duration::from_millis(1)).await;
67 assert_ne!(pin2.is_low(), invert_a);
68 Timer::after(Duration::from_millis(5)).await;
69 assert_ne!(pin2.is_high(), invert_a);
70 Timer::after(Duration::from_millis(5)).await;
71 assert_ne!(pin2.is_low(), invert_a);
72 Timer::after(Duration::from_millis(5)).await;
73 assert_ne!(pin2.is_high(), invert_a);
74 }
75
76 // Test output from A+B
77 {
78 let pin1 = Input::new(&mut p9, Pull::None);
79 let pin2 = Input::new(&mut p11, Pull::None);
80 let _pwm = Pwm::new_output_ab(&mut p.PWM_CH3, &mut p6, &mut p7, cfg.clone());
81 Timer::after(Duration::from_millis(1)).await;
82 assert_eq!(pin1.is_low(), invert_a);
83 assert_ne!(pin2.is_low(), invert_a);
84 Timer::after(Duration::from_millis(5)).await;
85 assert_eq!(pin1.is_high(), invert_a);
86 assert_ne!(pin2.is_high(), invert_a);
87 Timer::after(Duration::from_millis(5)).await;
88 assert_eq!(pin1.is_low(), invert_a);
89 assert_ne!(pin2.is_low(), invert_a);
90 Timer::after(Duration::from_millis(5)).await;
91 assert_eq!(pin1.is_high(), invert_a);
92 assert_ne!(pin2.is_high(), invert_a);
93 }
94 }
95
96 // Test level-gated
97 {
98 let mut pin2 = Output::new(&mut p11, Level::Low);
99 let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::Level, cfg.clone());
100 assert_eq!(pwm.counter(), 0);
101 Timer::after(Duration::from_millis(5)).await;
102 assert_eq!(pwm.counter(), 0);
103 pin2.set_high();
104 Timer::after(Duration::from_millis(1)).await;
105 pin2.set_low();
106 let ctr = pwm.counter();
107 assert!(ctr >= 1000);
108 Timer::after(Duration::from_millis(1)).await;
109 assert_eq!(pwm.counter(), ctr);
110 }
111
112 // Test rising-gated
113 {
114 let mut pin2 = Output::new(&mut p11, Level::Low);
115 let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::RisingEdge, cfg.clone());
116 assert_eq!(pwm.counter(), 0);
117 Timer::after(Duration::from_millis(5)).await;
118 assert_eq!(pwm.counter(), 0);
119 pin2.set_high();
120 Timer::after(Duration::from_millis(1)).await;
121 pin2.set_low();
122 assert_eq!(pwm.counter(), 1);
123 Timer::after(Duration::from_millis(1)).await;
124 assert_eq!(pwm.counter(), 1);
125 }
126
127 // Test falling-gated
128 {
129 let mut pin2 = Output::new(&mut p11, Level::High);
130 let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::FallingEdge, cfg.clone());
131 assert_eq!(pwm.counter(), 0);
132 Timer::after(Duration::from_millis(5)).await;
133 assert_eq!(pwm.counter(), 0);
134 pin2.set_low();
135 Timer::after(Duration::from_millis(1)).await;
136 pin2.set_high();
137 assert_eq!(pwm.counter(), 1);
138 Timer::after(Duration::from_millis(1)).await;
139 assert_eq!(pwm.counter(), 1);
140 }
141
142 info!("Test OK");
143 cortex_m::asm::bkpt();
144}
diff --git a/tests/rp/src/bin/spi.rs b/tests/rp/src/bin/spi.rs
new file mode 100644
index 000000000..84dfa5a2c
--- /dev/null
+++ b/tests/rp/src/bin/spi.rs
@@ -0,0 +1,30 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use defmt::{assert_eq, *};
8use embassy_executor::Spawner;
9use embassy_rp::spi::{Config, Spi};
10use {defmt_rtt as _, panic_probe as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let p = embassy_rp::init(Default::default());
15 info!("Hello World!");
16
17 let clk = p.PIN_2;
18 let mosi = p.PIN_3;
19 let miso = p.PIN_4;
20
21 let mut spi = Spi::new_blocking(p.SPI0, clk, mosi, miso, Config::default());
22
23 let tx_buf = [1_u8, 2, 3, 4, 5, 6];
24 let mut rx_buf = [0_u8; 6];
25 spi.blocking_transfer(&mut rx_buf, &tx_buf).unwrap();
26 assert_eq!(rx_buf, tx_buf);
27
28 info!("Test OK");
29 cortex_m::asm::bkpt();
30}
diff --git a/tests/rp/src/bin/spi_async.rs b/tests/rp/src/bin/spi_async.rs
new file mode 100644
index 000000000..a4080b03d
--- /dev/null
+++ b/tests/rp/src/bin/spi_async.rs
@@ -0,0 +1,86 @@
1//! Make sure to connect GPIO pins 3 (`PIN_3`) and 4 (`PIN_4`) together
2//! to run this test.
3//!
4#![no_std]
5#![no_main]
6#![feature(type_alias_impl_trait)]
7#[path = "../common.rs"]
8mod common;
9
10use defmt::{assert_eq, *};
11use embassy_executor::Spawner;
12use embassy_rp::spi::{Config, Spi};
13use {defmt_rtt as _, panic_probe as _};
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) {
17 let p = embassy_rp::init(Default::default());
18 info!("Hello World!");
19
20 let clk = p.PIN_2;
21 let mosi = p.PIN_3;
22 let miso = p.PIN_4;
23
24 let mut spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default());
25
26 // equal rx & tx buffers
27 {
28 let tx_buf = [1_u8, 2, 3, 4, 5, 6];
29 let mut rx_buf = [0_u8; 6];
30 spi.transfer(&mut rx_buf, &tx_buf).await.unwrap();
31 assert_eq!(rx_buf, tx_buf);
32 }
33
34 // tx > rx buffer
35 {
36 let tx_buf = [7_u8, 8, 9, 10, 11, 12];
37
38 let mut rx_buf = [0_u8; 3];
39 spi.transfer(&mut rx_buf, &tx_buf).await.unwrap();
40 assert_eq!(rx_buf, tx_buf[..3]);
41
42 defmt::info!("tx > rx buffer - OK");
43 }
44
45 // we make sure to that clearing FIFO works after the uneven buffers
46
47 // equal rx & tx buffers
48 {
49 let tx_buf = [13_u8, 14, 15, 16, 17, 18];
50 let mut rx_buf = [0_u8; 6];
51 spi.transfer(&mut rx_buf, &tx_buf).await.unwrap();
52 assert_eq!(rx_buf, tx_buf);
53
54 defmt::info!("buffer rx length == tx length - OK");
55 }
56
57 // rx > tx buffer
58 {
59 let tx_buf = [19_u8, 20, 21];
60 let mut rx_buf = [0_u8; 6];
61
62 // we should have written dummy data to tx buffer to sync clock.
63 spi.transfer(&mut rx_buf, &tx_buf).await.unwrap();
64
65 assert_eq!(
66 rx_buf[..3],
67 tx_buf,
68 "only the first 3 TX bytes should have been received in the RX buffer"
69 );
70 assert_eq!(rx_buf[3..], [0, 0, 0], "the rest of the RX bytes should be empty");
71 defmt::info!("buffer rx length > tx length - OK");
72 }
73
74 // equal rx & tx buffers
75 {
76 let tx_buf = [22_u8, 23, 24, 25, 26, 27];
77 let mut rx_buf = [0_u8; 6];
78 spi.transfer(&mut rx_buf, &tx_buf).await.unwrap();
79
80 assert_eq!(rx_buf, tx_buf);
81 defmt::info!("buffer rx length = tx length - OK");
82 }
83
84 info!("Test OK");
85 cortex_m::asm::bkpt();
86}
diff --git a/tests/rp/src/bin/uart.rs b/tests/rp/src/bin/uart.rs
new file mode 100644
index 000000000..2331c7d36
--- /dev/null
+++ b/tests/rp/src/bin/uart.rs
@@ -0,0 +1,171 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use defmt::{assert_eq, *};
8use embassy_executor::Spawner;
9use embassy_rp::gpio::{Level, Output};
10use embassy_rp::uart::{Blocking, Config, Error, Instance, Parity, Uart, UartRx};
11use embassy_time::{Duration, Timer};
12use {defmt_rtt as _, panic_probe as _};
13
14fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Blocking>) -> Result<[u8; N], Error> {
15 let mut buf = [255; N];
16 uart.blocking_read(&mut buf)?;
17 Ok(buf)
18}
19
20fn read1<const N: usize>(uart: &mut UartRx<'_, impl Instance, Blocking>) -> Result<[u8; N], Error> {
21 let mut buf = [255; N];
22 uart.blocking_read(&mut buf)?;
23 Ok(buf)
24}
25
26async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) {
27 pin.set_low();
28 Timer::after(Duration::from_millis(1)).await;
29 for i in 0..8 {
30 if v & (1 << i) == 0 {
31 pin.set_low();
32 } else {
33 pin.set_high();
34 }
35 Timer::after(Duration::from_millis(1)).await;
36 }
37 if let Some(b) = parity {
38 if b {
39 pin.set_high();
40 } else {
41 pin.set_low();
42 }
43 Timer::after(Duration::from_millis(1)).await;
44 }
45 pin.set_high();
46 Timer::after(Duration::from_millis(1)).await;
47}
48
49#[embassy_executor::main]
50async fn main(_spawner: Spawner) {
51 let p = embassy_rp::init(Default::default());
52 info!("Hello World!");
53
54 let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0);
55
56 {
57 let config = Config::default();
58 let mut uart = Uart::new_blocking(&mut uart, &mut tx, &mut rx, config);
59
60 // We can't send too many bytes, they have to fit in the FIFO.
61 // This is because we aren't sending+receiving at the same time.
62
63 let data = [0xC0, 0xDE];
64 uart.blocking_write(&data).unwrap();
65 assert_eq!(read(&mut uart).unwrap(), data);
66 }
67
68 info!("test overflow detection");
69 {
70 let config = Config::default();
71 let mut uart = Uart::new_blocking(&mut uart, &mut tx, &mut rx, config);
72
73 let data = [
74 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,
75 30, 31, 32,
76 ];
77 let overflow = [
78 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
79 ];
80 uart.blocking_write(&data).unwrap();
81 uart.blocking_write(&overflow).unwrap();
82 while uart.busy() {}
83
84 // prefix in fifo is valid
85 assert_eq!(read(&mut uart).unwrap(), data);
86 // next received character causes overrun error and is discarded
87 uart.blocking_write(&[1, 2, 3]).unwrap();
88 assert_eq!(read::<1>(&mut uart).unwrap_err(), Error::Overrun);
89 assert_eq!(read(&mut uart).unwrap(), [2, 3]);
90 }
91
92 info!("test break detection");
93 {
94 let config = Config::default();
95 let mut uart = Uart::new_blocking(&mut uart, &mut tx, &mut rx, config);
96
97 // break on empty fifo
98 uart.send_break(20).await;
99 uart.blocking_write(&[64]).unwrap();
100 assert_eq!(read::<1>(&mut uart).unwrap_err(), Error::Break);
101 assert_eq!(read(&mut uart).unwrap(), [64]);
102
103 // break on partially filled fifo
104 uart.blocking_write(&[65; 2]).unwrap();
105 uart.send_break(20).await;
106 uart.blocking_write(&[66]).unwrap();
107 assert_eq!(read(&mut uart).unwrap(), [65; 2]);
108 assert_eq!(read::<1>(&mut uart).unwrap_err(), Error::Break);
109 assert_eq!(read(&mut uart).unwrap(), [66]);
110 }
111
112 // parity detection. here we bitbang to not require two uarts.
113 info!("test parity error detection");
114 {
115 let mut pin = Output::new(&mut tx, Level::High);
116 let mut config = Config::default();
117 config.baudrate = 1000;
118 config.parity = Parity::ParityEven;
119 let mut uart = UartRx::new_blocking(&mut uart, &mut rx, config);
120
121 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u8) {
122 send(pin, v, Some(parity != 0)).await;
123 }
124
125 // first check that we can send correctly
126 chr(&mut pin, 64, 1).await;
127 assert_eq!(read1(&mut uart).unwrap(), [64]);
128
129 // all good, check real errors
130 chr(&mut pin, 2, 1).await;
131 chr(&mut pin, 3, 0).await;
132 chr(&mut pin, 4, 0).await;
133 chr(&mut pin, 5, 0).await;
134 assert_eq!(read1(&mut uart).unwrap(), [2, 3]);
135 assert_eq!(read1::<1>(&mut uart).unwrap_err(), Error::Parity);
136 assert_eq!(read1(&mut uart).unwrap(), [5]);
137 }
138
139 // framing error detection. here we bitbang because there's no other way.
140 info!("test framing error detection");
141 {
142 let mut pin = Output::new(&mut tx, Level::High);
143 let mut config = Config::default();
144 config.baudrate = 1000;
145 let mut uart = UartRx::new_blocking(&mut uart, &mut rx, config);
146
147 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) {
148 if good {
149 send(pin, v, None).await;
150 } else {
151 send(pin, v, Some(false)).await;
152 }
153 }
154
155 // first check that we can send correctly
156 chr(&mut pin, 64, true).await;
157 assert_eq!(read1(&mut uart).unwrap(), [64]);
158
159 // all good, check real errors
160 chr(&mut pin, 2, true).await;
161 chr(&mut pin, 3, true).await;
162 chr(&mut pin, 4, false).await;
163 chr(&mut pin, 5, true).await;
164 assert_eq!(read1(&mut uart).unwrap(), [2, 3]);
165 assert_eq!(read1::<1>(&mut uart).unwrap_err(), Error::Framing);
166 assert_eq!(read1(&mut uart).unwrap(), [5]);
167 }
168
169 info!("Test OK");
170 cortex_m::asm::bkpt();
171}
diff --git a/tests/rp/src/bin/uart_buffered.rs b/tests/rp/src/bin/uart_buffered.rs
new file mode 100644
index 000000000..e74e9986c
--- /dev/null
+++ b/tests/rp/src/bin/uart_buffered.rs
@@ -0,0 +1,256 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use defmt::{assert_eq, panic, *};
8use embassy_executor::Spawner;
9use embassy_rp::bind_interrupts;
10use embassy_rp::gpio::{Level, Output};
11use embassy_rp::peripherals::UART0;
12use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config, Error, Instance, Parity};
13use embassy_time::{Duration, Timer};
14use embedded_io::asynch::{Read, ReadExactError, Write};
15use {defmt_rtt as _, panic_probe as _};
16
17bind_interrupts!(struct Irqs {
18 UART0_IRQ => BufferedInterruptHandler<UART0>;
19});
20
21async fn read<const N: usize>(uart: &mut BufferedUart<'_, impl Instance>) -> Result<[u8; N], Error> {
22 let mut buf = [255; N];
23 match uart.read_exact(&mut buf).await {
24 Ok(()) => Ok(buf),
25 // we should not ever produce an Eof condition
26 Err(ReadExactError::UnexpectedEof) => panic!(),
27 Err(ReadExactError::Other(e)) => Err(e),
28 }
29}
30
31async fn read1<const N: usize>(uart: &mut BufferedUartRx<'_, impl Instance>) -> Result<[u8; N], Error> {
32 let mut buf = [255; N];
33 match uart.read_exact(&mut buf).await {
34 Ok(()) => Ok(buf),
35 // we should not ever produce an Eof condition
36 Err(ReadExactError::UnexpectedEof) => panic!(),
37 Err(ReadExactError::Other(e)) => Err(e),
38 }
39}
40
41async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) {
42 pin.set_low();
43 Timer::after(Duration::from_millis(1)).await;
44 for i in 0..8 {
45 if v & (1 << i) == 0 {
46 pin.set_low();
47 } else {
48 pin.set_high();
49 }
50 Timer::after(Duration::from_millis(1)).await;
51 }
52 if let Some(b) = parity {
53 if b {
54 pin.set_high();
55 } else {
56 pin.set_low();
57 }
58 Timer::after(Duration::from_millis(1)).await;
59 }
60 pin.set_high();
61 Timer::after(Duration::from_millis(1)).await;
62}
63
64#[embassy_executor::main]
65async fn main(_spawner: Spawner) {
66 let p = embassy_rp::init(Default::default());
67 info!("Hello World!");
68
69 let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0);
70
71 {
72 let config = Config::default();
73 let tx_buf = &mut [0u8; 16];
74 let rx_buf = &mut [0u8; 16];
75 let mut uart = BufferedUart::new(&mut uart, Irqs, &mut tx, &mut rx, tx_buf, rx_buf, config);
76
77 // Make sure we send more bytes than fits in the FIFO, to test the actual
78 // bufferedUart.
79
80 let data = [
81 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,
82 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
83 ];
84 uart.write_all(&data).await.unwrap();
85 info!("Done writing");
86
87 assert_eq!(read(&mut uart).await.unwrap(), data);
88 }
89
90 info!("test overflow detection");
91 {
92 let config = Config::default();
93 let tx_buf = &mut [0u8; 16];
94 let rx_buf = &mut [0u8; 16];
95 let mut uart = BufferedUart::new(&mut uart, Irqs, &mut tx, &mut rx, tx_buf, rx_buf, config);
96
97 // Make sure we send more bytes than fits in the FIFO, to test the actual
98 // bufferedUart.
99
100 let data = [
101 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,
102 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
103 ];
104 let overflow = [
105 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
106 ];
107 // give each block time to settle into the fifo. we want the overrun to occur at a well-defined point.
108 uart.write_all(&data).await.unwrap();
109 uart.blocking_flush().unwrap();
110 while uart.busy() {}
111 uart.write_all(&overflow).await.unwrap();
112 uart.blocking_flush().unwrap();
113 while uart.busy() {}
114
115 // already buffered/fifod prefix is valid
116 assert_eq!(read(&mut uart).await.unwrap(), data);
117 // next received character causes overrun error and is discarded
118 uart.write_all(&[1, 2, 3]).await.unwrap();
119 uart.blocking_flush().unwrap();
120 assert_eq!(read::<1>(&mut uart).await.unwrap_err(), Error::Overrun);
121 assert_eq!(read(&mut uart).await.unwrap(), [2, 3]);
122 }
123
124 info!("test break detection");
125 {
126 let mut config = Config::default();
127 config.baudrate = 1000;
128 let tx_buf = &mut [0u8; 16];
129 let rx_buf = &mut [0u8; 16];
130 let mut uart = BufferedUart::new(&mut uart, Irqs, &mut tx, &mut rx, tx_buf, rx_buf, config);
131
132 // break on empty buffer
133 uart.send_break(20).await;
134 assert_eq!(read::<1>(&mut uart).await.unwrap_err(), Error::Break);
135 uart.write_all(&[64]).await.unwrap();
136 assert_eq!(read(&mut uart).await.unwrap(), [64]);
137
138 // break on partially filled buffer
139 uart.write_all(&[65; 2]).await.unwrap();
140 uart.send_break(20).await;
141 uart.write_all(&[66]).await.unwrap();
142 assert_eq!(read(&mut uart).await.unwrap(), [65; 2]);
143 assert_eq!(read::<1>(&mut uart).await.unwrap_err(), Error::Break);
144 assert_eq!(read(&mut uart).await.unwrap(), [66]);
145
146 // break on full buffer
147 uart.write_all(&[64; 16]).await.unwrap();
148 uart.send_break(20).await;
149 uart.write_all(&[65]).await.unwrap();
150 assert_eq!(read(&mut uart).await.unwrap(), [64; 16]);
151 assert_eq!(read::<1>(&mut uart).await.unwrap_err(), Error::Break);
152 assert_eq!(read(&mut uart).await.unwrap(), [65]);
153 }
154
155 // parity detection. here we bitbang to not require two uarts.
156 info!("test parity error detection");
157 {
158 let mut pin = Output::new(&mut tx, Level::High);
159 // choose a very slow baud rate to make tests reliable even with O0
160 let mut config = Config::default();
161 config.baudrate = 1000;
162 config.parity = Parity::ParityEven;
163 let rx_buf = &mut [0u8; 16];
164 let mut uart = BufferedUartRx::new(&mut uart, Irqs, &mut rx, rx_buf, config);
165
166 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u32) {
167 send(pin, v, Some(parity != 0)).await;
168 }
169
170 // first check that we can send correctly
171 chr(&mut pin, 64, 1).await;
172 assert_eq!(read1(&mut uart).await.unwrap(), [64]);
173
174 // parity on empty buffer
175 chr(&mut pin, 64, 0).await;
176 chr(&mut pin, 4, 1).await;
177 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity);
178 assert_eq!(read1(&mut uart).await.unwrap(), [4]);
179
180 // parity on partially filled buffer
181 chr(&mut pin, 64, 1).await;
182 chr(&mut pin, 32, 1).await;
183 chr(&mut pin, 64, 0).await;
184 chr(&mut pin, 65, 0).await;
185 assert_eq!(read1(&mut uart).await.unwrap(), [64, 32]);
186 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity);
187 assert_eq!(read1(&mut uart).await.unwrap(), [65]);
188
189 // parity on full buffer
190 for i in 0..16 {
191 chr(&mut pin, i, i.count_ones() % 2).await;
192 }
193 chr(&mut pin, 64, 0).await;
194 chr(&mut pin, 65, 0).await;
195 assert_eq!(
196 read1(&mut uart).await.unwrap(),
197 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
198 );
199 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity);
200 assert_eq!(read1(&mut uart).await.unwrap(), [65]);
201 }
202
203 // framing error detection. here we bitbang because there's no other way.
204 info!("test framing error detection");
205 {
206 let mut pin = Output::new(&mut tx, Level::High);
207 // choose a very slow baud rate to make tests reliable even with O0
208 let mut config = Config::default();
209 config.baudrate = 1000;
210 let rx_buf = &mut [0u8; 16];
211 let mut uart = BufferedUartRx::new(&mut uart, Irqs, &mut rx, rx_buf, config);
212
213 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) {
214 if good {
215 send(pin, v, None).await;
216 } else {
217 send(pin, v, Some(false)).await;
218 }
219 }
220
221 // first check that we can send correctly
222 chr(&mut pin, 64, true).await;
223 assert_eq!(read1(&mut uart).await.unwrap(), [64]);
224
225 // framing on empty buffer
226 chr(&mut pin, 64, false).await;
227 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing);
228 chr(&mut pin, 65, true).await;
229 assert_eq!(read1(&mut uart).await.unwrap(), [65]);
230
231 // framing on partially filled buffer
232 chr(&mut pin, 64, true).await;
233 chr(&mut pin, 32, true).await;
234 chr(&mut pin, 64, false).await;
235 chr(&mut pin, 65, true).await;
236 assert_eq!(read1(&mut uart).await.unwrap(), [64, 32]);
237 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing);
238 assert_eq!(read1(&mut uart).await.unwrap(), [65]);
239
240 // framing on full buffer
241 for i in 0..16 {
242 chr(&mut pin, i, true).await;
243 }
244 chr(&mut pin, 64, false).await;
245 chr(&mut pin, 65, true).await;
246 assert_eq!(
247 read1(&mut uart).await.unwrap(),
248 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
249 );
250 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing);
251 assert_eq!(read1(&mut uart).await.unwrap(), [65]);
252 }
253
254 info!("Test OK");
255 cortex_m::asm::bkpt();
256}
diff --git a/tests/rp/src/bin/uart_dma.rs b/tests/rp/src/bin/uart_dma.rs
new file mode 100644
index 000000000..fee6c825d
--- /dev/null
+++ b/tests/rp/src/bin/uart_dma.rs
@@ -0,0 +1,252 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use defmt::{assert_eq, *};
8use embassy_executor::Spawner;
9use embassy_rp::bind_interrupts;
10use embassy_rp::gpio::{Level, Output};
11use embassy_rp::peripherals::UART0;
12use embassy_rp::uart::{Async, Config, Error, Instance, InterruptHandler, Parity, Uart, UartRx};
13use embassy_time::{Duration, Timer};
14use {defmt_rtt as _, panic_probe as _};
15
16bind_interrupts!(struct Irqs {
17 UART0_IRQ => InterruptHandler<UART0>;
18});
19
20async fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Async>) -> Result<[u8; N], Error> {
21 let mut buf = [255; N];
22 uart.read(&mut buf).await?;
23 Ok(buf)
24}
25
26async fn read1<const N: usize>(uart: &mut UartRx<'_, impl Instance, Async>) -> Result<[u8; N], Error> {
27 let mut buf = [255; N];
28 uart.read(&mut buf).await?;
29 Ok(buf)
30}
31
32async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) {
33 pin.set_low();
34 Timer::after(Duration::from_millis(1)).await;
35 for i in 0..8 {
36 if v & (1 << i) == 0 {
37 pin.set_low();
38 } else {
39 pin.set_high();
40 }
41 Timer::after(Duration::from_millis(1)).await;
42 }
43 if let Some(b) = parity {
44 if b {
45 pin.set_high();
46 } else {
47 pin.set_low();
48 }
49 Timer::after(Duration::from_millis(1)).await;
50 }
51 pin.set_high();
52 Timer::after(Duration::from_millis(1)).await;
53}
54
55#[embassy_executor::main]
56async fn main(_spawner: Spawner) {
57 let mut p = embassy_rp::init(Default::default());
58 info!("Hello World!");
59
60 let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0);
61
62 // We can't send too many bytes, they have to fit in the FIFO.
63 // This is because we aren't sending+receiving at the same time.
64 {
65 let config = Config::default();
66 let mut uart = Uart::new(
67 &mut uart,
68 &mut tx,
69 &mut rx,
70 Irqs,
71 &mut p.DMA_CH0,
72 &mut p.DMA_CH1,
73 config,
74 );
75
76 let data = [0xC0, 0xDE];
77 uart.write(&data).await.unwrap();
78
79 let mut buf = [0; 2];
80 uart.read(&mut buf).await.unwrap();
81 assert_eq!(buf, data);
82 }
83
84 info!("test overflow detection");
85 {
86 let config = Config::default();
87 let mut uart = Uart::new(
88 &mut uart,
89 &mut tx,
90 &mut rx,
91 Irqs,
92 &mut p.DMA_CH0,
93 &mut p.DMA_CH1,
94 config,
95 );
96
97 uart.blocking_write(&[42; 32]).unwrap();
98 uart.blocking_write(&[1, 2, 3]).unwrap();
99 uart.blocking_flush().unwrap();
100
101 // can receive regular fifo contents
102 assert_eq!(read(&mut uart).await, Ok([42; 16]));
103 assert_eq!(read(&mut uart).await, Ok([42; 16]));
104 // receiving the rest fails with overrun
105 assert_eq!(read::<16>(&mut uart).await, Err(Error::Overrun));
106 // new data is accepted, latest overrunning byte first
107 assert_eq!(read(&mut uart).await, Ok([3]));
108 uart.blocking_write(&[8, 9]).unwrap();
109 Timer::after(Duration::from_millis(1)).await;
110 assert_eq!(read(&mut uart).await, Ok([8, 9]));
111 }
112
113 info!("test break detection");
114 {
115 let config = Config::default();
116 let (mut tx, mut rx) = Uart::new(
117 &mut uart,
118 &mut tx,
119 &mut rx,
120 Irqs,
121 &mut p.DMA_CH0,
122 &mut p.DMA_CH1,
123 config,
124 )
125 .split();
126
127 // break before read
128 tx.send_break(20).await;
129 tx.write(&[64]).await.unwrap();
130 assert_eq!(read1::<1>(&mut rx).await.unwrap_err(), Error::Break);
131 assert_eq!(read1(&mut rx).await.unwrap(), [64]);
132
133 // break during read
134 {
135 let r = read1::<2>(&mut rx);
136 tx.write(&[2]).await.unwrap();
137 tx.send_break(20).await;
138 tx.write(&[3]).await.unwrap();
139 assert_eq!(r.await.unwrap_err(), Error::Break);
140 assert_eq!(read1(&mut rx).await.unwrap(), [3]);
141 }
142
143 // break after read
144 {
145 let r = read1(&mut rx);
146 tx.write(&[2]).await.unwrap();
147 tx.send_break(20).await;
148 tx.write(&[3]).await.unwrap();
149 assert_eq!(r.await.unwrap(), [2]);
150 assert_eq!(read1::<1>(&mut rx).await.unwrap_err(), Error::Break);
151 assert_eq!(read1(&mut rx).await.unwrap(), [3]);
152 }
153 }
154
155 // parity detection. here we bitbang to not require two uarts.
156 info!("test parity error detection");
157 {
158 let mut pin = Output::new(&mut tx, Level::High);
159 // choose a very slow baud rate to make tests reliable even with O0
160 let mut config = Config::default();
161 config.baudrate = 1000;
162 config.parity = Parity::ParityEven;
163 let mut uart = UartRx::new(&mut uart, &mut rx, Irqs, &mut p.DMA_CH0, config);
164
165 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u32) {
166 send(pin, v, Some(parity != 0)).await;
167 }
168
169 // first check that we can send correctly
170 chr(&mut pin, 32, 1).await;
171 assert_eq!(read1(&mut uart).await.unwrap(), [32]);
172
173 // parity error before read
174 chr(&mut pin, 32, 0).await;
175 chr(&mut pin, 31, 1).await;
176 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity);
177 assert_eq!(read1(&mut uart).await.unwrap(), [31]);
178
179 // parity error during read
180 {
181 let r = read1::<2>(&mut uart);
182 chr(&mut pin, 2, 1).await;
183 chr(&mut pin, 32, 0).await;
184 chr(&mut pin, 3, 0).await;
185 assert_eq!(r.await.unwrap_err(), Error::Parity);
186 assert_eq!(read1(&mut uart).await.unwrap(), [3]);
187 }
188
189 // parity error after read
190 {
191 let r = read1(&mut uart);
192 chr(&mut pin, 2, 1).await;
193 chr(&mut pin, 32, 0).await;
194 chr(&mut pin, 3, 0).await;
195 assert_eq!(r.await.unwrap(), [2]);
196 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity);
197 assert_eq!(read1(&mut uart).await.unwrap(), [3]);
198 }
199 }
200
201 // framing error detection. here we bitbang because there's no other way.
202 info!("test framing error detection");
203 {
204 let mut pin = Output::new(&mut tx, Level::High);
205 // choose a very slow baud rate to make tests reliable even with O0
206 let mut config = Config::default();
207 config.baudrate = 1000;
208 let mut uart = UartRx::new(&mut uart, &mut rx, Irqs, &mut p.DMA_CH0, config);
209
210 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) {
211 if good {
212 send(pin, v, None).await;
213 } else {
214 send(pin, v, Some(false)).await;
215 }
216 }
217
218 // first check that we can send correctly
219 chr(&mut pin, 32, true).await;
220 assert_eq!(read1(&mut uart).await.unwrap(), [32]);
221
222 // parity error before read
223 chr(&mut pin, 32, false).await;
224 chr(&mut pin, 31, true).await;
225 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing);
226 assert_eq!(read1(&mut uart).await.unwrap(), [31]);
227
228 // parity error during read
229 {
230 let r = read1::<2>(&mut uart);
231 chr(&mut pin, 2, true).await;
232 chr(&mut pin, 32, false).await;
233 chr(&mut pin, 3, true).await;
234 assert_eq!(r.await.unwrap_err(), Error::Framing);
235 assert_eq!(read1(&mut uart).await.unwrap(), [3]);
236 }
237
238 // parity error after read
239 {
240 let r = read1(&mut uart);
241 chr(&mut pin, 2, true).await;
242 chr(&mut pin, 32, false).await;
243 chr(&mut pin, 3, true).await;
244 assert_eq!(r.await.unwrap(), [2]);
245 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing);
246 assert_eq!(read1(&mut uart).await.unwrap(), [3]);
247 }
248 }
249
250 info!("Test OK");
251 cortex_m::asm::bkpt();
252}
diff --git a/tests/rp/src/bin/uart_upgrade.rs b/tests/rp/src/bin/uart_upgrade.rs
new file mode 100644
index 000000000..760e53954
--- /dev/null
+++ b/tests/rp/src/bin/uart_upgrade.rs
@@ -0,0 +1,60 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use defmt::{assert_eq, *};
8use embassy_executor::Spawner;
9use embassy_rp::bind_interrupts;
10use embassy_rp::peripherals::UART0;
11use embassy_rp::uart::{BufferedInterruptHandler, Config, Uart};
12use embedded_io::asynch::{Read, Write};
13use {defmt_rtt as _, panic_probe as _};
14
15bind_interrupts!(struct Irqs {
16 UART0_IRQ => BufferedInterruptHandler<UART0>;
17});
18
19#[embassy_executor::main]
20async fn main(_spawner: Spawner) {
21 let p = embassy_rp::init(Default::default());
22 info!("Hello World!");
23
24 let (tx, rx, uart) = (p.PIN_0, p.PIN_1, p.UART0);
25
26 let config = Config::default();
27 let mut uart = Uart::new_blocking(uart, tx, rx, config);
28
29 // We can't send too many bytes, they have to fit in the FIFO.
30 // This is because we aren't sending+receiving at the same time.
31
32 let data = [0xC0, 0xDE];
33 uart.blocking_write(&data).unwrap();
34
35 let mut buf = [0; 2];
36 uart.blocking_read(&mut buf).unwrap();
37 assert_eq!(buf, data);
38
39 let tx_buf = &mut [0u8; 16];
40 let rx_buf = &mut [0u8; 16];
41
42 let mut uart = uart.into_buffered(Irqs, tx_buf, rx_buf);
43
44 // Make sure we send more bytes than fits in the FIFO, to test the actual
45 // bufferedUart.
46
47 let data = [
48 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,
49 30, 31,
50 ];
51 uart.write_all(&data).await.unwrap();
52 info!("Done writing");
53
54 let mut buf = [0; 31];
55 uart.read_exact(&mut buf).await.unwrap();
56 assert_eq!(buf, data);
57
58 info!("Test OK");
59 cortex_m::asm::bkpt();
60}
diff --git a/tests/rp/src/common.rs b/tests/rp/src/common.rs
new file mode 100644
index 000000000..955674f27
--- /dev/null
+++ b/tests/rp/src/common.rs
@@ -0,0 +1 @@
teleprobe_meta::target!(b"rpi-pico");