mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-29 15:04:32 +01:00
TQ handlers being generated
This commit is contained in:
parent
ef50aeb2e8
commit
b23bb1192c
10 changed files with 157 additions and 140 deletions
|
@ -6,7 +6,7 @@
|
||||||
use panic_semihosting as _; // panic handler
|
use panic_semihosting as _; // panic handler
|
||||||
use rtic::app;
|
use rtic::app;
|
||||||
|
|
||||||
#[app(device = lm3s6965)]
|
#[app(device = lm3s6965, dispatchers = [UART])]
|
||||||
mod app {
|
mod app {
|
||||||
#[monotonic(binds = SomeISR1)]
|
#[monotonic(binds = SomeISR1)]
|
||||||
type Mono1 = hal::Mono1;
|
type Mono1 = hal::Mono1;
|
||||||
|
@ -17,5 +17,11 @@ mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) {
|
fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[task]
|
||||||
|
fn task1(_: task1::Context) {}
|
||||||
|
|
||||||
|
#[task]
|
||||||
|
fn task2(_: task2::Context) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ use syn::{parse, Path};
|
||||||
|
|
||||||
pub struct Extra {
|
pub struct Extra {
|
||||||
pub device: Path,
|
pub device: Path,
|
||||||
pub monotonic: Option<Path>,
|
|
||||||
pub peripherals: bool,
|
pub peripherals: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +75,6 @@ pub fn app(app: &App, _analysis: &Analysis) -> parse::Result<Extra> {
|
||||||
if let Some(device) = app.args.device.clone() {
|
if let Some(device) = app.args.device.clone() {
|
||||||
Ok(Extra {
|
Ok(Extra {
|
||||||
device,
|
device,
|
||||||
monotonic: None,
|
|
||||||
peripherals: app.args.peripherals,
|
peripherals: app.args.peripherals,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -70,19 +70,21 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
let inputs = util::inputs_ident(name);
|
let inputs = util::inputs_ident(name);
|
||||||
let (_, tupled, pats, _) = util::regroup_inputs(&task.inputs);
|
let (_, tupled, pats, _) = util::regroup_inputs(&task.inputs);
|
||||||
|
|
||||||
let (let_instant, instant) = if extra.monotonic.is_some() {
|
// TODO: Fix for new monotonics
|
||||||
let instants = util::instants_ident(name);
|
// let (let_instant, instant) = if extra.monotonic.is_some() {
|
||||||
|
// let instants = util::instants_ident(name);
|
||||||
|
|
||||||
(
|
// (
|
||||||
quote!(
|
// quote!(
|
||||||
let instant =
|
// let instant =
|
||||||
#instants.get_unchecked(usize::from(index)).as_ptr().read();
|
// #instants.get_unchecked(usize::from(index)).as_ptr().read();
|
||||||
),
|
// ),
|
||||||
quote!(, instant),
|
// quote!(, instant),
|
||||||
)
|
// )
|
||||||
} else {
|
// } else {
|
||||||
(quote!(), quote!())
|
// (quote!(), quote!())
|
||||||
};
|
// };
|
||||||
|
let (let_instant, instant) = (quote!(), quote!());
|
||||||
|
|
||||||
let locals_new = if task.locals.is_empty() {
|
let locals_new = if task.locals.is_empty() {
|
||||||
quote!()
|
quote!()
|
||||||
|
|
|
@ -29,14 +29,15 @@ pub fn codegen(
|
||||||
let mut user_tasks = vec![];
|
let mut user_tasks = vec![];
|
||||||
|
|
||||||
for (name, task) in &app.hardware_tasks {
|
for (name, task) in &app.hardware_tasks {
|
||||||
let (let_instant, instant) = if let Some(ref m) = extra.monotonic {
|
// let (let_instant, instant) = if let Some(ref m) = extra.monotonic {
|
||||||
(
|
// (
|
||||||
Some(quote!(let instant = <#m as rtic::Monotonic>::now();)),
|
// Some(quote!(let instant = <#m as rtic::Monotonic>::now();)),
|
||||||
Some(quote!(, instant)),
|
// Some(quote!(, instant)),
|
||||||
)
|
// )
|
||||||
} else {
|
// } else {
|
||||||
(None, None)
|
// (None, None)
|
||||||
};
|
// };
|
||||||
|
let (let_instant, instant) = (quote!(), quote!());
|
||||||
|
|
||||||
let locals_new = if task.locals.is_empty() {
|
let locals_new = if task.locals.is_empty() {
|
||||||
quote!()
|
quote!()
|
||||||
|
|
|
@ -23,24 +23,25 @@ pub fn codegen(
|
||||||
let mut lt = None;
|
let mut lt = None;
|
||||||
match ctxt {
|
match ctxt {
|
||||||
Context::Init => {
|
Context::Init => {
|
||||||
if let Some(m) = &extra.monotonic {
|
// TODO: What fields are needed?
|
||||||
fields.push(quote!(
|
// if let Some(m) = &extra.monotonic {
|
||||||
/// System start time = `Instant(0 /* cycles */)`
|
// fields.push(quote!(
|
||||||
pub start: <#m as rtic::Monotonic>::Instant
|
// /// System start time = `Instant(0 /* cycles */)`
|
||||||
));
|
// pub start: <#m as rtic::Monotonic>::Instant
|
||||||
|
// ));
|
||||||
|
|
||||||
values.push(quote!(start: <#m as rtic::Monotonic>::zero()));
|
// values.push(quote!(start: <#m as rtic::Monotonic>::zero()));
|
||||||
|
|
||||||
fields.push(quote!(
|
// fields.push(quote!(
|
||||||
/// Core (Cortex-M) peripherals minus the SysTick
|
// /// Core (Cortex-M) peripherals minus the SysTick
|
||||||
pub core: rtic::Peripherals
|
// pub core: rtic::Peripherals
|
||||||
));
|
// ));
|
||||||
} else {
|
// } else {
|
||||||
fields.push(quote!(
|
// fields.push(quote!(
|
||||||
/// Core (Cortex-M) peripherals
|
// /// Core (Cortex-M) peripherals
|
||||||
pub core: rtic::export::Peripherals
|
// pub core: rtic::export::Peripherals
|
||||||
));
|
// ));
|
||||||
}
|
// }
|
||||||
|
|
||||||
if extra.peripherals {
|
if extra.peripherals {
|
||||||
let device = &extra.device;
|
let device = &extra.device;
|
||||||
|
@ -67,29 +68,31 @@ pub fn codegen(
|
||||||
Context::Idle => {}
|
Context::Idle => {}
|
||||||
|
|
||||||
Context::HardwareTask(..) => {
|
Context::HardwareTask(..) => {
|
||||||
if let Some(m) = &extra.monotonic {
|
// TODO: What fields are needed for monotonic?
|
||||||
fields.push(quote!(
|
// if let Some(m) = &extra.monotonic {
|
||||||
/// Time at which this handler started executing
|
// fields.push(quote!(
|
||||||
pub start: <#m as rtic::Monotonic>::Instant
|
// /// Time at which this handler started executing
|
||||||
));
|
// pub start: <#m as rtic::Monotonic>::Instant
|
||||||
|
// ));
|
||||||
|
|
||||||
values.push(quote!(start: instant));
|
// values.push(quote!(start: instant));
|
||||||
|
|
||||||
needs_instant = true;
|
// needs_instant = true;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
Context::SoftwareTask(..) => {
|
Context::SoftwareTask(..) => {
|
||||||
if let Some(m) = &extra.monotonic {
|
// TODO: What fields are needed for monotonic?
|
||||||
fields.push(quote!(
|
// if let Some(m) = &extra.monotonic {
|
||||||
/// The time at which this task was scheduled to run
|
// fields.push(quote!(
|
||||||
pub scheduled: <#m as rtic::Monotonic>::Instant
|
// /// The time at which this task was scheduled to run
|
||||||
));
|
// pub scheduled: <#m as rtic::Monotonic>::Instant
|
||||||
|
// ));
|
||||||
|
|
||||||
values.push(quote!(scheduled: instant));
|
// values.push(quote!(scheduled: instant));
|
||||||
|
|
||||||
needs_instant = true;
|
// needs_instant = true;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,11 +155,7 @@ pub fn codegen(
|
||||||
};
|
};
|
||||||
|
|
||||||
let core = if ctxt.is_init() {
|
let core = if ctxt.is_init() {
|
||||||
if extra.monotonic.is_some() {
|
Some(quote!(core: rtic::export::Peripherals,))
|
||||||
Some(quote!(core: rtic::Peripherals,))
|
|
||||||
} else {
|
|
||||||
Some(quote!(core: rtic::export::Peripherals,))
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -167,13 +166,15 @@ pub fn codegen(
|
||||||
Some(quote!(priority: &#lt rtic::export::Priority))
|
Some(quote!(priority: &#lt rtic::export::Priority))
|
||||||
};
|
};
|
||||||
|
|
||||||
let instant = if needs_instant {
|
// TODO: What is needed for the new monotonic?
|
||||||
let m = extra.monotonic.clone().expect("RTIC-ICE: UNREACHABLE");
|
// let instant = if needs_instant {
|
||||||
|
// let m = extra.monotonic.clone().expect("RTIC-ICE: UNREACHABLE");
|
||||||
|
|
||||||
Some(quote!(, instant: <#m as rtic::Monotonic>::Instant))
|
// Some(quote!(, instant: <#m as rtic::Monotonic>::Instant))
|
||||||
} else {
|
// } else {
|
||||||
None
|
// None
|
||||||
};
|
// };
|
||||||
|
let instant = quote!();
|
||||||
|
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
/// Execution context
|
/// Execution context
|
||||||
|
@ -250,50 +251,51 @@ pub fn codegen(
|
||||||
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Schedule caller
|
// TODO: Needs updating for new monotonic.
|
||||||
if let Some(m) = &extra.monotonic {
|
// // Schedule caller
|
||||||
let instants = util::instants_ident(name);
|
// if let Some(m) = &extra.monotonic {
|
||||||
|
// let instants = util::instants_ident(name);
|
||||||
|
|
||||||
let tq = util::tq_ident();
|
// let tq = util::tq_ident();
|
||||||
let t = util::schedule_t_ident();
|
// let t = util::schedule_t_ident();
|
||||||
|
|
||||||
items.push(quote!(
|
// items.push(quote!(
|
||||||
#(#cfgs)*
|
// #(#cfgs)*
|
||||||
pub fn schedule(
|
// pub fn schedule(
|
||||||
instant: <#m as rtic::Monotonic>::Instant
|
// instant: <#m as rtic::Monotonic>::Instant
|
||||||
#(,#args)*
|
// #(,#args)*
|
||||||
) -> Result<(), #ty> {
|
// ) -> Result<(), #ty> {
|
||||||
unsafe {
|
// unsafe {
|
||||||
use rtic::Mutex as _;
|
// use rtic::Mutex as _;
|
||||||
use rtic::mutex_prelude::*;
|
// use rtic::mutex_prelude::*;
|
||||||
|
|
||||||
let input = #tupled;
|
// let input = #tupled;
|
||||||
if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.dequeue()) {
|
// if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.dequeue()) {
|
||||||
#app_path::#inputs
|
// #app_path::#inputs
|
||||||
.get_unchecked_mut(usize::from(index))
|
// .get_unchecked_mut(usize::from(index))
|
||||||
.as_mut_ptr()
|
// .as_mut_ptr()
|
||||||
.write(input);
|
// .write(input);
|
||||||
|
|
||||||
#app_path::#instants
|
// #app_path::#instants
|
||||||
.get_unchecked_mut(usize::from(index))
|
// .get_unchecked_mut(usize::from(index))
|
||||||
.as_mut_ptr()
|
// .as_mut_ptr()
|
||||||
.write(instant);
|
// .write(instant);
|
||||||
|
|
||||||
let nr = rtic::export::NotReady {
|
// let nr = rtic::export::NotReady {
|
||||||
instant,
|
// instant,
|
||||||
index,
|
// index,
|
||||||
task: #app_path::#t::#name,
|
// task: #app_path::#t::#name,
|
||||||
};
|
// };
|
||||||
|
|
||||||
rtic::export::interrupt::free(|_| #app_path::#tq.enqueue_unchecked(nr));
|
// rtic::export::interrupt::free(|_| #app_path::#tq.enqueue_unchecked(nr));
|
||||||
|
|
||||||
Ok(())
|
// Ok(())
|
||||||
} else {
|
// } else {
|
||||||
Err(input)
|
// Err(input)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}));
|
// }));
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if !items.is_empty() {
|
if !items.is_empty() {
|
||||||
|
|
|
@ -74,24 +74,25 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
);));
|
);));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the SysTick if there exist a TimerQueue
|
// TODO: Update for noew monotonic
|
||||||
if extra.monotonic.is_some() {
|
// // Initialize the SysTick if there exist a TimerQueue
|
||||||
let priority = analysis.channels.keys().max().unwrap();
|
// if extra.monotonic.is_some() {
|
||||||
|
// let priority = analysis.channels.keys().max().unwrap();
|
||||||
|
|
||||||
// Compile time assert that this priority is supported by the device
|
// // Compile time assert that this priority is supported by the device
|
||||||
stmts.push(quote!(let _ = [(); ((1 << #nvic_prio_bits) - #priority as usize)];));
|
// stmts.push(quote!(let _ = [(); ((1 << #nvic_prio_bits) - #priority as usize)];));
|
||||||
|
|
||||||
stmts.push(quote!(core.SCB.set_priority(
|
// stmts.push(quote!(core.SCB.set_priority(
|
||||||
rtic::export::SystemHandler::SysTick,
|
// rtic::export::SystemHandler::SysTick,
|
||||||
rtic::export::logical2hw(#priority, #nvic_prio_bits),
|
// rtic::export::logical2hw(#priority, #nvic_prio_bits),
|
||||||
);));
|
// );));
|
||||||
|
|
||||||
stmts.push(quote!(
|
// stmts.push(quote!(
|
||||||
core.SYST.set_clock_source(rtic::export::SystClkSource::Core);
|
// core.SYST.set_clock_source(rtic::export::SystClkSource::Core);
|
||||||
core.SYST.enable_counter();
|
// core.SYST.enable_counter();
|
||||||
core.DCB.enable_trace();
|
// core.DCB.enable_trace();
|
||||||
));
|
// ));
|
||||||
}
|
// }
|
||||||
|
|
||||||
// If there's no user `#[idle]` then optimize returning from interrupt handlers
|
// If there's no user `#[idle]` then optimize returning from interrupt handlers
|
||||||
if app.idles.is_empty() {
|
if app.idles.is_empty() {
|
||||||
|
|
|
@ -57,18 +57,19 @@ pub fn codegen(
|
||||||
.map(|_| quote!(core::mem::MaybeUninit::uninit()))
|
.map(|_| quote!(core::mem::MaybeUninit::uninit()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if let Some(m) = &extra.monotonic {
|
// TODO: Update for new monotonic
|
||||||
let instants = util::instants_ident(name);
|
// if let Some(m) = &extra.monotonic {
|
||||||
|
// let instants = util::instants_ident(name);
|
||||||
|
|
||||||
let uninit = mk_uninit();
|
// let uninit = mk_uninit();
|
||||||
mod_app.push(quote!(
|
// mod_app.push(quote!(
|
||||||
#uninit
|
// #uninit
|
||||||
/// Buffer that holds the instants associated to the inputs of a task
|
// /// Buffer that holds the instants associated to the inputs of a task
|
||||||
static mut #instants:
|
// static mut #instants:
|
||||||
[core::mem::MaybeUninit<<#m as rtic::Monotonic>::Instant>; #cap_lit] =
|
// [core::mem::MaybeUninit<<#m as rtic::Monotonic>::Instant>; #cap_lit] =
|
||||||
[#(#elems,)*];
|
// [#(#elems,)*];
|
||||||
));
|
// ));
|
||||||
}
|
// }
|
||||||
|
|
||||||
let uninit = mk_uninit();
|
let uninit = mk_uninit();
|
||||||
let inputs_ident = util::inputs_ident(name);
|
let inputs_ident = util::inputs_ident(name);
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::{analyze::Analysis, check::Extra, codegen::util};
|
||||||
pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> {
|
pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> {
|
||||||
let mut items = vec![];
|
let mut items = vec![];
|
||||||
|
|
||||||
if let Some(m) = &extra.monotonic {
|
if !app.monotonics.is_empty() {
|
||||||
let t = util::schedule_t_ident();
|
let t = util::schedule_t_ident();
|
||||||
|
|
||||||
// Enumeration of `schedule`-able tasks
|
// Enumeration of `schedule`-able tasks
|
||||||
|
@ -36,12 +36,17 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let tq = util::tq_ident();
|
for (_, monotonic) in &app.monotonics {
|
||||||
|
let monotonic_name = monotonic.ident.to_string();
|
||||||
|
let tq = util::tq_ident(&monotonic_name);
|
||||||
|
let t = util::schedule_t_ident();
|
||||||
|
let m = &monotonic.ident;
|
||||||
|
|
||||||
// Static variable and resource proxy
|
// Static variables and resource proxy
|
||||||
{
|
{
|
||||||
let doc = "Timer queue".to_string();
|
let doc = &format!("Timer queue for {}", monotonic_name);
|
||||||
let cap = app
|
let cap = app
|
||||||
.software_tasks
|
.software_tasks
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -71,6 +76,8 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
let rq = util::rq_ident(priority);
|
let rq = util::rq_ident(priority);
|
||||||
let rqt = util::spawn_t_ident(priority);
|
let rqt = util::spawn_t_ident(priority);
|
||||||
let enum_ = util::interrupt_ident();
|
let enum_ = util::interrupt_ident();
|
||||||
|
|
||||||
|
// The interrupt that runs the task dispatcher
|
||||||
let interrupt = &analysis.interrupts.get(&priority).expect("RTIC-ICE: interrupt not found").0;
|
let interrupt = &analysis.interrupts.get(&priority).expect("RTIC-ICE: interrupt not found").0;
|
||||||
|
|
||||||
let pend = {
|
let pend = {
|
||||||
|
@ -90,10 +97,10 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let sys_tick = util::suffixed("SysTick");
|
let bound_interrupt = &monotonic.args.binds;
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe fn #sys_tick() {
|
unsafe fn #bound_interrupt() {
|
||||||
use rtic::Mutex as _;
|
use rtic::Mutex as _;
|
||||||
|
|
||||||
while let Some((task, index)) = rtic::export::interrupt::free(|_| #tq.dequeue())
|
while let Some((task, index)) = rtic::export::interrupt::free(|_| #tq.dequeue())
|
||||||
|
@ -106,5 +113,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
items
|
items
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,8 +247,6 @@ pub fn suffixed(name: &str) -> Ident {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates an identifier for a timer queue
|
/// Generates an identifier for a timer queue
|
||||||
///
|
pub fn tq_ident(name: &str) -> Ident {
|
||||||
/// At most there is one timer queue
|
Ident::new(&format!("TQ_{}", name), Span::call_site())
|
||||||
pub fn tq_ident() -> Ident {
|
|
||||||
Ident::new(&"TQ".to_string(), Span::call_site())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use core::{
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
//pub use crate::tq::{NotReady, TimerQueue};
|
// pub use crate::tq::{NotReady, TimerQueue};
|
||||||
pub use bare_metal::CriticalSection;
|
pub use bare_metal::CriticalSection;
|
||||||
#[cfg(armv7m)]
|
#[cfg(armv7m)]
|
||||||
pub use cortex_m::register::basepri;
|
pub use cortex_m::register::basepri;
|
||||||
|
|
Loading…
Reference in a new issue