mirror of
https://github.com/rtic-rs/rtic.git
synced 2025-12-16 12:55:23 +01:00
Remove stale code, fix comment styling
This commit is contained in:
parent
d8c9476372
commit
d06cf91acc
24 changed files with 45 additions and 617 deletions
|
|
@ -20,7 +20,7 @@ impl<'a> Extra<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result<Extra<'a>> {
|
pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result<Extra<'a>> {
|
||||||
// check that all exceptions are valid; only exceptions with configurable priorities are
|
// Check that all exceptions are valid; only exceptions with configurable priorities are
|
||||||
// accepted
|
// accepted
|
||||||
for (name, task) in &app.hardware_tasks {
|
for (name, task) in &app.hardware_tasks {
|
||||||
let name_s = task.args.binds.to_string();
|
let name_s = task.args.binds.to_string();
|
||||||
|
|
@ -48,7 +48,7 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result<Extra<'a>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that external (device-specific) interrupts are not named after known (Cortex-M)
|
// Check that external (device-specific) interrupts are not named after known (Cortex-M)
|
||||||
// exceptions
|
// exceptions
|
||||||
for name in app.extern_interrupts.keys() {
|
for name in app.extern_interrupts.keys() {
|
||||||
let name_s = name.to_string();
|
let name_s = name.to_string();
|
||||||
|
|
@ -66,7 +66,7 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result<Extra<'a>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that there are enough external interrupts to dispatch the software tasks and the timer
|
// Check that there are enough external interrupts to dispatch the software tasks and the timer
|
||||||
// queue handler
|
// queue handler
|
||||||
let mut first = None;
|
let mut first = None;
|
||||||
let priorities = app
|
let priorities = app
|
||||||
|
|
@ -91,8 +91,7 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result<Extra<'a>> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// If not enough tasks and first still is None, may cause
|
// If not enough tasks and first still is None, may cause
|
||||||
// "custom attribute panicked"
|
// "custom attribute panicked" due to unwrap on None
|
||||||
// unwrap on None
|
|
||||||
return Err(parse::Error::new(first.unwrap().span(), &s));
|
return Err(parse::Error::new(first.unwrap().span(), &s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,34 +127,10 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result<Extra<'a>> {
|
||||||
|
|
||||||
"peripherals" => match v {
|
"peripherals" => match v {
|
||||||
CustomArg::Bool(x) => peripherals = if *x { true } else { false },
|
CustomArg::Bool(x) => peripherals = if *x { true } else { false },
|
||||||
|
|
||||||
/*
|
|
||||||
CustomArg::UInt(s) if app.args.cores != 1 => {
|
|
||||||
let x = s.parse::<u8>().ok();
|
|
||||||
peripherals = if x.is_some() && x.unwrap() < app.args.cores {
|
|
||||||
Some(x.unwrap())
|
|
||||||
} else {
|
|
||||||
return Err(parse::Error::new(
|
|
||||||
k.span(),
|
|
||||||
&format!(
|
|
||||||
"unexpected argument value; \
|
|
||||||
this should be an integer in the range 0..={}",
|
|
||||||
app.args.cores
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(parse::Error::new(
|
return Err(parse::Error::new(
|
||||||
k.span(),
|
k.span(),
|
||||||
//if app.args.cores == 1 {
|
|
||||||
"unexpected argument value; this should be a boolean",
|
"unexpected argument value; this should be a boolean",
|
||||||
/*
|
|
||||||
} else {
|
|
||||||
"unexpected argument value; this should be an integer"
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,226 +0,0 @@
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
|
||||||
use quote::quote;
|
|
||||||
use rtic_syntax::ast::App;
|
|
||||||
|
|
||||||
use crate::{analyze::Analysis, check::Extra};
|
|
||||||
|
|
||||||
mod assertions;
|
|
||||||
mod dispatchers;
|
|
||||||
mod hardware_tasks;
|
|
||||||
mod idle;
|
|
||||||
mod init;
|
|
||||||
mod locals;
|
|
||||||
mod module;
|
|
||||||
mod post_init;
|
|
||||||
mod pre_init;
|
|
||||||
mod resources;
|
|
||||||
mod resources_struct;
|
|
||||||
mod schedule;
|
|
||||||
mod schedule_body;
|
|
||||||
mod software_tasks;
|
|
||||||
mod spawn;
|
|
||||||
mod spawn_body;
|
|
||||||
mod timer_queue;
|
|
||||||
mod util;
|
|
||||||
|
|
||||||
// TODO document the syntax here or in `rtic-syntax`
|
|
||||||
pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
|
||||||
let mut const_app = vec![];
|
|
||||||
let mut mains = vec![];
|
|
||||||
let mut root = vec![];
|
|
||||||
let mut user = vec![];
|
|
||||||
let mut imports = vec![];
|
|
||||||
|
|
||||||
// generate a `main` function for each core
|
|
||||||
for core in 0..app.args.cores {
|
|
||||||
let assertion_stmts = assertions::codegen(core, analysis, extra);
|
|
||||||
|
|
||||||
let (const_app_pre_init, pre_init_stmts) = pre_init::codegen(core, &app, analysis, extra);
|
|
||||||
|
|
||||||
let (const_app_init, _root_init, user_init, user_init_imports, call_init) =
|
|
||||||
init::codegen(core, app, analysis, extra);
|
|
||||||
|
|
||||||
let (const_app_post_init, post_init_stmts) =
|
|
||||||
post_init::codegen(core, &app, analysis, extra);
|
|
||||||
|
|
||||||
let (const_app_idle, _root_idle, user_idle, user_idle_imports, call_idle) =
|
|
||||||
idle::codegen(core, app, analysis, extra);
|
|
||||||
|
|
||||||
user.push(quote!(
|
|
||||||
/// USER INIT
|
|
||||||
#user_init
|
|
||||||
|
|
||||||
/// USER IDLE
|
|
||||||
#user_idle
|
|
||||||
));
|
|
||||||
|
|
||||||
// Stow away the imports generated for each core
|
|
||||||
imports.push(quote!(
|
|
||||||
/// USER IMPORTS
|
|
||||||
#(#user_init_imports)*
|
|
||||||
|
|
||||||
/// USER IDLE
|
|
||||||
#(#user_idle_imports)*
|
|
||||||
));
|
|
||||||
|
|
||||||
root.push(quote!(
|
|
||||||
#(#_root_init)*
|
|
||||||
|
|
||||||
#(#_root_idle)*
|
|
||||||
));
|
|
||||||
|
|
||||||
const_app.push(quote!(
|
|
||||||
#(#const_app_pre_init)*
|
|
||||||
|
|
||||||
#const_app_init
|
|
||||||
|
|
||||||
#(#const_app_post_init)*
|
|
||||||
|
|
||||||
#const_app_idle
|
|
||||||
));
|
|
||||||
|
|
||||||
let cfg_core = util::cfg_core(core, app.args.cores);
|
|
||||||
let main = util::suffixed("main", core);
|
|
||||||
let section = util::link_section("text", core);
|
|
||||||
mains.push(quote!(
|
|
||||||
#[no_mangle]
|
|
||||||
#section
|
|
||||||
#cfg_core
|
|
||||||
unsafe extern "C" fn #main() -> ! {
|
|
||||||
#(#assertion_stmts)*
|
|
||||||
|
|
||||||
#(#pre_init_stmts)*
|
|
||||||
|
|
||||||
#call_init
|
|
||||||
|
|
||||||
#(#post_init_stmts)*
|
|
||||||
|
|
||||||
#call_idle
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let (const_app_resources, mod_resources, mod_resources_imports) =
|
|
||||||
resources::codegen(app, analysis, extra);
|
|
||||||
|
|
||||||
let (
|
|
||||||
const_app_hardware_tasks,
|
|
||||||
root_hardware_tasks,
|
|
||||||
user_hardware_tasks,
|
|
||||||
user_hardware_tasks_imports,
|
|
||||||
) = hardware_tasks::codegen(app, analysis, extra);
|
|
||||||
|
|
||||||
let (
|
|
||||||
const_app_software_tasks,
|
|
||||||
root_software_tasks,
|
|
||||||
user_software_tasks,
|
|
||||||
user_software_tasks_imports,
|
|
||||||
) = software_tasks::codegen(app, analysis, extra);
|
|
||||||
|
|
||||||
let const_app_dispatchers = dispatchers::codegen(app, analysis, extra);
|
|
||||||
|
|
||||||
let const_app_spawn = spawn::codegen(app, analysis, extra);
|
|
||||||
|
|
||||||
let const_app_timer_queue = timer_queue::codegen(app, analysis, extra);
|
|
||||||
|
|
||||||
let const_app_schedule = schedule::codegen(app, extra);
|
|
||||||
|
|
||||||
let cores = app.args.cores.to_string();
|
|
||||||
let cfg_core = quote!(#[cfg(core = #cores)]);
|
|
||||||
let msg = format!(
|
|
||||||
"specified {} core{} but tried to compile for more than {0} core{1}",
|
|
||||||
app.args.cores,
|
|
||||||
if app.args.cores > 1 { "s" } else { "" }
|
|
||||||
);
|
|
||||||
let check_excess_cores = quote!(
|
|
||||||
#cfg_core
|
|
||||||
compile_error!(#msg);
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
for s in root.clone() {
|
|
||||||
println!("{}", s.to_string());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
let user_imports = app.user_imports.clone();
|
|
||||||
let user_code = app.user_code.clone();
|
|
||||||
let name = &app.name;
|
|
||||||
let device = extra.device;
|
|
||||||
let endresult = quote!(
|
|
||||||
/// USER
|
|
||||||
#(#user)*
|
|
||||||
|
|
||||||
/// USER_HW_TASKS
|
|
||||||
#(#user_hardware_tasks)*
|
|
||||||
|
|
||||||
/// USER_SW_TASKS
|
|
||||||
#(#user_software_tasks)*
|
|
||||||
|
|
||||||
/// ROOT
|
|
||||||
//#(#root)*
|
|
||||||
|
|
||||||
/// MOD_RESOURCES
|
|
||||||
#mod_resources
|
|
||||||
|
|
||||||
/// root_hardware_tasks
|
|
||||||
#(#root_hardware_tasks)*
|
|
||||||
|
|
||||||
/// root_software_tasks
|
|
||||||
#(#root_software_tasks)*
|
|
||||||
|
|
||||||
/// Implementation details
|
|
||||||
mod #name {
|
|
||||||
/// Always include the device crate which contains the vector table
|
|
||||||
use #device as _;
|
|
||||||
#(#imports)*
|
|
||||||
/// User imports
|
|
||||||
#(#user_imports)*
|
|
||||||
|
|
||||||
/// User code from within the module
|
|
||||||
#(#user_code)*
|
|
||||||
|
|
||||||
/// User hardware tasks import
|
|
||||||
#(#user_hardware_tasks_imports)*
|
|
||||||
|
|
||||||
/// User software_tasks
|
|
||||||
#(#user_software_tasks_imports)*
|
|
||||||
|
|
||||||
/// Mod resources imports
|
|
||||||
#(#mod_resources_imports)*
|
|
||||||
|
|
||||||
#check_excess_cores
|
|
||||||
|
|
||||||
/// Const app
|
|
||||||
#(#const_app)*
|
|
||||||
|
|
||||||
/// Const app resources
|
|
||||||
#(#const_app_resources)*
|
|
||||||
|
|
||||||
/// Const app hw tasks
|
|
||||||
#(#const_app_hardware_tasks)*
|
|
||||||
|
|
||||||
/// Const app sw tasks
|
|
||||||
#(#const_app_software_tasks)*
|
|
||||||
|
|
||||||
/// Const app dispatchers
|
|
||||||
#(#const_app_dispatchers)*
|
|
||||||
|
|
||||||
/// Const app spawn
|
|
||||||
#(#const_app_spawn)*
|
|
||||||
/// Const app spawn end
|
|
||||||
|
|
||||||
#(#const_app_timer_queue)*
|
|
||||||
|
|
||||||
#(#const_app_schedule)*
|
|
||||||
|
|
||||||
/// Mains
|
|
||||||
#(#mains)*
|
|
||||||
}
|
|
||||||
);
|
|
||||||
for s in endresult.clone() {
|
|
||||||
eprintln!("{}", s.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
endresult
|
|
||||||
}
|
|
||||||
|
|
@ -30,14 +30,14 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
let mut root = vec![];
|
let mut root = vec![];
|
||||||
let mut user = vec![];
|
let mut user = vec![];
|
||||||
|
|
||||||
// generate the `main` function
|
// Generate the `main` function
|
||||||
let assertion_stmts = assertions::codegen(analysis);
|
let assertion_stmts = assertions::codegen(analysis);
|
||||||
|
|
||||||
let pre_init_stmts = pre_init::codegen(&app, analysis, extra);
|
let pre_init_stmts = pre_init::codegen(&app, analysis, extra);
|
||||||
|
|
||||||
let (const_app_init, root_init, user_init, call_init) = init::codegen(app, analysis, extra);
|
let (const_app_init, root_init, user_init, call_init) = init::codegen(app, analysis, extra);
|
||||||
|
|
||||||
let (const_app_post_init, post_init_stmts) = post_init::codegen(&app, analysis);
|
let post_init_stmts = post_init::codegen(&app, analysis);
|
||||||
|
|
||||||
let (const_app_idle, root_idle, user_idle, call_idle) = idle::codegen(app, analysis, extra);
|
let (const_app_idle, root_idle, user_idle, call_idle) = idle::codegen(app, analysis, extra);
|
||||||
|
|
||||||
|
|
@ -56,16 +56,12 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
const_app.push(quote!(
|
const_app.push(quote!(
|
||||||
#const_app_init
|
#const_app_init
|
||||||
|
|
||||||
#(#const_app_post_init)*
|
|
||||||
|
|
||||||
#const_app_idle
|
#const_app_idle
|
||||||
));
|
));
|
||||||
|
|
||||||
let main = util::suffixed("main");
|
let main = util::suffixed("main");
|
||||||
let section = util::link_section("text");
|
|
||||||
mains.push(quote!(
|
mains.push(quote!(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#section
|
|
||||||
unsafe extern "C" fn #main() -> ! {
|
unsafe extern "C" fn #main() -> ! {
|
||||||
let _TODO: () = ();
|
let _TODO: () = ();
|
||||||
|
|
||||||
|
|
@ -115,7 +111,7 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
#(#root_software_tasks)*
|
#(#root_software_tasks)*
|
||||||
|
|
||||||
/// Implementation details
|
/// Implementation details
|
||||||
// the user can't access the items within this `const` item
|
// The user can't access the items within this `const` item
|
||||||
const #name: () = {
|
const #name: () = {
|
||||||
/// Always include the device crate which contains the vector table
|
/// Always include the device crate which contains the vector table
|
||||||
use #device as _;
|
use #device as _;
|
||||||
|
|
|
||||||
|
|
@ -7,29 +7,13 @@ use crate::analyze::Analysis;
|
||||||
pub fn codegen(analysis: &Analysis) -> Vec<TokenStream2> {
|
pub fn codegen(analysis: &Analysis) -> Vec<TokenStream2> {
|
||||||
let mut stmts = vec![];
|
let mut stmts = vec![];
|
||||||
|
|
||||||
// we don't generate *all* assertions on all cores because the user could conditionally import a
|
|
||||||
// type only on some core (e.g. `#[cfg(core = "0")] use some::Type;`)
|
|
||||||
|
|
||||||
//if let Some(types) = analysis.send_types {
|
|
||||||
for ty in &analysis.send_types {
|
for ty in &analysis.send_types {
|
||||||
stmts.push(quote!(rtic::export::assert_send::<#ty>();));
|
stmts.push(quote!(rtic::export::assert_send::<#ty>();));
|
||||||
}
|
}
|
||||||
//}
|
|
||||||
|
|
||||||
//if let Some(types) = analysis.sync_types {
|
|
||||||
for ty in &analysis.sync_types {
|
for ty in &analysis.sync_types {
|
||||||
stmts.push(quote!(rtic::export::assert_sync::<#ty>();));
|
stmts.push(quote!(rtic::export::assert_sync::<#ty>();));
|
||||||
}
|
}
|
||||||
//}
|
|
||||||
|
|
||||||
// if the `schedule` API is used in more than one core then we need to check that the
|
|
||||||
// `monotonic` timer can be used in multi-core context
|
|
||||||
/*
|
|
||||||
if analysis.timer_queues.len() > 1 && analysis.timer_queues.contains_key(&core) {
|
|
||||||
let monotonic = extra.monotonic();
|
|
||||||
stmts.push(quote!(rtic::export::assert_multicore::<#monotonic>();));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
stmts
|
stmts
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,12 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
|
|
||||||
let n = util::capacity_typenum(channel.capacity, true);
|
let n = util::capacity_typenum(channel.capacity, true);
|
||||||
let rq = util::rq_ident(level);
|
let rq = util::rq_ident(level);
|
||||||
let (rq_ty, rq_expr, section) = {
|
let (rq_ty, rq_expr) = {
|
||||||
(
|
(
|
||||||
quote!(rtic::export::SCRQ<#t, #n>),
|
quote!(rtic::export::SCRQ<#t, #n>),
|
||||||
quote!(rtic::export::Queue(unsafe {
|
quote!(rtic::export::Queue(unsafe {
|
||||||
rtic::export::iQueue::u8_sc()
|
rtic::export::iQueue::u8_sc()
|
||||||
})),
|
})),
|
||||||
util::link_section("bss"),
|
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -58,7 +57,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
);
|
);
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#[doc = #doc]
|
#[doc = #doc]
|
||||||
#section
|
|
||||||
static mut #rq: #rq_ty = #rq_expr;
|
static mut #rq: #rq_ty = #rq_expr;
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
@ -137,13 +135,11 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
));
|
));
|
||||||
|
|
||||||
let doc = format!("Interrupt handler to dispatch tasks at priority {}", level);
|
let doc = format!("Interrupt handler to dispatch tasks at priority {}", level);
|
||||||
let section = util::link_section("text");
|
|
||||||
let interrupt = util::suffixed(&interrupts[&level].to_string());
|
let interrupt = util::suffixed(&interrupts[&level].to_string());
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[doc = #doc]
|
#[doc = #doc]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#section
|
|
||||||
unsafe fn #interrupt() {
|
unsafe fn #interrupt() {
|
||||||
/// The priority of this interrupt handler
|
/// The priority of this interrupt handler
|
||||||
const PRIORITY: u8 = #level;
|
const PRIORITY: u8 = #level;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use rtic_syntax::{ast::App, Context};
|
||||||
use crate::{
|
use crate::{
|
||||||
analyze::Analysis,
|
analyze::Analysis,
|
||||||
check::Extra,
|
check::Extra,
|
||||||
codegen::{locals, module, resources_struct, util},
|
codegen::{locals, module, resources_struct},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Generate support code for hardware tasks (`#[exception]`s and `#[interrupt]`s)
|
/// Generate support code for hardware tasks (`#[exception]`s and `#[interrupt]`s)
|
||||||
|
|
@ -49,11 +49,9 @@ pub fn codegen(
|
||||||
let symbol = task.args.binds.clone();
|
let symbol = task.args.binds.clone();
|
||||||
let priority = task.args.priority;
|
let priority = task.args.priority;
|
||||||
|
|
||||||
let section = util::link_section("text");
|
|
||||||
const_app.push(quote!(
|
const_app.push(quote!(
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#section
|
|
||||||
unsafe fn #symbol() {
|
unsafe fn #symbol() {
|
||||||
const PRIORITY: u8 = #priority;
|
const PRIORITY: u8 = #priority;
|
||||||
|
|
||||||
|
|
@ -104,12 +102,10 @@ pub fn codegen(
|
||||||
let attrs = &task.attrs;
|
let attrs = &task.attrs;
|
||||||
let context = &task.context;
|
let context = &task.context;
|
||||||
let stmts = &task.stmts;
|
let stmts = &task.stmts;
|
||||||
let section = util::link_section("text");
|
|
||||||
let locals_pat = locals_pat.iter();
|
let locals_pat = locals_pat.iter();
|
||||||
user_tasks.push(quote!(
|
user_tasks.push(quote!(
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#section
|
|
||||||
fn #name(#(#locals_pat,)* #context: #name::Context) {
|
fn #name(#(#locals_pat,)* #context: #name::Context) {
|
||||||
use rtic::Mutex as _;
|
use rtic::Mutex as _;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use rtic_syntax::{ast::App, Context};
|
||||||
use crate::{
|
use crate::{
|
||||||
analyze::Analysis,
|
analyze::Analysis,
|
||||||
check::Extra,
|
check::Extra,
|
||||||
codegen::{locals, module, resources_struct, util},
|
codegen::{locals, module, resources_struct},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Generates support code for `#[idle]` functions
|
/// Generates support code for `#[idle]` functions
|
||||||
|
|
@ -56,12 +56,10 @@ pub fn codegen(
|
||||||
let attrs = &idle.attrs;
|
let attrs = &idle.attrs;
|
||||||
let context = &idle.context;
|
let context = &idle.context;
|
||||||
let stmts = &idle.stmts;
|
let stmts = &idle.stmts;
|
||||||
let section = util::link_section("text");
|
|
||||||
let locals_pat = locals_pat.iter();
|
let locals_pat = locals_pat.iter();
|
||||||
let user_idle = Some(quote!(
|
let user_idle = Some(quote!(
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#section
|
|
||||||
fn #name(#(#locals_pat,)* #context: #name::Context) -> ! {
|
fn #name(#(#locals_pat,)* #context: #name::Context) -> ! {
|
||||||
use rtic::Mutex as _;
|
use rtic::Mutex as _;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,12 +81,10 @@ pub fn codegen(
|
||||||
let context = &init.context;
|
let context = &init.context;
|
||||||
let attrs = &init.attrs;
|
let attrs = &init.attrs;
|
||||||
let stmts = &init.stmts;
|
let stmts = &init.stmts;
|
||||||
let section = util::link_section("text");
|
|
||||||
let locals_pat = locals_pat.iter();
|
let locals_pat = locals_pat.iter();
|
||||||
let user_init = Some(quote!(
|
let user_init = Some(quote!(
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#section
|
|
||||||
fn #name(#(#locals_pat,)* #context: #name::Context) #ret {
|
fn #name(#(#locals_pat,)* #context: #name::Context) #ret {
|
||||||
#(#stmts)*
|
#(#stmts)*
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,6 @@ pub fn codegen(
|
||||||
let cfgs = &local.cfgs;
|
let cfgs = &local.cfgs;
|
||||||
has_cfgs |= !cfgs.is_empty();
|
has_cfgs |= !cfgs.is_empty();
|
||||||
|
|
||||||
/*
|
|
||||||
let section = if local.shared && cfg!(feature = "heterogeneous") {
|
|
||||||
Some(quote!(#[rtic::export::shared]))
|
|
||||||
} else {
|
|
||||||
util::link_section("data", core)
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
let expr = &local.expr;
|
let expr = &local.expr;
|
||||||
let ty = &local.ty;
|
let ty = &local.ty;
|
||||||
fields.push(quote!(
|
fields.push(quote!(
|
||||||
|
|
@ -56,7 +49,6 @@ pub fn codegen(
|
||||||
));
|
));
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
//#section
|
|
||||||
static mut #name: #ty = #expr
|
static mut #name: #ty = #expr
|
||||||
));
|
));
|
||||||
values.push(quote!(
|
values.push(quote!(
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) ->
|
||||||
|
|
||||||
let name = ctxt.ident(app);
|
let name = ctxt.ident(app);
|
||||||
|
|
||||||
//let core = ctxt.core(app);
|
|
||||||
let mut needs_instant = false;
|
let mut needs_instant = false;
|
||||||
let mut lt = None;
|
let mut lt = None;
|
||||||
match ctxt {
|
match ctxt {
|
||||||
|
|
@ -312,12 +311,9 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) ->
|
||||||
));
|
));
|
||||||
|
|
||||||
if !items.is_empty() {
|
if !items.is_empty() {
|
||||||
//let cfg_core = util::cfg_core(ctxt.core(app), app.args.cores);
|
|
||||||
|
|
||||||
quote!(
|
quote!(
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[doc = #doc]
|
#[doc = #doc]
|
||||||
//#cfg_core
|
|
||||||
pub mod #name {
|
pub mod #name {
|
||||||
#(#items)*
|
#(#items)*
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,14 @@ use rtic_syntax::ast::App;
|
||||||
use crate::analyze::Analysis;
|
use crate::analyze::Analysis;
|
||||||
|
|
||||||
/// Generates code that runs after `#[init]` returns
|
/// Generates code that runs after `#[init]` returns
|
||||||
pub fn codegen(app: &App, analysis: &Analysis) -> (Vec<TokenStream2>, Vec<TokenStream2>) {
|
pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
|
||||||
//#TODO remove
|
|
||||||
let const_app = vec![];
|
|
||||||
let mut stmts = vec![];
|
let mut stmts = vec![];
|
||||||
|
|
||||||
// initialize late resources
|
// Initialize late resources
|
||||||
//if let Some(late_resources) = analysis.late_resources {
|
|
||||||
//for name in late_resources {
|
|
||||||
if analysis.late_resources.len() > 0 {
|
if analysis.late_resources.len() > 0 {
|
||||||
// #TODO, check soundness of this, why the wrapping
|
|
||||||
// BTreeSet wrapped in a vector
|
// BTreeSet wrapped in a vector
|
||||||
for name in &analysis.late_resources[0] {
|
for name in analysis.late_resources.first().unwrap() {
|
||||||
// if it's live
|
// If it's live
|
||||||
let cfgs = app.late_resources[name].cfgs.clone();
|
let cfgs = app.late_resources[name].cfgs.clone();
|
||||||
if analysis.locations.get(name).is_some() {
|
if analysis.locations.get(name).is_some() {
|
||||||
// Need to also include the cfgs
|
// Need to also include the cfgs
|
||||||
|
|
@ -29,140 +24,8 @@ pub fn codegen(app: &App, analysis: &Analysis) -> (Vec<TokenStream2>, Vec<TokenS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Enable the interrupts -- this completes the `init`-ialization phase
|
||||||
if analysis.timer_queues.is_empty() {
|
|
||||||
/*
|
|
||||||
// cross-initialization barriers -- notify *other* cores that their resources have been
|
|
||||||
// initialized
|
|
||||||
for (user, initializers) in &analysis.initialization_barriers {
|
|
||||||
if !initializers.contains(&core) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ib = util::init_barrier(*user);
|
|
||||||
let shared = if cfg!(feature = "heterogeneous") {
|
|
||||||
Some(quote!(
|
|
||||||
#[rtic::export::shared]
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
const_app.push(quote!(
|
|
||||||
#shared
|
|
||||||
static #ib: rtic::export::Barrier = rtic::export::Barrier::new();
|
|
||||||
));
|
|
||||||
|
|
||||||
stmts.push(quote!(
|
|
||||||
#ib.release();
|
|
||||||
));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
// then wait until the other cores have initialized *our* resources
|
|
||||||
if analysis.initialization_barriers.contains_key(&core) {
|
|
||||||
let ib = util::init_barrier(core);
|
|
||||||
|
|
||||||
stmts.push(quote!(
|
|
||||||
#ib.wait();
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// cross-spawn barriers: wait until other cores are ready to receive messages
|
|
||||||
for (&receiver, senders) in &analysis.spawn_barriers {
|
|
||||||
if senders.get(&core) == Some(&false) {
|
|
||||||
let sb = util::spawn_barrier(receiver);
|
|
||||||
|
|
||||||
stmts.push(quote!(
|
|
||||||
#sb.wait();
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
// if the `schedule` API is used then we'll synchronize all cores to leave the
|
|
||||||
// `init`-ialization phase at the same time. In this case the rendezvous barrier makes the
|
|
||||||
// cross-initialization and spawn barriers unnecessary
|
|
||||||
|
|
||||||
let m = extra.monotonic();
|
|
||||||
|
|
||||||
if analysis.timer_queues.len() == 1 {
|
|
||||||
// reset the monotonic timer / counter
|
|
||||||
stmts.push(quote!(
|
|
||||||
<#m as rtic::Monotonic>::reset();
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
// in the multi-core case we need a rendezvous (RV) barrier between *all* the cores that
|
|
||||||
// use the `schedule` API; otherwise one of the cores could observe the before-reset
|
|
||||||
// value of the monotonic counter
|
|
||||||
// (this may be easier to implement with `AtomicU8.fetch_sub` but that API is not
|
|
||||||
// available on ARMv6-M)
|
|
||||||
|
|
||||||
// this core will reset the monotonic counter
|
|
||||||
const FIRST: u8 = 0;
|
|
||||||
|
|
||||||
if core == FIRST {
|
|
||||||
for &i in analysis.timer_queues.keys() {
|
|
||||||
let rv = util::rendezvous_ident(i);
|
|
||||||
let shared = if cfg!(feature = "heterogeneous") {
|
|
||||||
Some(quote!(
|
|
||||||
#[rtic::export::shared]
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
const_app.push(quote!(
|
|
||||||
#shared
|
|
||||||
static #rv: rtic::export::Barrier = rtic::export::Barrier::new();
|
|
||||||
));
|
|
||||||
|
|
||||||
// wait until all the other cores have reached the RV point
|
|
||||||
if i != FIRST {
|
|
||||||
stmts.push(quote!(
|
|
||||||
#rv.wait();
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let rv = util::rendezvous_ident(core);
|
|
||||||
stmts.push(quote!(
|
|
||||||
// the compiler fences are used to prevent `reset` from being re-ordering wrt to
|
|
||||||
// the atomic operations -- we don't know if `reset` contains load or store
|
|
||||||
// operations
|
|
||||||
|
|
||||||
core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
|
||||||
|
|
||||||
// reset the counter
|
|
||||||
<#m as rtic::Monotonic>::reset();
|
|
||||||
|
|
||||||
core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
|
||||||
|
|
||||||
// now unblock all the other cores
|
|
||||||
#rv.release();
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
let rv = util::rendezvous_ident(core);
|
|
||||||
|
|
||||||
// let the first core know that we have reached the RV point
|
|
||||||
stmts.push(quote!(
|
|
||||||
#rv.release();
|
|
||||||
));
|
|
||||||
|
|
||||||
let rv = util::rendezvous_ident(FIRST);
|
|
||||||
|
|
||||||
// wait until the first core has reset the monotonic timer
|
|
||||||
stmts.push(quote!(
|
|
||||||
#rv.wait();
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// enable the interrupts -- this completes the `init`-ialization phase
|
|
||||||
stmts.push(quote!(rtic::export::interrupt::enable();));
|
stmts.push(quote!(rtic::export::interrupt::enable();));
|
||||||
|
|
||||||
(const_app, stmts)
|
stmts
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@ 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![];
|
||||||
|
|
||||||
// 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();));
|
||||||
|
|
||||||
// populate the FreeQueue
|
// Populate the FreeQueue
|
||||||
for fq in &analysis.free_queues {
|
for fq in &analysis.free_queues {
|
||||||
// Get the task name
|
// Get the task name
|
||||||
let name = fq.0;
|
let name = fq.0;
|
||||||
|
|
@ -33,7 +33,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
let device = extra.device;
|
let device = extra.device;
|
||||||
let nvic_prio_bits = quote!(#device::NVIC_PRIO_BITS);
|
let nvic_prio_bits = quote!(#device::NVIC_PRIO_BITS);
|
||||||
|
|
||||||
// unmask interrupts and set their priorities
|
// Unmask interrupts and set their priorities
|
||||||
for (&priority, name) in analysis
|
for (&priority, name) in analysis
|
||||||
.interrupts
|
.interrupts
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -41,12 +41,12 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
if !util::is_exception(&task.args.binds) {
|
if !util::is_exception(&task.args.binds) {
|
||||||
Some((&task.args.priority, &task.args.binds))
|
Some((&task.args.priority, &task.args.binds))
|
||||||
} else {
|
} else {
|
||||||
// we do exceptions in another pass
|
// We do exceptions in another pass
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
// 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
|
// NOTE this also checks that the interrupt exists in the `Interrupt` enumeration
|
||||||
|
|
@ -63,32 +63,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
stmts.push(quote!(rtic::export::NVIC::unmask(#device::#interrupt::#name);));
|
stmts.push(quote!(rtic::export::NVIC::unmask(#device::#interrupt::#name);));
|
||||||
}
|
}
|
||||||
|
|
||||||
// cross-spawn barriers: now that priorities have been set and the interrupts have been unmasked
|
// Set exception priorities
|
||||||
// we are ready to receive messages from *other* cores
|
|
||||||
/*
|
|
||||||
if analysis.spawn_barriers.contains_key(&core) {
|
|
||||||
let sb = util::spawn_barrier(core);
|
|
||||||
let shared = if cfg!(feature = "heterogeneous") {
|
|
||||||
Some(quote!(
|
|
||||||
#[rtic::export::shared]
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
const_app.push(quote!(
|
|
||||||
#shared
|
|
||||||
static #sb: rtic::export::Barrier = rtic::export::Barrier::new();
|
|
||||||
));
|
|
||||||
|
|
||||||
// unblock cores that may send us a message
|
|
||||||
stmts.push(quote!(
|
|
||||||
#sb.release();
|
|
||||||
));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// set exception priorities
|
|
||||||
for (name, priority) in app.hardware_tasks.values().filter_map(|task| {
|
for (name, priority) in app.hardware_tasks.values().filter_map(|task| {
|
||||||
if util::is_exception(&task.args.binds) {
|
if util::is_exception(&task.args.binds) {
|
||||||
Some((&task.args.binds, task.args.priority))
|
Some((&task.args.binds, task.args.priority))
|
||||||
|
|
@ -96,7 +71,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
// 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(
|
||||||
|
|
@ -105,11 +80,11 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
);));
|
);));
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize the SysTick if there exist a TimerQueue
|
// Initialize the SysTick if there exist a TimerQueue
|
||||||
if let Some(tq) = analysis.timer_queues.first() {
|
if let Some(tq) = analysis.timer_queues.first() {
|
||||||
let priority = tq.priority;
|
let priority = tq.priority;
|
||||||
|
|
||||||
// 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(
|
||||||
|
|
@ -124,25 +99,11 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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() {
|
||||||
// Set SLEEPONEXIT bit to enter sleep mode when returning from ISR
|
// Set SLEEPONEXIT bit to enter sleep mode when returning from ISR
|
||||||
stmts.push(quote!(core.SCB.scr.modify(|r| r | 1 << 1);));
|
stmts.push(quote!(core.SCB.scr.modify(|r| r | 1 << 1);));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// cross-spawn barriers: wait until other cores are ready to receive messages
|
|
||||||
for (&receiver, senders) in &analysis.spawn_barriers {
|
|
||||||
// only block here if `init` can send messages to `receiver`
|
|
||||||
if senders.get(&core) == Some(&true) {
|
|
||||||
let sb = util::spawn_barrier(receiver);
|
|
||||||
|
|
||||||
stmts.push(quote!(
|
|
||||||
#sb.wait();
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
stmts
|
stmts
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,24 +23,11 @@ pub fn codegen(
|
||||||
let ty = &res.ty;
|
let ty = &res.ty;
|
||||||
|
|
||||||
{
|
{
|
||||||
//let loc_attr = None;
|
|
||||||
let section = if expr.is_none() {
|
let section = if expr.is_none() {
|
||||||
util::link_section_uninit(true)
|
util::link_section_uninit(true)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
/*
|
|
||||||
let (loc_attr, section) = match loc {
|
|
||||||
Location::Owned => (
|
|
||||||
None,
|
|
||||||
if expr.is_none() {
|
|
||||||
util::link_section_uninit(true)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
),
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
let (ty, expr) = if let Some(expr) = expr {
|
let (ty, expr) = if let Some(expr) = expr {
|
||||||
(quote!(#ty), quote!(#expr))
|
(quote!(#ty), quote!(#expr))
|
||||||
|
|
@ -56,7 +43,6 @@ pub fn codegen(
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
//#loc_attr
|
|
||||||
#section
|
#section
|
||||||
static mut #name: #ty = #expr;
|
static mut #name: #ty = #expr;
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ pub fn codegen(
|
||||||
|
|
||||||
if ctxt.is_init() {
|
if ctxt.is_init() {
|
||||||
if !analysis.ownerships.contains_key(name) {
|
if !analysis.ownerships.contains_key(name) {
|
||||||
// owned by `init`
|
// Owned by `init`
|
||||||
fields.push(quote!(
|
fields.push(quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
pub #name: &'static #mut_ #ty
|
pub #name: &'static #mut_ #ty
|
||||||
|
|
@ -50,7 +50,7 @@ pub fn codegen(
|
||||||
#name: &#mut_ #name
|
#name: &#mut_ #name
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
// owned by someone else
|
// Owned by someone else
|
||||||
lt = Some(quote!('a));
|
lt = Some(quote!('a));
|
||||||
|
|
||||||
fields.push(quote!(
|
fields.push(quote!(
|
||||||
|
|
@ -75,7 +75,7 @@ pub fn codegen(
|
||||||
pub #name: &'a #ty
|
pub #name: &'a #ty
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
// resource proxy
|
// Resource proxy
|
||||||
lt = Some(quote!('a));
|
lt = Some(quote!('a));
|
||||||
|
|
||||||
fields.push(quote!(
|
fields.push(quote!(
|
||||||
|
|
@ -136,7 +136,7 @@ pub fn codegen(
|
||||||
if lt.is_some() {
|
if lt.is_some() {
|
||||||
*needs_lt = true;
|
*needs_lt = true;
|
||||||
|
|
||||||
// the struct could end up empty due to `cfg`s leading to an error due to `'a` being unused
|
// The struct could end up empty due to `cfg`s leading to an error due to `'a` being unused
|
||||||
if has_cfgs {
|
if has_cfgs {
|
||||||
fields.push(quote!(
|
fields.push(quote!(
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,8 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec<TokenStream2> {
|
||||||
|
|
||||||
let body = schedule_body::codegen(scheduler, &name, app);
|
let body = schedule_body::codegen(scheduler, &name, app);
|
||||||
|
|
||||||
let section = util::link_section("text");
|
|
||||||
methods.push(quote!(
|
methods.push(quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
#section
|
|
||||||
fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> {
|
fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> {
|
||||||
#body
|
#body
|
||||||
}
|
}
|
||||||
|
|
@ -44,15 +42,13 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec<TokenStream2> {
|
||||||
let schedule = util::schedule_ident(name);
|
let schedule = util::schedule_ident(name);
|
||||||
|
|
||||||
if !seen.contains(name) {
|
if !seen.contains(name) {
|
||||||
// generate a `schedule_${name}_S${sender}` function
|
// Generate a `schedule_${name}_S${sender}` function
|
||||||
seen.insert(name);
|
seen.insert(name);
|
||||||
|
|
||||||
let body = schedule_body::codegen(scheduler, &name, app);
|
let body = schedule_body::codegen(scheduler, &name, app);
|
||||||
|
|
||||||
let section = util::link_section("text");
|
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
#section
|
|
||||||
unsafe fn #schedule(
|
unsafe fn #schedule(
|
||||||
priority: &rtic::export::Priority,
|
priority: &rtic::export::Priority,
|
||||||
instant: #instant
|
instant: #instant
|
||||||
|
|
|
||||||
|
|
@ -35,26 +35,22 @@ pub fn codegen(
|
||||||
let cap_lit = util::capacity_literal(cap);
|
let cap_lit = util::capacity_literal(cap);
|
||||||
let cap_ty = util::capacity_typenum(cap, true);
|
let cap_ty = util::capacity_typenum(cap, true);
|
||||||
|
|
||||||
// create free queues and inputs / instants buffers
|
// Create free queues and inputs / instants buffers
|
||||||
//if let Some(free_queues) = analysis.free_queues.get(name) {
|
|
||||||
//for (&sender, &ceiling) in free_queues {
|
|
||||||
if let Some(&ceiling) = analysis.free_queues.get(name) {
|
if let Some(&ceiling) = analysis.free_queues.get(name) {
|
||||||
let fq = util::fq_ident(name);
|
let fq = util::fq_ident(name);
|
||||||
|
|
||||||
let (fq_ty, fq_expr, bss, mk_uninit): (_, _, _, Box<dyn Fn() -> Option<_>>) = {
|
let (fq_ty, fq_expr, mk_uninit): (_, _, Box<dyn Fn() -> Option<_>>) = {
|
||||||
(
|
(
|
||||||
quote!(rtic::export::SCFQ<#cap_ty>),
|
quote!(rtic::export::SCFQ<#cap_ty>),
|
||||||
quote!(rtic::export::Queue(unsafe {
|
quote!(rtic::export::Queue(unsafe {
|
||||||
rtic::export::iQueue::u8_sc()
|
rtic::export::iQueue::u8_sc()
|
||||||
})),
|
})),
|
||||||
util::link_section("bss"),
|
|
||||||
Box::new(|| util::link_section_uninit(true)),
|
Box::new(|| util::link_section_uninit(true)),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
const_app.push(quote!(
|
const_app.push(quote!(
|
||||||
/// Queue version of a free-list that keeps track of empty slots in
|
/// Queue version of a free-list that keeps track of empty slots in
|
||||||
/// the following buffers
|
/// the following buffers
|
||||||
#bss
|
|
||||||
static mut #fq: #fq_ty = #fq_expr;
|
static mut #fq: #fq_ty = #fq_expr;
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
@ -130,7 +126,6 @@ pub fn codegen(
|
||||||
root.push(struct_);
|
root.push(struct_);
|
||||||
}
|
}
|
||||||
|
|
||||||
let section = util::link_section("text");
|
|
||||||
let context = &task.context;
|
let context = &task.context;
|
||||||
let attrs = &task.attrs;
|
let attrs = &task.attrs;
|
||||||
let cfgs = &task.cfgs;
|
let cfgs = &task.cfgs;
|
||||||
|
|
@ -140,7 +135,6 @@ pub fn codegen(
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#section
|
|
||||||
fn #name(#(#locals_pat,)* #context: #name::Context #(,#inputs)*) {
|
fn #name(#(#locals_pat,)* #context: #name::Context #(,#inputs)*) {
|
||||||
use rtic::Mutex as _;
|
use rtic::Mutex as _;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
|
|
||||||
for name in spawnees {
|
for name in spawnees {
|
||||||
let spawnee = &app.software_tasks[name];
|
let spawnee = &app.software_tasks[name];
|
||||||
//let receiver = spawnee.args.core;
|
|
||||||
let cfgs = &spawnee.cfgs;
|
let cfgs = &spawnee.cfgs;
|
||||||
let (args, _, untupled, ty) = util::regroup_inputs(&spawnee.inputs);
|
let (args, _, untupled, ty) = util::regroup_inputs(&spawnee.inputs);
|
||||||
let args = &args;
|
let args = &args;
|
||||||
|
|
@ -39,10 +38,8 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let section = util::link_section("text");
|
|
||||||
methods.push(quote!(
|
methods.push(quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
#section
|
|
||||||
fn #name(&self #(,#args)*) -> Result<(), #ty> {
|
fn #name(&self #(,#args)*) -> Result<(), #ty> {
|
||||||
#let_instant
|
#let_instant
|
||||||
#body
|
#body
|
||||||
|
|
@ -52,7 +49,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
let spawn = util::spawn_ident(name);
|
let spawn = util::spawn_ident(name);
|
||||||
|
|
||||||
if !seen.contains(name) {
|
if !seen.contains(name) {
|
||||||
// generate a `spawn_${name}_S${sender}` function
|
// Generate a `spawn_${name}_S${sender}` function
|
||||||
seen.insert(name);
|
seen.insert(name);
|
||||||
|
|
||||||
let instant = if app.uses_schedule() {
|
let instant = if app.uses_schedule() {
|
||||||
|
|
@ -65,11 +62,8 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
|
|
||||||
let body = spawn_body::codegen(spawner, &name, app, analysis, extra);
|
let body = spawn_body::codegen(spawner, &name, app, analysis, extra);
|
||||||
|
|
||||||
let section = util::link_section("text");
|
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
//#cfg_sender
|
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
#section
|
|
||||||
unsafe fn #spawn(
|
unsafe fn #spawn(
|
||||||
priority: &rtic::export::Priority
|
priority: &rtic::export::Priority
|
||||||
#instant
|
#instant
|
||||||
|
|
@ -117,7 +111,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
let spawner = spawner.ident(app);
|
let spawner = spawner.ident(app);
|
||||||
debug_assert!(!methods.is_empty());
|
debug_assert!(!methods.is_empty());
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
//#cfg_sender
|
|
||||||
impl<#lt> #spawner::Spawn<#lt> {
|
impl<#lt> #spawner::Spawn<#lt> {
|
||||||
#(#methods)*
|
#(#methods)*
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
let mut items = vec![];
|
let mut items = vec![];
|
||||||
|
|
||||||
if let Some(timer_queue) = &analysis.timer_queues.first() {
|
if let Some(timer_queue) = &analysis.timer_queues.first() {
|
||||||
//let cfg_sender = util::cfg_core(sender, app.args.cores);
|
|
||||||
let t = util::schedule_t_ident();
|
let t = util::schedule_t_ident();
|
||||||
|
|
||||||
// Enumeration of `schedule`-able tasks
|
// Enumeration of `schedule`-able tasks
|
||||||
|
|
@ -29,7 +28,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
|
|
||||||
let doc = format!("Tasks that can be scheduled");
|
let doc = format!("Tasks that can be scheduled");
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
//#cfg_sender
|
|
||||||
#[doc = #doc]
|
#[doc = #doc]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
|
@ -48,18 +46,14 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
let n = util::capacity_typenum(timer_queue.capacity, false);
|
let n = util::capacity_typenum(timer_queue.capacity, false);
|
||||||
let tq_ty = quote!(rtic::export::TimerQueue<#m, #t, #n>);
|
let tq_ty = quote!(rtic::export::TimerQueue<#m, #t, #n>);
|
||||||
|
|
||||||
let section = util::link_section("bss");
|
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
//#cfg_sender
|
|
||||||
#[doc = #doc]
|
#[doc = #doc]
|
||||||
#section
|
|
||||||
static mut #tq: #tq_ty = rtic::export::TimerQueue(
|
static mut #tq: #tq_ty = rtic::export::TimerQueue(
|
||||||
rtic::export::BinaryHeap(
|
rtic::export::BinaryHeap(
|
||||||
rtic::export::iBinaryHeap::new()
|
rtic::export::iBinaryHeap::new()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
//#cfg_sender
|
|
||||||
struct #tq<'a> {
|
struct #tq<'a> {
|
||||||
priority: &'a rtic::export::Priority,
|
priority: &'a rtic::export::Priority,
|
||||||
}
|
}
|
||||||
|
|
@ -68,7 +62,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
items.push(util::impl_mutex(
|
items.push(util::impl_mutex(
|
||||||
extra,
|
extra,
|
||||||
&[],
|
&[],
|
||||||
//cfg_sender.as_ref(),
|
|
||||||
false,
|
false,
|
||||||
&tq,
|
&tq,
|
||||||
tq_ty,
|
tq_ty,
|
||||||
|
|
@ -114,11 +107,8 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
|
|
||||||
let priority = timer_queue.priority;
|
let priority = timer_queue.priority;
|
||||||
let sys_tick = util::suffixed("SysTick");
|
let sys_tick = util::suffixed("SysTick");
|
||||||
let section = util::link_section("text");
|
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
//#cfg_sender
|
|
||||||
#section
|
|
||||||
unsafe fn #sys_tick() {
|
unsafe fn #sys_tick() {
|
||||||
use rtic::Mutex as _;
|
use rtic::Mutex as _;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,24 +25,7 @@ pub fn capacity_typenum(capacity: u8, round_up_to_power_of_two: bool) -> TokenSt
|
||||||
quote!(rtic::export::consts::#ident)
|
quote!(rtic::export::consts::#ident)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
/// Generates a `#[cfg(core = "0")]` attribute if we are in multi-core mode
|
|
||||||
pub fn cfg_core(core: Core, cores: u8) -> Option<TokenStream2> {
|
|
||||||
if cores == 1 {
|
|
||||||
None
|
|
||||||
} else if cfg!(feature = "heterogeneous") {
|
|
||||||
let core = core.to_string();
|
|
||||||
Some(quote!(#[cfg(core = #core)]))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// Identifier for the free queue
|
/// Identifier for the free queue
|
||||||
///
|
|
||||||
/// There may be more than one free queue per task because we need one for each sender core so we
|
|
||||||
/// include the sender (e.g. `S0`) in the name
|
|
||||||
pub fn fq_ident(task: &Ident) -> Ident {
|
pub fn fq_ident(task: &Ident) -> Ident {
|
||||||
Ident::new(&format!("{}_FQ", task.to_string()), Span::call_site())
|
Ident::new(&format!("{}_FQ", task.to_string()), Span::call_site())
|
||||||
}
|
}
|
||||||
|
|
@ -51,7 +34,6 @@ pub fn fq_ident(task: &Ident) -> Ident {
|
||||||
pub fn impl_mutex(
|
pub fn impl_mutex(
|
||||||
extra: &Extra,
|
extra: &Extra,
|
||||||
cfgs: &[Attribute],
|
cfgs: &[Attribute],
|
||||||
//cfg_core: Option<&TokenStream2>,
|
|
||||||
resources_prefix: bool,
|
resources_prefix: bool,
|
||||||
name: &Ident,
|
name: &Ident,
|
||||||
ty: TokenStream2,
|
ty: TokenStream2,
|
||||||
|
|
@ -67,7 +49,6 @@ pub fn impl_mutex(
|
||||||
let device = extra.device;
|
let device = extra.device;
|
||||||
quote!(
|
quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
//#cfg_core
|
|
||||||
impl<'a> rtic::Mutex for #path<'a> {
|
impl<'a> rtic::Mutex for #path<'a> {
|
||||||
type T = #ty;
|
type T = #ty;
|
||||||
|
|
||||||
|
|
@ -90,13 +71,6 @@ pub fn impl_mutex(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
/// Generates an identifier for a cross-initialization barrier
|
|
||||||
pub fn init_barrier(initializer: Core) -> Ident {
|
|
||||||
Ident::new(&format!("IB{}", initializer), Span::call_site())
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// Generates an identifier for the `INPUTS` buffer (`spawn` & `schedule` API)
|
/// Generates an identifier for the `INPUTS` buffer (`spawn` & `schedule` API)
|
||||||
pub fn inputs_ident(task: &Ident) -> Ident {
|
pub fn inputs_ident(task: &Ident) -> Ident {
|
||||||
Ident::new(&format!("{}_INPUTS", task), Span::call_site())
|
Ident::new(&format!("{}_INPUTS", task), Span::call_site())
|
||||||
|
|
@ -138,18 +112,6 @@ fn link_section_index() -> usize {
|
||||||
INDEX.fetch_add(1, Ordering::Relaxed)
|
INDEX.fetch_add(1, Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn link_section(_section: &str) -> Option<TokenStream2> {
|
|
||||||
/*
|
|
||||||
if cfg!(feature = "homogeneous") {
|
|
||||||
let section = format!(".{}_{}.rtic{}", section, core, link_section_index());
|
|
||||||
Some(quote!(#[link_section = #section]))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE `None` means in shared memory
|
// NOTE `None` means in shared memory
|
||||||
pub fn link_section_uninit(empty_expr: bool) -> Option<TokenStream2> {
|
pub fn link_section_uninit(empty_expr: bool) -> Option<TokenStream2> {
|
||||||
let section = if empty_expr {
|
let section = if empty_expr {
|
||||||
|
|
@ -175,13 +137,6 @@ pub fn locals_ident(ctxt: Context, app: &App) -> Ident {
|
||||||
Ident::new(&s, Span::call_site())
|
Ident::new(&s, Span::call_site())
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
/// Generates an identifier for a rendezvous barrier
|
|
||||||
pub fn rendezvous_ident() -> Ident {
|
|
||||||
Ident::new(&format!("RV"), Span::call_site())
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Regroups the inputs of a task
|
// Regroups the inputs of a task
|
||||||
//
|
//
|
||||||
// `inputs` could be &[`input: Foo`] OR &[`mut x: i32`, `ref y: i64`]
|
// `inputs` could be &[`input: Foo`] OR &[`mut x: i32`, `ref y: i64`]
|
||||||
|
|
@ -246,17 +201,15 @@ pub fn resources_ident(ctxt: Context, app: &App) -> Ident {
|
||||||
|
|
||||||
/// Generates an identifier for a ready queue
|
/// Generates an identifier for a ready queue
|
||||||
///
|
///
|
||||||
/// Each core may have several task dispatchers, one for each priority level. Each task dispatcher
|
/// There may be several task dispatchers, one for each priority level.
|
||||||
/// in turn may use more than one ready queue because the queues are SPSC queues so one is needed
|
/// The ready queues are SPSC queues
|
||||||
/// per sender core.
|
|
||||||
pub fn rq_ident(priority: u8) -> Ident {
|
pub fn rq_ident(priority: u8) -> Ident {
|
||||||
Ident::new(&format!("P{}_RQ", priority), Span::call_site())
|
Ident::new(&format!("P{}_RQ", priority), Span::call_site())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates an identifier for a "schedule" function
|
/// Generates an identifier for a "schedule" function
|
||||||
///
|
///
|
||||||
/// The methods of the `Schedule` structs invoke these functions. As one task may be `schedule`-ed
|
/// The methods of the `Schedule` structs invoke these functions.
|
||||||
/// by different cores we need one "schedule" function per possible task-sender pair
|
|
||||||
pub fn schedule_ident(name: &Ident) -> Ident {
|
pub fn schedule_ident(name: &Ident) -> Ident {
|
||||||
Ident::new(&format!("schedule_{}", name.to_string()), Span::call_site())
|
Ident::new(&format!("schedule_{}", name.to_string()), Span::call_site())
|
||||||
}
|
}
|
||||||
|
|
@ -268,8 +221,7 @@ pub fn schedule_t_ident() -> Ident {
|
||||||
|
|
||||||
/// Generates an identifier for a "spawn" function
|
/// Generates an identifier for a "spawn" function
|
||||||
///
|
///
|
||||||
/// The methods of the `Spawn` structs invoke these functions. As one task may be `spawn`-ed by
|
/// The methods of the `Spawn` structs invoke these functions.
|
||||||
/// different cores we need one "spawn" function per possible task-sender pair
|
|
||||||
pub fn spawn_ident(name: &Ident) -> Ident {
|
pub fn spawn_ident(name: &Ident) -> Ident {
|
||||||
Ident::new(&format!("spawn_{}", name.to_string()), Span::call_site())
|
Ident::new(&format!("spawn_{}", name.to_string()), Span::call_site())
|
||||||
}
|
}
|
||||||
|
|
@ -289,7 +241,7 @@ pub fn suffixed(name: &str) -> Ident {
|
||||||
|
|
||||||
/// Generates an identifier for a timer queue
|
/// Generates an identifier for a timer queue
|
||||||
///
|
///
|
||||||
/// At most there's one timer queue per core
|
/// At most there is one timer queue
|
||||||
pub fn tq_ident() -> Ident {
|
pub fn tq_ident() -> Ident {
|
||||||
Ident::new(&format!("TQ"), Span::call_site())
|
Ident::new(&format!("TQ"), Span::call_site())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ fn analyze() {
|
||||||
#[task(priority = 2)]
|
#[task(priority = 2)]
|
||||||
fn b(_: b::Context) {}
|
fn b(_: b::Context) {}
|
||||||
|
|
||||||
// first interrupt is assigned to the highest priority dispatcher
|
// First interrupt is assigned to the highest priority dispatcher
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn B();
|
fn B();
|
||||||
fn A();
|
fn A();
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,6 @@ use crate::Fraction;
|
||||||
/// Adding or subtracting a `Duration` of more than `(1 << 31)` cycles to an `Instant` effectively
|
/// Adding or subtracting a `Duration` of more than `(1 << 31)` cycles to an `Instant` effectively
|
||||||
/// makes it "wrap around" and creates an incorrect value. This is also true if the operation is
|
/// makes it "wrap around" and creates an incorrect value. This is also true if the operation is
|
||||||
/// done in steps, e.g. `(instant + dur) + dur` where `dur` is `(1 << 30)` ticks.
|
/// done in steps, e.g. `(instant + dur) + dur` where `dur` is `(1 << 30)` ticks.
|
||||||
///
|
|
||||||
/// In multi-core contexts: this value is tied to the CYCCNT of *one* core so sending it a different
|
|
||||||
/// core makes it lose its meaning -- each Cortex-M core has its own CYCCNT counter and these are
|
|
||||||
/// usually unsynchronized and may even be running at different frequencies.
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
pub struct Instant {
|
pub struct Instant {
|
||||||
inner: i32,
|
inner: i32,
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ where
|
||||||
F: FnOnce(),
|
F: FnOnce(),
|
||||||
{
|
{
|
||||||
if priority == 1 {
|
if priority == 1 {
|
||||||
// if the priority of this interrupt is `1` then BASEPRI can only be `0`
|
// If the priority of this interrupt is `1` then BASEPRI can only be `0`
|
||||||
f();
|
f();
|
||||||
unsafe { basepri::write(0) }
|
unsafe { basepri::write(0) }
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -80,7 +80,7 @@ impl Priority {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// these two methods are used by `lock` (see below) but can't be used from the RTIC application
|
// These two methods are used by `lock` (see below) but can't be used from the RTIC application
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn set(&self, value: u8) {
|
fn set(&self, value: u8) {
|
||||||
self.inner.set(value)
|
self.inner.set(value)
|
||||||
|
|
|
||||||
|
|
@ -28,13 +28,6 @@
|
||||||
//! release.
|
//! release.
|
||||||
//!
|
//!
|
||||||
//! [SemVer]: https://semver.org/spec/v2.0.0.html
|
//! [SemVer]: https://semver.org/spec/v2.0.0.html
|
||||||
//!
|
|
||||||
//! # Cargo features
|
|
||||||
//!
|
|
||||||
//! - `heterogeneous`. This opt-in feature enables the *experimental* heterogeneous multi-core
|
|
||||||
//! support. This feature depends on unstable feature and requires the use of the nightly channel.
|
|
||||||
//!
|
|
||||||
//! - `homogeneous`. This opt-in feature enables the *experimental* homogeneous multi-core support.
|
|
||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
#![deny(rust_2018_compatibility)]
|
#![deny(rust_2018_compatibility)]
|
||||||
|
|
@ -48,7 +41,6 @@ use cortex_m::{
|
||||||
interrupt::Nr,
|
interrupt::Nr,
|
||||||
peripheral::{CBP, CPUID, DCB, DWT, FPB, FPU, ITM, MPU, NVIC, SCB, TPIU},
|
peripheral::{CBP, CPUID, DCB, DWT, FPB, FPU, ITM, MPU, NVIC, SCB, TPIU},
|
||||||
};
|
};
|
||||||
#[cfg(all(not(feature = "heterogeneous"), not(feature = "homogeneous")))]
|
|
||||||
use cortex_m_rt as _; // vector table
|
use cortex_m_rt as _; // vector table
|
||||||
pub use cortex_m_rtic_macros::app;
|
pub use cortex_m_rtic_macros::app;
|
||||||
pub use rtic_core::{Exclusive, Mutex};
|
pub use rtic_core::{Exclusive, Mutex};
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ where
|
||||||
mem::transmute::<_, SYST>(()).enable_interrupt();
|
mem::transmute::<_, SYST>(()).enable_interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
// set SysTick pending
|
// Set SysTick pending
|
||||||
SCB::set_pendst();
|
SCB::set_pendst();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,13 +79,13 @@ where
|
||||||
};
|
};
|
||||||
mem::transmute::<_, SYST>(()).set_reload(dur);
|
mem::transmute::<_, SYST>(()).set_reload(dur);
|
||||||
|
|
||||||
// start counting down from the new reload
|
// Start counting down from the new reload
|
||||||
mem::transmute::<_, SYST>(()).clear_current();
|
mem::transmute::<_, SYST>(()).clear_current();
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// the queue is empty
|
// The queue is empty
|
||||||
mem::transmute::<_, SYST>(()).disable_interrupt();
|
mem::transmute::<_, SYST>(()).disable_interrupt();
|
||||||
|
|
||||||
None
|
None
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue