Now handling SysTick as well

This commit is contained in:
Emil Fresk 2020-12-13 14:52:16 +01:00
parent 0e134a41b5
commit 6277183906
6 changed files with 61 additions and 17 deletions

View file

@ -8,7 +8,7 @@ use rtic::app;
#[app(device = lm3s6965, dispatchers = [UART])] #[app(device = lm3s6965, dispatchers = [UART])]
mod app { mod app {
#[monotonic(binds = SomeISR1)] #[monotonic(binds = SysTick)]
type MyMono1 = hal::Mono1; type MyMono1 = hal::Mono1;
#[monotonic(binds = SomeISR2, default = true)] #[monotonic(binds = SomeISR2, default = true)]

View file

@ -114,11 +114,13 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
}) })
.collect(); .collect();
let rt_err = util::rt_err_ident();
quote!( quote!(
/// Implementation details /// Implementation details
pub mod #name { pub mod #name {
/// Always include the device crate which contains the vector table /// Always include the device crate which contains the vector table
use #device as you_must_enable_the_rt_feature_for_the_pac_in_your_cargo_toml; use #device as #rt_err;
#(#monotonic_imports)* #(#monotonic_imports)*

View file

@ -246,6 +246,19 @@ pub fn codegen(
items.push(quote!(pub use #m::spawn_at;)); items.push(quote!(pub use #m::spawn_at;));
} }
let (unmask, pend) = if &*m_isr.to_string() == "SysTick" {
(
quote!(core::mem::transmute::<_, cortex_m::peripheral::SYST>(()).disable_interrupt()),
quote!(cortex_m::peripheral::SCB::set_pendst()),
)
} else {
let rt_err = util::rt_err_ident();
(
quote!(rtic::export::NVIC::unmask(#app_path::#rt_err::#enum_::#m_isr)),
quote!(rtic::pend(#app_path::#rt_err::#enum_::#m_isr)),
)
};
items.push(quote!( items.push(quote!(
pub mod #m { pub mod #m {
#(#cfgs)* #(#cfgs)*
@ -287,8 +300,8 @@ pub fn codegen(
rtic::export::interrupt::free(|_| #app_path::#tq.enqueue_unchecked( rtic::export::interrupt::free(|_| #app_path::#tq.enqueue_unchecked(
nr, nr,
|| rtic::export::NVIC::unmask(#app_path::you_must_enable_the_rt_feature_for_the_pac_in_your_cargo_toml::#enum_::#m_isr), || #unmask,
|| rtic::pend(#app_path::you_must_enable_the_rt_feature_for_the_pac_in_your_cargo_toml::#enum_::#m_isr), || #pend,
)); ));
Ok(()) Ok(())

View file

@ -8,6 +8,8 @@ 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 stmts = vec![]; let mut stmts = vec![];
let rt_err = util::rt_err_ident();
// Disable interrupts -- `init` must run with interrupts disabled // Disable interrupts -- `init` must run with interrupts disabled
stmts.push(quote!(rtic::export::interrupt::disable();)); stmts.push(quote!(rtic::export::interrupt::disable();));
@ -47,14 +49,14 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
let interrupt = util::interrupt_ident(); let interrupt = util::interrupt_ident();
stmts.push(quote!( stmts.push(quote!(
core.NVIC.set_priority( core.NVIC.set_priority(
you_must_enable_the_rt_feature_for_the_pac_in_your_cargo_toml::#interrupt::#name, #rt_err::#interrupt::#name,
rtic::export::logical2hw(#priority, #nvic_prio_bits), rtic::export::logical2hw(#priority, #nvic_prio_bits),
); );
)); ));
// NOTE unmask the interrupt *after* setting its priority: changing the priority of a pended // NOTE unmask the interrupt *after* setting its priority: changing the priority of a pended
// interrupt is implementation defined // interrupt is implementation defined
stmts.push(quote!(rtic::export::NVIC::unmask(you_must_enable_the_rt_feature_for_the_pac_in_your_cargo_toml::#interrupt::#name);)); stmts.push(quote!(rtic::export::NVIC::unmask(#rt_err::#interrupt::#name);));
} }
// Set exception priorities // Set exception priorities
@ -83,14 +85,24 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
// 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)];));
// NOTE this also checks that the interrupt exists in the `Interrupt` enumeration
let interrupt = util::interrupt_ident(); if &*name.to_string() == "SysTick" {
stmts.push(quote!( stmts.push(quote!(
core.NVIC.set_priority( core.SCB.set_priority(
you_must_enable_the_rt_feature_for_the_pac_in_your_cargo_toml::#interrupt::#name, rtic::export::SystemHandler::SysTick,
rtic::export::logical2hw(#priority, #nvic_prio_bits), rtic::export::logical2hw(#priority, #nvic_prio_bits),
); );
)); ));
} else {
// NOTE this also checks that the interrupt exists in the `Interrupt` enumeration
let interrupt = util::interrupt_ident();
stmts.push(quote!(
core.NVIC.set_priority(
#rt_err::#interrupt::#name,
rtic::export::logical2hw(#priority, #nvic_prio_bits),
);
));
}
// NOTE we do not unmask the interrupt as this is part of the monotonic to keep track of // NOTE we do not unmask the interrupt as this is part of the monotonic to keep track of
} }

View file

@ -68,6 +68,9 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
// Timer queue handler // Timer queue handler
{ {
let enum_ = util::interrupt_ident(); let enum_ = util::interrupt_ident();
let app_name = &app.name;
let app_path = quote! {crate::#app_name};
let rt_err = util::rt_err_ident();
let arms = app let arms = app
.software_tasks .software_tasks
@ -83,7 +86,7 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
let pend = { let pend = {
quote!( quote!(
rtic::pend(you_must_enable_the_rt_feature_for_the_pac_in_your_cargo_toml::#enum_::#interrupt); rtic::pend(#rt_err::#enum_::#interrupt);
) )
}; };
@ -99,6 +102,11 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let bound_interrupt = &monotonic.args.binds; let bound_interrupt = &monotonic.args.binds;
let enable_isr = if &*bound_interrupt.to_string() == "SysTick" {
quote!(core::mem::transmute::<_, cortex_m::peripheral::SYST>(()).enable_interrupt())
} else {
quote!(rtic::export::NVIC::mask(#rt_err::#enum_::#bound_interrupt))
};
items.push(quote!( items.push(quote!(
#[no_mangle] #[no_mangle]
@ -106,7 +114,7 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
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(
|| rtic::export::NVIC::unmask(you_must_enable_the_rt_feature_for_the_pac_in_your_cargo_toml::#enum_::#bound_interrupt), || #enable_isr,
)) ))
{ {
match task { match task {

View file

@ -217,7 +217,7 @@ pub fn rq_ident(priority: u8) -> Ident {
/// Generates an identifier for the `enum` of `schedule`-able tasks /// Generates an identifier for the `enum` of `schedule`-able tasks
pub fn schedule_t_ident() -> Ident { pub fn schedule_t_ident() -> Ident {
Ident::new(&"SCHED_T".to_string(), Span::call_site()) Ident::new(&"SCHED_T", Span::call_site())
} }
/// Generates an identifier for the `enum` of `spawn`-able tasks /// Generates an identifier for the `enum` of `spawn`-able tasks
@ -228,6 +228,7 @@ pub fn spawn_t_ident(priority: u8) -> Ident {
Ident::new(&format!("P{}_T", priority), Span::call_site()) Ident::new(&format!("P{}_T", priority), Span::call_site())
} }
/// Suffixed identifier
pub fn suffixed(name: &str) -> Ident { pub fn suffixed(name: &str) -> Ident {
let span = Span::call_site(); let span = Span::call_site();
Ident::new(name, span) Ident::new(name, span)
@ -237,3 +238,11 @@ pub fn suffixed(name: &str) -> Ident {
pub fn tq_ident(name: &str) -> Ident { pub fn tq_ident(name: &str) -> Ident {
Ident::new(&format!("TQ_{}", name), Span::call_site()) Ident::new(&format!("TQ_{}", name), Span::call_site())
} }
/// The name to get better RT flag errors
pub fn rt_err_ident() -> Ident {
Ident::new(
&"you_must_enable_the_rt_feature_for_the_pac_in_your_cargo_toml",
Span::call_site(),
)
}