mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-23 20:22:51 +01:00
now with codegen
This commit is contained in:
parent
b163e3ec27
commit
72f78ce4db
2 changed files with 86 additions and 68 deletions
|
@ -13,7 +13,7 @@ use core::pin::Pin;
|
||||||
// use core::ptr;
|
// use core::ptr;
|
||||||
// use core::ptr::NonNull;
|
// use core::ptr::NonNull;
|
||||||
// use core::sync::atomic::{AtomicPtr, AtomicU32, Ordering};
|
// use core::sync::atomic::{AtomicPtr, AtomicU32, Ordering};
|
||||||
use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
|
use core::task::{Context, Poll, Waker};
|
||||||
use rtic::async_util::Task;
|
use rtic::async_util::Task;
|
||||||
|
|
||||||
use cortex_m_semihosting::{debug, hprintln};
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
|
@ -46,65 +46,29 @@ mod app {
|
||||||
|
|
||||||
#[idle]
|
#[idle]
|
||||||
fn idle(_: idle::Context) -> ! {
|
fn idle(_: idle::Context) -> ! {
|
||||||
// debug::exit(debug::EXIT_SUCCESS);
|
let mut i = 0;
|
||||||
loop {
|
loop {
|
||||||
hprintln!("idle").ok();
|
i += 1;
|
||||||
|
hprintln!("idle {}", i).ok();
|
||||||
|
if i == 3 {
|
||||||
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
|
}
|
||||||
cortex_m::asm::wfi(); // put the MCU in sleep mode until interrupt occurs
|
cortex_m::asm::wfi(); // put the MCU in sleep mode until interrupt occurs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(resources = [systick])]
|
#[task(resources = [systick])]
|
||||||
async fn foo(mut cx: foo::Context) {
|
async fn foo(cx: foo::Context) {
|
||||||
// BEGIN BOILERPLATE
|
|
||||||
type F = impl Future + 'static;
|
|
||||||
fn create(cx: foo::Context<'static>) -> F {
|
|
||||||
task(cx)
|
|
||||||
}
|
|
||||||
|
|
||||||
static mut TASK: Task<F> = Task::new();
|
|
||||||
|
|
||||||
hprintln!("foo trampoline").ok();
|
|
||||||
unsafe {
|
|
||||||
match TASK {
|
|
||||||
Task::Idle | Task::Done(_) => {
|
|
||||||
hprintln!("foo spawn task").ok();
|
|
||||||
TASK.spawn(|| create(mem::transmute(cx)));
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
|
|
||||||
hprintln!("foo trampoline poll").ok();
|
|
||||||
TASK.poll(|| {
|
|
||||||
let _ = foo::spawn();
|
|
||||||
});
|
|
||||||
|
|
||||||
match TASK {
|
|
||||||
Task::Done(ref r) => {
|
|
||||||
hprintln!("foo trampoline done").ok();
|
|
||||||
// hprintln!("r = {:?}", mem::transmute::<_, &u32>(r)).ok();
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
hprintln!("foo trampoline running").ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// END BOILERPLATE
|
|
||||||
|
|
||||||
async fn task(mut cx: foo::Context<'static>) {
|
|
||||||
hprintln!("foo task").ok();
|
hprintln!("foo task").ok();
|
||||||
|
let mut systick = cx.resources.systick;
|
||||||
|
|
||||||
hprintln!("prepare two futures").ok();
|
hprintln!("delay long time").ok();
|
||||||
let d1 = timer_delay(&mut cx.resources.systick, 5000000);
|
timer_delay(&mut systick, 5000000).await;
|
||||||
let d2 = timer_delay(&mut cx.resources.systick, 1000000);
|
|
||||||
|
|
||||||
//let pair = futures::future::join(d1, d2);
|
|
||||||
hprintln!("foo task resumed").ok();
|
|
||||||
|
|
||||||
hprintln!("delay short time").ok();
|
hprintln!("delay short time").ok();
|
||||||
timer_delay(&mut cx.resources.systick, 1000000).await;
|
timer_delay(&mut systick, 1000000).await;
|
||||||
hprintln!("foo task resumed").ok();
|
hprintln!("foo task resumed").ok();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// RTIC task bound to the HW SysTick interrupt
|
// RTIC task bound to the HW SysTick interrupt
|
||||||
#[task(binds = SysTick, resources = [systick], priority = 2)]
|
#[task(binds = SysTick, resources = [systick], priority = 2)]
|
||||||
|
@ -131,7 +95,7 @@ mod app {
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use heapless::binary_heap::{BinaryHeap, Max};
|
use heapless::binary_heap::{BinaryHeap, Max};
|
||||||
use heapless::consts::U8;
|
use heapless::consts::U8;
|
||||||
use heapless::Vec;
|
// use heapless::Vec;
|
||||||
|
|
||||||
pub enum State {
|
pub enum State {
|
||||||
Started,
|
Started,
|
||||||
|
@ -189,25 +153,24 @@ impl<'a, T: Mutex<T = Systick>> Future for Timer<'a, T> {
|
||||||
s.syst.enable_counter();
|
s.syst.enable_counter();
|
||||||
s.syst.enable_interrupt();
|
s.syst.enable_interrupt();
|
||||||
s.state = State::Started;
|
s.state = State::Started;
|
||||||
s.queue.push(Timeout {
|
s.queue
|
||||||
|
.push(Timeout {
|
||||||
time: t,
|
time: t,
|
||||||
waker: cx.waker().clone(),
|
waker: cx.waker().clone(),
|
||||||
});
|
})
|
||||||
|
.ok();
|
||||||
});
|
});
|
||||||
|
|
||||||
match s.state {
|
match s.state {
|
||||||
State::Done => Poll::Ready(()),
|
State::Done => Poll::Ready(()),
|
||||||
State::Started => {
|
State::Started => Poll::Pending,
|
||||||
// s.waker = Some(cx.waker().clone());
|
|
||||||
Poll::Pending
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn timer_delay<'a, T: Mutex<T = Systick>>(systick: &'a mut T, t: u32) -> Timer<'a, T> {
|
fn timer_delay<'a, T: Mutex<T = Systick>>(systick: &'a mut T, t: u32) -> Timer<'a, T> {
|
||||||
hprintln!("timer_delay {}", t);
|
hprintln!("timer_delay {}", t).ok();
|
||||||
Timer {
|
Timer {
|
||||||
request: Some(t),
|
request: Some(t),
|
||||||
systick,
|
systick,
|
||||||
|
|
|
@ -99,6 +99,64 @@ pub fn codegen(
|
||||||
root.push(struct_);
|
root.push(struct_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if task.is_async {
|
||||||
|
// generate preamble for async task
|
||||||
|
let context = &task.context;
|
||||||
|
let attrs = &task.attrs;
|
||||||
|
let cfgs = &task.cfgs;
|
||||||
|
let stmts = &task.stmts;
|
||||||
|
let locals_pat = locals_pat.iter();
|
||||||
|
let locals_pat2 = locals_pat.clone();
|
||||||
|
|
||||||
|
// TODO, should we require the user to give <'static>
|
||||||
|
// (not feasible today, as RTIC lends out a non static lifetime of cx)
|
||||||
|
user_tasks.push(quote!(
|
||||||
|
#(#attrs)*
|
||||||
|
#(#cfgs)*
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn #name(#(#locals_pat,)* #context: #name::Context #(,#inputs)*) {
|
||||||
|
type F = impl Future + 'static;
|
||||||
|
fn create(cx: #name::Context<'static>) -> F {
|
||||||
|
task(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
static mut TASK: Task<F> = Task::new();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
match TASK {
|
||||||
|
Task::Idle | Task::Done(_) => {
|
||||||
|
// TODO, soundness - reject tasks with &mut T resources?
|
||||||
|
TASK.spawn(|| create(mem::transmute(cx)));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
TASK.poll(|| {
|
||||||
|
// TODO, should we panic here on error?
|
||||||
|
let _ = foo::spawn();
|
||||||
|
});
|
||||||
|
|
||||||
|
match TASK {
|
||||||
|
Task::Done(ref _r) => {
|
||||||
|
// TODO, how to deal with return value?
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#(#attrs)*
|
||||||
|
#(#cfgs)*
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
// TODO, should we require the user to give <'static>
|
||||||
|
// (now we auto generate it)
|
||||||
|
async fn task(#(#locals_pat2,)* #context: #name::Context<'static> #(,#inputs)*) {
|
||||||
|
use rtic::Mutex as _;
|
||||||
|
|
||||||
|
#(#stmts)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
// emit task with attributes if not extern
|
||||||
if !&task.is_extern {
|
if !&task.is_extern {
|
||||||
let context = &task.context;
|
let context = &task.context;
|
||||||
let attrs = &task.attrs;
|
let attrs = &task.attrs;
|
||||||
|
@ -116,9 +174,6 @@ pub fn codegen(
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if &task.is_async {
|
|
||||||
eprintln!("")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
root.push(module::codegen(
|
root.push(module::codegen(
|
||||||
|
|
Loading…
Reference in a new issue