Merge pull request #3121 from embassy-rs/nrftests

nRF uart fixes, better tests.
This commit is contained in:
Dario Nieuwenhuis 2024-06-25 22:02:12 +00:00 committed by GitHub
commit a2acb3e3dc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 219 additions and 81 deletions

View file

@ -27,7 +27,7 @@ use crate::ppi::{
};
use crate::timer::{Instance as TimerInstance, Timer};
use crate::uarte::{configure, drop_tx_rx, Config, Instance as UarteInstance};
use crate::{interrupt, pac, Peripheral};
use crate::{interrupt, pac, Peripheral, EASY_DMA_SIZE};
pub(crate) struct State {
tx_buf: RingBuffer,
@ -186,6 +186,7 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
// If not TXing, start.
if s.tx_count.load(Ordering::Relaxed) == 0 {
let (ptr, len) = tx.pop_buf();
let len = len.min(EASY_DMA_SIZE);
if len != 0 {
//trace!(" irq_tx: starting {:?}", len);
s.tx_count.store(len, Ordering::Relaxed);
@ -304,6 +305,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
let tx = BufferedUarteTx::new_innerer(unsafe { peri.clone_unchecked() }, txd, cts, tx_buffer);
let rx = BufferedUarteRx::new_innerer(peri, timer, ppi_ch1, ppi_ch2, ppi_group, rxd, rts, rx_buffer);
U::regs().enable.write(|w| w.enable().enabled());
U::Interrupt::pend();
unsafe { U::Interrupt::enable() };
@ -405,6 +407,7 @@ impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> {
let this = Self::new_innerer(peri, txd, cts, tx_buffer);
U::regs().enable.write(|w| w.enable().enabled());
U::Interrupt::pend();
unsafe { U::Interrupt::enable() };
@ -602,6 +605,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> {
let this = Self::new_innerer(peri, timer, ppi_ch1, ppi_ch2, ppi_group, rxd, rts, rx_buffer);
U::regs().enable.write(|w| w.enable().enabled());
U::Interrupt::pend();
unsafe { U::Interrupt::enable() };
@ -638,8 +642,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> {
s.rx_started_count.store(0, Ordering::Relaxed);
s.rx_ended_count.store(0, Ordering::Relaxed);
s.rx_started.store(false, Ordering::Relaxed);
let len = rx_buffer.len();
unsafe { s.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
let rx_len = rx_buffer.len().min(EASY_DMA_SIZE * 2);
unsafe { s.rx_buf.init(rx_buffer.as_mut_ptr(), rx_len) };
// clear errors
let errors = r.errorsrc.read().bits();
@ -660,7 +664,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> {
// Configure byte counter.
let timer = Timer::new_counter(timer);
timer.cc(1).write(rx_buffer.len() as u32 * 2);
timer.cc(1).write(rx_len as u32 * 2);
timer.cc(1).short_compare_clear();
timer.clear();
timer.start();

View file

@ -221,6 +221,7 @@ impl<'d, T: Instance> Uarte<'d, T> {
T::Interrupt::unpend();
unsafe { T::Interrupt::enable() };
r.enable.write(|w| w.enable().enabled());
let s = T::state();
s.tx_rx_refcount.store(2, Ordering::Relaxed);
@ -319,9 +320,7 @@ pub(crate) fn configure(r: &RegisterBlock, config: Config, hardware_flow_control
r.psel.cts.write(|w| w.connect().disconnected());
r.psel.rts.write(|w| w.connect().disconnected());
// Enable
apply_workaround_for_enable_anomaly(r);
r.enable.write(|w| w.enable().enabled());
}
impl<'d, T: Instance> UarteTx<'d, T> {
@ -369,6 +368,7 @@ impl<'d, T: Instance> UarteTx<'d, T> {
T::Interrupt::unpend();
unsafe { T::Interrupt::enable() };
r.enable.write(|w| w.enable().enabled());
let s = T::state();
s.tx_rx_refcount.store(1, Ordering::Relaxed);
@ -567,6 +567,7 @@ impl<'d, T: Instance> UarteRx<'d, T> {
T::Interrupt::unpend();
unsafe { T::Interrupt::enable() };
r.enable.write(|w| w.enable().enabled());
let s = T::state();
s.tx_rx_refcount.store(1, Ordering::Relaxed);

View file

@ -30,14 +30,15 @@ panic-probe = { version = "0.3", features = ["print-defmt"] }
portable-atomic = { version = "1.6.0" }
[features]
nrf51422 = ["embassy-nrf/nrf51", "portable-atomic/unsafe-assume-single-core"]
nrf51422 = ["embassy-nrf/nrf51", "portable-atomic/unsafe-assume-single-core"]
nrf52832 = ["embassy-nrf/nrf52832", "easydma"]
nrf52833 = ["embassy-nrf/nrf52833", "easydma"]
nrf52840 = ["embassy-nrf/nrf52840", "easydma"]
nrf5340 = ["embassy-nrf/nrf5340-app-s", "easydma"]
nrf9160 = ["embassy-nrf/nrf9160-s", "easydma"]
nrf52833 = ["embassy-nrf/nrf52833", "easydma", "two-uarts"]
nrf52840 = ["embassy-nrf/nrf52840", "easydma", "two-uarts"]
nrf5340 = ["embassy-nrf/nrf5340-app-s", "easydma", "two-uarts"]
nrf9160 = ["embassy-nrf/nrf9160-s", "easydma", "two-uarts"]
easydma = []
two-uarts = []
[profile.release]
codegen-units = 1
@ -53,22 +54,22 @@ overflow-checks = false
[[bin]]
name = "buffered_uart"
path = "src/bin/buffered_uart.rs"
required-features = [ "nrf52840",]
required-features = [ "easydma",]
[[bin]]
name = "buffered_uart_full"
path = "src/bin/buffered_uart_full.rs"
required-features = [ "nrf52840",]
required-features = [ "easydma",]
[[bin]]
name = "buffered_uart_halves"
path = "src/bin/buffered_uart_halves.rs"
required-features = [ "nrf52840",]
required-features = [ "two-uarts",]
[[bin]]
name = "buffered_uart_spam"
path = "src/bin/buffered_uart_spam.rs"
required-features = [ "nrf52840",]
required-features = [ "two-uarts",]
[[bin]]
name = "ethernet_enc28j60_perf"
@ -90,6 +91,16 @@ name = "timer"
path = "src/bin/timer.rs"
required-features = []
[[bin]]
name = "uart_halves"
path = "src/bin/uart_halves.rs"
required-features = [ "two-uarts",]
[[bin]]
name = "uart_split"
path = "src/bin/uart_split.rs"
required-features = [ "easydma",]
[[bin]]
name = "wifi_esp_hosted_perf"
path = "src/bin/wifi_esp_hosted_perf.rs"

View file

@ -1,19 +1,17 @@
// required-features: nrf52840
// required-features: easydma
#![no_std]
#![no_main]
teleprobe_meta::target!(b"nrf52840-dk");
use defmt::{assert_eq, *};
#[path = "../common.rs"]
mod common;
use defmt::{panic, *};
use embassy_executor::Spawner;
use embassy_futures::join::join;
use embassy_nrf::buffered_uarte::{self, BufferedUarte};
use embassy_nrf::{bind_interrupts, peripherals, uarte};
use embassy_nrf::{peripherals, uarte};
use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
UARTE0_UART0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>;
});
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let mut p = embassy_nrf::init(Default::default());
@ -27,14 +25,14 @@ async fn main(_spawner: Spawner) {
// test teardown + recreate of the buffereduarte works fine.
for _ in 0..2 {
let u = BufferedUarte::new(
&mut p.UARTE0,
&mut peri!(p, UART0),
&mut p.TIMER0,
&mut p.PPI_CH0,
&mut p.PPI_CH1,
&mut p.PPI_GROUP0,
Irqs,
&mut p.P1_03,
&mut p.P1_02,
irqs!(UART0_BUFFERED),
&mut peri!(p, PIN_A),
&mut peri!(p, PIN_B),
config.clone(),
&mut rx_buffer,
&mut tx_buffer,
@ -65,7 +63,9 @@ async fn main(_spawner: Spawner) {
let buf = unwrap!(rx.fill_buf().await);
for &b in buf {
assert_eq!(b, i as u8);
if b != i as u8 {
panic!("mismatch {} vs {}, index {}", b, i as u8, i);
}
i = i + 1;
}

View file

@ -1,19 +1,17 @@
// required-features: nrf52840
// required-features: easydma
#![no_std]
#![no_main]
teleprobe_meta::target!(b"nrf52840-dk");
#[path = "../common.rs"]
mod common;
use defmt::{assert_eq, *};
use embassy_executor::Spawner;
use embassy_nrf::buffered_uarte::{self, BufferedUarte};
use embassy_nrf::{bind_interrupts, peripherals, uarte};
use embassy_nrf::{peripherals, uarte};
use embedded_io_async::{Read, Write};
use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
UARTE0_UART0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>;
});
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_nrf::init(Default::default());
@ -21,18 +19,18 @@ async fn main(_spawner: Spawner) {
config.parity = uarte::Parity::EXCLUDED;
config.baudrate = uarte::Baudrate::BAUD1M;
let mut tx_buffer = [0u8; 1024];
let mut rx_buffer = [0u8; 1024];
let mut tx_buffer = [0u8; 500];
let mut rx_buffer = [0u8; 500];
let u = BufferedUarte::new(
p.UARTE0,
peri!(p, UART0),
p.TIMER0,
p.PPI_CH0,
p.PPI_CH1,
p.PPI_GROUP0,
Irqs,
p.P1_03,
p.P1_02,
irqs!(UART0_BUFFERED),
peri!(p, PIN_A),
peri!(p, PIN_B),
config.clone(),
&mut rx_buffer,
&mut tx_buffer,
@ -42,22 +40,22 @@ async fn main(_spawner: Spawner) {
let (mut rx, mut tx) = u.split();
let mut buf = [0; 1024];
let mut buf = [0; 500];
for (j, b) in buf.iter_mut().enumerate() {
*b = j as u8;
}
// Write 1024b. This causes the rx buffer to get exactly full.
// Write 500b. This causes the rx buffer to get exactly full.
unwrap!(tx.write_all(&buf).await);
unwrap!(tx.flush().await);
// Read those 1024b.
// Read those 500b.
unwrap!(rx.read_exact(&mut buf).await);
for (j, b) in buf.iter().enumerate() {
assert_eq!(*b, j as u8);
}
// The buffer should now be unclogged. Write 1024b again.
// The buffer should now be unclogged. Write 500b again.
unwrap!(tx.write_all(&buf).await);
unwrap!(tx.flush().await);

View file

@ -1,20 +1,17 @@
// required-features: nrf52840
// required-features: two-uarts
#![no_std]
#![no_main]
teleprobe_meta::target!(b"nrf52840-dk");
#[path = "../common.rs"]
mod common;
use defmt::{assert_eq, *};
use embassy_executor::Spawner;
use embassy_futures::join::join;
use embassy_nrf::buffered_uarte::{self, BufferedUarteRx, BufferedUarteTx};
use embassy_nrf::{bind_interrupts, peripherals, uarte};
use embassy_nrf::{peripherals, uarte};
use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
UARTE0_UART0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>;
UARTE1 => buffered_uarte::InterruptHandler<peripherals::UARTE1>;
});
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let mut p = embassy_nrf::init(Default::default());
@ -29,16 +26,22 @@ async fn main(_spawner: Spawner) {
for _ in 0..2 {
const COUNT: usize = 40_000;
let mut tx = BufferedUarteTx::new(&mut p.UARTE1, Irqs, &mut p.P1_02, config.clone(), &mut tx_buffer);
let mut tx = BufferedUarteTx::new(
&mut peri!(p, UART1),
irqs!(UART1_BUFFERED),
&mut peri!(p, PIN_A),
config.clone(),
&mut tx_buffer,
);
let mut rx = BufferedUarteRx::new(
&mut p.UARTE0,
&mut peri!(p, UART0),
&mut p.TIMER0,
&mut p.PPI_CH0,
&mut p.PPI_CH1,
&mut p.PPI_GROUP0,
Irqs,
&mut p.P1_03,
irqs!(UART0_BUFFERED),
&mut peri!(p, PIN_B),
config.clone(),
&mut rx_buffer,
);

View file

@ -1,26 +1,23 @@
// required-features: nrf52840
// required-features: two-uarts
#![no_std]
#![no_main]
teleprobe_meta::target!(b"nrf52840-dk");
#[path = "../common.rs"]
mod common;
use core::mem;
use core::ptr::NonNull;
use defmt::{assert_eq, *};
use embassy_executor::Spawner;
use embassy_nrf::buffered_uarte::{self, BufferedUarte};
use embassy_nrf::buffered_uarte::{self, BufferedUarteRx};
use embassy_nrf::gpio::{Level, Output, OutputDrive};
use embassy_nrf::ppi::{Event, Ppi, Task};
use embassy_nrf::uarte::Uarte;
use embassy_nrf::{bind_interrupts, pac, peripherals, uarte};
use embassy_nrf::uarte::UarteTx;
use embassy_nrf::{pac, peripherals, uarte};
use embassy_time::Timer;
use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
UARTE0_UART0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>;
UARTE1 => uarte::InterruptHandler<peripherals::UARTE1>;
});
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let mut p = embassy_nrf::init(Default::default());
@ -28,23 +25,20 @@ async fn main(_spawner: Spawner) {
config.parity = uarte::Parity::EXCLUDED;
config.baudrate = uarte::Baudrate::BAUD1M;
let mut tx_buffer = [0u8; 1024];
let mut rx_buffer = [0u8; 1024];
mem::forget(Output::new(&mut p.P1_02, Level::High, OutputDrive::Standard));
mem::forget(Output::new(&mut peri!(p, PIN_A), Level::High, OutputDrive::Standard));
let mut u = BufferedUarte::new(
p.UARTE0,
let mut u = BufferedUarteRx::new(
peri!(p, UART0),
p.TIMER0,
p.PPI_CH0,
p.PPI_CH1,
p.PPI_GROUP0,
Irqs,
p.P1_03,
p.P1_04,
irqs!(UART0_BUFFERED),
peri!(p, PIN_B),
config.clone(),
&mut rx_buffer,
&mut tx_buffer,
);
info!("uarte initialized!");
@ -55,7 +49,7 @@ async fn main(_spawner: Spawner) {
// Tx spam in a loop.
const NSPAM: usize = 17;
static mut TX_BUF: [u8; NSPAM] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
let _spam = Uarte::new(p.UARTE1, Irqs, p.P1_01, p.P1_02, config.clone());
let _spam = UarteTx::new(peri!(p, UART1), irqs!(UART1), peri!(p, PIN_A), config.clone());
let spam_peri: pac::UARTE1 = unsafe { mem::transmute(()) };
let event = unsafe { Event::new_unchecked(NonNull::new_unchecked(&spam_peri.events_endtx as *const _ as _)) };
let task = unsafe { Task::new_unchecked(NonNull::new_unchecked(&spam_peri.tasks_starttx as *const _ as _)) };

View file

@ -0,0 +1,41 @@
// required-features: two-uarts
#![no_std]
#![no_main]
#[path = "../common.rs"]
mod common;
use defmt::{assert_eq, *};
use embassy_executor::Spawner;
use embassy_futures::join::join;
use embassy_nrf::uarte::{UarteRx, UarteTx};
use embassy_nrf::{peripherals, uarte};
use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let mut p = embassy_nrf::init(Default::default());
let mut config = uarte::Config::default();
config.parity = uarte::Parity::EXCLUDED;
config.baudrate = uarte::Baudrate::BAUD1M;
let mut tx = UarteTx::new(&mut peri!(p, UART0), irqs!(UART0), &mut peri!(p, PIN_A), config.clone());
let mut rx = UarteRx::new(&mut peri!(p, UART1), irqs!(UART1), &mut peri!(p, PIN_B), config.clone());
let data = [
0x42, 0x43, 0x44, 0x45, 0x66, 0x12, 0x23, 0x34, 0x45, 0x19, 0x91, 0xaa, 0xff, 0xa5, 0x5a, 0x77,
];
let tx_fut = async {
tx.write(&data).await.unwrap();
};
let rx_fut = async {
let mut buf = [0u8; 16];
rx.read(&mut buf).await.unwrap();
assert_eq!(data, buf);
};
join(rx_fut, tx_fut).await;
info!("Test OK");
cortex_m::asm::bkpt();
}

View file

@ -0,0 +1,49 @@
// required-features: easydma
#![no_std]
#![no_main]
#[path = "../common.rs"]
mod common;
use defmt::{assert_eq, *};
use embassy_executor::Spawner;
use embassy_futures::join::join;
use embassy_nrf::uarte::Uarte;
use embassy_nrf::{peripherals, uarte};
use embassy_time::Timer;
use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let mut p = embassy_nrf::init(Default::default());
let mut config = uarte::Config::default();
config.parity = uarte::Parity::EXCLUDED;
config.baudrate = uarte::Baudrate::BAUD9600;
let uarte = Uarte::new(
&mut peri!(p, UART0),
irqs!(UART0),
&mut peri!(p, PIN_A),
&mut peri!(p, PIN_B),
config.clone(),
);
let (mut tx, mut rx) = uarte.split();
let data = [
0x42, 0x43, 0x44, 0x45, 0x66, 0x12, 0x23, 0x34, 0x45, 0x19, 0x91, 0xaa, 0xff, 0xa5, 0x5a, 0x77,
];
let tx_fut = async {
Timer::after_millis(10).await;
tx.write(&data).await.unwrap();
};
let rx_fut = async {
let mut buf = [0u8; 16];
rx.read(&mut buf).await.unwrap();
assert_eq!(data, buf);
};
join(rx_fut, tx_fut).await;
info!("Test OK");
cortex_m::asm::bkpt();
}

View file

@ -50,16 +50,53 @@ macro_rules! define_peris {
define_peris!(PIN_A = P0_13, PIN_B = P0_14,);
#[cfg(feature = "nrf52832")]
define_peris!(PIN_A = P0_11, PIN_B = P0_12,);
define_peris!(
PIN_A = P0_11, PIN_B = P0_12,
UART0 = UARTE0,
@irq UART0 = {UARTE0_UART0 => uarte::InterruptHandler<peripherals::UARTE0>;},
@irq UART0_BUFFERED = {UARTE0_UART0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>;},
);
#[cfg(feature = "nrf52833")]
define_peris!(PIN_A = P1_01, PIN_B = P1_02,);
define_peris!(
PIN_A = P1_01, PIN_B = P1_02,
UART0 = UARTE0,
UART1 = UARTE1,
@irq UART0 = {UARTE0_UART0 => uarte::InterruptHandler<peripherals::UARTE0>;},
@irq UART1 = {UARTE1 => uarte::InterruptHandler<peripherals::UARTE1>;},
@irq UART0_BUFFERED = {UARTE0_UART0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>;},
@irq UART1_BUFFERED = {UARTE1 => buffered_uarte::InterruptHandler<peripherals::UARTE1>;},
);
#[cfg(feature = "nrf52840")]
define_peris!(PIN_A = P1_02, PIN_B = P1_03,);
define_peris!(
PIN_A = P1_02, PIN_B = P1_03,
UART0 = UARTE0,
UART1 = UARTE1,
@irq UART0 = {UARTE0_UART0 => uarte::InterruptHandler<peripherals::UARTE0>;},
@irq UART1 = {UARTE1 => uarte::InterruptHandler<peripherals::UARTE1>;},
@irq UART0_BUFFERED = {UARTE0_UART0 => buffered_uarte::InterruptHandler<peripherals::UARTE0>;},
@irq UART1_BUFFERED = {UARTE1 => buffered_uarte::InterruptHandler<peripherals::UARTE1>;},
);
#[cfg(feature = "nrf5340")]
define_peris!(PIN_A = P1_00, PIN_B = P1_01,);
define_peris!(
PIN_A = P1_08, PIN_B = P1_09,
UART0 = SERIAL0,
UART1 = SERIAL1,
@irq UART0 = {SERIAL0 => uarte::InterruptHandler<peripherals::SERIAL0>;},
@irq UART1 = {SERIAL1 => uarte::InterruptHandler<peripherals::SERIAL1>;},
@irq UART0_BUFFERED = {SERIAL0 => buffered_uarte::InterruptHandler<peripherals::SERIAL0>;},
@irq UART1_BUFFERED = {SERIAL1 => buffered_uarte::InterruptHandler<peripherals::SERIAL1>;},
);
#[cfg(feature = "nrf9160")]
define_peris!(PIN_A = P0_00, PIN_B = P0_01,);
define_peris!(
PIN_A = P0_00, PIN_B = P0_01,
UART0 = SERIAL0,
UART1 = SERIAL1,
@irq UART0 = {UARTE0_SPIM0_SPIS0_TWIM0_TWIS0 => uarte::InterruptHandler<peripherals::SERIAL0>;},
@irq UART1 = {UARTE1_SPIM1_SPIS1_TWIM1_TWIS1 => uarte::InterruptHandler<peripherals::SERIAL1>;},
@irq UART0_BUFFERED = {UARTE0_SPIM0_SPIS0_TWIM0_TWIS0 => buffered_uarte::InterruptHandler<peripherals::SERIAL0>;},
@irq UART1_BUFFERED = {UARTE1_SPIM1_SPIS1_TWIM1_TWIS1 => buffered_uarte::InterruptHandler<peripherals::SERIAL1>;},
);