mirror of
https://github.com/rtic-rs/rtic.git
synced 2025-12-18 13:55:23 +01:00
make task.$T.enabled optional
and move the logic that differentiates interrupts from exceptions from the crate to the procedural macro logic
This commit is contained in:
parent
ad2a523cf9
commit
d396da5950
17 changed files with 112 additions and 92 deletions
|
|
@ -16,8 +16,39 @@ pub struct App {
|
|||
|
||||
pub type Tasks = HashMap<Ident, Task>;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum Exception {
|
||||
PENDSV,
|
||||
SVCALL,
|
||||
SYS_TICK,
|
||||
}
|
||||
|
||||
impl Exception {
|
||||
pub fn from(s: &str) -> Option<Self> {
|
||||
Some(match s {
|
||||
"PENDSV" => Exception::PENDSV,
|
||||
"SVCALL" => Exception::SVCALL,
|
||||
"SYS_TICK" => Exception::SYS_TICK,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn nr(&self) -> usize {
|
||||
match *self {
|
||||
Exception::PENDSV => 14,
|
||||
Exception::SVCALL => 11,
|
||||
Exception::SYS_TICK => 15,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Kind {
|
||||
Exception(Exception),
|
||||
Interrupt { enabled: bool },
|
||||
}
|
||||
|
||||
pub struct Task {
|
||||
pub enabled: Option<bool>,
|
||||
pub kind: Kind,
|
||||
pub path: Option<Path>,
|
||||
pub priority: u8,
|
||||
pub resources: Idents,
|
||||
|
|
@ -31,8 +62,13 @@ pub fn app(app: check::App) -> Result<App> {
|
|||
resources: app.resources,
|
||||
tasks: app.tasks
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, ::check::task(v)))
|
||||
.collect(),
|
||||
.map(|(k, v)| {
|
||||
let v = ::check::task(k.as_ref(), v)
|
||||
.chain_err(|| format!("checking task `{}`", k))?;
|
||||
|
||||
Ok((k, v))
|
||||
})
|
||||
.collect::<Result<_>>()?,
|
||||
};
|
||||
|
||||
::check::resources(&app)
|
||||
|
|
@ -60,11 +96,34 @@ fn resources(app: &App) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn task(task: syntax::check::Task) -> Task {
|
||||
Task {
|
||||
enabled: task.enabled,
|
||||
fn task(name: &str, task: syntax::check::Task) -> Result<Task> {
|
||||
let kind = match Exception::from(name) {
|
||||
Some(e) => {
|
||||
ensure!(
|
||||
task.enabled.is_none(),
|
||||
"`enabled` field is not valid for exceptions"
|
||||
);
|
||||
|
||||
Kind::Exception(e)
|
||||
}
|
||||
None => {
|
||||
if task.enabled == Some(true) {
|
||||
bail!(
|
||||
"`enabled: true` is the default value; this line can be \
|
||||
omitted"
|
||||
);
|
||||
}
|
||||
|
||||
Kind::Interrupt {
|
||||
enabled: task.enabled.unwrap_or(true),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Task {
|
||||
kind,
|
||||
path: task.path,
|
||||
priority: task.priority.unwrap_or(1),
|
||||
resources: task.resources,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use quote::{Ident, Tokens};
|
|||
use syn::{Lit, StrStyle};
|
||||
|
||||
use analyze::{Ownership, Ownerships};
|
||||
use check::App;
|
||||
use check::{App, Kind};
|
||||
|
||||
fn krate() -> Ident {
|
||||
Ident::from("rtfm")
|
||||
|
|
@ -236,44 +236,47 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
|
|||
let mut exceptions = vec![];
|
||||
let mut interrupts = vec![];
|
||||
for (name, task) in &app.tasks {
|
||||
if let Some(enabled) = task.enabled {
|
||||
// Interrupt. These can be enabled / disabled through the NVIC
|
||||
if interrupts.is_empty() {
|
||||
interrupts.push(quote! {
|
||||
let nvic = &*#device::NVIC.get();
|
||||
});
|
||||
}
|
||||
match task.kind {
|
||||
Kind::Exception(ref e) => {
|
||||
if exceptions.is_empty() {
|
||||
exceptions.push(quote! {
|
||||
let scb = &*#device::SCB.get();
|
||||
});
|
||||
}
|
||||
|
||||
let priority = task.priority;
|
||||
interrupts.push(quote! {
|
||||
let prio_bits = #device::NVIC_PRIO_BITS;
|
||||
let hw = ((1 << prio_bits) - #priority) << (8 - prio_bits);
|
||||
nvic.set_priority(#device::Interrupt::#name, hw);
|
||||
});
|
||||
|
||||
if enabled {
|
||||
interrupts.push(quote! {
|
||||
nvic.enable(#device::Interrupt::#name);
|
||||
});
|
||||
} else {
|
||||
interrupts.push(quote! {
|
||||
nvic.disable(#device::Interrupt::#name);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Exception
|
||||
if exceptions.is_empty() {
|
||||
let nr = e.nr();
|
||||
let priority = task.priority;
|
||||
exceptions.push(quote! {
|
||||
let scb = &*#device::SCB.get();
|
||||
let prio_bits = #device::NVIC_PRIO_BITS;
|
||||
let hw = ((1 << prio_bits) - #priority) << (8 - prio_bits);
|
||||
scb.shpr[#nr - 4].write(hw);
|
||||
});
|
||||
}
|
||||
Kind::Interrupt { enabled } => {
|
||||
// Interrupt. These can be enabled / disabled through the NVIC
|
||||
if interrupts.is_empty() {
|
||||
interrupts.push(quote! {
|
||||
let nvic = &*#device::NVIC.get();
|
||||
});
|
||||
}
|
||||
|
||||
let priority = task.priority;
|
||||
exceptions.push(quote! {
|
||||
let prio_bits = #device::NVIC_PRIO_BITS;
|
||||
let hw = ((1 << prio_bits) - #priority) << (8 - prio_bits);
|
||||
scb.shpr[#krate::Exception::#name.nr() - 4].write(hw);
|
||||
});
|
||||
let priority = task.priority;
|
||||
interrupts.push(quote! {
|
||||
let prio_bits = #device::NVIC_PRIO_BITS;
|
||||
let hw = ((1 << prio_bits) - #priority) << (8 - prio_bits);
|
||||
nvic.set_priority(#device::Interrupt::#name, hw);
|
||||
});
|
||||
|
||||
if enabled {
|
||||
interrupts.push(quote! {
|
||||
nvic.enable(#device::Interrupt::#name);
|
||||
});
|
||||
} else {
|
||||
interrupts.push(quote! {
|
||||
nvic.disable(#device::Interrupt::#name);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue