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 rtic::app;
#[app(device = lm3s6965)]
#[app(device = lm3s6965, dispatchers = [UART])]
mod app {
#[monotonic(binds = SomeISR1)]
type Mono1 = hal::Mono1;
@ -17,5 +17,11 @@ mod app {
#[init]
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 device: Path,
pub monotonic: Option<Path>,
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() {
Ok(Extra {
device,
monotonic: None,
peripherals: app.args.peripherals,
})
} 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 (_, tupled, pats, _) = util::regroup_inputs(&task.inputs);
let (let_instant, instant) = if extra.monotonic.is_some() {
let instants = util::instants_ident(name);
// TODO: Fix for new monotonics
// let (let_instant, instant) = if extra.monotonic.is_some() {
// let instants = util::instants_ident(name);
(
quote!(
let instant =
#instants.get_unchecked(usize::from(index)).as_ptr().read();
),
quote!(, instant),
)
} else {
(quote!(), quote!())
};
// (
// quote!(
// let instant =
// #instants.get_unchecked(usize::from(index)).as_ptr().read();
// ),
// quote!(, instant),
// )
// } else {
// (quote!(), quote!())
// };
let (let_instant, instant) = (quote!(), quote!());
let locals_new = if task.locals.is_empty() {
quote!()

View file

@ -29,14 +29,15 @@ pub fn codegen(
let mut user_tasks = vec![];
for (name, task) in &app.hardware_tasks {
let (let_instant, instant) = if let Some(ref m) = extra.monotonic {
(
Some(quote!(let instant = <#m as rtic::Monotonic>::now();)),
Some(quote!(, instant)),
)
} else {
(None, None)
};
// let (let_instant, instant) = if let Some(ref m) = extra.monotonic {
// (
// Some(quote!(let instant = <#m as rtic::Monotonic>::now();)),
// Some(quote!(, instant)),
// )
// } else {
// (None, None)
// };
let (let_instant, instant) = (quote!(), quote!());
let locals_new = if task.locals.is_empty() {
quote!()

View file

@ -23,24 +23,25 @@ pub fn codegen(
let mut lt = None;
match ctxt {
Context::Init => {
if let Some(m) = &extra.monotonic {
fields.push(quote!(
/// System start time = `Instant(0 /* cycles */)`
pub start: <#m as rtic::Monotonic>::Instant
));
// TODO: What fields are needed?
// if let Some(m) = &extra.monotonic {
// fields.push(quote!(
// /// 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!(
/// Core (Cortex-M) peripherals minus the SysTick
pub core: rtic::Peripherals
));
} else {
fields.push(quote!(
/// Core (Cortex-M) peripherals
pub core: rtic::export::Peripherals
));
}
// fields.push(quote!(
// /// Core (Cortex-M) peripherals minus the SysTick
// pub core: rtic::Peripherals
// ));
// } else {
// fields.push(quote!(
// /// Core (Cortex-M) peripherals
// pub core: rtic::export::Peripherals
// ));
// }
if extra.peripherals {
let device = &extra.device;
@ -67,29 +68,31 @@ pub fn codegen(
Context::Idle => {}
Context::HardwareTask(..) => {
if let Some(m) = &extra.monotonic {
fields.push(quote!(
/// Time at which this handler started executing
pub start: <#m as rtic::Monotonic>::Instant
));
// TODO: What fields are needed for monotonic?
// if let Some(m) = &extra.monotonic {
// fields.push(quote!(
// /// 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(..) => {
if let Some(m) = &extra.monotonic {
fields.push(quote!(
/// The time at which this task was scheduled to run
pub scheduled: <#m as rtic::Monotonic>::Instant
));
// TODO: What fields are needed for monotonic?
// if let Some(m) = &extra.monotonic {
// fields.push(quote!(
// /// 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() {
if extra.monotonic.is_some() {
Some(quote!(core: rtic::Peripherals,))
} else {
Some(quote!(core: rtic::export::Peripherals,))
}
Some(quote!(core: rtic::export::Peripherals,))
} else {
None
};
@ -167,13 +166,15 @@ pub fn codegen(
Some(quote!(priority: &#lt rtic::export::Priority))
};
let instant = if needs_instant {
let m = extra.monotonic.clone().expect("RTIC-ICE: UNREACHABLE");
// TODO: What is needed for the new monotonic?
// let instant = if needs_instant {
// let m = extra.monotonic.clone().expect("RTIC-ICE: UNREACHABLE");
Some(quote!(, instant: <#m as rtic::Monotonic>::Instant))
} else {
None
};
// Some(quote!(, instant: <#m as rtic::Monotonic>::Instant))
// } else {
// None
// };
let instant = quote!();
items.push(quote!(
/// Execution context
@ -250,50 +251,51 @@ pub fn codegen(
}));
// Schedule caller
if let Some(m) = &extra.monotonic {
let instants = util::instants_ident(name);
// TODO: Needs updating for new monotonic.
// // Schedule caller
// if let Some(m) = &extra.monotonic {
// let instants = util::instants_ident(name);
let tq = util::tq_ident();
let t = util::schedule_t_ident();
// let tq = util::tq_ident();
// let t = util::schedule_t_ident();
items.push(quote!(
#(#cfgs)*
pub fn schedule(
instant: <#m as rtic::Monotonic>::Instant
#(,#args)*
) -> Result<(), #ty> {
unsafe {
use rtic::Mutex as _;
use rtic::mutex_prelude::*;
// items.push(quote!(
// #(#cfgs)*
// pub fn schedule(
// instant: <#m as rtic::Monotonic>::Instant
// #(,#args)*
// ) -> Result<(), #ty> {
// unsafe {
// use rtic::Mutex as _;
// use rtic::mutex_prelude::*;
let input = #tupled;
if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.dequeue()) {
#app_path::#inputs
.get_unchecked_mut(usize::from(index))
.as_mut_ptr()
.write(input);
// let input = #tupled;
// if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.dequeue()) {
// #app_path::#inputs
// .get_unchecked_mut(usize::from(index))
// .as_mut_ptr()
// .write(input);
#app_path::#instants
.get_unchecked_mut(usize::from(index))
.as_mut_ptr()
.write(instant);
// #app_path::#instants
// .get_unchecked_mut(usize::from(index))
// .as_mut_ptr()
// .write(instant);
let nr = rtic::export::NotReady {
instant,
index,
task: #app_path::#t::#name,
};
// let nr = rtic::export::NotReady {
// instant,
// index,
// 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(())
} else {
Err(input)
}
}
}));
}
// Ok(())
// } else {
// Err(input)
// }
// }
// }));
// }
}
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
if extra.monotonic.is_some() {
let priority = analysis.channels.keys().max().unwrap();
// TODO: Update for noew monotonic
// // Initialize the SysTick if there exist a TimerQueue
// if extra.monotonic.is_some() {
// let priority = analysis.channels.keys().max().unwrap();
// Compile time assert that this priority is supported by the device
stmts.push(quote!(let _ = [(); ((1 << #nvic_prio_bits) - #priority as usize)];));
// // 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!(core.SCB.set_priority(
rtic::export::SystemHandler::SysTick,
rtic::export::logical2hw(#priority, #nvic_prio_bits),
);));
// stmts.push(quote!(core.SCB.set_priority(
// rtic::export::SystemHandler::SysTick,
// rtic::export::logical2hw(#priority, #nvic_prio_bits),
// );));
stmts.push(quote!(
core.SYST.set_clock_source(rtic::export::SystClkSource::Core);
core.SYST.enable_counter();
core.DCB.enable_trace();
));
}
// stmts.push(quote!(
// core.SYST.set_clock_source(rtic::export::SystClkSource::Core);
// core.SYST.enable_counter();
// core.DCB.enable_trace();
// ));
// }
// If there's no user `#[idle]` then optimize returning from interrupt handlers
if app.idles.is_empty() {

View file

@ -57,18 +57,19 @@ pub fn codegen(
.map(|_| quote!(core::mem::MaybeUninit::uninit()))
.collect::<Vec<_>>();
if let Some(m) = &extra.monotonic {
let instants = util::instants_ident(name);
// TODO: Update for new monotonic
// if let Some(m) = &extra.monotonic {
// let instants = util::instants_ident(name);
let uninit = mk_uninit();
mod_app.push(quote!(
#uninit
/// Buffer that holds the instants associated to the inputs of a task
static mut #instants:
[core::mem::MaybeUninit<<#m as rtic::Monotonic>::Instant>; #cap_lit] =
[#(#elems,)*];
));
}
// let uninit = mk_uninit();
// mod_app.push(quote!(
// #uninit
// /// Buffer that holds the instants associated to the inputs of a task
// static mut #instants:
// [core::mem::MaybeUninit<<#m as rtic::Monotonic>::Instant>; #cap_lit] =
// [#(#elems,)*];
// ));
// }
let uninit = mk_uninit();
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> {
let mut items = vec![];
if let Some(m) = &extra.monotonic {
if !app.monotonics.is_empty() {
let t = util::schedule_t_ident();
// 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
.software_tasks
.iter()
@ -71,6 +76,8 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
let rq = util::rq_ident(priority);
let rqt = util::spawn_t_ident(priority);
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 pend = {
@ -90,10 +97,10 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
})
.collect::<Vec<_>>();
let sys_tick = util::suffixed("SysTick");
let bound_interrupt = &monotonic.args.binds;
items.push(quote!(
#[no_mangle]
unsafe fn #sys_tick() {
unsafe fn #bound_interrupt() {
use rtic::Mutex as _;
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
}

View file

@ -247,8 +247,6 @@ pub fn suffixed(name: &str) -> Ident {
}
/// Generates an identifier for a timer queue
///
/// At most there is one timer queue
pub fn tq_ident() -> Ident {
Ident::new(&"TQ".to_string(), Span::call_site())
pub fn tq_ident(name: &str) -> Ident {
Ident::new(&format!("TQ_{}", name), Span::call_site())
}

View file

@ -3,7 +3,7 @@ use core::{
sync::atomic::{AtomicBool, Ordering},
};
//pub use crate::tq::{NotReady, TimerQueue};
// pub use crate::tq::{NotReady, TimerQueue};
pub use bare_metal::CriticalSection;
#[cfg(armv7m)]
pub use cortex_m::register::basepri;