diff --git a/qemu/examples/1-rtic2.rs b/qemu/examples/1-rtic2.rs new file mode 100644 index 0000000000000000000000000000000000000000..7b615270ee8b6015821fc8791e8b937ba9b3ba10 --- /dev/null +++ b/qemu/examples/1-rtic2.rs @@ -0,0 +1,79 @@ +#![deny(unsafe_code)] +// #![deny(warnings)] +#![no_main] +#![no_std] + +use async_cortex_m::{task, unsync::Mutex}; +use cortex_m_semihosting::{debug, hprintln}; +use panic_halt as _; // panic handler +use rtic::app; + +#[rtic::app(device = lm3s6965)] +mod app { + #[resources] + struct Resources { + #[init(9)] + x: u32, + } + + #[idle(resources = [x])] + fn idle(mut cx: idle::Context) -> ! { + static mut X: Mutex<i64> = Mutex::new(0); + let c: &'static _ = X; + + cx.resources.x.lock(|x| { + hprintln!("x {}", x).ok(); + }); + + task::spawn(a1(c)); + + task::block_on(async { + loop { + hprintln!("B: before lock").ok(); + + // cannot immediately make progress; context switch to A + let mut lock = c.lock().await; + + hprintln!("B: {}", *lock).ok(); + *lock += 1; + + if *lock > 3 { + debug::exit(debug::EXIT_SUCCESS); + } else { + drop(lock); + hprintln!("B: yield").ok(); + task::r#yield().await; + } + } + }); + + loop { + continue; + } + } + #[task(binds = UART0, resources = [x])] + fn rt_task(cx: rt_task::Context) { + hprintln!("x {}", cx.resources.x).ok(); + } +} + +async fn a1(c: &Mutex<i64>) { + loop { + hprintln!("A: before lock").ok(); + + let mut lock = c.lock().await; + + hprintln!("A: before write {}", *lock).ok(); + *lock += 1; + drop(lock); + + hprintln!("A: after releasing the lock").ok(); + + hprintln!("A: manual yield").ok(); + task::r#yield().await; + } +} + +// fn some_driver() -> impl Future { +// task::r#yield() +// } diff --git a/qemu/examples/1-rtic3.rs b/qemu/examples/1-rtic3.rs new file mode 100644 index 0000000000000000000000000000000000000000..f81d0dfaad87941826663ac5d3651700da30dd6f --- /dev/null +++ b/qemu/examples/1-rtic3.rs @@ -0,0 +1,115 @@ +// #![deny(unsafe_code)] +// #![deny(warnings)] +#![no_main] +#![no_std] + +use async_cortex_m::{task, unsync::Mutex}; +use cortex_m_semihosting::{debug, hprintln}; +use panic_halt as _; // panic handler +use rtic::app; + +#[rtic::app(device = lm3s6965)] +mod app { + #[resources] + struct Resources { + #[init(9)] + x: u32, + } + + #[idle(resources = [x])] + fn idle(mut cx: idle::Context) -> ! { + let mut x = cx.resources.x; + task::spawn(a1()); + task::spawn(spawn_a1a()); + // task::spawn(a1a(&mut x)); // needs to be static + + task::spawn(a2()); + + task::block_on(async { + let mut local = 0; + loop { + local += 1; + x.lock(|x| { + hprintln!("B: x {:?}", x).ok(); + }); + + if local > 3 { + debug::exit(debug::EXIT_SUCCESS); + } else { + hprintln!("B: yield").ok(); + task::r#yield().await; + } + } + }); + + loop { + continue; + } + } + #[task(binds = UART0, resources = [x])] + fn rt_task(cx: rt_task::Context) { + hprintln!("x {}", cx.resources.x).ok(); + } +} + +// static mut r: resources::x = resources::x::new(&rtic::export::Priority::new(1)); + +// some uggly code +fn spawn_a1a() -> impl core::future::Future + 'static { + static prio: rtic::export::Priority = unsafe { rtic::export::Priority::new(0) }; + static mut X: resources::x = resources::x { priority: &prio }; + a1a(unsafe { &mut X }) +} + +async fn a1a<'a>(x: &mut resources::x<'a>) { + use rtic::Mutex; + loop { + hprintln!("A1: before lock").ok(); + x.lock(|x| { + hprintln!("A1: x {:?}", x).ok(); + *x = 56; + // task::r#yield().await; // we are protected by the compiler + }); + + hprintln!("A1: manual yield").ok(); + task::r#yield().await; + } +} + +async fn a1() { + // this code must be injected by RTIC + use rtic::Mutex; + let prio = unsafe { rtic::export::Priority::new(0) }; + let xr = &mut unsafe { resources::x::new(&prio) }; + + // here is the user code + let mut nr_calls = 1; + loop { + hprintln!("A1: before lock").ok(); + xr.lock(|x| { + hprintln!("A1: x {:?}, nr_calls {:?}", x, nr_calls).ok(); + *x += nr_calls; + nr_calls += 1; + // xr.lock(|x| { + // // we are protected by the compiler + // hprintln!("A1: x {:?}", x).ok(); + // *x = 56; + // }); + }); + + hprintln!("A1: manual yield").ok(); + task::r#yield().await; + } +} + +async fn a2() { + loop { + hprintln!("A2: before lock").ok(); + + hprintln!("A2: manual yield").ok(); + task::r#yield().await; + } +} +// fn some_driver() -> impl Future { +// task::r#yield() +// }