111: some refactors r=japaric a=japaric



Co-authored-by: Jorge Aparicio <jorge@japaric.io>
This commit is contained in:
bors[bot] 2018-12-15 20:18:11 +00:00
commit eba691a5f2
11 changed files with 165 additions and 150 deletions

View file

@ -4,26 +4,23 @@ matrix:
include: include:
# NOTE used to build docs on successful merges to master # NOTE used to build docs on successful merges to master
- env: TARGET=x86_64-unknown-linux-gnu - env: TARGET=x86_64-unknown-linux-gnu
rust: beta
- env: TARGET=thumbv6m-none-eabi - env: TARGET=thumbv6m-none-eabi
rust: beta
if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master) if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master)
- env: TARGET=thumbv7m-none-eabi - env: TARGET=thumbv7m-none-eabi
rust: beta
if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master) if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master)
- env: TARGET=x86_64-unknown-linux-gnu - env: TARGET=x86_64-unknown-linux-gnu
rust: nightly rust: nightly-2018-12-06
if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master) if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master)
- env: TARGET=thumbv6m-none-eabi - env: TARGET=thumbv6m-none-eabi
rust: nightly rust: nightly-2018-12-06
if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master) if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master)
- env: TARGET=thumbv7m-none-eabi - env: TARGET=thumbv7m-none-eabi
rust: nightly rust: nightly-2018-12-06
if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master) if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master)
before_install: set -e before_install: set -e

View file

@ -5,10 +5,11 @@ main() {
if [ $T = x86_64-unknown-linux-gnu ]; then if [ $T = x86_64-unknown-linux-gnu ]; then
# compile-fail and compile-pass tests # compile-fail and compile-pass tests
if [ $TRAVIS_RUST_VERSION = nightly ]; then case $TRAVIS_RUST_VERSION in
# TODO how to run a subset of these tests when timer-queue is disabled? nightly*)
cargo test --features timer-queue --test compiletest --target $T # TODO how to run a subset of these tests when timer-queue is disabled?
fi cargo test --features timer-queue --test compiletest --target $T
esac
cargo check --target $T cargo check --target $T
cargo check --features timer-queue --target $T cargo check --features timer-queue --target $T

View file

@ -24,58 +24,55 @@ struct Context {
// Alias // Alias
#[cfg(feature = "timer-queue")] #[cfg(feature = "timer-queue")]
baseline: Ident, baseline: Ident,
// Dispatcher -> Alias (`enum`) dispatchers: HashMap<u8, Dispatcher>,
enums: HashMap<u8, Ident>,
// Task -> Alias (`static` / resource)
free_queues: Aliases,
// Alias (`fn`) // Alias (`fn`)
idle: Ident, idle: Ident,
// Alias (`fn`) // Alias (`fn`)
init: Ident, init: Ident,
// Task -> Alias (`static`)
inputs: Aliases,
// Alias // Alias
priority: Ident, priority: Ident,
// Dispatcher -> Alias (`static` / resource)
ready_queues: HashMap<u8, Ident>,
// For non-singletons this maps the resource name to its `static mut` variable name // For non-singletons this maps the resource name to its `static mut` variable name
statics: Aliases, statics: Aliases,
/// Task -> Alias (`struct`) /// Task -> Alias (`struct`)
resources: HashMap<Kind, Resources>, resources: HashMap<Kind, Resources>,
// Task -> Alias (`static`)
#[cfg(feature = "timer-queue")]
scheduleds: Aliases,
// Task -> Alias (`fn`)
spawn_fn: Aliases,
// Alias (`enum`) // Alias (`enum`)
schedule_enum: Ident, schedule_enum: Ident,
// Task -> Alias (`fn`) // Task -> Alias (`fn`)
schedule_fn: Aliases, schedule_fn: Aliases,
tasks: Aliases, tasks: HashMap<Ident, Task>,
// Alias (`struct` / `static mut`) // Alias (`struct` / `static mut`)
timer_queue: Ident, timer_queue: Ident,
} }
struct Dispatcher {
enum_: Ident,
ready_queue: Ident,
}
struct Task {
alias: Ident,
free_queue: Ident,
inputs: Ident,
spawn_fn: Ident,
#[cfg(feature = "timer-queue")]
scheduleds: Ident,
}
impl Default for Context { impl Default for Context {
fn default() -> Self { fn default() -> Self {
Context { Context {
#[cfg(feature = "timer-queue")] #[cfg(feature = "timer-queue")]
baseline: mk_ident(None), baseline: mk_ident(None),
enums: HashMap::new(), dispatchers: HashMap::new(),
free_queues: Aliases::new(),
idle: mk_ident(Some("idle")), idle: mk_ident(Some("idle")),
init: mk_ident(Some("init")), init: mk_ident(Some("init")),
inputs: Aliases::new(),
priority: mk_ident(None), priority: mk_ident(None),
ready_queues: HashMap::new(),
statics: Aliases::new(), statics: Aliases::new(),
resources: HashMap::new(), resources: HashMap::new(),
#[cfg(feature = "timer-queue")]
scheduleds: Aliases::new(),
spawn_fn: Aliases::new(),
schedule_enum: mk_ident(None), schedule_enum: mk_ident(None),
schedule_fn: Aliases::new(), schedule_fn: Aliases::new(),
tasks: Aliases::new(), tasks: HashMap::new(),
timer_queue: mk_ident(None), timer_queue: mk_ident(None),
} }
} }
@ -145,7 +142,7 @@ pub fn app(app: &App, analysis: &Analysis) -> TokenStream {
let timer_queue = timer_queue(&ctxt, app, analysis); let timer_queue = timer_queue(&ctxt, app, analysis);
let pre_init = pre_init(&ctxt, analysis); let pre_init = pre_init(&ctxt, &app, analysis);
let assertions = assertions(app, analysis); let assertions = assertions(app, analysis);
@ -388,16 +385,6 @@ fn post_init(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
// the device into compile errors // the device into compile errors
let device = &app.args.device; let device = &app.args.device;
let nvic_prio_bits = quote!(#device::NVIC_PRIO_BITS); let nvic_prio_bits = quote!(#device::NVIC_PRIO_BITS);
for (name, interrupt) in &app.interrupts {
let priority = interrupt.args.priority;
exprs.push(quote!(p.NVIC.enable(#device::Interrupt::#name)));
exprs.push(quote!(assert!(#priority <= (1 << #nvic_prio_bits))));
exprs.push(quote!(p.NVIC.set_priority(
#device::Interrupt::#name,
((1 << #nvic_prio_bits) - #priority) << (8 - #nvic_prio_bits),
)));
}
for (name, exception) in &app.exceptions { for (name, exception) in &app.exceptions {
let priority = exception.args.priority; let priority = exception.args.priority;
exprs.push(quote!(assert!(#priority <= (1 << #nvic_prio_bits)))); exprs.push(quote!(assert!(#priority <= (1 << #nvic_prio_bits))));
@ -416,16 +403,6 @@ fn post_init(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
))); )));
} }
for (priority, dispatcher) in &analysis.dispatchers {
let name = &dispatcher.interrupt;
exprs.push(quote!(p.NVIC.enable(#device::Interrupt::#name)));
exprs.push(quote!(assert!(#priority <= (1 << #nvic_prio_bits))));
exprs.push(quote!(p.NVIC.set_priority(
#device::Interrupt::#name,
((1 << #nvic_prio_bits) - #priority) << (8 - #nvic_prio_bits),
)));
}
if app.idle.is_none() { if app.idle.is_none() {
// Set SLEEPONEXIT bit to enter sleep mode when returning from ISR // Set SLEEPONEXIT bit to enter sleep mode when returning from ISR
exprs.push(quote!(p.SCB.scr.modify(|r| r | 1 << 1))); exprs.push(quote!(p.SCB.scr.modify(|r| r | 1 << 1)));
@ -802,15 +779,6 @@ fn prelude(
} }
if !spawn.is_empty() { if !spawn.is_empty() {
// Populate `spawn_fn`
for task in spawn {
if ctxt.spawn_fn.contains_key(task) {
continue;
}
ctxt.spawn_fn.insert(task.clone(), mk_ident(None));
}
if kind.is_idle() { if kind.is_idle() {
items.push(quote!( items.push(quote!(
#[allow(unused_variables)] #[allow(unused_variables)]
@ -1067,6 +1035,8 @@ fn interrupts(
fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenStream { fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenStream {
let mut items = vec![]; let mut items = vec![];
// first pass to generate buffers (statics and resources) and spawn aliases
for (name, task) in &app.tasks { for (name, task) in &app.tasks {
#[cfg(feature = "timer-queue")] #[cfg(feature = "timer-queue")]
let scheduleds_alias = mk_ident(None); let scheduleds_alias = mk_ident(None);
@ -1074,21 +1044,7 @@ fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
let inputs_alias = mk_ident(None); let inputs_alias = mk_ident(None);
let task_alias = mk_ident(Some(&name.to_string())); let task_alias = mk_ident(Some(&name.to_string()));
let attrs = &task.attrs;
let inputs = &task.inputs; let inputs = &task.inputs;
let locals = mk_locals(&task.statics, false);
let stmts = &task.stmts;
let prelude = prelude(
ctxt,
Kind::Task(name.clone()),
&task.args.resources,
&task.args.spawn,
&task.args.schedule,
app,
task.args.priority,
analysis,
);
let ty = tuple_ty(inputs); let ty = tuple_ty(inputs);
@ -1121,28 +1077,8 @@ fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
() => quote!(), () => quote!(),
}; };
let scheduled_let = match () {
#[cfg(feature = "timer-queue")]
() => {
let baseline = &ctxt.baseline;
quote!(let scheduled = #baseline;)
}
#[cfg(not(feature = "timer-queue"))]
() => quote!(),
};
let baseline_arg = match () {
#[cfg(feature = "timer-queue")]
() => {
let baseline = &ctxt.baseline;
quote!(#baseline: rtfm::Instant,)
}
#[cfg(not(feature = "timer-queue"))]
() => quote!(),
};
let inputs_symbol = format!("{}::INPUTS::{}", name, inputs_alias); let inputs_symbol = format!("{}::INPUTS::{}", name, inputs_alias);
let free_symbol = format!("{}::FREE_QUEUE::{}", name, free_alias); let free_symbol = format!("{}::FREE_QUEUE::{}", name, free_alias);
let unsafety = &task.unsafety;
items.push(quote!( items.push(quote!(
// FIXME(MaybeUninit) MaybeUninit won't be necessary when core::mem::MaybeUninit // FIXME(MaybeUninit) MaybeUninit won't be necessary when core::mem::MaybeUninit
// stabilizes because heapless constructors will work in const context // stabilizes because heapless constructors will work in const context
@ -1158,7 +1094,70 @@ fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
rtfm::export::MaybeUninit::uninitialized(); rtfm::export::MaybeUninit::uninitialized();
#scheduleds_static #scheduleds_static
));
ctxt.tasks.insert(
name.clone(),
Task {
alias: task_alias,
free_queue: free_alias,
inputs: inputs_alias,
spawn_fn: mk_ident(None),
#[cfg(feature = "timer-queue")]
scheduleds: scheduleds_alias,
},
);
}
// second pass to generate the actual task function
for (name, task) in &app.tasks {
let attrs = &task.attrs;
let inputs = &task.inputs;
let locals = mk_locals(&task.statics, false);
let stmts = &task.stmts;
let unsafety = &task.unsafety;
let scheduled_let = match () {
#[cfg(feature = "timer-queue")]
() => {
let baseline = &ctxt.baseline;
quote!(let scheduled = #baseline;)
}
#[cfg(not(feature = "timer-queue"))]
() => quote!(),
};
let prelude = prelude(
ctxt,
Kind::Task(name.clone()),
&task.args.resources,
&task.args.spawn,
&task.args.schedule,
app,
task.args.priority,
analysis,
);
items.push(module(
ctxt,
Kind::Task(name.clone()),
!task.args.schedule.is_empty(),
!task.args.spawn.is_empty(),
app,
));
let task_alias = &ctxt.tasks[name].alias;
let baseline_arg = match () {
#[cfg(feature = "timer-queue")]
() => {
let baseline = &ctxt.baseline;
quote!(#baseline: rtfm::Instant,)
}
#[cfg(not(feature = "timer-queue"))]
() => quote!(),
};
items.push(quote!(
#(#attrs)* #(#attrs)*
#unsafety fn #task_alias(#baseline_arg #(#inputs,)*) { #unsafety fn #task_alias(#baseline_arg #(#inputs,)*) {
#(#locals)* #(#locals)*
@ -1170,20 +1169,6 @@ fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
#(#stmts)* #(#stmts)*
} }
)); ));
items.push(module(
ctxt,
Kind::Task(name.clone()),
!task.args.schedule.is_empty(),
!task.args.spawn.is_empty(),
app,
));
#[cfg(feature = "timer-queue")]
ctxt.scheduleds.insert(name.clone(), scheduleds_alias);
ctxt.free_queues.insert(name.clone(), free_alias);
ctxt.inputs.insert(name.clone(), inputs_alias);
ctxt.tasks.insert(name.clone(), task_alias);
} }
quote!(#(#items)*) quote!(#(#items)*)
@ -1233,17 +1218,18 @@ fn dispatchers(
.tasks .tasks
.iter() .iter()
.map(|task| { .map(|task| {
let inputs = &ctxt.inputs[task]; let task_ = &ctxt.tasks[task];
let free = &ctxt.free_queues[task]; let inputs = &task_.inputs;
let free = &task_.free_queue;
let pats = tuple_pat(&app.tasks[task].inputs); let pats = tuple_pat(&app.tasks[task].inputs);
let alias = &ctxt.tasks[task]; let alias = &task_.alias;
let baseline_let; let baseline_let;
let call; let call;
match () { match () {
#[cfg(feature = "timer-queue")] #[cfg(feature = "timer-queue")]
() => { () => {
let scheduleds = &ctxt.scheduleds[task]; let scheduleds = &task_.scheduleds;
baseline_let = quote!( baseline_let = quote!(
let baseline = let baseline =
ptr::read(#scheduleds.get_ref().get_unchecked(usize::from(index))); ptr::read(#scheduleds.get_ref().get_unchecked(usize::from(index)));
@ -1284,8 +1270,13 @@ fn dispatchers(
} }
)); ));
ctxt.ready_queues.insert(*level, ready_alias); ctxt.dispatchers.insert(
ctxt.enums.insert(*level, enum_alias); *level,
Dispatcher {
ready_queue: ready_alias,
enum_: enum_alias,
},
);
} }
(quote!(#(#data)*), quote!(#(#dispatchers)*)) (quote!(#(#data)*), quote!(#(#dispatchers)*))
@ -1299,21 +1290,24 @@ fn spawn(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenSt
let priority = &ctxt.priority; let priority = &ctxt.priority;
#[cfg(feature = "timer-queue")] #[cfg(feature = "timer-queue")]
let baseline = &ctxt.baseline; let baseline = &ctxt.baseline;
for (task, alias) in &ctxt.spawn_fn { for (name, task) in &ctxt.tasks {
let free = &ctxt.free_queues[task]; let alias = &task.spawn_fn;
let level = app.tasks[task].args.priority; let task_ = &app.tasks[name];
let ready = &ctxt.ready_queues[&level]; let free = &task.free_queue;
let enum_ = &ctxt.enums[&level]; let level = task_.args.priority;
let dispatcher = &ctxt.dispatchers[&level];
let ready = &dispatcher.ready_queue;
let enum_ = &dispatcher.enum_;
let dispatcher = &analysis.dispatchers[&level].interrupt; let dispatcher = &analysis.dispatchers[&level].interrupt;
let inputs = &ctxt.inputs[task]; let inputs = &task.inputs;
let args = &app.tasks[task].inputs; let args = &task_.inputs;
let ty = tuple_ty(args); let ty = tuple_ty(args);
let pats = tuple_pat(args); let pats = tuple_pat(args);
let scheduleds_write = match () { let scheduleds_write = match () {
#[cfg(feature = "timer-queue")] #[cfg(feature = "timer-queue")]
() => { () => {
let scheduleds = &ctxt.scheduleds[task]; let scheduleds = &ctxt.tasks[name].scheduleds;
quote!( quote!(
ptr::write( ptr::write(
#scheduleds.get_mut().get_unchecked_mut(usize::from(index)), #scheduleds.get_mut().get_unchecked_mut(usize::from(index)),
@ -1348,7 +1342,7 @@ fn spawn(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenSt
#scheduleds_write #scheduleds_write
#ready { #priority }.lock(|rq| { #ready { #priority }.lock(|rq| {
rq.split().0.enqueue_unchecked((#enum_::#task, index)) rq.split().0.enqueue_unchecked((#enum_::#name, index))
}); });
rtfm::pend(#device::Interrupt::#dispatcher); rtfm::pend(#device::Interrupt::#dispatcher);
@ -1372,7 +1366,7 @@ fn spawn(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenSt
let mut methods = vec![]; let mut methods = vec![];
for task in spawn { for task in spawn {
let alias = &ctxt.spawn_fn[task]; let alias = &ctxt.tasks[task].spawn_fn;
let inputs = &app.tasks[task].inputs; let inputs = &app.tasks[task].inputs;
let ty = tuple_ty(inputs); let ty = tuple_ty(inputs);
let pats = tuple_pat(inputs); let pats = tuple_pat(inputs);
@ -1416,10 +1410,11 @@ fn schedule(ctxt: &Context, app: &App) -> proc_macro2::TokenStream {
let priority = &ctxt.priority; let priority = &ctxt.priority;
let timer_queue = &ctxt.timer_queue; let timer_queue = &ctxt.timer_queue;
for (task, alias) in &ctxt.schedule_fn { for (task, alias) in &ctxt.schedule_fn {
let free = &ctxt.free_queues[task]; let task_ = &ctxt.tasks[task];
let free = &task_.free_queue;
let enum_ = &ctxt.schedule_enum; let enum_ = &ctxt.schedule_enum;
let inputs = &ctxt.inputs[task]; let inputs = &task_.inputs;
let scheduleds = &ctxt.scheduleds[task]; let scheduleds = &task_.scheduleds;
let args = &app.tasks[task].inputs; let args = &app.tasks[task].inputs;
let ty = tuple_ty(args); let ty = tuple_ty(args);
let pats = tuple_pat(args); let pats = tuple_pat(args);
@ -1538,8 +1533,9 @@ fn timer_queue(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::T
.iter() .iter()
.map(|task| { .map(|task| {
let level = app.tasks[task].args.priority; let level = app.tasks[task].args.priority;
let tenum = &ctxt.enums[&level]; let dispatcher_ = &ctxt.dispatchers[&level];
let ready = &ctxt.ready_queues[&level]; let tenum = &dispatcher_.enum_;
let ready = &dispatcher_.ready_queue;
let dispatcher = &analysis.dispatchers[&level].interrupt; let dispatcher = &analysis.dispatchers[&level].interrupt;
quote!( quote!(
@ -1576,7 +1572,7 @@ fn timer_queue(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::T
quote!(#(#items)*) quote!(#(#items)*)
} }
fn pre_init(ctxt: &Context, analysis: &Analysis) -> proc_macro2::TokenStream { fn pre_init(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenStream {
let mut exprs = vec![]; let mut exprs = vec![];
// FIXME(MaybeUninit) Because we are using a fake MaybeUninit we need to set the Option tag to // FIXME(MaybeUninit) Because we are using a fake MaybeUninit we need to set the Option tag to
@ -1584,23 +1580,27 @@ fn pre_init(ctxt: &Context, analysis: &Analysis) -> proc_macro2::TokenStream {
// be constructed in const context; we have to initialize them at runtime (i.e. here). // be constructed in const context; we have to initialize them at runtime (i.e. here).
// these are `MaybeUninit` arrays // these are `MaybeUninit` arrays
for inputs in ctxt.inputs.values() { for task in ctxt.tasks.values() {
let inputs = &task.inputs;
exprs.push(quote!(#inputs.set(core::mem::uninitialized());)) exprs.push(quote!(#inputs.set(core::mem::uninitialized());))
} }
#[cfg(feature = "timer-queue")] #[cfg(feature = "timer-queue")]
for inputs in ctxt.scheduleds.values() { for task in ctxt.tasks.values() {
exprs.push(quote!(#inputs.set(core::mem::uninitialized());)) let scheduleds = &task.scheduleds;
exprs.push(quote!(#scheduleds.set(core::mem::uninitialized());))
} }
// these are `MaybeUninit` `ReadyQueue`s // these are `MaybeUninit` `ReadyQueue`s
for queue in ctxt.ready_queues.values() { for dispatcher in ctxt.dispatchers.values() {
exprs.push(quote!(#queue.set(rtfm::export::ReadyQueue::new());)) let rq = &dispatcher.ready_queue;
exprs.push(quote!(#rq.set(rtfm::export::ReadyQueue::new());))
} }
// these are `MaybeUninit` `FreeQueue`s // these are `MaybeUninit` `FreeQueue`s
for free in ctxt.free_queues.values() { for task in ctxt.tasks.values() {
exprs.push(quote!(#free.set(rtfm::export::FreeQueue::new());)) let fq = &task.free_queue;
exprs.push(quote!(#fq.set(rtfm::export::FreeQueue::new());))
} }
// end-of-FIXME // end-of-FIXME
@ -1612,15 +1612,40 @@ fn pre_init(ctxt: &Context, analysis: &Analysis) -> proc_macro2::TokenStream {
} }
// Populate the `FreeQueue`s // Populate the `FreeQueue`s
for (task, alias) in &ctxt.free_queues { for (name, task) in &ctxt.tasks {
let capacity = analysis.capacities[task]; let fq = &task.free_queue;
let capacity = analysis.capacities[name];
exprs.push(quote!( exprs.push(quote!(
for i in 0..#capacity { for i in 0..#capacity {
#alias.get_mut().enqueue_unchecked(i); #fq.get_mut().enqueue_unchecked(i);
} }
)) ))
} }
// TODO turn the assertions that check that the priority is not larger than what's supported by
// the device into compile errors
let device = &app.args.device;
let nvic_prio_bits = quote!(#device::NVIC_PRIO_BITS);
for (name, interrupt) in &app.interrupts {
let priority = interrupt.args.priority;
exprs.push(quote!(p.NVIC.enable(#device::Interrupt::#name);));
exprs.push(quote!(assert!(#priority <= (1 << #nvic_prio_bits));));
exprs.push(quote!(p.NVIC.set_priority(
#device::Interrupt::#name,
((1 << #nvic_prio_bits) - #priority) << (8 - #nvic_prio_bits),
);));
}
for (priority, dispatcher) in &analysis.dispatchers {
let name = &dispatcher.interrupt;
exprs.push(quote!(p.NVIC.enable(#device::Interrupt::#name);));
exprs.push(quote!(assert!(#priority <= (1 << #nvic_prio_bits));));
exprs.push(quote!(p.NVIC.set_priority(
#device::Interrupt::#name,
((1 << #nvic_prio_bits) - #priority) << (8 - #nvic_prio_bits),
);));
}
// Set the cycle count to 0 and disable it while `init` executes // Set the cycle count to 0 and disable it while `init` executes
if cfg!(feature = "timer-queue") { if cfg!(feature = "timer-queue") {
exprs.push(quote!(p.DWT.ctrl.modify(|r| r & !1);)); exprs.push(quote!(p.DWT.ctrl.modify(|r| r & !1);));

View file

@ -1,4 +1,3 @@
#![feature(extern_crate_item_prelude)] // ???
#![no_main] #![no_main]
#![no_std] #![no_std]

View file

@ -1,5 +1,4 @@
//! Runtime initialized resources //! Runtime initialized resources
#![feature(extern_crate_item_prelude)] // ???
#![no_main] #![no_main]
#![no_std] #![no_std]

View file

@ -1,5 +1,4 @@
//! Core and device peripherals //! Core and device peripherals
#![feature(extern_crate_item_prelude)] // ???
#![no_main] #![no_main]
#![no_std] #![no_std]

View file

@ -1,6 +1,5 @@
//! Check code generation of resources //! Check code generation of resources
#![feature(extern_crate_item_prelude)] // ???
#![no_main] #![no_main]
#![no_std] #![no_std]

View file

@ -1,4 +1,3 @@
#![feature(extern_crate_item_prelude)] // ???
#![no_main] #![no_main]
#![no_std] #![no_std]

View file

@ -1,4 +1,3 @@
#![feature(extern_crate_item_prelude)] // ???
#![no_main] #![no_main]
#![no_std] #![no_std]

View file

@ -1,5 +1,4 @@
//! Check code generation of `spawn` //! Check code generation of `spawn`
#![feature(extern_crate_item_prelude)] // ???
#![no_main] #![no_main]
#![no_std] #![no_std]

View file

@ -1,5 +1,4 @@
//! Check code generation of `unsafe` `init` / `idle` / `exception` / `interrupt` / `task` //! Check code generation of `unsafe` `init` / `idle` / `exception` / `interrupt` / `task`
#![feature(extern_crate_item_prelude)] // ???
#![no_main] #![no_main]
#![no_std] #![no_std]