TQ handlers being generated

This commit is contained in:
Emil Fresk 2020-12-08 20:49:13 +01:00
parent ef50aeb2e8
commit b23bb1192c
10 changed files with 157 additions and 140 deletions

View file

@ -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) {}
} }

View file

@ -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 {

View file

@ -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!()

View file

@ -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!()

View file

@ -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() {

View file

@ -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() {

View file

@ -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);

View file

@ -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
} }

View file

@ -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())
} }

View file

@ -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;