esp-hal/examples/src/bin/embassy_multiprio.rs
Scott Mabin 60a2c76005
[1/4] Timer refactor: system timer (#2576)
* system timer simplfication

* Removes _all_ type params on Alarm
* Systimer no longer implements peripheral ref, the peripheral ref
  pattern is instead intended to be used on the higher level timer
  drivers
* Removed `Unit` as a type, in favour of an enum
* Alarms are back in the main `SystemTimer` "driver"
* Made all `Unit` modification methods unsafe, it's not possible to
  modify the `Unit`'s safely whilst timers and or the `time::now` API is
  in use

* fix examples and tests (by removing them :D)

* changelog and migration

* /unit_count/unit_value/g

* etm doctest

* Review feedback
2024-11-22 11:24:06 +00:00

105 lines
3.6 KiB
Rust

//! This example shows how to use the interrupt executors to prioritize some
//! tasks over others.
//!
//! The example creates three tasks:
//! - A low priority task that is not actually async, but simulates some
//! blocking work. This task will run for 5 seconds, then sleep for 5
//! seconds.
//! - A low priority task that is actually async, but will not be able to run
//! while the blocking task is running.
//! - A high priority task that prints something every second. The example
//! demonstrates that this task will continue to run even while the low
//! priority blocking task is running.
// The thread-executor is created by the `#[esp_hal_embassy::main]` macro and is used to spawn `low_prio_async` and `low_prio_blocking`.
// The interrupt-executor is created in `main` and is used to spawn `high_prio`.
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embassy esp-hal-embassy/log esp-hal-embassy/integrated-timers
#![no_std]
#![no_main]
use embassy_executor::Spawner;
use embassy_time::{Duration, Instant, Ticker, Timer};
use esp_backtrace as _;
use esp_hal::{
interrupt::{software::SoftwareInterruptControl, Priority},
timer::{timg::TimerGroup, AnyTimer},
};
use esp_hal_embassy::InterruptExecutor;
use esp_println::println;
use static_cell::StaticCell;
/// Periodically print something.
#[embassy_executor::task]
async fn high_prio() {
println!("Starting high_prio()");
let mut ticker = Ticker::every(Duration::from_secs(1));
loop {
println!("High priority ticks");
ticker.next().await;
}
}
/// Simulates some blocking (badly behaving) task.
#[embassy_executor::task]
async fn low_prio_blocking() {
println!("Starting low-priority task that isn't actually async");
loop {
println!("Doing some long and complicated calculation");
let start = Instant::now();
while start.elapsed() < Duration::from_secs(5) {}
println!("Calculation finished");
Timer::after(Duration::from_secs(5)).await;
}
}
/// A well-behaved, but starved async task.
#[embassy_executor::task]
async fn low_prio_async() {
println!("Starting low-priority task that will not be able to run while the blocking task is running");
let mut ticker = Ticker::every(Duration::from_secs(1));
loop {
println!("Low priority ticks");
ticker.next().await;
}
}
#[esp_hal_embassy::main]
async fn main(low_prio_spawner: Spawner) {
esp_println::logger::init_logger_from_env();
println!("Init!");
let peripherals = esp_hal::init(esp_hal::Config::default());
let sw_ints = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
let timg0 = TimerGroup::new(peripherals.TIMG0);
let timer0: AnyTimer = timg0.timer0.into();
cfg_if::cfg_if! {
if #[cfg(feature = "esp32c2")] {
use esp_hal::timer::systimer::SystemTimer;
let systimer = SystemTimer::new(peripherals.SYSTIMER);
let timer1: AnyTimer = systimer.alarm0.into();
} else {
let timg1 = TimerGroup::new(peripherals.TIMG1);
let timer1: AnyTimer = timg1.timer0.into();
}
}
esp_hal_embassy::init([timer0, timer1]);
static EXECUTOR: StaticCell<InterruptExecutor<2>> = StaticCell::new();
let executor = InterruptExecutor::new(sw_ints.software_interrupt2);
let executor = EXECUTOR.init(executor);
let spawner = executor.start(Priority::Priority3);
spawner.must_spawn(high_prio());
println!("Spawning low-priority tasks");
low_prio_spawner.must_spawn(low_prio_async());
low_prio_spawner.must_spawn(low_prio_blocking());
}