aboutsummaryrefslogtreecommitdiff
path: root/examples/rp235x/src/bin/multiprio.rs
diff options
context:
space:
mode:
authorCurly <[email protected]>2025-02-23 07:33:58 -0800
committerCurly <[email protected]>2025-02-23 07:33:58 -0800
commit3932835998802fc3abf7cce4f736e072858ebfd1 (patch)
tree5dd714b99bc74a03556c58809237c88691c293bb /examples/rp235x/src/bin/multiprio.rs
parentc3c67db93e627a4fafe5e1a1123e5cbb4abafe47 (diff)
rename `rp23` (?) folder to `rp235x`; fix `ci.sh` to use `rp235x` folder
Diffstat (limited to 'examples/rp235x/src/bin/multiprio.rs')
-rw-r--r--examples/rp235x/src/bin/multiprio.rs145
1 files changed, 145 insertions, 0 deletions
diff --git a/examples/rp235x/src/bin/multiprio.rs b/examples/rp235x/src/bin/multiprio.rs
new file mode 100644
index 000000000..2b397f97d
--- /dev/null
+++ b/examples/rp235x/src/bin/multiprio.rs
@@ -0,0 +1,145 @@
1//! This example showcases how to create multiple Executor instances to run tasks at
2//! different priority levels.
3//!
4//! Low priority executor runs in thread mode (not interrupt), and uses `sev` for signaling
5//! there's work in the queue, and `wfe` for waiting for work.
6//!
7//! Medium and high priority executors run in two interrupts with different priorities.
8//! Signaling work is done by pending the interrupt. No "waiting" needs to be done explicitly, since
9//! when there's work the interrupt will trigger and run the executor.
10//!
11//! Sample output below. Note that high priority ticks can interrupt everything else, and
12//! medium priority computations can interrupt low priority computations, making them to appear
13//! to take significantly longer time.
14//!
15//! ```not_rust
16//! [med] Starting long computation
17//! [med] done in 992 ms
18//! [high] tick!
19//! [low] Starting long computation
20//! [med] Starting long computation
21//! [high] tick!
22//! [high] tick!
23//! [med] done in 993 ms
24//! [med] Starting long computation
25//! [high] tick!
26//! [high] tick!
27//! [med] done in 993 ms
28//! [low] done in 3972 ms
29//! [med] Starting long computation
30//! [high] tick!
31//! [high] tick!
32//! [med] done in 993 ms
33//! ```
34//!
35//! For comparison, try changing the code so all 3 tasks get spawned on the low priority executor.
36//! You will get an output like the following. Note that no computation is ever interrupted.
37//!
38//! ```not_rust
39//! [high] tick!
40//! [med] Starting long computation
41//! [med] done in 496 ms
42//! [low] Starting long computation
43//! [low] done in 992 ms
44//! [med] Starting long computation
45//! [med] done in 496 ms
46//! [high] tick!
47//! [low] Starting long computation
48//! [low] done in 992 ms
49//! [high] tick!
50//! [med] Starting long computation
51//! [med] done in 496 ms
52//! [high] tick!
53//! ```
54//!
55
56#![no_std]
57#![no_main]
58
59use cortex_m_rt::entry;
60use defmt::{info, unwrap};
61use embassy_executor::{Executor, InterruptExecutor};
62use embassy_rp::interrupt;
63use embassy_rp::interrupt::{InterruptExt, Priority};
64use embassy_time::{Instant, Timer, TICK_HZ};
65use static_cell::StaticCell;
66use {defmt_rtt as _, panic_probe as _};
67
68#[embassy_executor::task]
69async fn run_high() {
70 loop {
71 info!(" [high] tick!");
72 Timer::after_ticks(673740).await;
73 }
74}
75
76#[embassy_executor::task]
77async fn run_med() {
78 loop {
79 let start = Instant::now();
80 info!(" [med] Starting long computation");
81
82 // Spin-wait to simulate a long CPU computation
83 embassy_time::block_for(embassy_time::Duration::from_secs(1)); // ~1 second
84
85 let end = Instant::now();
86 let ms = end.duration_since(start).as_ticks() * 1000 / TICK_HZ;
87 info!(" [med] done in {} ms", ms);
88
89 Timer::after_ticks(53421).await;
90 }
91}
92
93#[embassy_executor::task]
94async fn run_low() {
95 loop {
96 let start = Instant::now();
97 info!("[low] Starting long computation");
98
99 // Spin-wait to simulate a long CPU computation
100 embassy_time::block_for(embassy_time::Duration::from_secs(2)); // ~2 seconds
101
102 let end = Instant::now();
103 let ms = end.duration_since(start).as_ticks() * 1000 / TICK_HZ;
104 info!("[low] done in {} ms", ms);
105
106 Timer::after_ticks(82983).await;
107 }
108}
109
110static EXECUTOR_HIGH: InterruptExecutor = InterruptExecutor::new();
111static EXECUTOR_MED: InterruptExecutor = InterruptExecutor::new();
112static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
113
114#[interrupt]
115unsafe fn SWI_IRQ_1() {
116 EXECUTOR_HIGH.on_interrupt()
117}
118
119#[interrupt]
120unsafe fn SWI_IRQ_0() {
121 EXECUTOR_MED.on_interrupt()
122}
123
124#[entry]
125fn main() -> ! {
126 info!("Hello World!");
127
128 let _p = embassy_rp::init(Default::default());
129
130 // High-priority executor: SWI_IRQ_1, priority level 2
131 interrupt::SWI_IRQ_1.set_priority(Priority::P2);
132 let spawner = EXECUTOR_HIGH.start(interrupt::SWI_IRQ_1);
133 unwrap!(spawner.spawn(run_high()));
134
135 // Medium-priority executor: SWI_IRQ_0, priority level 3
136 interrupt::SWI_IRQ_0.set_priority(Priority::P3);
137 let spawner = EXECUTOR_MED.start(interrupt::SWI_IRQ_0);
138 unwrap!(spawner.spawn(run_med()));
139
140 // Low priority executor: runs in thread mode, using WFE/SEV
141 let executor = EXECUTOR_LOW.init(Executor::new());
142 executor.run(|spawner| {
143 unwrap!(spawner.spawn(run_low()));
144 });
145}