mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-28 21:00:59 +00:00

* feat: Avoid using nb::Result in spi * feat: Avoid using nb::Result in hmac * feat: Avoid using nb::Result in sha * feat: Avoid using nb::Result in usb_serial_jtag * feat: Avoid using nb::Result in adc::read_oneshot * feat: Avoid using nb::Result in rsa::ready * feat: Avoid using nb::Result in timer::wait * feat: Avoid using nb in uart and twai. Udpate examples and tests to avoid using block! * feat: Block on sha calls, remove Option<> results * feat: Block on hmac calls, remove Option<> results * fix: Clippy lints * feat: Block on spi calls, remove Option<> results * feat: Block on timer calls, remove Option<> results * feat: Block on twai calls, remove Option<> results * docs: Fix wait docstring * feat: Remove embedded_hal_nb traits * feat: Block on uart calls, remove Option<> results * feat: Remove nb stuff from usb_serial_jtag * feat: Block on rsa calls, remove Option<> results * feat: Clippy lints * feat: Make read_bytes return how many bytes it read from the fifo and fix docs/tests * fix: run_test_periodic_timer test * feat: Only remove nb from stabilizing drivers * feat: Remove unused functions * feat: Remove emnbedded-hal-nb * test: Adapt tests * docs: Update changelog and migration * test: Adapt tests * docs: Update migration guide * docs: Update migration Co-authored-by: Dániel Buga <bugadani@gmail.com> * docs: Update changelog and migration guide * feat: Make `write_bytes` return an Result --------- Co-authored-by: Dániel Buga <bugadani@gmail.com>
277 lines
7.9 KiB
Rust
277 lines
7.9 KiB
Rust
//! Embassy timer and executor Test
|
|
|
|
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
|
//% FEATURES: unstable embassy
|
|
|
|
#![no_std]
|
|
#![no_main]
|
|
|
|
use embassy_time::{Duration, Ticker, Timer};
|
|
#[cfg(not(feature = "esp32"))]
|
|
use esp_hal::{
|
|
interrupt::software::SoftwareInterruptControl,
|
|
interrupt::Priority,
|
|
timer::systimer::SystemTimer,
|
|
timer::AnyTimer,
|
|
};
|
|
use esp_hal::{
|
|
peripherals::Peripherals,
|
|
time::ExtU64,
|
|
timer::{timg::TimerGroup, OneShotTimer, PeriodicTimer},
|
|
};
|
|
#[cfg(not(feature = "esp32"))]
|
|
use esp_hal_embassy::InterruptExecutor;
|
|
use hil_test as _;
|
|
|
|
#[cfg(not(feature = "esp32"))]
|
|
macro_rules! mk_static {
|
|
($t:ty,$val:expr) => {{
|
|
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
|
|
#[deny(unused_attributes)]
|
|
let x = STATIC_CELL.uninit().write(($val));
|
|
x
|
|
}};
|
|
}
|
|
|
|
// List of the functions that are ACTUALLY TESTS but are called in the invokers
|
|
mod test_helpers {
|
|
use super::*;
|
|
|
|
#[embassy_executor::task]
|
|
pub async fn e_task30ms() {
|
|
Timer::after_millis(30).await;
|
|
}
|
|
}
|
|
|
|
mod test_cases {
|
|
use esp_hal::peripheral::Peripheral;
|
|
|
|
use super::*;
|
|
|
|
pub async fn run_test_one_shot_async() {
|
|
let t1 = esp_hal::time::now();
|
|
Timer::after_millis(50).await;
|
|
Timer::after_millis(30).await;
|
|
let t2 = esp_hal::time::now();
|
|
|
|
assert!(t2 > t1, "t2: {:?}, t1: {:?}", t2, t1);
|
|
assert!(
|
|
(t2 - t1).to_millis() >= 80u64,
|
|
"diff: {:?}",
|
|
(t2 - t1).to_millis()
|
|
);
|
|
}
|
|
|
|
pub fn run_test_periodic_timer<T: esp_hal::timer::Timer>(timer: impl Peripheral<P = T>) {
|
|
let mut periodic = PeriodicTimer::new(timer);
|
|
|
|
let t1 = esp_hal::time::now();
|
|
periodic.start(100.millis()).unwrap();
|
|
|
|
periodic.wait();
|
|
|
|
let t2 = esp_hal::time::now();
|
|
|
|
assert!(t2 > t1, "t2: {:?}, t1: {:?}", t2, t1);
|
|
assert!(
|
|
(t2 - t1).to_millis() >= 100u64,
|
|
"diff: {:?}",
|
|
(t2 - t1).to_millis()
|
|
);
|
|
}
|
|
|
|
pub fn run_test_oneshot_timer<T: esp_hal::timer::Timer>(timer: impl Peripheral<P = T>) {
|
|
let mut timer = OneShotTimer::new(timer);
|
|
|
|
let t1 = esp_hal::time::now();
|
|
timer.delay_millis(50);
|
|
let t2 = esp_hal::time::now();
|
|
|
|
assert!(t2 > t1, "t2: {:?}, t1: {:?}", t2, t1);
|
|
assert!(
|
|
(t2 - t1).to_millis() >= 50u64,
|
|
"diff: {:?}",
|
|
(t2 - t1).to_millis()
|
|
);
|
|
}
|
|
|
|
pub async fn run_join_test() {
|
|
let t1 = esp_hal::time::now();
|
|
embassy_futures::join::join(Timer::after_millis(50), Timer::after_millis(30)).await;
|
|
Timer::after_millis(50).await;
|
|
let t2 = esp_hal::time::now();
|
|
|
|
assert!(t2 > t1, "t2: {:?}, t1: {:?}", t2, t1);
|
|
assert!(
|
|
(t2 - t1).to_millis() >= 100u64,
|
|
"diff: {:?}",
|
|
(t2 - t1).to_millis()
|
|
);
|
|
}
|
|
}
|
|
|
|
fn set_up_embassy_with_timg0(peripherals: Peripherals) {
|
|
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
|
esp_hal_embassy::init(timg0.timer0);
|
|
}
|
|
|
|
#[cfg(not(feature = "esp32"))]
|
|
fn set_up_embassy_with_systimer(peripherals: Peripherals) {
|
|
let systimer = SystemTimer::new(peripherals.SYSTIMER);
|
|
esp_hal_embassy::init(systimer.alarm0);
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[embedded_test::tests(default_timeout = 3, executor = hil_test::Executor::new())]
|
|
mod test {
|
|
use super::*;
|
|
use crate::test_cases::*;
|
|
#[cfg(not(feature = "esp32"))]
|
|
use crate::test_helpers::*;
|
|
|
|
#[init]
|
|
fn init() -> Peripherals {
|
|
esp_hal::init(esp_hal::Config::default())
|
|
}
|
|
|
|
#[test]
|
|
async fn test_one_shot_timg(peripherals: Peripherals) {
|
|
set_up_embassy_with_timg0(peripherals);
|
|
|
|
run_test_one_shot_async().await;
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(not(feature = "esp32"))]
|
|
async fn test_one_shot_systimer(peripherals: Peripherals) {
|
|
set_up_embassy_with_systimer(peripherals);
|
|
|
|
run_test_one_shot_async().await;
|
|
}
|
|
|
|
#[test]
|
|
fn test_periodic_timg(peripherals: Peripherals) {
|
|
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
|
|
|
run_test_periodic_timer(timg0.timer0);
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(not(feature = "esp32"))]
|
|
fn test_periodic_systimer(peripherals: Peripherals) {
|
|
let systimer = SystemTimer::new(peripherals.SYSTIMER);
|
|
|
|
run_test_periodic_timer(systimer.alarm0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_periodic_oneshot_timg(peripherals: Peripherals) {
|
|
let mut timg0 = TimerGroup::new(peripherals.TIMG0);
|
|
run_test_periodic_timer(&mut timg0.timer0);
|
|
run_test_oneshot_timer(&mut timg0.timer0);
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(not(feature = "esp32"))]
|
|
fn test_periodic_oneshot_systimer(peripherals: Peripherals) {
|
|
let mut systimer = SystemTimer::new(peripherals.SYSTIMER);
|
|
run_test_periodic_timer(&mut systimer.alarm0);
|
|
run_test_oneshot_timer(&mut systimer.alarm0);
|
|
}
|
|
|
|
#[test]
|
|
async fn test_join_timg(peripherals: Peripherals) {
|
|
set_up_embassy_with_timg0(peripherals);
|
|
|
|
run_join_test().await;
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(not(feature = "esp32"))]
|
|
async fn test_join_systimer(peripherals: Peripherals) {
|
|
set_up_embassy_with_systimer(peripherals);
|
|
|
|
run_join_test().await;
|
|
}
|
|
|
|
/// Test that the ticker works in tasks ran by the interrupt executors.
|
|
#[test]
|
|
#[cfg(not(feature = "esp32"))]
|
|
async fn test_interrupt_executor(peripherals: Peripherals) {
|
|
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
|
let timer0: AnyTimer = timg0.timer0.into();
|
|
|
|
let systimer = SystemTimer::new(peripherals.SYSTIMER);
|
|
let alarm0: AnyTimer = systimer.alarm0.into();
|
|
|
|
esp_hal_embassy::init([timer0, alarm0]);
|
|
|
|
let sw_ints = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
|
|
|
|
let executor = mk_static!(
|
|
InterruptExecutor<2>,
|
|
InterruptExecutor::new(sw_ints.software_interrupt2)
|
|
);
|
|
|
|
#[embassy_executor::task]
|
|
#[cfg(not(feature = "esp32"))]
|
|
async fn test_interrupt_executor_invoker() {
|
|
let outcome = async {
|
|
let mut ticker = Ticker::every(Duration::from_millis(30));
|
|
|
|
let t1 = esp_hal::time::now();
|
|
ticker.next().await;
|
|
ticker.next().await;
|
|
ticker.next().await;
|
|
let t2 = esp_hal::time::now();
|
|
|
|
assert!(t2 > t1, "t2: {:?}, t1: {:?}", t2, t1);
|
|
assert!(
|
|
(t2 - t1).to_micros() >= 85000u64,
|
|
"diff: {:?}",
|
|
(t2 - t1).to_micros()
|
|
);
|
|
};
|
|
|
|
embedded_test::export::check_outcome(outcome.await);
|
|
}
|
|
|
|
let spawner_int = executor.start(Priority::Priority3);
|
|
spawner_int.must_spawn(test_interrupt_executor_invoker());
|
|
|
|
let spawner = embassy_executor::Spawner::for_current_executor().await;
|
|
spawner.must_spawn(e_task30ms());
|
|
|
|
// The test ends once the interrupt executor's task has finished
|
|
loop {}
|
|
}
|
|
|
|
/// Test that timg0 and systimer don't have vastly different tick rates.
|
|
#[test]
|
|
async fn tick_test_timer_tick_rates(peripherals: Peripherals) {
|
|
set_up_embassy_with_timg0(peripherals);
|
|
|
|
// We are retrying 5 times because probe-rs polling RTT may introduce some
|
|
// jitter.
|
|
for _ in 0..5 {
|
|
let t1 = esp_hal::time::now();
|
|
|
|
let mut ticker = Ticker::every(Duration::from_hz(100_000));
|
|
for _ in 0..2000 {
|
|
ticker.next().await;
|
|
}
|
|
let t2 = esp_hal::time::now();
|
|
|
|
assert!(t2 > t1, "t2: {:?}, t1: {:?}", t2, t1);
|
|
let duration = (t2 - t1).to_micros();
|
|
|
|
assert!(duration >= 19000, "diff: {:?}", (t2 - t1).to_micros());
|
|
if duration <= 21000 {
|
|
return;
|
|
}
|
|
}
|
|
|
|
assert!(false, "Test failed after 5 retries");
|
|
}
|
|
}
|