aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32f0
diff options
context:
space:
mode:
Diffstat (limited to 'examples/stm32f0')
-rw-r--r--examples/stm32f0/src/bin/priority.rs139
1 files changed, 139 insertions, 0 deletions
diff --git a/examples/stm32f0/src/bin/priority.rs b/examples/stm32f0/src/bin/priority.rs
new file mode 100644
index 000000000..7fed6a773
--- /dev/null
+++ b/examples/stm32f0/src/bin/priority.rs
@@ -0,0 +1,139 @@
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#![feature(type_alias_impl_trait)]
59
60use cortex_m_rt::entry;
61use defmt::*;
62use embassy_stm32::executor::{Executor, InterruptExecutor};
63use embassy_stm32::interrupt;
64use embassy_stm32::interrupt::InterruptExt;
65use embassy_time::{Duration, Instant, Timer};
66use static_cell::StaticCell;
67use {defmt_rtt as _, panic_probe as _};
68
69#[embassy_executor::task]
70async fn run_high() {
71 loop {
72 // info!(" [high] tick!");
73 Timer::after(Duration::from_ticks(27374)).await;
74 }
75}
76
77#[embassy_executor::task]
78async fn run_med() {
79 loop {
80 let start = Instant::now();
81 info!(" [med] Starting long computation");
82
83 // Spin-wait to simulate a long CPU computation
84 cortex_m::asm::delay(8_000_000); // ~1 second
85
86 let end = Instant::now();
87 let ms = end.duration_since(start).as_ticks() / 33;
88 info!(" [med] done in {} ms", ms);
89
90 Timer::after(Duration::from_ticks(23421)).await;
91 }
92}
93
94#[embassy_executor::task]
95async fn run_low() {
96 loop {
97 let start = Instant::now();
98 info!("[low] Starting long computation");
99
100 // Spin-wait to simulate a long CPU computation
101 cortex_m::asm::delay(16_000_000); // ~2 seconds
102
103 let end = Instant::now();
104 let ms = end.duration_since(start).as_ticks() / 33;
105 info!("[low] done in {} ms", ms);
106
107 Timer::after(Duration::from_ticks(32983)).await;
108 }
109}
110
111static EXECUTOR_HIGH: StaticCell<InterruptExecutor<interrupt::USART1>> = StaticCell::new();
112static EXECUTOR_MED: StaticCell<InterruptExecutor<interrupt::USART2>> = StaticCell::new();
113static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
114
115#[entry]
116fn main() -> ! {
117 // Initialize and create handle for devicer peripherals
118 let _p = embassy_stm32::init(Default::default());
119
120 // High-priority executor: USART1, priority level 6
121 let irq = interrupt::take!(USART1);
122 irq.set_priority(interrupt::Priority::P6);
123 let executor = EXECUTOR_HIGH.init(InterruptExecutor::new(irq));
124 let spawner = executor.start();
125 unwrap!(spawner.spawn(run_high()));
126
127 // Medium-priority executor: USART2, priority level 7
128 let irq = interrupt::take!(USART2);
129 irq.set_priority(interrupt::Priority::P7);
130 let executor = EXECUTOR_MED.init(InterruptExecutor::new(irq));
131 let spawner = executor.start();
132 unwrap!(spawner.spawn(run_med()));
133
134 // Low priority executor: runs in thread mode, using WFE/SEV
135 let executor = EXECUTOR_LOW.init(Executor::new());
136 executor.run(|spawner| {
137 unwrap!(spawner.spawn(run_low()));
138 });
139}