aboutsummaryrefslogtreecommitdiff
path: root/tests/nrf/src
diff options
context:
space:
mode:
authorDion Dokter <[email protected]>2025-11-20 13:22:38 +0100
committerDion Dokter <[email protected]>2025-11-20 13:22:38 +0100
commit4f2c36e447455e8d33607d586859d3d075cabf1d (patch)
tree003cd822d688acd7c074dd229663b4648d100f71 /tests/nrf/src
parent663732d85abbae400f2dbab2c411802a5b60e9b1 (diff)
parent661874d11de7d93ed52e08e020a9d4c7ee11122d (diff)
Merge branch 'main' into u0-lcd
Diffstat (limited to 'tests/nrf/src')
-rw-r--r--tests/nrf/src/bin/buffered_uart.rs82
-rw-r--r--tests/nrf/src/bin/buffered_uart_full.rs70
-rw-r--r--tests/nrf/src/bin/buffered_uart_halves.rs86
-rw-r--r--tests/nrf/src/bin/buffered_uart_spam.rs90
-rw-r--r--tests/nrf/src/bin/ethernet_enc28j60_perf.rs85
-rw-r--r--tests/nrf/src/bin/gpio.rs31
-rw-r--r--tests/nrf/src/bin/gpiote.rs50
-rw-r--r--tests/nrf/src/bin/spim.rs42
-rw-r--r--tests/nrf/src/bin/timer.rs26
-rw-r--r--tests/nrf/src/bin/uart_halves.rs51
-rw-r--r--tests/nrf/src/bin/uart_split.rs49
-rw-r--r--tests/nrf/src/bin/wifi_esp_hosted_perf.rs106
-rw-r--r--tests/nrf/src/common.rs117
13 files changed, 885 insertions, 0 deletions
diff --git a/tests/nrf/src/bin/buffered_uart.rs b/tests/nrf/src/bin/buffered_uart.rs
new file mode 100644
index 000000000..8c4827464
--- /dev/null
+++ b/tests/nrf/src/bin/buffered_uart.rs
@@ -0,0 +1,82 @@
1// required-features: easydma
2#![no_std]
3#![no_main]
4
5#[path = "../common.rs"]
6mod common;
7
8use defmt::{panic, *};
9use embassy_executor::Spawner;
10use embassy_futures::join::join;
11use embassy_nrf::buffered_uarte::{self, BufferedUarte};
12use embassy_nrf::{peripherals, uarte};
13use {defmt_rtt as _, panic_probe as _};
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) {
17 let mut p = embassy_nrf::init(Default::default());
18 let mut config = uarte::Config::default();
19 config.parity = uarte::Parity::EXCLUDED;
20 config.baudrate = uarte::Baudrate::BAUD1M;
21
22 let mut tx_buffer = [0u8; 1024];
23 let mut rx_buffer = [0u8; 1024];
24
25 // test teardown + recreate of the buffereduarte works fine.
26 for _ in 0..2 {
27 let u = BufferedUarte::new(
28 peri!(p, UART0).reborrow(),
29 p.TIMER0.reborrow(),
30 p.PPI_CH0.reborrow(),
31 p.PPI_CH1.reborrow(),
32 p.PPI_GROUP0.reborrow(),
33 peri!(p, PIN_A).reborrow(),
34 peri!(p, PIN_B).reborrow(),
35 irqs!(UART0_BUFFERED),
36 config.clone(),
37 &mut rx_buffer,
38 &mut tx_buffer,
39 );
40
41 info!("uarte initialized!");
42
43 let (mut rx, mut tx) = u.split();
44
45 const COUNT: usize = 40_000;
46
47 let tx_fut = async {
48 let mut tx_buf = [0; 215];
49 let mut i = 0;
50 while i < COUNT {
51 let n = tx_buf.len().min(COUNT - i);
52 let tx_buf = &mut tx_buf[..n];
53 for (j, b) in tx_buf.iter_mut().enumerate() {
54 *b = (i + j) as u8;
55 }
56 let n = unwrap!(tx.write(tx_buf).await);
57 i += n;
58 }
59 };
60 let rx_fut = async {
61 let mut i = 0;
62 while i < COUNT {
63 let buf = unwrap!(rx.fill_buf().await);
64
65 for &b in buf {
66 if b != i as u8 {
67 panic!("mismatch {} vs {}, index {}", b, i as u8, i);
68 }
69 i = i + 1;
70 }
71
72 let n = buf.len();
73 rx.consume(n);
74 }
75 };
76
77 join(rx_fut, tx_fut).await;
78 }
79
80 info!("Test OK");
81 cortex_m::asm::bkpt();
82}
diff --git a/tests/nrf/src/bin/buffered_uart_full.rs b/tests/nrf/src/bin/buffered_uart_full.rs
new file mode 100644
index 000000000..e0f41b891
--- /dev/null
+++ b/tests/nrf/src/bin/buffered_uart_full.rs
@@ -0,0 +1,70 @@
1// required-features: easydma
2#![no_std]
3#![no_main]
4
5#[path = "../common.rs"]
6mod common;
7
8use defmt::{assert_eq, *};
9use embassy_executor::Spawner;
10use embassy_nrf::buffered_uarte::{self, BufferedUarte};
11use embassy_nrf::{peripherals, uarte};
12use embedded_io_async::{Read, Write};
13use {defmt_rtt as _, panic_probe as _};
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) {
17 let p = embassy_nrf::init(Default::default());
18 let mut config = uarte::Config::default();
19 config.parity = uarte::Parity::EXCLUDED;
20 config.baudrate = uarte::Baudrate::BAUD1M;
21
22 let mut tx_buffer = [0u8; 500];
23 let mut rx_buffer = [0u8; 500];
24
25 let u = BufferedUarte::new(
26 peri!(p, UART0),
27 p.TIMER0,
28 p.PPI_CH0,
29 p.PPI_CH1,
30 p.PPI_GROUP0,
31 peri!(p, PIN_A),
32 peri!(p, PIN_B),
33 irqs!(UART0_BUFFERED),
34 config.clone(),
35 &mut rx_buffer,
36 &mut tx_buffer,
37 );
38
39 info!("uarte initialized!");
40
41 let (mut rx, mut tx) = u.split();
42
43 let mut buf = [0; 500];
44 for (j, b) in buf.iter_mut().enumerate() {
45 *b = j as u8;
46 }
47
48 // Write 500b. This causes the rx buffer to get exactly full.
49 unwrap!(tx.write_all(&buf).await);
50 unwrap!(tx.flush().await);
51
52 // Read those 500b.
53 unwrap!(rx.read_exact(&mut buf).await);
54 for (j, b) in buf.iter().enumerate() {
55 assert_eq!(*b, j as u8);
56 }
57
58 // The buffer should now be unclogged. Write 500b again.
59 unwrap!(tx.write_all(&buf).await);
60 unwrap!(tx.flush().await);
61
62 // Read should work again.
63 unwrap!(rx.read_exact(&mut buf).await);
64 for (j, b) in buf.iter().enumerate() {
65 assert_eq!(*b, j as u8);
66 }
67
68 info!("Test OK");
69 cortex_m::asm::bkpt();
70}
diff --git a/tests/nrf/src/bin/buffered_uart_halves.rs b/tests/nrf/src/bin/buffered_uart_halves.rs
new file mode 100644
index 000000000..e6debd76e
--- /dev/null
+++ b/tests/nrf/src/bin/buffered_uart_halves.rs
@@ -0,0 +1,86 @@
1// required-features: two-uarts
2#![no_std]
3#![no_main]
4
5#[path = "../common.rs"]
6mod common;
7
8use defmt::{assert_eq, *};
9use embassy_executor::Spawner;
10use embassy_futures::join::join;
11use embassy_nrf::buffered_uarte::{self, BufferedUarteRx, BufferedUarteTx};
12use embassy_nrf::{peripherals, uarte};
13use {defmt_rtt as _, panic_probe as _};
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) {
17 let mut p = embassy_nrf::init(Default::default());
18 let mut config = uarte::Config::default();
19 config.parity = uarte::Parity::EXCLUDED;
20 config.baudrate = uarte::Baudrate::BAUD1M;
21
22 let mut tx_buffer = [0u8; 1024];
23 let mut rx_buffer = [0u8; 1024];
24
25 // test teardown + recreate of the buffereduarte works fine.
26 for _ in 0..2 {
27 const COUNT: usize = 40_000;
28
29 let mut tx = BufferedUarteTx::new(
30 peri!(p, UART1).reborrow(),
31 peri!(p, PIN_A).reborrow(),
32 irqs!(UART1_BUFFERED),
33 config.clone(),
34 &mut tx_buffer,
35 );
36
37 let mut rx = BufferedUarteRx::new(
38 peri!(p, UART0).reborrow(),
39 p.TIMER0.reborrow(),
40 p.PPI_CH0.reborrow(),
41 p.PPI_CH1.reborrow(),
42 p.PPI_GROUP0.reborrow(),
43 irqs!(UART0_BUFFERED),
44 peri!(p, PIN_B).reborrow(),
45 config.clone(),
46 &mut rx_buffer,
47 );
48
49 let tx_fut = async {
50 info!("tx initialized!");
51
52 let mut tx_buf = [0; 215];
53 let mut i = 0;
54 while i < COUNT {
55 let n = tx_buf.len().min(COUNT - i);
56 let tx_buf = &mut tx_buf[..n];
57 for (j, b) in tx_buf.iter_mut().enumerate() {
58 *b = (i + j) as u8;
59 }
60 let n = unwrap!(tx.write(tx_buf).await);
61 i += n;
62 }
63 };
64 let rx_fut = async {
65 info!("rx initialized!");
66
67 let mut i = 0;
68 while i < COUNT {
69 let buf = unwrap!(rx.fill_buf().await);
70
71 for &b in buf {
72 assert_eq!(b, i as u8);
73 i = i + 1;
74 }
75
76 let n = buf.len();
77 rx.consume(n);
78 }
79 };
80
81 join(rx_fut, tx_fut).await;
82 }
83
84 info!("Test OK");
85 cortex_m::asm::bkpt();
86}
diff --git a/tests/nrf/src/bin/buffered_uart_spam.rs b/tests/nrf/src/bin/buffered_uart_spam.rs
new file mode 100644
index 000000000..6d862e19d
--- /dev/null
+++ b/tests/nrf/src/bin/buffered_uart_spam.rs
@@ -0,0 +1,90 @@
1// required-features: two-uarts
2#![no_std]
3#![no_main]
4
5#[path = "../common.rs"]
6mod common;
7
8use core::mem;
9use core::ptr::NonNull;
10
11use defmt::{assert_eq, *};
12use embassy_executor::Spawner;
13use embassy_nrf::buffered_uarte::{self, BufferedUarteRx};
14use embassy_nrf::gpio::{Level, Output, OutputDrive};
15use embassy_nrf::ppi::{Event, Ppi, Task};
16use embassy_nrf::uarte::UarteTx;
17use embassy_nrf::{pac, peripherals, uarte};
18use embassy_time::Timer;
19use {defmt_rtt as _, panic_probe as _};
20
21#[embassy_executor::main]
22async fn main(_spawner: Spawner) {
23 let mut p = embassy_nrf::init(Default::default());
24 let mut config = uarte::Config::default();
25 config.parity = uarte::Parity::EXCLUDED;
26 config.baudrate = uarte::Baudrate::BAUD1M;
27
28 let mut rx_buffer = [0u8; 1024];
29
30 mem::forget(Output::new(
31 peri!(p, PIN_A).reborrow(),
32 Level::High,
33 OutputDrive::Standard,
34 ));
35
36 let mut u = BufferedUarteRx::new(
37 peri!(p, UART0),
38 p.TIMER0,
39 p.PPI_CH0,
40 p.PPI_CH1,
41 p.PPI_GROUP0,
42 irqs!(UART0_BUFFERED),
43 peri!(p, PIN_B),
44 config.clone(),
45 &mut rx_buffer,
46 );
47
48 info!("uarte initialized!");
49
50 // uarte needs some quiet time to start rxing properly.
51 Timer::after_millis(10).await;
52
53 // Tx spam in a loop.
54 const NSPAM: usize = 17;
55 static mut TX_BUF: [u8; NSPAM] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
56 let _spam = UarteTx::new(peri!(p, UART1), irqs!(UART1), peri!(p, PIN_A), config.clone());
57 let spam_peri = pac::UARTE1;
58 let event = unsafe { Event::new_unchecked(NonNull::new_unchecked(spam_peri.events_dma().tx().end().as_ptr())) };
59 let task = unsafe { Task::new_unchecked(NonNull::new_unchecked(spam_peri.tasks_dma().tx().start().as_ptr())) };
60 let mut spam_ppi = Ppi::new_one_to_one(p.PPI_CH2, event, task);
61 spam_ppi.enable();
62 let p = (&raw mut TX_BUF) as *mut u8;
63 spam_peri.dma().tx().ptr().write_value(p as u32);
64 spam_peri.dma().tx().maxcnt().write(|w| w.set_maxcnt(NSPAM as _));
65 spam_peri.tasks_dma().tx().start().write_value(1);
66
67 let mut i = 0;
68 let mut total = 0;
69 while total < 256 * 1024 {
70 let buf = unwrap!(u.fill_buf().await);
71 //info!("rx {}", buf);
72
73 for &b in buf {
74 assert_eq!(b, unsafe { TX_BUF[i] });
75
76 i = i + 1;
77 if i == NSPAM {
78 i = 0;
79 }
80 }
81
82 // Read bytes have to be explicitly consumed, otherwise fill_buf() will return them again
83 let n = buf.len();
84 u.consume(n);
85 total += n;
86 }
87
88 info!("Test OK");
89 cortex_m::asm::bkpt();
90}
diff --git a/tests/nrf/src/bin/ethernet_enc28j60_perf.rs b/tests/nrf/src/bin/ethernet_enc28j60_perf.rs
new file mode 100644
index 000000000..bd6a2effd
--- /dev/null
+++ b/tests/nrf/src/bin/ethernet_enc28j60_perf.rs
@@ -0,0 +1,85 @@
1// required-features: nrf52840
2#![no_std]
3#![no_main]
4teleprobe_meta::target!(b"ak-gwe-r7");
5teleprobe_meta::timeout!(120);
6
7use defmt::{info, unwrap};
8use embassy_executor::Spawner;
9use embassy_net::StackResources;
10use embassy_net_enc28j60::Enc28j60;
11use embassy_nrf::gpio::{Level, Output, OutputDrive};
12use embassy_nrf::rng::Rng;
13use embassy_nrf::spim::{self, Spim};
14use embassy_nrf::{bind_interrupts, peripherals};
15use embassy_time::Delay;
16use embedded_hal_bus::spi::ExclusiveDevice;
17use static_cell::StaticCell;
18use {defmt_rtt as _, panic_probe as _};
19
20bind_interrupts!(struct Irqs {
21 SPIM3 => spim::InterruptHandler<peripherals::SPI3>;
22 RNG => embassy_nrf::rng::InterruptHandler<peripherals::RNG>;
23});
24
25type MyDriver = Enc28j60<ExclusiveDevice<Spim<'static>, Output<'static>, Delay>, Output<'static>>;
26
27#[embassy_executor::task]
28async fn net_task(mut runner: embassy_net::Runner<'static, MyDriver>) -> ! {
29 runner.run().await
30}
31
32#[embassy_executor::main]
33async fn main(spawner: Spawner) {
34 let p = embassy_nrf::init(Default::default());
35 info!("running!");
36
37 let eth_sck = p.P0_20;
38 let eth_mosi = p.P0_22;
39 let eth_miso = p.P0_24;
40 let eth_cs = p.P0_15;
41 let eth_rst = p.P0_13;
42 let _eth_irq = p.P0_12;
43
44 let mut config = spim::Config::default();
45 config.frequency = spim::Frequency::M16;
46 let spi = spim::Spim::new(p.SPI3, Irqs, eth_sck, eth_miso, eth_mosi, config);
47 let cs = Output::new(eth_cs, Level::High, OutputDrive::Standard);
48 let spi = ExclusiveDevice::new(spi, cs, Delay);
49
50 let rst = Output::new(eth_rst, Level::High, OutputDrive::Standard);
51 let mac_addr = [2, 3, 4, 5, 6, 7];
52 let device = Enc28j60::new(spi, Some(rst), mac_addr);
53
54 let config = embassy_net::Config::dhcpv4(Default::default());
55 // let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
56 // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24),
57 // dns_servers: Vec::new(),
58 // gateway: Some(Ipv4Address::new(10, 42, 0, 1)),
59 // });
60
61 // Generate random seed
62 let mut rng = Rng::new(p.RNG, Irqs);
63 let mut seed = [0; 8];
64 rng.blocking_fill_bytes(&mut seed);
65 let seed = u64::from_le_bytes(seed);
66
67 // Init network stack
68 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
69 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
70
71 spawner.spawn(unwrap!(net_task(runner)));
72
73 perf_client::run(
74 stack,
75 perf_client::Expected {
76 down_kbps: 200,
77 up_kbps: 200,
78 updown_kbps: 150,
79 },
80 )
81 .await;
82
83 info!("Test OK");
84 cortex_m::asm::bkpt();
85}
diff --git a/tests/nrf/src/bin/gpio.rs b/tests/nrf/src/bin/gpio.rs
new file mode 100644
index 000000000..4995d244c
--- /dev/null
+++ b/tests/nrf/src/bin/gpio.rs
@@ -0,0 +1,31 @@
1#![no_std]
2#![no_main]
3
4#[path = "../common.rs"]
5mod common;
6
7use defmt::{assert, info};
8use embassy_executor::Spawner;
9use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull};
10use embassy_time::Timer;
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let p = embassy_nrf::init(Default::default());
15
16 let input = Input::new(peri!(p, PIN_A), Pull::Up);
17 let mut output = Output::new(peri!(p, PIN_B), Level::Low, OutputDrive::Standard);
18
19 output.set_low();
20 assert!(output.is_set_low());
21 Timer::after_millis(10).await;
22 assert!(input.is_low());
23
24 output.set_high();
25 assert!(output.is_set_high());
26 Timer::after_millis(10).await;
27 assert!(input.is_high());
28
29 info!("Test OK");
30 cortex_m::asm::bkpt();
31}
diff --git a/tests/nrf/src/bin/gpiote.rs b/tests/nrf/src/bin/gpiote.rs
new file mode 100644
index 000000000..0700016d1
--- /dev/null
+++ b/tests/nrf/src/bin/gpiote.rs
@@ -0,0 +1,50 @@
1#![no_std]
2#![no_main]
3
4#[path = "../common.rs"]
5mod common;
6
7use defmt::{assert, info};
8use embassy_executor::Spawner;
9use embassy_futures::join::join;
10use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull};
11use embassy_time::{Duration, Instant, Timer};
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) {
15 let p = embassy_nrf::init(Default::default());
16
17 let mut input = Input::new(peri!(p, PIN_A), Pull::Up);
18 let mut output = Output::new(peri!(p, PIN_B), Level::Low, OutputDrive::Standard);
19
20 let fut1 = async {
21 Timer::after_millis(100).await;
22 output.set_high();
23 };
24 let fut2 = async {
25 let start = Instant::now();
26 input.wait_for_high().await;
27 let dur = Instant::now() - start;
28 info!("took {} ms", dur.as_millis());
29 assert!((Duration::from_millis(90)..Duration::from_millis(110)).contains(&dur));
30 };
31
32 join(fut1, fut2).await;
33
34 let fut1 = async {
35 Timer::after_millis(100).await;
36 output.set_low();
37 };
38 let fut2 = async {
39 let start = Instant::now();
40 input.wait_for_low().await;
41 let dur = Instant::now() - start;
42 info!("took {} ms", dur.as_millis());
43 assert!((Duration::from_millis(90)..Duration::from_millis(110)).contains(&dur));
44 };
45
46 join(fut1, fut2).await;
47
48 info!("Test OK");
49 cortex_m::asm::bkpt();
50}
diff --git a/tests/nrf/src/bin/spim.rs b/tests/nrf/src/bin/spim.rs
new file mode 100644
index 000000000..2b38f0409
--- /dev/null
+++ b/tests/nrf/src/bin/spim.rs
@@ -0,0 +1,42 @@
1// required-features: easydma
2#![no_std]
3#![no_main]
4
5#[path = "../common.rs"]
6mod common;
7
8use defmt::{assert_eq, *};
9use embassy_executor::Spawner;
10use embassy_nrf::spim::Spim;
11use embassy_nrf::{peripherals, spim};
12use {defmt_rtt as _, panic_probe as _};
13
14#[embassy_executor::main]
15async fn main(_spawner: Spawner) {
16 let mut p = embassy_nrf::init(Default::default());
17 let mut config = spim::Config::default();
18 config.frequency = spim::Frequency::M1;
19 let mut spim = Spim::new(
20 peri!(p, SPIM0).reborrow(),
21 irqs!(SPIM0),
22 peri!(p, PIN_X).reborrow(),
23 peri!(p, PIN_A).reborrow(), // MISO
24 peri!(p, PIN_B).reborrow(), // MOSI
25 config.clone(),
26 );
27 let data = [
28 0x42, 0x43, 0x44, 0x45, 0x66, 0x12, 0x23, 0x34, 0x45, 0x19, 0x91, 0xaa, 0xff, 0xa5, 0x5a, 0x77,
29 ];
30 let mut buf = [0u8; 16];
31
32 buf.fill(0);
33 spim.blocking_transfer(&mut buf, &data).unwrap();
34 assert_eq!(data, buf);
35
36 buf.fill(0);
37 spim.transfer(&mut buf, &data).await.unwrap();
38 assert_eq!(data, buf);
39
40 info!("Test OK");
41 cortex_m::asm::bkpt();
42}
diff --git a/tests/nrf/src/bin/timer.rs b/tests/nrf/src/bin/timer.rs
new file mode 100644
index 000000000..1ae9dd647
--- /dev/null
+++ b/tests/nrf/src/bin/timer.rs
@@ -0,0 +1,26 @@
1#![no_std]
2#![no_main]
3
4#[path = "../common.rs"]
5mod common;
6
7use defmt::{assert, info};
8use embassy_executor::Spawner;
9use embassy_time::{Instant, Timer};
10use {defmt_rtt as _, panic_probe as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let _p = embassy_nrf::init(Default::default());
15 info!("Hello World!");
16
17 let start = Instant::now();
18 Timer::after_millis(100).await;
19 let end = Instant::now();
20 let ms = (end - start).as_millis();
21 info!("slept for {} ms", ms);
22 assert!(ms >= 99);
23
24 info!("Test OK");
25 cortex_m::asm::bkpt();
26}
diff --git a/tests/nrf/src/bin/uart_halves.rs b/tests/nrf/src/bin/uart_halves.rs
new file mode 100644
index 000000000..a462f80ce
--- /dev/null
+++ b/tests/nrf/src/bin/uart_halves.rs
@@ -0,0 +1,51 @@
1// required-features: two-uarts
2#![no_std]
3#![no_main]
4
5#[path = "../common.rs"]
6mod common;
7
8use defmt::{assert_eq, *};
9use embassy_executor::Spawner;
10use embassy_futures::join::join;
11use embassy_nrf::uarte::{UarteRx, UarteTx};
12use embassy_nrf::{peripherals, uarte};
13use {defmt_rtt as _, panic_probe as _};
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) {
17 let mut p = embassy_nrf::init(Default::default());
18 let mut config = uarte::Config::default();
19 config.parity = uarte::Parity::EXCLUDED;
20 config.baudrate = uarte::Baudrate::BAUD1M;
21
22 let mut tx = UarteTx::new(
23 peri!(p, UART0).reborrow(),
24 irqs!(UART0),
25 peri!(p, PIN_A).reborrow(),
26 config.clone(),
27 );
28 let mut rx = UarteRx::new(
29 peri!(p, UART1).reborrow(),
30 irqs!(UART1),
31 peri!(p, PIN_B).reborrow(),
32 config.clone(),
33 );
34
35 let data = [
36 0x42, 0x43, 0x44, 0x45, 0x66, 0x12, 0x23, 0x34, 0x45, 0x19, 0x91, 0xaa, 0xff, 0xa5, 0x5a, 0x77,
37 ];
38
39 let tx_fut = async {
40 tx.write(&data).await.unwrap();
41 };
42 let rx_fut = async {
43 let mut buf = [0u8; 16];
44 rx.read(&mut buf).await.unwrap();
45 assert_eq!(data, buf);
46 };
47 join(rx_fut, tx_fut).await;
48
49 info!("Test OK");
50 cortex_m::asm::bkpt();
51}
diff --git a/tests/nrf/src/bin/uart_split.rs b/tests/nrf/src/bin/uart_split.rs
new file mode 100644
index 000000000..8fe710068
--- /dev/null
+++ b/tests/nrf/src/bin/uart_split.rs
@@ -0,0 +1,49 @@
1// required-features: easydma
2#![no_std]
3#![no_main]
4
5#[path = "../common.rs"]
6mod common;
7
8use defmt::{assert_eq, *};
9use embassy_executor::Spawner;
10use embassy_futures::join::join;
11use embassy_nrf::uarte::Uarte;
12use embassy_nrf::{peripherals, uarte};
13use embassy_time::Timer;
14use {defmt_rtt as _, panic_probe as _};
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 let mut p = embassy_nrf::init(Default::default());
19 let mut config = uarte::Config::default();
20 config.parity = uarte::Parity::EXCLUDED;
21 config.baudrate = uarte::Baudrate::BAUD9600;
22
23 let uarte = Uarte::new(
24 peri!(p, UART0).reborrow(),
25 peri!(p, PIN_A).reborrow(),
26 peri!(p, PIN_B).reborrow(),
27 irqs!(UART0),
28 config.clone(),
29 );
30 let (mut tx, mut rx) = uarte.split();
31
32 let data = [
33 0x42, 0x43, 0x44, 0x45, 0x66, 0x12, 0x23, 0x34, 0x45, 0x19, 0x91, 0xaa, 0xff, 0xa5, 0x5a, 0x77,
34 ];
35
36 let tx_fut = async {
37 Timer::after_millis(10).await;
38 tx.write(&data).await.unwrap();
39 };
40 let rx_fut = async {
41 let mut buf = [0u8; 16];
42 rx.read(&mut buf).await.unwrap();
43 assert_eq!(data, buf);
44 };
45 join(rx_fut, tx_fut).await;
46
47 info!("Test OK");
48 cortex_m::asm::bkpt();
49}
diff --git a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs
new file mode 100644
index 000000000..ac082dbb8
--- /dev/null
+++ b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs
@@ -0,0 +1,106 @@
1// required-features: nrf52840
2#![no_std]
3#![no_main]
4teleprobe_meta::target!(b"nrf52840-dk");
5teleprobe_meta::timeout!(120);
6
7use defmt::{info, unwrap};
8use embassy_executor::Spawner;
9use embassy_net::{Config, StackResources};
10use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull};
11use embassy_nrf::rng::Rng;
12use embassy_nrf::spim::{self, Spim};
13use embassy_nrf::{bind_interrupts, peripherals};
14use embassy_time::Delay;
15use embedded_hal_bus::spi::ExclusiveDevice;
16use static_cell::StaticCell;
17use {defmt_rtt as _, embassy_net_esp_hosted as hosted, panic_probe as _};
18
19bind_interrupts!(struct Irqs {
20 SPIM3 => spim::InterruptHandler<peripherals::SPI3>;
21 RNG => embassy_nrf::rng::InterruptHandler<peripherals::RNG>;
22});
23
24// Test-only wifi network, no internet access!
25const WIFI_NETWORK: &str = "EmbassyTest";
26const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud";
27
28#[embassy_executor::task]
29async fn wifi_task(
30 runner: hosted::Runner<
31 'static,
32 hosted::SpiInterface<ExclusiveDevice<Spim<'static>, Output<'static>, Delay>, Input<'static>>,
33 Output<'static>,
34 >,
35) -> ! {
36 runner.run().await
37}
38
39type MyDriver = hosted::NetDriver<'static>;
40
41#[embassy_executor::task]
42async fn net_task(mut runner: embassy_net::Runner<'static, MyDriver>) -> ! {
43 runner.run().await
44}
45
46#[embassy_executor::main]
47async fn main(spawner: Spawner) {
48 info!("Hello World!");
49
50 let p = embassy_nrf::init(Default::default());
51
52 let miso = p.P0_28;
53 let sck = p.P0_29;
54 let mosi = p.P0_30;
55 let cs = Output::new(p.P0_31, Level::High, OutputDrive::HighDrive);
56 let handshake = Input::new(p.P1_01, Pull::Up);
57 let ready = Input::new(p.P1_04, Pull::None);
58 let reset = Output::new(p.P1_05, Level::Low, OutputDrive::Standard);
59
60 let mut config = spim::Config::default();
61 config.frequency = spim::Frequency::M32;
62 config.mode = spim::MODE_2; // !!!
63 let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config);
64 let spi = ExclusiveDevice::new(spi, cs, Delay);
65
66 let iface = hosted::SpiInterface::new(spi, handshake, ready);
67
68 static STATE: StaticCell<embassy_net_esp_hosted::State> = StaticCell::new();
69 let (device, mut control, runner) =
70 embassy_net_esp_hosted::new(STATE.init(embassy_net_esp_hosted::State::new()), iface, reset).await;
71
72 spawner.spawn(unwrap!(wifi_task(runner)));
73
74 unwrap!(control.init().await);
75 unwrap!(control.connect(WIFI_NETWORK, WIFI_PASSWORD).await);
76
77 // Generate random seed
78 let mut rng = Rng::new(p.RNG, Irqs);
79 let mut seed = [0; 8];
80 rng.blocking_fill_bytes(&mut seed);
81 let seed = u64::from_le_bytes(seed);
82
83 // Init network stack
84 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
85 let (stack, runner) = embassy_net::new(
86 device,
87 Config::dhcpv4(Default::default()),
88 RESOURCES.init(StackResources::new()),
89 seed,
90 );
91
92 spawner.spawn(unwrap!(net_task(runner)));
93
94 perf_client::run(
95 stack,
96 perf_client::Expected {
97 down_kbps: 50,
98 up_kbps: 50,
99 updown_kbps: 50,
100 },
101 )
102 .await;
103
104 info!("Test OK");
105 cortex_m::asm::bkpt();
106}
diff --git a/tests/nrf/src/common.rs b/tests/nrf/src/common.rs
new file mode 100644
index 000000000..ebd332d15
--- /dev/null
+++ b/tests/nrf/src/common.rs
@@ -0,0 +1,117 @@
1#![macro_use]
2
3use {defmt_rtt as _, panic_probe as _};
4
5#[cfg(feature = "nrf52832")]
6teleprobe_meta::target!(b"nrf52832-dk");
7#[cfg(feature = "nrf52840")]
8teleprobe_meta::target!(b"nrf52840-dk");
9#[cfg(feature = "nrf52833")]
10teleprobe_meta::target!(b"nrf52833-dk");
11#[cfg(feature = "nrf5340")]
12teleprobe_meta::target!(b"nrf5340-dk");
13#[cfg(feature = "nrf9160")]
14teleprobe_meta::target!(b"nrf9160-dk");
15#[cfg(feature = "nrf51422")]
16teleprobe_meta::target!(b"nrf51-dk");
17
18macro_rules! define_peris {
19 ($($name:ident = $peri:ident,)* $(@irq $irq_name:ident = $irq_code:tt,)*) => {
20 #[allow(unused_macros)]
21 macro_rules! peri {
22 $(
23 ($p:expr, $name) => {
24 $p.$peri
25 };
26 )*
27 }
28 #[allow(unused_macros)]
29 macro_rules! irqs {
30 $(
31 ($irq_name) => {{
32 embassy_nrf::bind_interrupts!(struct Irqs $irq_code);
33 Irqs
34 }};
35 )*
36 ( @ dummy ) => {};
37 }
38
39 #[allow(unused)]
40 #[allow(non_camel_case_types)]
41 pub mod peris {
42 $(
43 pub type $name = embassy_nrf::peripherals::$peri;
44 )*
45 }
46 };
47}
48
49#[cfg(feature = "nrf51422")]
50define_peris!(PIN_A = P0_13, PIN_B = P0_14,);
51
52#[cfg(feature = "nrf52832")]
53define_peris!(
54 PIN_A = P0_11, PIN_B = P0_12,
55 PIN_X = P0_13,
56 UART0 = UARTE0,
57 SPIM0 = TWISPI0,
58 @irq UART0 = {UARTE0 => uarte::InterruptHandler<peripherals::UARTE0>;},
59 @irq UART0_BUFFERED = {UARTE0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>;},
60 @irq SPIM0 = {TWISPI0 => spim::InterruptHandler<peripherals::TWISPI0>;},
61);
62
63#[cfg(feature = "nrf52833")]
64define_peris!(
65 PIN_A = P1_01, PIN_B = P1_02,
66 PIN_X = P1_03,
67 UART0 = UARTE0,
68 UART1 = UARTE1,
69 SPIM0 = TWISPI0,
70 @irq UART0 = {UARTE0 => uarte::InterruptHandler<peripherals::UARTE0>;},
71 @irq UART1 = {UARTE1 => uarte::InterruptHandler<peripherals::UARTE1>;},
72 @irq UART0_BUFFERED = {UARTE0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>;},
73 @irq UART1_BUFFERED = {UARTE1 => buffered_uarte::InterruptHandler<peripherals::UARTE1>;},
74 @irq SPIM0 = {TWISPI0 => spim::InterruptHandler<peripherals::TWISPI0>;},
75);
76
77#[cfg(feature = "nrf52840")]
78define_peris!(
79 PIN_A = P1_02, PIN_B = P1_03,
80 PIN_X = P1_04,
81 UART0 = UARTE0,
82 UART1 = UARTE1,
83 SPIM0 = TWISPI0,
84 @irq UART0 = {UARTE0 => uarte::InterruptHandler<peripherals::UARTE0>;},
85 @irq UART1 = {UARTE1 => uarte::InterruptHandler<peripherals::UARTE1>;},
86 @irq UART0_BUFFERED = {UARTE0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>;},
87 @irq UART1_BUFFERED = {UARTE1 => buffered_uarte::InterruptHandler<peripherals::UARTE1>;},
88 @irq SPIM0 = {TWISPI0 => spim::InterruptHandler<peripherals::TWISPI0>;},
89);
90
91#[cfg(feature = "nrf5340")]
92define_peris!(
93 PIN_A = P1_08, PIN_B = P1_09,
94 PIN_X = P1_10,
95 UART0 = SERIAL0,
96 UART1 = SERIAL1,
97 SPIM0 = SERIAL0,
98 @irq UART0 = {SERIAL0 => uarte::InterruptHandler<peripherals::SERIAL0>;},
99 @irq UART1 = {SERIAL1 => uarte::InterruptHandler<peripherals::SERIAL1>;},
100 @irq UART0_BUFFERED = {SERIAL0 => buffered_uarte::InterruptHandler<peripherals::SERIAL0>;},
101 @irq UART1_BUFFERED = {SERIAL1 => buffered_uarte::InterruptHandler<peripherals::SERIAL1>;},
102 @irq SPIM0 = {SERIAL0 => spim::InterruptHandler<peripherals::SERIAL0>;},
103);
104
105#[cfg(feature = "nrf9160")]
106define_peris!(
107 PIN_A = P0_00, PIN_B = P0_01,
108 PIN_X = P0_02,
109 UART0 = SERIAL0,
110 UART1 = SERIAL1,
111 SPIM0 = SERIAL0,
112 @irq UART0 = {SERIAL0 => uarte::InterruptHandler<peripherals::SERIAL0>;},
113 @irq UART1 = {SERIAL1 => uarte::InterruptHandler<peripherals::SERIAL1>;},
114 @irq UART0_BUFFERED = {SERIAL0 => buffered_uarte::InterruptHandler<peripherals::SERIAL0>;},
115 @irq UART1_BUFFERED = {SERIAL1 => buffered_uarte::InterruptHandler<peripherals::SERIAL1>;},
116 @irq SPIM0 = {SERIAL0 => spim::InterruptHandler<peripherals::SERIAL0>;},
117);