aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bors[bot] <26634292+bors[bot]@users.noreply.github.com> 2021-03-04 19:12:35 +0000
committerGravatar GitHub <noreply@github.com> 2021-03-04 19:12:35 +0000
commit89a5c8004efaa8f42c86a1aedb609f49ec511333 (patch)
tree6db5b553e24a540284edc3f3fbf87043c638defc
parent81a8a591353b1ea0208c68b28ee81286629039cc (diff)
parent2e4a4ffd87c8a031f27635c060042019511523dc (diff)
downloadrtic-89a5c8004efaa8f42c86a1aedb609f49ec511333.tar.gz
rtic-89a5c8004efaa8f42c86a1aedb609f49ec511333.tar.zst
rtic-89a5c8004efaa8f42c86a1aedb609f49ec511333.zip
Merge #436v0.6.0-alpha.1
436: New monotonic r=AfoHT a=korken89 Design document: https://hackmd.io/vWa9GvssR8qBfUYgMZm0CQ Closes #433 Closes #432 Closes #427 Closes #426 Closes #403 Closes #332 Closes #312 Closes #309 Closes #299 Closes #292 Closes #247 Closes #219 Co-authored-by: Emil Fresk <emil.fresk@gmail.com>
-rw-r--r--.github/workflows/build.yml4
-rw-r--r--Cargo.toml18
-rw-r--r--examples/baseline.rs50
-rw-r--r--examples/big-struct-opt.rs15
-rw-r--r--examples/binds.rs4
-rw-r--r--examples/capacity.rs4
-rw-r--r--examples/cfg-whole-task.rs4
-rw-r--r--examples/cfg.rs4
-rw-r--r--examples/destructure.rs4
-rw-r--r--examples/double_schedule.rs28
-rw-r--r--examples/extern_binds.rs4
-rw-r--r--examples/extern_spawn.rs4
-rw-r--r--examples/generics.rs4
-rw-r--r--examples/hardware.rs4
-rw-r--r--examples/idle.rs4
-rw-r--r--examples/init.rs4
-rw-r--r--examples/late.rs4
-rw-r--r--examples/lock.rs4
-rw-r--r--examples/message.rs4
-rw-r--r--examples/multilock.rs4
-rw-r--r--examples/not-sync.rs6
-rw-r--r--examples/only-shared-access.rs4
-rw-r--r--examples/periodic.rs32
-rw-r--r--examples/peripherals-taken.rs4
-rw-r--r--examples/pool.rs4
-rw-r--r--examples/preempt.rs4
-rw-r--r--examples/ramfunc.rs4
-rw-r--r--examples/resource-user-struct.rs4
-rw-r--r--examples/resource.rs4
-rw-r--r--examples/schedule.rs44
-rw-r--r--examples/spawn.rs4
-rw-r--r--examples/spawn2.rs4
-rw-r--r--examples/static.rs4
-rw-r--r--examples/t-binds.rs6
-rw-r--r--examples/t-cfg-resources.rs19
-rw-r--r--examples/t-cfg.rs8
-rw-r--r--examples/t-htask-main.rs4
-rw-r--r--examples/t-idle-main.rs4
-rw-r--r--examples/t-init-main.rs4
-rw-r--r--examples/t-late-not-send.rs13
-rw-r--r--examples/t-resource.rs6
-rw-r--r--examples/t-schedule-core-stable.rs10
-rw-r--r--examples/t-schedule.rs55
-rw-r--r--examples/t-spawn.rs6
-rw-r--r--examples/t-stask-main.rs4
-rw-r--r--examples/task-local-minimal.rs4
-rw-r--r--examples/task-local.rs4
-rw-r--r--examples/task.rs4
-rw-r--r--examples/task_named_main.rs4
-rw-r--r--examples/types.rs25
-rw-r--r--macros/Cargo.toml4
-rw-r--r--macros/src/check.rs14
-rw-r--r--macros/src/codegen.rs86
-rw-r--r--macros/src/codegen/assertions.rs8
-rw-r--r--macros/src/codegen/dispatchers.rs43
-rw-r--r--macros/src/codegen/hardware_tasks.rs13
-rw-r--r--macros/src/codegen/init.rs35
-rw-r--r--macros/src/codegen/locals.rs1
-rw-r--r--macros/src/codegen/module.rs259
-rw-r--r--macros/src/codegen/post_init.rs18
-rw-r--r--macros/src/codegen/pre_init.rs58
-rw-r--r--macros/src/codegen/resources.rs3
-rw-r--r--macros/src/codegen/resources_struct.rs3
-rw-r--r--macros/src/codegen/software_tasks.rs21
-rw-r--r--macros/src/codegen/timer_queue.rs73
-rw-r--r--macros/src/codegen/util.rs41
-rw-r--r--macros/src/lib.rs4
-rw-r--r--src/export.rs8
-rw-r--r--src/lib.rs111
-rw-r--r--src/tq.rs169
-rw-r--r--tests/tests.rs (renamed from tests/single.rs)2
-rw-r--r--ui/exception-invalid.rs (renamed from ui/single/exception-invalid.rs)0
-rw-r--r--ui/exception-invalid.stderr (renamed from ui/single/exception-invalid.stderr)0
-rw-r--r--ui/extern-interrupt-not-enough.rs (renamed from ui/single/extern-interrupt-not-enough.rs)0
-rw-r--r--ui/extern-interrupt-not-enough.stderr (renamed from ui/single/extern-interrupt-not-enough.stderr)0
-rw-r--r--ui/extern-interrupt-used.rs (renamed from ui/single/extern-interrupt-used.rs)0
-rw-r--r--ui/extern-interrupt-used.stderr (renamed from ui/single/extern-interrupt-used.stderr)0
-rw-r--r--ui/local-cfg-task-local-err.rs (renamed from ui/single/local-cfg-task-local-err.rs)17
-rw-r--r--ui/local-cfg-task-local-err.stderr (renamed from ui/single/local-cfg-task-local-err.stderr)8
-rw-r--r--ui/local-err.rs (renamed from ui/single/local-err.rs)4
-rw-r--r--ui/local-err.stderr (renamed from ui/single/local-err.stderr)0
-rw-r--r--ui/locals-cfg.rs (renamed from ui/single/locals-cfg.rs)7
-rw-r--r--ui/locals-cfg.stderr29
-rw-r--r--ui/resources-cfg.rs (renamed from ui/single/resources-cfg.rs)7
-rw-r--r--ui/resources-cfg.stderr119
-rw-r--r--ui/single/exception-systick-used.rs7
-rw-r--r--ui/single/exception-systick-used.stderr5
-rw-r--r--ui/single/locals-cfg.stderr35
-rw-r--r--ui/single/resources-cfg.stderr125
-rw-r--r--ui/task-priority-too-high.rs (renamed from ui/single/task-priority-too-high.rs)4
-rw-r--r--ui/task-priority-too-high.stderr (renamed from ui/single/task-priority-too-high.stderr)0
91 files changed, 914 insertions, 904 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d9be5200..e5f99434 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -474,7 +474,7 @@ jobs:
with:
use-cross: false
command: test
- args: --test single --features __v7
+ args: --test tests --features __v7
# Run test suite for thumbv6m
testv6:
@@ -515,7 +515,7 @@ jobs:
with:
use-cross: false
command: test
- args: --test single
+ args: --test tests
# Build documentation, check links
docs:
diff --git a/Cargo.toml b/Cargo.toml
index fee6485a..d7c2056b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,16 +13,12 @@ license = "MIT OR Apache-2.0"
name = "cortex-m-rtic"
readme = "README.md"
repository = "https://github.com/rtic-rs/cortex-m-rtic"
-version = "0.6.0-alpha.0"
+version = "0.6.0-alpha.1"
[lib]
name = "rtic"
[[example]]
-name = "baseline"
-required-features = ["__v7"]
-
-[[example]]
name = "periodic"
required-features = ["__v7"]
@@ -57,16 +53,20 @@ required-features = ["__v7"]
[dependencies]
cortex-m = "0.7.0"
cortex-m-rtic-macros = { path = "macros", version = "0.6.0-alpha.0" }
+rtic-monotonic = "0.1.0-alpha.0"
rtic-core = "0.3.1"
-heapless = "0.5.0"
+heapless = "0.6.1"
bare-metal = "1.0.0"
+[dependencies.dwt-systick-monotonic]
+version = "0.1.0-alpha.0"
+optional = true
+
[build-dependencies]
version_check = "0.9"
[dev-dependencies]
lm3s6965 = "0.1.3"
-panic-halt = "0.2.0"
cortex-m-semihosting = "0.3.3"
[dev-dependencies.panic-semihosting]
@@ -78,8 +78,8 @@ trybuild = "1"
[features]
# used for testing this crate; do not use in applications
-__v7 =[]
-__min_r1_43 =[]
+__v7 = ["dwt-systick-monotonic"]
+__min_r1_43 = []
[profile.release]
codegen-units = 1
diff --git a/examples/baseline.rs b/examples/baseline.rs
deleted file mode 100644
index 17278748..00000000
--- a/examples/baseline.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-//! examples/baseline.rs
-
-#![deny(unsafe_code)]
-#![deny(warnings)]
-#![no_main]
-#![no_std]
-
-use panic_semihosting as _;
-
-// NOTE: does NOT properly work on QEMU
-#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0])]
-mod app {
- use cortex_m_semihosting::{debug, hprintln};
- use lm3s6965::Interrupt;
-
- #[init]
- fn init(cx: init::Context) -> init::LateResources {
- // omitted: initialization of `CYCCNT`
-
- hprintln!("init(baseline = {:?})", cx.start).unwrap();
-
- // `foo` inherits the baseline of `init`: `Instant(0)`
- foo::spawn().unwrap();
-
- init::LateResources {}
- }
-
- #[task]
- fn foo(cx: foo::Context) {
- static mut ONCE: bool = true;
-
- hprintln!("foo(baseline = {:?})", cx.scheduled).unwrap();
-
- if *ONCE {
- *ONCE = false;
-
- rtic::pend(Interrupt::UART0);
- } else {
- debug::exit(debug::EXIT_SUCCESS);
- }
- }
-
- #[task(binds = UART0)]
- fn uart0(cx: uart0::Context) {
- hprintln!("UART0(baseline = {:?})", cx.start).unwrap();
-
- // `foo` inherits the baseline of `UART0`: its `start` time
- foo::spawn().unwrap();
- }
-}
diff --git a/examples/big-struct-opt.rs b/examples/big-struct-opt.rs
index 85ec5e61..e6a5c172 100644
--- a/examples/big-struct-opt.rs
+++ b/examples/big-struct-opt.rs
@@ -6,7 +6,7 @@
#![no_main]
#![no_std]
-use panic_halt as _;
+use panic_semihosting as _;
/// Some big struct
pub struct BigStruct {
@@ -31,7 +31,7 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
let big_struct = unsafe {
static mut BIG_STRUCT: MaybeUninit<BigStruct> = MaybeUninit::uninit();
@@ -40,9 +40,12 @@ mod app {
&mut *BIG_STRUCT.as_mut_ptr()
};
- init::LateResources {
- // assign the reference so we can use the resource
- big_struct,
- }
+ (
+ init::LateResources {
+ // assign the reference so we can use the resource
+ big_struct,
+ },
+ init::Monotonics(),
+ )
}
}
diff --git a/examples/binds.rs b/examples/binds.rs
index f681aa57..9cbe2994 100644
--- a/examples/binds.rs
+++ b/examples/binds.rs
@@ -14,12 +14,12 @@ mod app {
use lm3s6965::Interrupt;
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(Interrupt::UART0);
hprintln!("init").unwrap();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[idle]
diff --git a/examples/capacity.rs b/examples/capacity.rs
index b25a7584..06bd921e 100644
--- a/examples/capacity.rs
+++ b/examples/capacity.rs
@@ -13,10 +13,10 @@ mod app {
use lm3s6965::Interrupt;
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(Interrupt::UART0);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[task(binds = UART0)]
diff --git a/examples/cfg-whole-task.rs b/examples/cfg-whole-task.rs
index b19c280c..47c3530e 100644
--- a/examples/cfg-whole-task.rs
+++ b/examples/cfg-whole-task.rs
@@ -24,11 +24,11 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
foo::spawn().unwrap();
foo::spawn().unwrap();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[idle]
diff --git a/examples/cfg.rs b/examples/cfg.rs
index d3f2cea1..43c2593c 100644
--- a/examples/cfg.rs
+++ b/examples/cfg.rs
@@ -21,11 +21,11 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
foo::spawn().unwrap();
foo::spawn().unwrap();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[idle]
diff --git a/examples/destructure.rs b/examples/destructure.rs
index d843978b..d085e4bf 100644
--- a/examples/destructure.rs
+++ b/examples/destructure.rs
@@ -24,11 +24,11 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
// Direct destructure
diff --git a/examples/double_schedule.rs b/examples/double_schedule.rs
index 32477efe..403f3583 100644
--- a/examples/double_schedule.rs
+++ b/examples/double_schedule.rs
@@ -7,29 +7,37 @@
use panic_semihosting as _;
-#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0])]
+#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
mod app {
- use rtic::cyccnt::U32Ext;
+ use dwt_systick_monotonic::{
+ consts::{U0, U8},
+ DwtSystick,
+ };
+ use rtic::time::duration::Seconds;
- #[resources]
- struct Resources {
- nothing: (),
- }
+ #[monotonic(binds = SysTick, default = true)]
+ type MyMono = DwtSystick<U8, U0, U0>; // 8 MHz
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) {
task1::spawn().ok();
- init::LateResources { nothing: () }
+ let mut dcb = cx.core.DCB;
+ let dwt = cx.core.DWT;
+ let systick = cx.core.SYST;
+
+ let mono = DwtSystick::new(&mut dcb, dwt, systick, 8_000_000);
+
+ (init::LateResources {}, init::Monotonics(mono))
}
#[task]
fn task1(_cx: task1::Context) {
- task2::schedule(_cx.scheduled + 100.cycles()).ok();
+ task2::spawn_after(Seconds(1_u32)).ok();
}
#[task]
fn task2(_cx: task2::Context) {
- task1::schedule(_cx.scheduled + 100.cycles()).ok();
+ task1::spawn_after(Seconds(1_u32)).ok();
}
}
diff --git a/examples/extern_binds.rs b/examples/extern_binds.rs
index 632f4ca0..3c8786dd 100644
--- a/examples/extern_binds.rs
+++ b/examples/extern_binds.rs
@@ -20,12 +20,12 @@ mod app {
use lm3s6965::Interrupt;
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(Interrupt::UART0);
hprintln!("init").unwrap();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[idle]
diff --git a/examples/extern_spawn.rs b/examples/extern_spawn.rs
index 1be3d512..275ac539 100644
--- a/examples/extern_spawn.rs
+++ b/examples/extern_spawn.rs
@@ -22,10 +22,10 @@ mod app {
use crate::foo;
#[init]
- fn init(_c: init::Context) -> init::LateResources {
+ fn init(_c: init::Context) -> (init::LateResources, init::Monotonics) {
foo::spawn(1, 2).unwrap();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
extern "Rust" {
diff --git a/examples/generics.rs b/examples/generics.rs
index f3829a06..eabfff7e 100644
--- a/examples/generics.rs
+++ b/examples/generics.rs
@@ -21,11 +21,11 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[task(binds = UART0, resources = [shared])]
diff --git a/examples/hardware.rs b/examples/hardware.rs
index 99e8da2e..3cf98807 100644
--- a/examples/hardware.rs
+++ b/examples/hardware.rs
@@ -13,14 +13,14 @@ mod app {
use lm3s6965::Interrupt;
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
// Pends the UART0 interrupt but its handler won't run until *after*
// `init` returns because interrupts are disabled
rtic::pend(Interrupt::UART0); // equivalent to NVIC::pend
hprintln!("init").unwrap();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[idle]
diff --git a/examples/idle.rs b/examples/idle.rs
index 1aac56c2..db03dc70 100644
--- a/examples/idle.rs
+++ b/examples/idle.rs
@@ -12,10 +12,10 @@ mod app {
use cortex_m_semihosting::{debug, hprintln};
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
hprintln!("init").unwrap();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[idle]
diff --git a/examples/init.rs b/examples/init.rs
index ca67a2b7..9de79581 100644
--- a/examples/init.rs
+++ b/examples/init.rs
@@ -12,7 +12,7 @@ mod app {
use cortex_m_semihosting::{debug, hprintln};
#[init]
- fn init(cx: init::Context) -> init::LateResources {
+ fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) {
static mut X: u32 = 0;
// Cortex-M peripherals
@@ -32,6 +32,6 @@ mod app {
debug::exit(debug::EXIT_SUCCESS);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
}
diff --git a/examples/late.rs b/examples/late.rs
index d4efaba3..e65b6e69 100644
--- a/examples/late.rs
+++ b/examples/late.rs
@@ -25,13 +25,13 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
static mut Q: Queue<u32, U4> = Queue(i::Queue::new());
let (p, c) = Q.split();
// Initialization of late resources
- init::LateResources { p, c }
+ (init::LateResources { p, c }, init::Monotonics())
}
#[idle(resources = [c])]
diff --git a/examples/lock.rs b/examples/lock.rs
index 2fbf7608..75d47d24 100644
--- a/examples/lock.rs
+++ b/examples/lock.rs
@@ -19,10 +19,10 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(Interrupt::GPIOA);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
// when omitted priority is assumed to be `1`
diff --git a/examples/message.rs b/examples/message.rs
index 4c5d8997..722e73a7 100644
--- a/examples/message.rs
+++ b/examples/message.rs
@@ -12,10 +12,10 @@ mod app {
use cortex_m_semihosting::{debug, hprintln};
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
foo::spawn(/* no message */).unwrap();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[task]
diff --git a/examples/multilock.rs b/examples/multilock.rs
index a6985dfa..ad9d72ab 100644
--- a/examples/multilock.rs
+++ b/examples/multilock.rs
@@ -25,10 +25,10 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(Interrupt::GPIOA);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
// when omitted priority is assumed to be `1`
diff --git a/examples/not-sync.rs b/examples/not-sync.rs
index 21c316ae..f01d4043 100644
--- a/examples/not-sync.rs
+++ b/examples/not-sync.rs
@@ -6,7 +6,7 @@
#![no_std]
use core::marker::PhantomData;
-use panic_halt as _;
+use panic_semihosting as _;
pub struct NotSync {
_0: PhantomData<*const ()>,
@@ -25,10 +25,10 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
debug::exit(debug::EXIT_SUCCESS);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[task(resources = [&shared])]
diff --git a/examples/only-shared-access.rs b/examples/only-shared-access.rs
index 8d42fd4d..2c6ad4c4 100644
--- a/examples/only-shared-access.rs
+++ b/examples/only-shared-access.rs
@@ -18,11 +18,11 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
- init::LateResources { key: 0xdeadbeef }
+ (init::LateResources { key: 0xdeadbeef }, init::Monotonics())
}
#[task(binds = UART0, resources = [&key])]
diff --git a/examples/periodic.rs b/examples/periodic.rs
index 3ff9c907..82c21280 100644
--- a/examples/periodic.rs
+++ b/examples/periodic.rs
@@ -8,27 +8,33 @@
use panic_semihosting as _;
// NOTE: does NOT work on QEMU!
-#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0])]
+#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
mod app {
- use cortex_m_semihosting::hprintln;
- use rtic::cyccnt::{Instant, U32Ext};
+ use dwt_systick_monotonic::{
+ consts::{U0, U8},
+ DwtSystick,
+ };
+ use rtic::time::duration::Seconds;
- const PERIOD: u32 = 8_000_000;
+ #[monotonic(binds = SysTick, default = true)]
+ type MyMono = DwtSystick<U8, U0, U0>; // 8 MHz
#[init]
- fn init(cx: init::Context) -> init::LateResources {
- // omitted: initialization of `CYCCNT`
+ fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) {
+ let mut dcb = cx.core.DCB;
+ let dwt = cx.core.DWT;
+ let systick = cx.core.SYST;
- foo::schedule(cx.start + PERIOD.cycles()).unwrap();
+ let mono = DwtSystick::new(&mut dcb, dwt, systick, 8_000_000);
- init::LateResources {}
+ foo::spawn_after(Seconds(1_u32)).unwrap();
+
+ (init::LateResources {}, init::Monotonics(mono))
}
#[task]
- fn foo(cx: foo::Context) {
- let now = Instant::now();
- hprintln!("foo(scheduled = {:?}, now = {:?})", cx.scheduled, now).unwrap();
-
- foo::schedule(cx.scheduled + PERIOD.cycles()).unwrap();
+ fn foo(_cx: foo::Context) {
+ // Periodic
+ foo::spawn_after(Seconds(1_u32)).unwrap();
}
}
diff --git a/examples/peripherals-taken.rs b/examples/peripherals-taken.rs
index 98f06b08..6b4a282b 100644
--- a/examples/peripherals-taken.rs
+++ b/examples/peripherals-taken.rs
@@ -10,10 +10,10 @@ mod app {
use cortex_m_semihosting::debug;
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
assert!(cortex_m::Peripherals::take().is_none());
debug::exit(debug::EXIT_SUCCESS);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
}
diff --git a/examples/pool.rs b/examples/pool.rs
index eaad9c09..44405b49 100644
--- a/examples/pool.rs
+++ b/examples/pool.rs
@@ -25,7 +25,7 @@ mod app {
use super::P;
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
static mut MEMORY: [u8; 512] = [0; 512];
// Increase the capacity of the memory pool by ~4
@@ -33,7 +33,7 @@ mod app {
rtic::pend(Interrupt::I2C0);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[task(binds = I2C0, priority = 2)]
diff --git a/examples/preempt.rs b/examples/preempt.rs
index ee75c46f..14b3a0a6 100644
--- a/examples/preempt.rs
+++ b/examples/preempt.rs
@@ -12,10 +12,10 @@ mod app {
use lm3s6965::Interrupt;
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(Interrupt::GPIOA);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[task(binds = GPIOA, priority = 1)]
diff --git a/examples/ramfunc.rs b/examples/ramfunc.rs
index b5aa17b9..d9c8143f 100644
--- a/examples/ramfunc.rs
+++ b/examples/ramfunc.rs
@@ -19,10 +19,10 @@ mod app {
use cortex_m_semihosting::{debug, hprintln};
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
foo::spawn().unwrap();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[inline(never)]
diff --git a/examples/resource-user-struct.rs b/examples/resource-user-struct.rs
index a550bb2a..6ad540b0 100644
--- a/examples/resource-user-struct.rs
+++ b/examples/resource-user-struct.rs
@@ -27,11 +27,11 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
// `shared` cannot be accessed from this context
diff --git a/examples/resource.rs b/examples/resource.rs
index 60aa52b0..c8c57bf5 100644
--- a/examples/resource.rs
+++ b/examples/resource.rs
@@ -20,11 +20,11 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
// `shared` cannot be accessed from this context
diff --git a/examples/schedule.rs b/examples/schedule.rs
index 5f73c500..d6d44998 100644
--- a/examples/schedule.rs
+++ b/examples/schedule.rs
@@ -5,45 +5,47 @@
#![no_main]
#![no_std]
-use panic_halt as _;
+use panic_semihosting as _;
// NOTE: does NOT work on QEMU!
-#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0])]
+#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
mod app {
- use cortex_m::peripheral::DWT;
use cortex_m_semihosting::hprintln;
- use rtic::cyccnt::{Instant, U32Ext as _};
+ use dwt_systick_monotonic::{
+ consts::{U0, U8},
+ DwtSystick,
+ };
+ use rtic::time::duration::Seconds;
+
+ #[monotonic(binds = SysTick, default = true)]
+ type MyMono = DwtSystick<U8, U0, U0>; // 8 MHz
#[init()]
- fn init(mut cx: init::Context) -> init::LateResources {
- // Initialize (enable) the monotonic timer (CYCCNT)
- cx.core.DCB.enable_trace();
- // required on Cortex-M7 devices that software lock the DWT (e.g. STM32F7)
- DWT::unlock();
- cx.core.DWT.enable_cycle_counter();
+ fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) {
+ let mut dcb = cx.core.DCB;
+ let dwt = cx.core.DWT;
+ let systick = cx.core.SYST;
- // semantically, the monotonic timer is frozen at time "zero" during `init`
- // NOTE do *not* call `Instant::now` in this context; it will return a nonsense value
- let now = cx.start; // the start time of the system
+ let mono = DwtSystick::new(&mut dcb, dwt, systick, 8_000_000);
- hprintln!("init @ {:?}", now).unwrap();
+ hprintln!("init").unwrap();
- // Schedule `foo` to run 8e6 cycles (clock cycles) in the future
- foo::schedule(now + 8_000_000.cycles()).unwrap();
+ // Schedule `foo` to run 1 second in the future
+ foo::spawn_after(Seconds(1_u32)).unwrap();
- // Schedule `bar` to run 4e6 cycles in the future
- bar::schedule(now + 4_000_000.cycles()).unwrap();
+ // Schedule `bar` to run 2 seconds in the future
+ bar::spawn_after(Seconds(2_u32)).unwrap();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics(mono))
}
#[task]
fn foo(_: foo::Context) {
- hprintln!("foo @ {:?}", Instant::now()).unwrap();
+ hprintln!("foo").unwrap();
}
#[task]
fn bar(_: bar::Context) {
- hprintln!("bar @ {:?}", Instant::now()).unwrap();
+ hprintln!("bar").unwrap();
}
}
diff --git a/examples/spawn.rs b/examples/spawn.rs
index 449fcfb9..987ebf7d 100644
--- a/examples/spawn.rs
+++ b/examples/spawn.rs
@@ -12,10 +12,10 @@ mod app {
use cortex_m_semihosting::{debug, hprintln};
#[init]
- fn init(_c: init::Context) -> init::LateResources {
+ fn init(_c: init::Context) -> (init::LateResources, init::Monotonics) {
foo::spawn(1, 2).unwrap();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[task()]
diff --git a/examples/spawn2.rs b/examples/spawn2.rs
index c485b922..be113f79 100644
--- a/examples/spawn2.rs
+++ b/examples/spawn2.rs
@@ -12,10 +12,10 @@ mod app {
use cortex_m_semihosting::{debug, hprintln};
#[init]
- fn init(_c: init::Context) -> init::LateResources {
+ fn init(_c: init::Context) -> (init::LateResources, init::Monotonics) {
foo::spawn(1, 2).unwrap();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[task]
diff --git a/examples/static.rs b/examples/static.rs
index 7626c712..cbbc5399 100644
--- a/examples/static.rs
+++ b/examples/static.rs
@@ -26,13 +26,13 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
static mut Q: Queue<u32, U4> = Queue(i::Queue::new());
let (p, c) = Q.split();
// Initialization of late resources
- init::LateResources { p, c }
+ (init::LateResources { p, c }, init::Monotonics())
}
#[idle(resources = [c])]
diff --git a/examples/t-binds.rs b/examples/t-binds.rs
index 8d52f58a..fbc89e88 100644
--- a/examples/t-binds.rs
+++ b/examples/t-binds.rs
@@ -5,13 +5,13 @@
#![no_main]
#![no_std]
-use panic_halt as _;
+use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init]
- fn init(_: init::Context) -> init::LateResources {
- init::LateResources {}
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
+ (init::LateResources {}, init::Monotonics())
}
// Cortex-M exception
diff --git a/examples/t-cfg-resources.rs b/examples/t-cfg-resources.rs
index 61eb4c7b..1adcb905 100644
--- a/examples/t-cfg-resources.rs
+++ b/examples/t-cfg-resources.rs
@@ -3,7 +3,7 @@
#![no_main]
#![no_std]
-use panic_halt as _;
+use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
@@ -18,13 +18,16 @@ mod app {
dummy: (), // dummy such that we have at least one late resource
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
- init::LateResources {
- // The feature needs to be applied everywhere x is defined or used
- #[cfg(feature = "feature_x")]
- x: 0,
- dummy: (), // dummy such that we have at least one late resource
- }
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
+ (
+ init::LateResources {
+ // The feature needs to be applied everywhere x is defined or used
+ #[cfg(feature = "feature_x")]
+ x: 0,
+ dummy: (), // dummy such that we have at least one late resource
+ },
+ init::Monotonics(),
+ )
}
#[idle]
diff --git a/examples/t-cfg.rs b/examples/t-cfg.rs
index 5bcef0af..ef591c4d 100644
--- a/examples/t-cfg.rs
+++ b/examples/t-cfg.rs
@@ -3,9 +3,9 @@
#![no_main]
#![no_std]
-use panic_halt as _;
+use panic_semihosting as _;
-#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0, QEI0])]
+#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
mod app {
#[resources]
struct Resources {
@@ -15,11 +15,11 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
#[cfg(never)]
static mut BAR: u32 = 0;
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[idle]
diff --git a/examples/t-htask-main.rs b/examples/t-htask-main.rs
index 57076eca..2d480d0b 100644
--- a/examples/t-htask-main.rs
+++ b/examples/t-htask-main.rs
@@ -10,10 +10,10 @@ mod app {
use cortex_m_semihosting::debug;
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(lm3s6965::Interrupt::UART0);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[task(binds = UART0)]
diff --git a/examples/t-idle-main.rs b/examples/t-idle-main.rs
index 42dac904..891896fa 100644
--- a/examples/t-idle-main.rs
+++ b/examples/t-idle-main.rs
@@ -10,8 +10,8 @@ mod app {
use cortex_m_semihosting::debug;
#[init]
- fn init(_: init::Context) -> init::LateResources {
- init::LateResources {}
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
+ (init::LateResources {}, init::Monotonics())
}
#[idle]
diff --git a/examples/t-init-main.rs b/examples/t-init-main.rs
index 0456e874..b77a7df8 100644
--- a/examples/t-init-main.rs
+++ b/examples/t-init-main.rs
@@ -10,9 +10,9 @@ mod app {
use cortex_m_semihosting::debug;
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
debug::exit(debug::EXIT_SUCCESS);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
}
diff --git a/examples/t-late-not-send.rs b/examples/t-late-not-send.rs
index ce3bcbac..579f8436 100644
--- a/examples/t-late-not-send.rs
+++ b/examples/t-late-not-send.rs
@@ -5,7 +5,7 @@
use core::marker::PhantomData;
-use panic_halt as _;
+use panic_semihosting as _;
pub struct NotSend {
_0: PhantomData<*const ()>,
@@ -24,10 +24,13 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
- init::LateResources {
- x: NotSend { _0: PhantomData },
- }
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
+ (
+ init::LateResources {
+ x: NotSend { _0: PhantomData },
+ },
+ init::Monotonics(),
+ )
}
#[idle(resources = [x, y])]
diff --git a/examples/t-resource.rs b/examples/t-resource.rs
index 0a9f3bad..6e83069d 100644
--- a/examples/t-resource.rs
+++ b/examples/t-resource.rs
@@ -5,7 +5,7 @@
#![no_main]
#![no_std]
-use panic_halt as _;
+use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
@@ -32,8 +32,8 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
- init::LateResources {}
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
+ (init::LateResources {}, init::Monotonics())
}
#[idle(resources = [o2, &o4, s1, &s3])]
diff --git a/examples/t-schedule-core-stable.rs b/examples/t-schedule-core-stable.rs
index 10539014..98d42ce7 100644
--- a/examples/t-schedule-core-stable.rs
+++ b/examples/t-schedule-core-stable.rs
@@ -5,15 +5,15 @@
#![no_main]
#![no_std]
-use panic_halt as _;
+use panic_semihosting as _;
-#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0])]
+#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
mod app {
#[init]
- fn init(c: init::Context) -> init::LateResources {
- let _c: rtic::Peripherals = c.core;
+ fn init(c: init::Context) -> (init::LateResources, init::Monotonics) {
+ let _c: cortex_m::Peripherals = c.core;
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[task]
diff --git a/examples/t-schedule.rs b/examples/t-schedule.rs
index 9c94d1b4..bd0ab668 100644
--- a/examples/t-schedule.rs
+++ b/examples/t-schedule.rs
@@ -5,52 +5,47 @@
#![no_main]
#![no_std]
-use panic_halt as _;
+use panic_semihosting as _;
-#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0])]
+#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
mod app {
- use rtic::cyccnt::{Instant, U32Ext as _};
+ use dwt_systick_monotonic::{
+ consts::{U0, U8},
+ DwtSystick,
+ };
+ use rtic::time::duration::Seconds;
+
+ #[monotonic(binds = SysTick, default = true)]
+ type MyMono = DwtSystick<U8, U0, U0>; // 8 MHz
#[init]
- fn init(c: init::Context) -> init::LateResources {
- let _: Result<(), ()> = foo::schedule(c.start + 10.cycles());
- let _: Result<(), u32> = bar::schedule(c.start + 20.cycles(), 0);
- let _: Result<(), (u32, u32)> = baz::schedule(c.start + 30.cycles(), 0, 1);
+ fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) {
+ let mut dcb = cx.core.DCB;
+ let dwt = cx.core.DWT;
+ let systick = cx.core.SYST;
+
+ let mono = DwtSystick::new(&mut dcb, dwt, systick, 8_000_000);
- init::LateResources {}
+ let _: Result<(), ()> = foo::spawn_after(Seconds(1_u32));
+ let _: Result<(), u32> = bar::spawn_after(Seconds(2_u32), 0);
+ let _: Result<(), (u32, u32)> = baz::spawn_after(Seconds(3_u32), 0, 1);
+
+ (init::LateResources {}, init::Monotonics(mono))
}
#[idle]
fn idle(_: idle::Context) -> ! {
- let _: Result<(), ()> = foo::schedule(Instant::now() + 40.cycles());
- let _: Result<(), u32> = bar::schedule(Instant::now() + 50.cycles(), 0);
- let _: Result<(), (u32, u32)> = baz::schedule(Instant::now() + 60.cycles(), 0, 1);
+ let _: Result<(), ()> = foo::spawn_at(MyMono::now() + Seconds(3_u32));
+ let _: Result<(), u32> = bar::spawn_at(MyMono::now() + Seconds(4_u32), 0);
+ let _: Result<(), (u32, u32)> = baz::spawn_at(MyMono::now() + Seconds(5_u32), 0, 1);
loop {
cortex_m::asm::nop();
}
}
- #[task(binds = SVCall)]
- fn svcall(c: svcall::Context) {
- let _: Result<(), ()> = foo::schedule(c.start + 70.cycles());
- let _: Result<(), u32> = bar::schedule(c.start + 80.cycles(), 0);
- let _: Result<(), (u32, u32)> = baz::schedule(c.start + 90.cycles(), 0, 1);
- }
-
- #[task(binds = UART0)]
- fn uart0(c: uart0::Context) {
- let _: Result<(), ()> = foo::schedule(c.start + 100.cycles());
- let _: Result<(), u32> = bar::schedule(c.start + 110.cycles(), 0);
- let _: Result<(), (u32, u32)> = baz::schedule(c.start + 120.cycles(), 0, 1);
- }
-
#[task]
- fn foo(c: foo::Context) {
- let _: Result<(), ()> = foo::schedule(c.scheduled + 130.cycles());
- let _: Result<(), u32> = bar::schedule(c.scheduled + 140.cycles(), 0);
- let _: Result<(), (u32, u32)> = baz::schedule(c.scheduled + 150.cycles(), 0, 1);
- }
+ fn foo(_: foo::Context) {}
#[task]
fn bar(_: bar::Context, _x: u32) {}
diff --git a/examples/t-spawn.rs b/examples/t-spawn.rs
index c9949ef9..ca5c61b2 100644
--- a/examples/t-spawn.rs
+++ b/examples/t-spawn.rs
@@ -5,17 +5,17 @@
#![no_main]
#![no_std]
-use panic_halt as _;
+use panic_semihosting as _;
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
mod app {
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
let _: Result<(), ()> = foo::spawn();
let _: Result<(), u32> = bar::spawn(0);
let _: Result<(), (u32, u32)> = baz::spawn(0, 1);
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[idle]
diff --git a/examples/t-stask-main.rs b/examples/t-stask-main.rs
index 034ad7c5..cfc93425 100644
--- a/examples/t-stask-main.rs
+++ b/examples/t-stask-main.rs
@@ -10,10 +10,10 @@ mod app {
use cortex_m_semihosting::debug;
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
taskmain::spawn().ok();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[task]
diff --git a/examples/task-local-minimal.rs b/examples/task-local-minimal.rs
index 6e25c10d..f83493c2 100644
--- a/examples/task-local-minimal.rs
+++ b/examples/task-local-minimal.rs
@@ -18,8 +18,8 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
- init::LateResources { l: 42 }
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
+ (init::LateResources { l: 42 }, init::Monotonics())
}
// l is task_local
diff --git a/examples/task-local.rs b/examples/task-local.rs
index e86197a0..3020c3b3 100644
--- a/examples/task-local.rs
+++ b/examples/task-local.rs
@@ -38,10 +38,10 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
- init::LateResources { e2: 2, l2: 2 }
+ (init::LateResources { e2: 2, l2: 2 }, init::Monotonics())
}
// `shared` cannot be accessed from this context
diff --git a/examples/task.rs b/examples/task.rs
index 5e4769a5..9d4492f2 100644
--- a/examples/task.rs
+++ b/examples/task.rs
@@ -12,10 +12,10 @@ mod app {
use cortex_m_semihosting::{debug, hprintln};
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
foo::spawn().unwrap();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[task]
diff --git a/examples/task_named_main.rs b/examples/task_named_main.rs
index c3d21b58..c2c4e62d 100644
--- a/examples/task_named_main.rs
+++ b/examples/task_named_main.rs
@@ -12,10 +12,10 @@ mod app {
use cortex_m_semihosting::{debug, hprintln};
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
main::spawn().unwrap();
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[task]
diff --git a/examples/types.rs b/examples/types.rs
index bcdd30a9..ff7deb84 100644
--- a/examples/types.rs
+++ b/examples/types.rs
@@ -7,10 +7,16 @@
use panic_semihosting as _;
-#[rtic::app(device = lm3s6965, peripherals = true, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0])]
+#[rtic::app(device = lm3s6965, peripherals = true, dispatchers = [SSI0])]
mod app {
use cortex_m_semihosting::debug;
- use rtic::cyccnt;
+ use dwt_systick_monotonic::{
+ consts::{U0, U8},
+ DwtSystick,
+ };
+
+ #[monotonic(binds = SysTick, default = true)]
+ type MyMono = DwtSystick<U8, U0, U0>; // 8 MHz
#[resources]
struct Resources {
@@ -19,14 +25,19 @@ mod app {
}
#[init]
- fn init(cx: init::Context) -> init::LateResources {
- let _: cyccnt::Instant = cx.start;
- let _: rtic::Peripherals = cx.core;
+ fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) {
+ let _: cortex_m::Peripherals = cx.core;
let _: lm3s6965::Peripherals = cx.device;
debug::exit(debug::EXIT_SUCCESS);
- init::LateResources {}
+ let mut dcb = cx.core.DCB;
+ let dwt = cx.core.DWT;
+ let systick = cx.core.SYST;
+
+ let mono = DwtSystick::new(&mut dcb, dwt, systick, 8_000_000);
+
+ (init::LateResources {}, init::Monotonics(mono))
}
#[idle]
@@ -38,13 +49,11 @@ mod app {
#[task(binds = UART0, resources = [shared])]
fn uart0(cx: uart0::Context) {
- let _: cyccnt::Instant = cx.start;
let _: resources::shared = cx.resources.shared;
}
#[task(priority = 2, resources = [shared])]
fn foo(cx: foo::Context) {
- let _: cyccnt::Instant = cx.scheduled;
let _: resources::shared = cx.resources.shared;
let _: foo::Resources = cx.resources;
}
diff --git a/macros/Cargo.toml b/macros/Cargo.toml
index 3af48c76..f14b1046 100644
--- a/macros/Cargo.toml
+++ b/macros/Cargo.toml
@@ -12,7 +12,7 @@ license = "MIT OR Apache-2.0"
name = "cortex-m-rtic-macros"
readme = "../README.md"
repository = "https://github.com/rtic-rs/cortex-m-rtic"
-version = "0.6.0-alpha.0"
+version = "0.6.0-alpha.1"
[lib]
proc-macro = true
@@ -22,5 +22,5 @@ proc-macro2 = "1"
proc-macro-error = "1"
quote = "1"
syn = "1"
-rtic-syntax = { git = "https://github.com/rtic-rs/rtic-syntax", branch = "master", version = "0.5.0-alpha.0" }
+rtic-syntax = "0.5.0-alpha.1"
diff --git a/macros/src/check.rs b/macros/src/check.rs
index e3161cb9..374fcedd 100644
--- a/macros/src/check.rs
+++ b/macros/src/check.rs
@@ -6,7 +6,6 @@ use syn::{parse, Path};
pub struct Extra {
pub device: Path,
- pub monotonic: Option<Path>,
pub peripherals: bool,
}
@@ -62,18 +61,6 @@ pub fn app(app: &App, _analysis: &Analysis) -> parse::Result<Extra> {
for (name, task) in &app.hardware_tasks {
let name_s = task.args.binds.to_string();
match &*name_s {
- "SysTick" => {
- // If the timer queue is used, then SysTick is unavailable
- if app.args.monotonic.is_some() {
- return Err(parse::Error::new(
- name.span(),
- "this exception can't be used because it's being used by the runtime",
- ));
- } else {
- // OK
- }
- }
-
"NonMaskableInt" | "HardFault" => {
return Err(parse::Error::new(
name.span(),
@@ -88,7 +75,6 @@ pub fn app(app: &App, _analysis: &Analysis) -> parse::Result<Extra> {
if let Some(device) = app.args.device.clone() {
Ok(Extra {
device,
- monotonic: app.args.monotonic.clone(),
peripherals: app.args.peripherals,
})
} else {
diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs
index 3cddf570..c5d95687 100644
--- a/macros/src/codegen.rs
+++ b/macros/src/codegen.rs
@@ -27,13 +27,13 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
let mut user = vec![];
// Generate the `main` function
- let assertion_stmts = assertions::codegen(analysis);
+ let assertion_stmts = assertions::codegen(app, analysis);
- let pre_init_stmts = pre_init::codegen(&app, analysis, extra);
+ let pre_init_stmts = pre_init::codegen(app, analysis, extra);
let (mod_app_init, root_init, user_init, call_init) = init::codegen(app, analysis, extra);
- let post_init_stmts = post_init::codegen(&app, analysis);
+ let post_init_stmts = post_init::codegen(app, analysis);
let (mod_app_idle, root_idle, user_idle, call_idle) = idle::codegen(app, analysis, extra);
@@ -57,12 +57,11 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
let main = util::suffixed("main");
mains.push(quote!(
+ #[doc(hidden)]
mod rtic_ext {
use super::*;
#[no_mangle]
unsafe extern "C" fn #main() -> ! {
- let _TODO: () = ();
-
#(#assertion_stmts)*
#(#pre_init_stmts)*
@@ -90,27 +89,69 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
let user_code = &app.user_code;
let name = &app.name;
let device = &extra.device;
-
- // Get the list of all tasks
- // Currently unused, might be useful
- let task_list = analysis.tasks.clone();
-
- let mut tasks = vec![];
-
- if !task_list.is_empty() {
- tasks.push(quote!(
- #[allow(non_camel_case_types)]
- pub enum Tasks {
- #(#task_list),*
+ let app_name = &app.name;
+ let app_path = quote! {crate::#app_name};
+
+ let monotonic_parts: Vec<_> = app
+ .monotonics
+ .iter()
+ .map(|(_, monotonic)| {
+ let name = &monotonic.ident;
+ let name_str = &name.to_string();
+ let ty = &monotonic.ty;
+ let ident = util::monotonic_ident(&name_str);
+ let ident = util::mark_internal_ident(&ident);
+ let panic_str = &format!(
+ "Use of monotonic '{}' before it was passed to the runtime",
+ name_str
+ );
+ let doc = &format!(
+ "This module holds the static implementation for `{}::now()`",
+ name_str
+ );
+ let user_imports = &app.user_imports;
+
+ quote! {
+ pub use rtic::Monotonic as _;
+
+ #[doc = #doc]
+ #[allow(non_snake_case)]
+ pub mod #name {
+ #(
+ #[allow(unused_imports)]
+ #user_imports
+ )*
+
+ /// Read the current time from this monotonic
+ pub fn now() -> rtic::time::Instant<#ty> {
+ rtic::export::interrupt::free(|_| {
+ use rtic::Monotonic as _;
+ use rtic::time::Clock as _;
+ if let Some(m) = unsafe{ #app_path::#ident.as_ref() } {
+ if let Ok(v) = m.try_now() {
+ v
+ } else {
+ unreachable!("Your monotonic is not infallible!")
+ }
+ } else {
+ panic!(#panic_str);
+ }
+ })
+ }
+ }
}
- ));
- }
+ })
+ .collect();
+
+ let rt_err = util::rt_err_ident();
quote!(
- /// Implementation details
+ /// The RTIC application module
pub mod #name {
/// 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_parts)*
#(#user_imports)*
@@ -132,9 +173,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
#(#root_software_tasks)*
- /// Unused
- #(#tasks)*
-
/// app module
#(#mod_app)*
diff --git a/macros/src/codegen/assertions.rs b/macros/src/codegen/assertions.rs
index 4d9aae47..a8a4491b 100644
--- a/macros/src/codegen/assertions.rs
+++ b/macros/src/codegen/assertions.rs
@@ -2,9 +2,10 @@ use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use crate::analyze::Analysis;
+use rtic_syntax::ast::App;
/// Generates compile-time assertions that check that types implement the `Send` / `Sync` traits
-pub fn codegen(analysis: &Analysis) -> Vec<TokenStream2> {
+pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
let mut stmts = vec![];
for ty in &analysis.send_types {
@@ -15,5 +16,10 @@ pub fn codegen(analysis: &Analysis) -> Vec<TokenStream2> {
stmts.push(quote!(rtic::export::assert_sync::<#ty>();));
}
+ for (_, monotonic) in &app.monotonics {
+ let ty = &monotonic.ty;
+ stmts.push(quote!(rtic::export::assert_monotonic::<#ty>();));
+ }
+
stmts
}
diff --git a/macros/src/codegen/dispatchers.rs b/macros/src/codegen/dispatchers.rs
index a6c695f1..dc33b1af 100644
--- a/macros/src/codegen/dispatchers.rs
+++ b/macros/src/codegen/dispatchers.rs
@@ -5,7 +5,7 @@ use rtic_syntax::ast::App;
use crate::{analyze::Analysis, check::Extra, codegen::util};
/// Generates task dispatchers
-pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> {
+pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStream2> {
let mut items = vec![];
let interrupts = &analysis.interrupts;
@@ -26,15 +26,16 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
})
.collect::<Vec<_>>();
- let doc = format!(
- "Software tasks to be dispatched at priority level {}",
- level,
- );
+ // let doc = format!(
+ // "Software tasks to be dispatched at priority level {}",
+ // level,
+ // );
let t = util::spawn_t_ident(level);
items.push(quote!(
#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
- #[doc = #doc]
+ // #[doc = #doc]
+ #[doc(hidden)]
pub enum #t {
#(#variants,)*
}
@@ -42,6 +43,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
let n = util::capacity_typenum(channel.capacity, true);
let rq = util::rq_ident(level);
+ let rq = util::mark_internal_ident(&rq);
let (rq_ty, rq_expr) = {
(
quote!(rtic::export::SCRQ<#t, #n>),
@@ -51,12 +53,12 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
)
};
- let doc = format!(
- "Queue of tasks ready to be dispatched at priority level {}",
- level
- );
+ // let doc = format!(
+ // "Queue of tasks ready to be dispatched at priority level {}",
+ // level
+ // );
items.push(quote!(
- #[doc = #doc]
+ #[doc(hidden)]
static mut #rq: #rq_ty = #rq_expr;
));
@@ -67,23 +69,11 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
let task = &app.software_tasks[name];
let cfgs = &task.cfgs;
let fq = util::fq_ident(name);
+ let fq = util::mark_internal_ident(&fq);
let inputs = util::inputs_ident(name);
+ let inputs = util::mark_internal_ident(&inputs);
let (_, tupled, pats, _) = util::regroup_inputs(&task.inputs);
- let (let_instant, instant) = if extra.monotonic.is_some() {
- let instants = util::instants_ident(name);
-
- (
- quote!(
- let instant =
- #instants.get_unchecked(usize::from(index)).as_ptr().read();
- ),
- quote!(, instant),
- )
- } else {
- (quote!(), quote!())
- };
-
let locals_new = if task.locals.is_empty() {
quote!()
} else {
@@ -97,12 +87,11 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
#t::#name => {
let #tupled =
#inputs.get_unchecked(usize::from(index)).as_ptr().read();
- #let_instant
#fq.split().0.enqueue_unchecked(index);
let priority = &rtic::export::Priority::new(PRIORITY);
#app_path::#name(
#locals_new
- #name::Context::new(priority #instant)
+ #name::Context::new(priority)
#(,#pats)*
)
}
diff --git a/macros/src/codegen/hardware_tasks.rs b/macros/src/codegen/hardware_tasks.rs
index 6930d3e0..4a1d7492 100644
--- a/macros/src/codegen/hardware_tasks.rs
+++ b/macros/src/codegen/hardware_tasks.rs
@@ -29,15 +29,6 @@ pub fn codegen(
let mut user_tasks = vec![];
for (name, task) in &app.hardware_tasks {
- let (let_instant, instant) = if let Some(ref m) = extra.monotonic {
- (
- Some(quote!(let instant = <#m as rtic::Monotonic>::now();)),
- Some(quote!(, instant)),
- )
- } else {
- (None, None)
- };
-
let locals_new = if task.locals.is_empty() {
quote!()
} else {
@@ -55,12 +46,10 @@ pub fn codegen(
unsafe fn #symbol() {
const PRIORITY: u8 = #priority;
- #let_instant
-
rtic::export::run(PRIORITY, || {
#app_path::#name(
#locals_new
- #name::Context::new(&rtic::export::Priority::new(PRIORITY) #instant)
+ #name::Context::new(&rtic::export::Priority::new(PRIORITY))
)
});
}
diff --git a/macros/src/codegen/init.rs b/macros/src/codegen/init.rs
index 6376ce31..aa9adcb0 100644
--- a/macros/src/codegen/init.rs
+++ b/macros/src/codegen/init.rs
@@ -5,7 +5,7 @@ use rtic_syntax::{ast::App, Context};
use crate::{
analyze::Analysis,
check::Extra,
- codegen::{locals, module, resources_struct, util},
+ codegen::{locals, module, resources_struct},
};
type CodegenResult = (
@@ -32,32 +32,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> CodegenResult {
let mut root_init = vec![];
- let late_fields = analysis
- .late_resources
- .iter()
- .flat_map(|resources| {
- resources.iter().map(|name| {
- let ty = &app.late_resources[name].ty;
- let cfgs = &app.late_resources[name].cfgs;
-
- quote!(
- #(#cfgs)*
- pub #name: #ty
- )
- })
- })
- .collect::<Vec<_>>();
-
- let late_resources = util::late_resources_ident(&name);
-
- root_init.push(quote!(
- /// Resources initialized at runtime
- #[allow(non_snake_case)]
- pub struct #late_resources {
- #(#late_fields),*
- }
- ));
-
let mut locals_pat = None;
let mut locals_new = None;
if !init.locals.is_empty() {
@@ -72,10 +46,13 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> CodegenResult {
let attrs = &init.attrs;
let stmts = &init.stmts;
let locals_pat = locals_pat.iter();
+
+ let user_init_return = quote! {#name::LateResources, #name::Monotonics};
+
let user_init = Some(quote!(
#(#attrs)*
#[allow(non_snake_case)]
- fn #name(#(#locals_pat,)* #context: #name::Context) -> #name::LateResources {
+ fn #name(#(#locals_pat,)* #context: #name::Context) -> (#user_init_return) {
#(#stmts)*
}
));
@@ -92,7 +69,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> CodegenResult {
let app_path = quote! {crate::#app_name};
let locals_new = locals_new.iter();
let call_init = Some(
- quote!(let late = #app_path::#name(#(#locals_new,)* #name::Context::new(core.into()));),
+ quote!(let (late, mut monotonics) = #app_path::#name(#(#locals_new,)* #name::Context::new(core.into()));),
);
root_init.push(module::codegen(
diff --git a/macros/src/codegen/locals.rs b/macros/src/codegen/locals.rs
index 336c0b21..5725a151 100644
--- a/macros/src/codegen/locals.rs
+++ b/macros/src/codegen/locals.rs
@@ -49,6 +49,7 @@ pub fn codegen(
));
items.push(quote!(
#(#cfgs)*
+ #[doc(hidden)]
static mut #name: #ty = #expr
));
values.push(quote!(
diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs
index 2ff4801e..75435b54 100644
--- a/macros/src/codegen/module.rs
+++ b/macros/src/codegen/module.rs
@@ -18,29 +18,16 @@ pub fn codegen(
let mut task_cfgs = vec![];
let name = ctxt.ident(app);
+ let app_name = &app.name;
+ let app_path = quote! {crate::#app_name};
- let mut needs_instant = false;
let mut lt = None;
match ctxt {
Context::Init => {
- if let Some(m) = &extra.monotonic {
- fields.push(quote!(
- /// System start time = `Instant(0 /* cycles */)`
- pub start: <#m as rtic::Monotonic>::Instant
- ));
-
- values.push(quote!(start: <#m as rtic::Monotonic>::zero()));
-
- fields.push(quote!(
- /// Core (Cortex-M) peripherals minus the SysTick
- pub core: rtic::Peripherals
- ));
- } else {
- fields.push(quote!(
- /// Core (Cortex-M) peripherals
- pub core: rtic::export::Peripherals
- ));
- }
+ fields.push(quote!(
+ /// Core (Cortex-M) peripherals
+ pub core: rtic::export::Peripherals
+ ));
if extra.peripherals {
let device = &extra.device;
@@ -66,31 +53,9 @@ pub fn codegen(
Context::Idle => {}
- Context::HardwareTask(..) => {
- if let Some(m) = &extra.monotonic {
- fields.push(quote!(
- /// Time at which this handler started executing
- pub start: <#m as rtic::Monotonic>::Instant
- ));
+ Context::HardwareTask(_) => {}
- values.push(quote!(start: instant));
-
- needs_instant = true;
- }
- }
-
- Context::SoftwareTask(..) => {
- if let Some(m) = &extra.monotonic {
- fields.push(quote!(
- /// The time at which this task was scheduled to run
- pub scheduled: <#m as rtic::Monotonic>::Instant
- ));
-
- values.push(quote!(scheduled: instant));
-
- needs_instant = true;
- }
- }
+ Context::SoftwareTask(_) => {}
}
if ctxt.has_locals(app) {
@@ -103,6 +68,7 @@ pub fn codegen(
if ctxt.has_resources(app) {
let ident = util::resources_ident(ctxt, app);
+ let ident = util::mark_internal_ident(&ident);
let lt = if resources_tick {
lt = Some(quote!('a));
Some(quote!('a))
@@ -129,12 +95,45 @@ pub fn codegen(
}
if let Context::Init = ctxt {
- let init = &app.inits.first().unwrap();
- let late_resources = util::late_resources_ident(&init.name);
+ let late_fields = analysis
+ .late_resources
+ .iter()
+ .flat_map(|resources| {
+ resources.iter().map(|name| {
+ let ty = &app.late_resources[name].ty;
+ let cfgs = &app.late_resources[name].cfgs;
+
+ quote!(
+ #(#cfgs)*
+ pub #name: #ty
+ )
+ })
+ })
+ .collect::<Vec<_>>();
items.push(quote!(
- #[doc(inline)]
- pub use super::#late_resources as LateResources;
+ /// Resources initialized at runtime
+ #[allow(non_snake_case)]
+ pub struct LateResources {
+ #(#late_fields),*
+ }
+ ));
+
+ let monotonic_types: Vec<_> = app
+ .monotonics
+ .iter()
+ .map(|(_, monotonic)| {
+ let mono = &monotonic.ty;
+ quote! {#mono}
+ })
+ .collect();
+
+ items.push(quote!(
+ /// Monotonics used by the system
+ #[allow(non_snake_case)]
+ pub struct Monotonics(
+ #(pub #monotonic_types),*
+ );
));
}
@@ -146,11 +145,7 @@ pub fn codegen(
};
let core = if ctxt.is_init() {
- if extra.monotonic.is_some() {
- Some(quote!(core: rtic::Peripherals,))
- } else {
- Some(quote!(core: rtic::export::Peripherals,))
- }
+ Some(quote!(core: rtic::export::Peripherals,))
} else {
None
};
@@ -161,14 +156,6 @@ pub fn codegen(
Some(quote!(priority: &#lt rtic::export::Priority))
};
- let instant = if needs_instant {
- let m = extra.monotonic.clone().expect("RTIC-ICE: UNREACHABLE");
-
- Some(quote!(, instant: <#m as rtic::Monotonic>::Instant))
- } else {
- None
- };
-
items.push(quote!(
/// Execution context
pub struct Context<#lt> {
@@ -177,7 +164,7 @@ pub fn codegen(
impl<#lt> Context<#lt> {
#[inline(always)]
- pub unsafe fn new(#core #priority #instant) -> Self {
+ pub unsafe fn new(#core #priority) -> Self {
Context {
#(#values,)*
}
@@ -195,15 +182,15 @@ pub fn codegen(
let cfgs = &spawnee.cfgs;
// Store a copy of the task cfgs
task_cfgs = cfgs.clone();
- let (args, tupled, _untupled, ty) = util::regroup_inputs(&spawnee.inputs);
+ let (args, tupled, untupled, ty) = util::regroup_inputs(&spawnee.inputs);
let args = &args;
let tupled = &tupled;
let fq = util::fq_ident(name);
+ let fq = util::mark_internal_ident(&fq);
let rq = util::rq_ident(priority);
+ let rq = util::mark_internal_ident(&rq);
let inputs = util::inputs_ident(name);
-
- let app_name = &app.name;
- let app_path = quote! {crate::#app_name};
+ let inputs = util::mark_internal_ident(&inputs);
let device = &extra.device;
let enum_ = util::interrupt_ident();
@@ -216,11 +203,8 @@ pub fn codegen(
// Spawn caller
items.push(quote!(
#(#cfgs)*
+ /// Spawns the task directly
pub fn spawn(#(#args,)*) -> Result<(), #ty> {
- // #let_instant // do we need it?
- use rtic::Mutex as _;
- use rtic::mutex_prelude::*;
-
let input = #tupled;
unsafe {
@@ -245,45 +229,114 @@ pub fn codegen(
}));
// Schedule caller
- if let Some(m) = &extra.monotonic {
- let instants = util::instants_ident(name);
+ for (_, monotonic) in &app.monotonics {
+ let instants = util::monotonic_instants_ident(name, &monotonic.ident);
+ let instants = util::mark_internal_ident(&instants);
+ let monotonic_name = monotonic.ident.to_string();
- let tq = util::tq_ident();
+ let tq = util::tq_ident(&monotonic.ident.to_string());
+ let tq = util::mark_internal_ident(&tq);
let t = util::schedule_t_ident();
+ let m = &monotonic.ident;
+ let mono_type = &monotonic.ty;
+ let m_ident = util::monotonic_ident(&monotonic_name);
+ let m_ident = util::mark_internal_ident(&m_ident);
+ let m_isr = &monotonic.args.binds;
+ let enum_ = util::interrupt_ident();
+
+ if monotonic.args.default {
+ items.push(quote!(pub use #m::spawn_after;));
+ items.push(quote!(pub use #m::spawn_at;));
+ }
+
+ let (enable_interrupt, pend) = if &*m_isr.to_string() == "SysTick" {
+ (
+ quote!(core::mem::transmute::<_, cortex_m::peripheral::SYST>(())
+ .enable_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)),
+ )
+ };
+
+ let user_imports = &app.user_imports;
items.push(quote!(
- #(#cfgs)*
- pub fn schedule(
- instant: <#m as rtic::Monotonic>::Instant
- #(,#args)*
- ) -> Result<(), #ty> {
- unsafe {
- use rtic::Mutex as _;
- use rtic::mutex_prelude::*;
-
- let input = #tupled;
- if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.dequeue()) {
- #app_path::#inputs
- .get_unchecked_mut(usize::from(index))
- .as_mut_ptr()
- .write(input);
-
- #app_path::#instants
- .get_unchecked_mut(usize::from(index))
- .as_mut_ptr()
- .write(instant);
-
- let nr = rtic::export::NotReady {
- instant,
- index,
- task: #app_path::#t::#name,
- };
-
- rtic::export::interrupt::free(|_| #app_path::#tq.enqueue_unchecked(nr));
-
- Ok(())
+ /// Holds methods related to this monotonic
+ pub mod #m {
+ #(
+ #[allow(unused_imports)]
+ #user_imports
+ )*
+
+ #(#cfgs)*
+ /// Spawns the task after a set duration relative to the current time
+ ///
+ /// This will use the time `Instant::new(0)` as baseline if called in `#[init]`,
+ /// so if you use a non-resetable timer use `spawn_at` when in `#[init]`
+ pub fn spawn_after<D>(
+ duration: D
+ #(,#args)*
+ ) -> Result<(), #ty>
+ where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint,
+ D::T: Into<<#app_path::#mono_type as rtic::time::Clock>::T>,
+ {
+
+ let instant = if rtic::export::interrupt::free(|_| unsafe { #app_path::#m_ident.is_none() }) {
+ rtic::time::Instant::new(0)
} else {
- Err(input)
+ #app_path::#m::now()
+ };
+
+ spawn_at(instant + duration #(,#untupled)*)
+ }
+
+ #(#cfgs)*
+ /// Spawns the task at a fixed time instant
+ pub fn spawn_at(
+ instant: rtic::time::Instant<#app_path::#mono_type>
+ #(,#args)*
+ ) -> Result<(), #ty> {
+ unsafe {
+ let input = #tupled;
+ if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.dequeue()) {
+ #app_path::#inputs
+ .get_unchecked_mut(usize::from(index))
+ .as_mut_ptr()
+ .write(input);
+
+ #app_path::#instants
+ .get_unchecked_mut(usize::from(index))
+ .as_mut_ptr()
+ .write(instant);
+
+ let nr = rtic::export::NotReady {
+ instant,
+ index,
+ task: #app_path::#t::#name,
+ };
+
+ rtic::export::interrupt::free(|_|
+ if let Some(mono) = #app_path::#m_ident.as_mut() {
+ #app_path::#tq.enqueue_unchecked(
+ nr,
+ || #enable_interrupt,
+ || #pend,
+ mono)
+ } else {
+ // We can only use the timer queue if `init` has returned, and it
+ // writes the `Some(monotonic)` we are accessing here.
+ core::hint::unreachable_unchecked()
+ });
+
+ Ok(())
+ } else {
+ Err(input)
+ }
}
}
}));
diff --git a/macros/src/codegen/post_init.rs b/macros/src/codegen/post_init.rs
index 5545944d..96c5df80 100644
--- a/macros/src/codegen/post_init.rs
+++ b/macros/src/codegen/post_init.rs
@@ -1,6 +1,7 @@
-use proc_macro2::TokenStream as TokenStream2;
+use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::quote;
use rtic_syntax::ast::App;
+use syn::Index;
use crate::{analyze::Analysis, codegen::util};
@@ -12,7 +13,7 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
if !analysis.late_resources.is_empty() {
// BTreeSet wrapped in a vector
for name in analysis.late_resources.first().unwrap() {
- let mangled_name = util::mangle_ident(&name);
+ let mangled_name = util::mark_internal_ident(&name);
// If it's live
let cfgs = app.late_resources[name].cfgs.clone();
if analysis.locations.get(name).is_some() {
@@ -25,6 +26,19 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
}
}
+ for (i, (monotonic, _)) in app.monotonics.iter().enumerate() {
+ let idx = Index {
+ index: i as u32,
+ span: Span::call_site(),
+ };
+ stmts.push(quote!(monotonics.#idx.reset();));
+
+ // Store the monotonic
+ let name = util::monotonic_ident(&monotonic.to_string());
+ let name = util::mark_internal_ident(&name);
+ stmts.push(quote!(#name = Some(monotonics.#idx);));
+ }
+
// Enable the interrupts -- this completes the `init`-ialization phase
stmts.push(quote!(rtic::export::interrupt::enable();));
diff --git a/macros/src/codegen/pre_init.rs b/macros/src/codegen/pre_init.rs
index 969de84a..d5105445 100644
--- a/macros/src/codegen/pre_init.rs
+++ b/macros/src/codegen/pre_init.rs
@@ -8,6 +8,8 @@ use crate::{analyze::Analysis, check::Extra, codegen::util};
pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> {
let mut stmts = vec![];
+ let rt_err = util::rt_err_ident();
+
// Disable interrupts -- `init` must run with interrupts disabled
stmts.push(quote!(rtic::export::interrupt::disable();));
@@ -15,6 +17,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
for (name, task) in &app.software_tasks {
let cap = task.args.capacity;
let fq_ident = util::fq_ident(name);
+ let fq_ident = util::mark_internal_ident(&fq_ident);
stmts.push(quote!(
(0..#cap).for_each(|i| #fq_ident.enqueue_unchecked(i));
@@ -47,14 +50,14 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
let interrupt = util::interrupt_ident();
stmts.push(quote!(
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),
);
));
// NOTE unmask the interrupt *after* setting its priority: changing the priority of a pended
// 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
@@ -74,23 +77,48 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
);));
}
- // Initialize the SysTick if there exist a TimerQueue
- if extra.monotonic.is_some() {
- let priority = analysis.channels.keys().max().unwrap();
+ // Initialize monotonic's interrupts
+ for (_, monotonic) in app.monotonics.iter()
+ //.map(|(ident, monotonic)| (ident, &monotonic.args.priority, &monotonic.args.binds))
+ {
+ let priority = &monotonic.args.priority;
+ let binds = &monotonic.args.binds;
// Compile time assert that this priority is supported by the device
stmts.push(quote!(let _ = [(); ((1 << #nvic_prio_bits) - #priority as usize)];));
- stmts.push(quote!(core.SCB.set_priority(
- rtic::export::SystemHandler::SysTick,
- rtic::export::logical2hw(#priority, #nvic_prio_bits),
- );));
-
- stmts.push(quote!(
- core.SYST.set_clock_source(rtic::export::SystClkSource::Core);
- core.SYST.enable_counter();
- core.DCB.enable_trace();
- ));
+ let app_name = &app.name;
+ let app_path = quote! {crate::#app_name};
+ let mono_type = &monotonic.ty;
+
+ if &*binds.to_string() == "SysTick" {
+ stmts.push(quote!(
+ core.SCB.set_priority(
+ rtic::export::SystemHandler::SysTick,
+ rtic::export::logical2hw(#priority, #nvic_prio_bits),
+ );
+
+ // Always enable monotonic interrupts if they should never be off
+ if !<#mono_type as rtic::Monotonic>::DISABLE_INTERRUPT_ON_EMPTY_QUEUE {
+ core::mem::transmute::<_, cortex_m::peripheral::SYST>(())
+ .enable_interrupt();
+ }
+ ));
+ } 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::#binds,
+ rtic::export::logical2hw(#priority, #nvic_prio_bits),
+ );
+
+ // Always enable monotonic interrupts if they should never be off
+ if !<#mono_type as rtic::Monotonic>::DISABLE_INTERRUPT_ON_EMPTY_QUEUE {
+ rtic::export::NVIC::unmask(#app_path::#rt_err::#interrupt::#binds);
+ }
+ ));
+ }
}
// If there's no user `#[idle]` then optimize returning from interrupt handlers
diff --git a/macros/src/codegen/resources.rs b/macros/src/codegen/resources.rs
index 76871e59..fa52b86d 100644
--- a/macros/src/codegen/resources.rs
+++ b/macros/src/codegen/resources.rs
@@ -21,7 +21,7 @@ pub fn codegen(
for (name, res, expr, _) in app.resources(analysis) {
let cfgs = &res.cfgs;
let ty = &res.ty;
- let mangled_name = util::mangle_ident(&name);
+ let mangled_name = util::mark_internal_ident(&name);
{
let section = if expr.is_none() {
@@ -42,6 +42,7 @@ pub fn codegen(
let attrs = &res.attrs;
mod_app.push(quote!(
#[allow(non_upper_case_globals)]
+ #[doc(hidden)]
#(#attrs)*
#(#cfgs)*
#section
diff --git a/macros/src/codegen/resources_struct.rs b/macros/src/codegen/resources_struct.rs
index bffe9431..8ed8a291 100644
--- a/macros/src/codegen/resources_struct.rs
+++ b/macros/src/codegen/resources_struct.rs
@@ -31,7 +31,7 @@ pub fn codegen(ctxt: Context, needs_lt: &mut bool, app: &App) -> (TokenStream2,
None
};
let ty = &res.ty;
- let mangled_name = util::mangle_ident(&name);
+ let mangled_name = util::mark_internal_ident(&name);
// let ownership = &analysis.ownerships[name];
let r_prop = &res.properties;
@@ -112,6 +112,7 @@ pub fn codegen(ctxt: Context, needs_lt: &mut bool, app: &App) -> (TokenStream2,
let doc = format!("Resources `{}` has access to", ctxt.ident(app));
let ident = util::resources_ident(ctxt, app);
+ let ident = util::mark_internal_ident(&ident);
let item = quote!(
#[allow(non_snake_case)]
#[doc = #doc]
diff --git a/macros/src/codegen/software_tasks.rs b/macros/src/codegen/software_tasks.rs
index 9cb5f7a9..a39fe4cc 100644
--- a/macros/src/codegen/software_tasks.rs
+++ b/macros/src/codegen/software_tasks.rs
@@ -37,6 +37,7 @@ pub fn codegen(
// Create free queues and inputs / instants buffers
let fq = util::fq_ident(name);
+ let fq = util::mark_internal_ident(&fq);
let (fq_ty, fq_expr, mk_uninit): (_, _, Box<dyn Fn() -> Option<_>>) = {
(
@@ -48,8 +49,9 @@ pub fn codegen(
)
};
mod_app.push(quote!(
- /// Queue version of a free-list that keeps track of empty slots in
- /// the following buffers
+ // /// Queue version of a free-list that keeps track of empty slots in
+ // /// the following buffers
+ #[doc(hidden)]
static mut #fq: #fq_ty = #fq_expr;
));
@@ -57,24 +59,29 @@ pub fn codegen(
.map(|_| quote!(core::mem::MaybeUninit::uninit()))
.collect::<Vec<_>>();
- if let Some(m) = &extra.monotonic {
- let instants = util::instants_ident(name);
+ for (_, monotonic) in &app.monotonics {
+ let instants = util::monotonic_instants_ident(name, &monotonic.ident);
+ let instants = util::mark_internal_ident(&instants);
+ let mono_type = &monotonic.ty;
let uninit = mk_uninit();
mod_app.push(quote!(
#uninit
- /// Buffer that holds the instants associated to the inputs of a task
+ // /// Buffer that holds the instants associated to the inputs of a task
+ #[doc(hidden)]
static mut #instants:
- [core::mem::MaybeUninit<<#m as rtic::Monotonic>::Instant>; #cap_lit] =
+ [core::mem::MaybeUninit<rtic::time::Instant<#mono_type>>; #cap_lit] =
[#(#elems,)*];
));
}
let uninit = mk_uninit();
let inputs_ident = util::inputs_ident(name);
+ let inputs_ident = util::mark_internal_ident(&inputs_ident);
mod_app.push(quote!(
#uninit
- /// Buffer that holds the inputs of a task
+ // /// Buffer that holds the inputs of a task
+ #[doc(hidden)]
static mut #inputs_ident: [core::mem::MaybeUninit<#input_ty>; #cap_lit] =
[#(#elems,)*];
));
diff --git a/macros/src/codegen/timer_queue.rs b/macros/src/codegen/timer_queue.rs
index fa2c7b36..82d0ac98 100644
--- a/macros/src/codegen/timer_queue.rs
+++ b/macros/src/codegen/timer_queue.rs
@@ -5,10 +5,10 @@ use rtic_syntax::ast::App;
use crate::{analyze::Analysis, check::Extra, codegen::util};
/// Generates timer queues and timer queue handlers
-pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> {
+pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStream2> {
let mut items = vec![];
- if let Some(m) = &extra.monotonic {
+ if !app.monotonics.is_empty() {
let t = util::schedule_t_ident();
// Enumeration of `schedule`-able tasks
@@ -26,9 +26,10 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
})
.collect::<Vec<_>>();
- let doc = "Tasks that can be scheduled".to_string();
+ // let doc = "Tasks that can be scheduled".to_string();
items.push(quote!(
- #[doc = #doc]
+ // #[doc = #doc]
+ #[doc(hidden)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
enum #t {
@@ -36,32 +37,54 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
}
));
}
+ }
- let tq = util::tq_ident();
+ for (_, monotonic) in &app.monotonics {
+ let monotonic_name = monotonic.ident.to_string();
+ let tq = util::tq_ident(&monotonic_name);
+ let tq = util::mark_internal_ident(&tq);
+ let t = util::schedule_t_ident();
+ let mono_type = &monotonic.ty;
+ let m_ident = util::monotonic_ident(&monotonic_name);
+ let m_ident = util::mark_internal_ident(&m_ident);
+ let app_name = &app.name;
+ let app_path = quote! {crate::#app_name};
- // Static variable and resource proxy
+ // Static variables and resource proxy
{
- let doc = "Timer queue".to_string();
+ // let doc = &format!("Timer queue for {}", monotonic_name);
let cap = app
.software_tasks
.iter()
.map(|(_name, task)| task.args.capacity)
.sum();
let n = util::capacity_typenum(cap, false);
- let tq_ty = quote!(rtic::export::TimerQueue<#m, #t, #n>);
+ let tq_ty = quote!(rtic::export::TimerQueue<#mono_type, #t, #n>);
items.push(quote!(
- #[doc = #doc]
+ #[doc(hidden)]
static mut #tq: #tq_ty = rtic::export::TimerQueue(
rtic::export::BinaryHeap(
rtic::export::iBinaryHeap::new()
)
);
));
+
+ let mono = util::monotonic_ident(&monotonic_name);
+ let mono = util::mark_internal_ident(&mono);
+ // let doc = &format!("Storage for {}", monotonic_name);
+
+ items.push(quote!(
+ #[doc(hidden)]
+ static mut #mono: Option<#mono_type> = None;
+ ));
}
// Timer queue handler
{
+ let enum_ = util::interrupt_ident();
+ let rt_err = util::rt_err_ident();
+
let arms = app
.software_tasks
.iter()
@@ -69,13 +92,15 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
let cfgs = &task.cfgs;
let priority = task.args.priority;
let rq = util::rq_ident(priority);
+ let rq = util::mark_internal_ident(&rq);
let rqt = util::spawn_t_ident(priority);
- let enum_ = util::interrupt_ident();
+
+ // The interrupt that runs the task dispatcher
let interrupt = &analysis.interrupts.get(&priority).expect("RTIC-ICE: interrupt not found").0;
let pend = {
quote!(
- rtic::pend(you_must_enable_the_rt_feature_for_the_pac_in_your_cargo_toml::#enum_::#interrupt);
+ rtic::pend(#rt_err::#enum_::#interrupt);
)
};
@@ -90,21 +115,39 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
})
.collect::<Vec<_>>();
- let sys_tick = util::suffixed("SysTick");
+ let bound_interrupt = &monotonic.args.binds;
+ let disable_isr = if &*bound_interrupt.to_string() == "SysTick" {
+ quote!(core::mem::transmute::<_, cortex_m::peripheral::SYST>(()).disable_interrupt())
+ } else {
+ quote!(rtic::export::NVIC::mask(#rt_err::#enum_::#bound_interrupt))
+ };
+
items.push(quote!(
#[no_mangle]
- unsafe fn #sys_tick() {
- use rtic::Mutex as _;
+ #[allow(non_snake_case)]
+ unsafe fn #bound_interrupt() {
- while let Some((task, index)) = rtic::export::interrupt::free(|_| #tq.dequeue())
+ while let Some((task, index)) = rtic::export::interrupt::free(|_|
+ if let Some(mono) = #app_path::#m_ident.as_mut() {
+ #tq.dequeue(|| #disable_isr, mono)
+ } else {
+ // We can only use the timer queue if `init` has returned, and it
+ // writes the `Some(monotonic)` we are accessing here.
+ core::hint::unreachable_unchecked()
+ })
{
match task {
#(#arms)*
}
}
+
+ rtic::export::interrupt::free(|_| if let Some(mono) = #app_path::#m_ident.as_mut() {
+ mono.on_interrupt();
+ });
}
));
}
}
+
items
}
diff --git a/macros/src/codegen/util.rs b/macros/src/codegen/util.rs
index fb8f1a84..6589f62d 100644
--- a/macros/src/codegen/util.rs
+++ b/macros/src/codegen/util.rs
@@ -77,8 +77,11 @@ pub fn inputs_ident(task: &Ident) -> Ident {
}
/// Generates an identifier for the `INSTANTS` buffer (`schedule` API)
-pub fn instants_ident(task: &Ident) -> Ident {
- Ident::new(&format!("{}_INSTANTS", task), Span::call_site())
+pub fn monotonic_instants_ident(task: &Ident, monotonic: &Ident) -> Ident {
+ Ident::new(
+ &format!("{}_{}_INSTANTS", task, monotonic),
+ Span::call_site(),
+ )
}
pub fn interrupt_ident() -> Ident {
@@ -103,16 +106,8 @@ pub fn is_exception(name: &Ident) -> bool {
)
}
-/// Generates a pre-reexport identifier for the "late resources" struct
-pub fn late_resources_ident(init: &Ident) -> Ident {
- Ident::new(
- &format!("{}LateResources", init.to_string()),
- Span::call_site(),
- )
-}
-
-/// Mangle an ident
-pub fn mangle_ident(ident: &Ident) -> Ident {
+/// Mark an ident as internal
+pub fn mark_internal_ident(ident: &Ident) -> Ident {
Ident::new(
&format!("__rtic_internal_{}", ident.to_string()),
Span::call_site(),
@@ -222,7 +217,7 @@ pub fn rq_ident(priority: u8) -> Ident {
/// Generates an identifier for the `enum` of `schedule`-able tasks
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
@@ -233,14 +228,26 @@ pub fn spawn_t_ident(priority: u8) -> Ident {
Ident::new(&format!("P{}_T", priority), Span::call_site())
}
+/// Suffixed identifier
pub fn suffixed(name: &str) -> Ident {
let span = Span::call_site();
Ident::new(name, span)
}
/// Generates an identifier for a timer queue
-///
-/// At most there is one timer queue
-pub fn tq_ident() -> Ident {
- Ident::new(&"TQ".to_string(), Span::call_site())
+pub fn tq_ident(name: &str) -> Ident {
+ Ident::new(&format!("TQ_{}", name), Span::call_site())
+}
+
+/// Generates an identifier for monotonic timer storage
+pub fn monotonic_ident(name: &str) -> Ident {
+ Ident::new(&format!("MONOTONIC_STORAGE_{}", 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(),
+ )
}
diff --git a/macros/src/lib.rs b/macros/src/lib.rs
index dc37eaea..6ac7e2a4 100644
--- a/macros/src/lib.rs
+++ b/macros/src/lib.rs
@@ -1,4 +1,4 @@
-#![deny(warnings)]
+// #![deny(warnings)]
extern crate proc_macro;
@@ -20,7 +20,7 @@ mod tests;
#[proc_macro_attribute]
pub fn app(args: TokenStream, input: TokenStream) -> TokenStream {
let mut settings = Settings::default();
- settings.optimize_priorities = true;
+ settings.optimize_priorities = false;
settings.parse_binds = true;
settings.parse_extern_interrupt = true;
diff --git a/src/export.rs b/src/export.rs
index 72d954ab..91a4a5ef 100644
--- a/src/export.rs
+++ b/src/export.rs
@@ -16,6 +16,7 @@ pub use cortex_m::{
use heapless::spsc::SingleCore;
pub use heapless::{consts, i::Queue as iQueue, spsc::Queue};
pub use heapless::{i::BinaryHeap as iBinaryHeap, BinaryHeap};
+pub use rtic_monotonic as monotonic;
pub type SCFQ<N> = Queue<u8, N, u8, SingleCore>;
pub type SCRQ<T, N> = Queue<(T, u8), N, u8, SingleCore>;
@@ -112,6 +113,13 @@ where
{
}
+#[inline(always)]
+pub fn assert_monotonic<T>()
+where
+ T: monotonic::Monotonic,
+{
+}
+
/// Lock the resource proxy by setting the BASEPRI
/// and running the closure with interrupt::free
///
diff --git a/src/lib.rs b/src/lib.rs
index 360ea91d..82207399 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -35,123 +35,16 @@
#![deny(warnings)]
#![no_std]
-use core::ops::Sub;
-
-use cortex_m::{
- interrupt::InterruptNumber,
- peripheral::{CBP, CPUID, DCB, DWT, FPB, FPU, ITM, MPU, NVIC, SCB, TPIU},
-};
+use cortex_m::{interrupt::InterruptNumber, peripheral::NVIC};
pub use cortex_m_rtic_macros::app;
pub use rtic_core::{prelude as mutex_prelude, Exclusive, Mutex};
+pub use rtic_monotonic::{self, embedded_time as time, Monotonic};
-#[cfg(armv7m)]
-pub mod cyccnt;
#[doc(hidden)]
pub mod export;
#[doc(hidden)]
mod tq;
-/// `cortex_m::Peripherals` minus `SYST`
-#[allow(non_snake_case)]
-pub struct Peripherals {
- /// Cache and branch predictor maintenance operations (not present on Cortex-M0 variants)
- pub CBP: CBP,
-
- /// CPUID
- pub CPUID: CPUID,
-
- /// Debug Control Block
- pub DCB: DCB,
-
- /// Data Watchpoint and Trace unit
- pub DWT: DWT,
-
- /// Flash Patch and Breakpoint unit (not present on Cortex-M0 variants)
- pub FPB: FPB,
-
- /// Floating Point Unit (only present on `thumbv7em-none-eabihf`)
- pub FPU: FPU,
-
- /// Instrumentation Trace Macrocell (not present on Cortex-M0 variants)
- pub ITM: ITM,
-
- /// Memory Protection Unit
- pub MPU: MPU,
-
- /// Nested Vector Interrupt Controller
- pub NVIC: NVIC,
-
- /// System Control Block
- pub SCB: SCB,
-
- // SysTick: System Timer
- // pub SYST: SYST,
- /// Trace Port Interface Unit (not present on Cortex-M0 variants)
- pub TPIU: TPIU,
-}
-
-impl From<cortex_m::Peripherals> for Peripherals {
- fn from(p: cortex_m::Peripherals) -> Self {
- Self {
- CBP: p.CBP,
- CPUID: p.CPUID,
- DCB: p.DCB,
- DWT: p.DWT,
- FPB: p.FPB,
- FPU: p.FPU,
- ITM: p.ITM,
- MPU: p.MPU,
- NVIC: p.NVIC,
- SCB: p.SCB,
- TPIU: p.TPIU,
- }
- }
-}
-
-/// A fraction
-pub struct Fraction {
- /// The numerator
- pub numerator: u32,
-
- /// The denominator
- pub denominator: u32,
-}
-
-/// A monotonic clock / counter
-pub trait Monotonic {
- /// A measurement of this clock, use `CYCCNT` as a reference implementation for `Instant`.
- /// Note that the Instant must be a signed value such as `i32`.
- type Instant: Copy + Ord + Sub;
-
- /// The ratio between the system timer (SysTick) frequency and this clock frequency, i.e.
- /// `Monotonic clock * Fraction = System clock`
- ///
- /// The ratio must be expressed in *reduced* `Fraction` form to prevent overflows. That is
- /// `2 / 3` instead of `4 / 6`
- fn ratio() -> Fraction;
-
- /// Returns the current time
- ///
- /// # Correctness
- ///
- /// This function is *allowed* to return nonsensical values if called before `reset` is invoked
- /// by the runtime. Therefore application authors should *not* call this function during the
- /// `#[init]` phase.
- fn now() -> Self::Instant;
-
- /// Resets the counter to *zero*
- ///
- /// # Safety
- ///
- /// This function will be called *exactly once* by the RTIC runtime after `#[init]` returns and
- /// before tasks can start; this is also the case in multi-core applications. User code must
- /// *never* call this function.
- unsafe fn reset();
-
- /// A `Self::Instant` that represents a count of *zero*
- fn zero() -> Self::Instant;
-}
-
/// Sets the given `interrupt` as pending
///
/// This is a convenience function around
diff --git a/src/tq.rs b/src/tq.rs
index b2a84c85..063bbd8e 100644
--- a/src/tq.rs
+++ b/src/tq.rs
@@ -1,28 +1,21 @@
-use core::{
- cmp::{self, Ordering},
- convert::TryInto,
- mem,
- ops::Sub,
+use crate::{
+ time::{Clock, Instant},
+ Monotonic,
};
-
-use cortex_m::peripheral::{SCB, SYST};
+use core::cmp::Ordering;
use heapless::{binary_heap::Min, ArrayLength, BinaryHeap};
-use crate::Monotonic;
-
-pub struct TimerQueue<M, T, N>(pub BinaryHeap<NotReady<M, T>, N, Min>)
+pub struct TimerQueue<Mono, Task, N>(pub BinaryHeap<NotReady<Mono, Task>, N, Min>)
where
- M: Monotonic,
- <M::Instant as Sub>::Output: TryInto<u32>,
- N: ArrayLength<NotReady<M, T>>,
- T: Copy;
+ Mono: Monotonic,
+ N: ArrayLength<NotReady<Mono, Task>>,
+ Task: Copy;
-impl<M, T, N> TimerQueue<M, T, N>
+impl<Mono, Task, N> TimerQueue<Mono, Task, N>
where
- M: Monotonic,
- <M::Instant as Sub>::Output: TryInto<u32>,
- N: ArrayLength<NotReady<M, T>>,
- T: Copy,
+ Mono: Monotonic,
+ N: ArrayLength<NotReady<Mono, Task>>,
+ Task: Copy,
{
/// # Safety
///
@@ -31,7 +24,16 @@ where
///
/// Enqueue a task without checking if it is full
#[inline]
- pub unsafe fn enqueue_unchecked(&mut self, nr: NotReady<M, T>) {
+ pub unsafe fn enqueue_unchecked<F1, F2>(
+ &mut self,
+ nr: NotReady<Mono, Task>,
+ enable_interrupt: F1,
+ pend_handler: F2,
+ mono: &mut Mono,
+ ) where
+ F1: FnOnce(),
+ F2: FnOnce(),
+ {
let mut is_empty = true;
// Check if the top contains a non-empty element and if that element is
// greater than nr
@@ -44,111 +46,118 @@ where
})
.unwrap_or(true);
if if_heap_max_greater_than_nr {
- if is_empty {
- mem::transmute::<_, SYST>(()).enable_interrupt();
+ if Mono::DISABLE_INTERRUPT_ON_EMPTY_QUEUE && is_empty {
+ // mem::transmute::<_, SYST>(()).enable_interrupt();A
+ mono.enable_timer();
+ enable_interrupt();
}
// Set SysTick pending
- SCB::set_pendst();
+ // SCB::set_pendst();
+ pend_handler();
}
self.0.push_unchecked(nr);
}
+ /// Check if the timer queue is empty.
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.0.is_empty()
+ }
+
+ #[inline]
+ fn unwrapper<T, E>(val: Result<T, E>) -> T {
+ if let Ok(v) = val {
+ v
+ } else {
+ unreachable!("Your monotonic is not infallible")
+ }
+ }
+
/// Dequeue a task from the TimerQueue
#[inline]
- pub fn dequeue(&mut self) -> Option<(T, u8)> {
- unsafe {
- if let Some(instant) = self.0.peek().map(|p| p.instant) {
- let now = M::now();
+ pub fn dequeue<F>(&mut self, disable_interrupt: F, mono: &mut Mono) -> Option<(Task, u8)>
+ where
+ F: FnOnce(),
+ {
+ mono.clear_compare_flag();
+
+ if let Some(instant) = self.0.peek().map(|p| p.instant) {
+ if instant <= Self::unwrapper(Clock::try_now(mono)) {
+ // task became ready
+ let nr = unsafe { self.0.pop_unchecked() };
+
+ Some((nr.task, nr.index))
+ } else {
+ // Set compare
+ mono.set_compare(&instant);
- if instant < now {
- // task became ready
- let nr = self.0.pop_unchecked();
+ // Double check that the instant we set is really in the future, else
+ // dequeue. If the monotonic is fast enough it can happen that from the
+ // read of now to the set of the compare, the time can overflow. This is to
+ // guard against this.
+ if instant <= Self::unwrapper(Clock::try_now(mono)) {
+ let nr = unsafe { self.0.pop_unchecked() };
Some((nr.task, nr.index))
} else {
- // set a new timeout
- const MAX: u32 = 0x00ffffff;
-
- let ratio = M::ratio();
- let dur = match (instant - now).try_into().ok().and_then(|x| {
- x.checked_mul(ratio.numerator)
- .map(|x| x / ratio.denominator)
- }) {
- None => MAX,
-
- // ARM Architecture Reference Manual says:
- // "Setting SYST_RVR to zero has the effect of
- // disabling the SysTick counter independently
- // of the counter enable bit."
- Some(0) => 1,
-
- Some(x) => cmp::min(MAX, x),
- };
- mem::transmute::<_, SYST>(()).set_reload(dur);
-
- // Start counting down from the new reload
- mem::transmute::<_, SYST>(()).clear_current();
-
None
}
- } else {
- // The queue is empty
- mem::transmute::<_, SYST>(()).disable_interrupt();
-
- None
}
+ } else {
+ // The queue is empty, disable the interrupt.
+ if Mono::DISABLE_INTERRUPT_ON_EMPTY_QUEUE {
+ disable_interrupt();
+ mono.disable_timer();
+ }
+
+ None
}
}
}
-pub struct NotReady<M, T>
+pub struct NotReady<Mono, Task>
where
- T: Copy,
- M: Monotonic,
- <M::Instant as Sub>::Output: TryInto<u32>,
+ Task: Copy,
+ Mono: Monotonic,
{
pub index: u8,
- pub instant: M::Instant,
- pub task: T,
+ pub instant: Instant<Mono>,
+ pub task: Task,
}
-impl<M, T> Eq for NotReady<M, T>
+impl<Mono, Task> Eq for NotReady<Mono, Task>
where
- T: Copy,
- M: Monotonic,
- <M::Instant as Sub>::Output: TryInto<u32>,
+ Task: Copy,
+ Mono: Monotonic,
{
}
-impl<M, T> Ord for NotReady<M, T>
+impl<Mono, Task> Ord for NotReady<Mono, Task>
where
- T: Copy,
- M: Monotonic,
- <M::Instant as Sub>::Output: TryInto<u32>,
+ Task: Copy,
+ Mono: Monotonic,
{
fn cmp(&self, other: &Self) -> Ordering {
self.instant.cmp(&other.instant)
}
}
-impl<M, T> PartialEq for NotReady<M, T>
+impl<Mono, Task> PartialEq for NotReady<Mono, Task>
where
- T: Copy,
- M: Monotonic,
- <M::Instant as Sub>::Output: TryInto<u32>,
+ Task: Copy,
+ Mono: Monotonic,
{
fn eq(&self, other: &Self) -> bool {
self.instant == other.instant
}
}
-impl<M, T> PartialOrd for NotReady<M, T>
+impl<Mono, Task> PartialOrd for NotReady<Mono, Task>
where
- T: Copy,
- M: Monotonic,
- <M::Instant as Sub>::Output: TryInto<u32>,
+ Task: Copy,
+ Mono: Monotonic,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(&other))
diff --git a/tests/single.rs b/tests/tests.rs
index b5d480c7..9fb88a1b 100644
--- a/tests/single.rs
+++ b/tests/tests.rs
@@ -3,5 +3,5 @@ use trybuild::TestCases;
#[test]
fn ui() {
let t = TestCases::new();
- t.compile_fail("ui/single/*.rs");
+ t.compile_fail("ui/*.rs");
}
diff --git a/ui/single/exception-invalid.rs b/ui/exception-invalid.rs
index 04d9bc75..04d9bc75 100644
--- a/ui/single/exception-invalid.rs
+++ b/ui/exception-invalid.rs
diff --git a/ui/single/exception-invalid.stderr b/ui/exception-invalid.stderr
index 90213768..90213768 100644
--- a/ui/single/exception-invalid.stderr
+++ b/ui/exception-invalid.stderr
diff --git a/ui/single/extern-interrupt-not-enough.rs b/ui/extern-interrupt-not-enough.rs
index f2624036..f2624036 100644
--- a/ui/single/extern-interrupt-not-enough.rs
+++ b/ui/extern-interrupt-not-enough.rs
diff --git a/ui/single/extern-interrupt-not-enough.stderr b/ui/extern-interrupt-not-enough.stderr
index 14f8fe9c..14f8fe9c 100644
--- a/ui/single/extern-interrupt-not-enough.stderr
+++ b/ui/extern-interrupt-not-enough.stderr
diff --git a/ui/single/extern-interrupt-used.rs b/ui/extern-interrupt-used.rs
index 240e7363..240e7363 100644
--- a/ui/single/extern-interrupt-used.rs
+++ b/ui/extern-interrupt-used.rs
diff --git a/ui/single/extern-interrupt-used.stderr b/ui/extern-interrupt-used.stderr
index b4d8d160..b4d8d160 100644
--- a/ui/single/extern-interrupt-used.stderr
+++ b/ui/extern-interrupt-used.stderr
diff --git a/ui/single/local-cfg-task-local-err.rs b/ui/local-cfg-task-local-err.rs
index 412f6142..d4752edf 100644
--- a/ui/single/local-cfg-task-local-err.rs
+++ b/ui/local-cfg-task-local-err.rs
@@ -26,15 +26,18 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
- init::LateResources {
- #[cfg(feature = "feature_l2")]
- l2: 2,
- #[cfg(not(feature = "feature_l2"))]
- l2: 5,
- }
+ (
+ init::LateResources {
+ #[cfg(feature = "feature_l2")]
+ l2: 2,
+ #[cfg(not(feature = "feature_l2"))]
+ l2: 5,
+ },
+ init::Monotonics(),
+ )
}
// l1 ok (task_local)
diff --git a/ui/single/local-cfg-task-local-err.stderr b/ui/local-cfg-task-local-err.stderr
index 9a84ead4..73dfaeb6 100644
--- a/ui/single/local-cfg-task-local-err.stderr
+++ b/ui/local-cfg-task-local-err.stderr
@@ -5,15 +5,15 @@ error: task local resource "l2" is used by multiple tasks
| ^^
error: task local resource "l2" is used by task "uart0" with priority 1
- --> $DIR/local-cfg-task-local-err.rs:51:39
+ --> $DIR/local-cfg-task-local-err.rs:54:39
|
-51 | #[cfg(feature = "feature_l2")]l2,
+54 | #[cfg(feature = "feature_l2")]l2,
| ^^
error: task local resource "l2" is used by task "uart1" with priority 1
- --> $DIR/local-cfg-task-local-err.rs:60:44
+ --> $DIR/local-cfg-task-local-err.rs:63:44
|
-60 | #[cfg(not(feature = "feature_l2"))]l2
+63 | #[cfg(not(feature = "feature_l2"))]l2
| ^^
warning: unused import: `cortex_m_semihosting::debug`
diff --git a/ui/single/local-err.rs b/ui/local-err.rs
index 0fe98a4b..7ebfc069 100644
--- a/ui/single/local-err.rs
+++ b/ui/local-err.rs
@@ -39,10 +39,10 @@ mod app {
}
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
- init::LateResources { e2: 2, l2: 2 }
+ (init::LateResources { e2: 2, l2: 2 }, init::Monotonics())
}
// `shared` cannot be accessed from this context
diff --git a/ui/single/local-err.stderr b/ui/local-err.stderr
index 88369d8e..88369d8e 100644
--- a/ui/single/local-err.stderr
+++ b/ui/local-err.stderr
diff --git a/ui/single/locals-cfg.rs b/ui/locals-cfg.rs
index 3bfdaa1e..170d3026 100644
--- a/ui/single/locals-cfg.rs
+++ b/ui/locals-cfg.rs
@@ -1,16 +1,17 @@
#![no_main]
-use panic_halt as _;
+
+use panic_semihosting as _;
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
mod app {
#[init]
- fn init(_: init::Context) -> init::LateResources {
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
#[cfg(never)]
static mut FOO: u32 = 0;
FOO;
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[idle]
diff --git a/ui/locals-cfg.stderr b/ui/locals-cfg.stderr
new file mode 100644
index 00000000..33a80754
--- /dev/null
+++ b/ui/locals-cfg.stderr
@@ -0,0 +1,29 @@
+error[E0425]: cannot find value `FOO` in this scope
+ --> $DIR/locals-cfg.rs:12:9
+ |
+12 | FOO;
+ | ^^^ not found in this scope
+
+error[E0425]: cannot find value `FOO` in this scope
+ --> $DIR/locals-cfg.rs:22:9
+ |
+22 | FOO;
+ | ^^^ not found in this scope
+
+error[E0425]: cannot find value `FOO` in this scope
+ --> $DIR/locals-cfg.rs:32:9
+ |
+32 | FOO;
+ | ^^^ not found in this scope
+
+error[E0425]: cannot find value `FOO` in this scope
+ --> $DIR/locals-cfg.rs:40:9
+ |
+40 | FOO;
+ | ^^^ not found in this scope
+
+error[E0425]: cannot find value `FOO` in this scope
+ --> $DIR/locals-cfg.rs:48:9
+ |
+48 | FOO;
+ | ^^^ not found in this scope
diff --git a/ui/single/resources-cfg.rs b/ui/resources-cfg.rs
index 2ba65a04..c802a46f 100644
--- a/ui/single/resources-cfg.rs
+++ b/ui/resources-cfg.rs
@@ -1,5 +1,6 @@
#![no_main]
-use panic_halt as _;
+
+use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
@@ -43,14 +44,14 @@ mod app {
}
#[init(resources = [o1, o4, o5, o6, s3])]
- fn init(c: init::Context) -> init::LateResources {
+ fn init(c: init::Context) -> (init::LateResources, init::Monotonics) {
c.resources.o1;
c.resources.o4;
c.resources.o5;
c.resources.o6;
c.resources.s3;
- init::LateResources {}
+ (init::LateResources {}, init::Monotonics())
}
#[idle(resources = [o2, &o4, s1, &s3])]
diff --git a/ui/resources-cfg.stderr b/ui/resources-cfg.stderr
new file mode 100644
index 00000000..03612de0
--- /dev/null
+++ b/ui/resources-cfg.stderr
@@ -0,0 +1,119 @@
+error[E0609]: no field `o1` on type `__rtic_internal_initResources<'_>`
+ --> $DIR/resources-cfg.rs:48:21
+ |
+48 | c.resources.o1;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
+
+error[E0609]: no field `o4` on type `__rtic_internal_initResources<'_>`
+ --> $DIR/resources-cfg.rs:49:21
+ |
+49 | c.resources.o4;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
+
+error[E0609]: no field `o5` on type `__rtic_internal_initResources<'_>`
+ --> $DIR/resources-cfg.rs:50:21
+ |
+50 | c.resources.o5;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
+
+error[E0609]: no field `o6` on type `__rtic_internal_initResources<'_>`
+ --> $DIR/resources-cfg.rs:51:21
+ |
+51 | c.resources.o6;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
+
+error[E0609]: no field `s3` on type `__rtic_internal_initResources<'_>`
+ --> $DIR/resources-cfg.rs:52:21
+ |
+52 | c.resources.s3;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
+
+error[E0609]: no field `o2` on type `__rtic_internal_idleResources<'_>`
+ --> $DIR/resources-cfg.rs:59:21
+ |
+59 | c.resources.o2;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
+
+error[E0609]: no field `o4` on type `__rtic_internal_idleResources<'_>`
+ --> $DIR/resources-cfg.rs:60:21
+ |
+60 | c.resources.o4;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
+
+error[E0609]: no field `s1` on type `__rtic_internal_idleResources<'_>`
+ --> $DIR/resources-cfg.rs:61:21
+ |
+61 | c.resources.s1;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
+
+error[E0609]: no field `s3` on type `__rtic_internal_idleResources<'_>`
+ --> $DIR/resources-cfg.rs:62:21
+ |
+62 | c.resources.s3;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
+
+error[E0609]: no field `o3` on type `__rtic_internal_uart0Resources<'_>`
+ --> $DIR/resources-cfg.rs:69:21
+ |
+69 | c.resources.o3;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
+
+error[E0609]: no field `s1` on type `__rtic_internal_uart0Resources<'_>`
+ --> $DIR/resources-cfg.rs:70:21
+ |
+70 | c.resources.s1;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
+
+error[E0609]: no field `s2` on type `__rtic_internal_uart0Resources<'_>`
+ --> $DIR/resources-cfg.rs:71:21
+ |
+71 | c.resources.s2;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
+
+error[E0609]: no field `s3` on type `__rtic_internal_uart0Resources<'_>`
+ --> $DIR/resources-cfg.rs:72:21
+ |
+72 | c.resources.s3;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
+
+error[E0609]: no field `s2` on type `__rtic_internal_uart1Resources<'_>`
+ --> $DIR/resources-cfg.rs:77:21
+ |
+77 | c.resources.s2;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
+
+error[E0609]: no field `o5` on type `__rtic_internal_uart1Resources<'_>`
+ --> $DIR/resources-cfg.rs:78:21
+ |
+78 | c.resources.o5;
+ | ^^ unknown field
+ |
+ = note: available fields are: `__marker__`
diff --git a/ui/single/exception-systick-used.rs b/ui/single/exception-systick-used.rs
deleted file mode 100644
index 9e94c739..00000000
--- a/ui/single/exception-systick-used.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-#![no_main]
-
-#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
-mod app {
- #[task(binds = SysTick)]
- fn sys_tick(_: sys_tick::Context) {}
-}
diff --git a/ui/single/exception-systick-used.stderr b/ui/single/exception-systick-used.stderr
deleted file mode 100644
index 23b6dc4a..00000000
--- a/ui/single/exception-systick-used.stderr
+++ /dev/null
@@ -1,5 +0,0 @@
-error: this exception can't be used because it's being used by the runtime
- --> $DIR/exception-systick-used.rs:6:8
- |
-6 | fn sys_tick(_: sys_tick::Context) {}
- | ^^^^^^^^
diff --git a/ui/single/locals-cfg.stderr b/ui/single/locals-cfg.stderr
deleted file mode 100644
index 47992b3e..00000000
--- a/ui/single/locals-cfg.stderr
+++ /dev/null
@@ -1,35 +0,0 @@
-error[E0425]: cannot find value `FOO` in this scope
- --> $DIR/locals-cfg.rs:11:9
- |
-11 | FOO;
- | ^^^ not found in this scope
-
-error[E0425]: cannot find value `FOO` in this scope
- --> $DIR/locals-cfg.rs:21:9
- |
-21 | FOO;
- | ^^^ not found in this scope
-
-error[E0425]: cannot find value `FOO` in this scope
- --> $DIR/locals-cfg.rs:31:9
- |
-31 | FOO;
- | ^^^ not found in this scope
-
-error[E0425]: cannot find value `FOO` in this scope
- --> $DIR/locals-cfg.rs:39:9
- |
-39 | FOO;
- | ^^^ not found in this scope
-
-error[E0425]: cannot find value `FOO` in this scope
- --> $DIR/locals-cfg.rs:47:9
- |
-47 | FOO;
- | ^^^ not found in this scope
-
-error: duplicate lang item in crate `panic_halt` (which `$CRATE` depends on): `panic_impl`.
- |
- = note: the lang item is first defined in crate `std` (which `$CRATE` depends on)
- = note: first definition in `std` loaded from /usr/share/rust/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-e12de7683a34c500.rlib
- = note: second definition in `panic_halt` loaded from $DIR/target/tests/target/x86_64-unknown-linux-gnu/debug/deps/libpanic_halt-f6dc7d4a3dd7a21d.rmeta
diff --git a/ui/single/resources-cfg.stderr b/ui/single/resources-cfg.stderr
deleted file mode 100644
index 39f2c1aa..00000000
--- a/ui/single/resources-cfg.stderr
+++ /dev/null
@@ -1,125 +0,0 @@
-error: duplicate lang item in crate `panic_halt` (which `$CRATE` depends on): `panic_impl`.
- |
- = note: the lang item is first defined in crate `std` (which `$CRATE` depends on)
- = note: first definition in `std` loaded from /usr/share/rust/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-e12de7683a34c500.rlib
- = note: second definition in `panic_halt` loaded from $DIR/target/tests/target/x86_64-unknown-linux-gnu/debug/deps/libpanic_halt-f6dc7d4a3dd7a21d.rmeta
-
-error[E0609]: no field `o1` on type `initResources<'_>`
- --> $DIR/resources-cfg.rs:47:21
- |
-47 | c.resources.o1;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
-
-error[E0609]: no field `o4` on type `initResources<'_>`
- --> $DIR/resources-cfg.rs:48:21
- |
-48 | c.resources.o4;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
-
-error[E0609]: no field `o5` on type `initResources<'_>`
- --> $DIR/resources-cfg.rs:49:21
- |
-49 | c.resources.o5;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
-
-error[E0609]: no field `o6` on type `initResources<'_>`
- --> $DIR/resources-cfg.rs:50:21
- |
-50 | c.resources.o6;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
-
-error[E0609]: no field `s3` on type `initResources<'_>`
- --> $DIR/resources-cfg.rs:51:21
- |
-51 | c.resources.s3;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
-
-error[E0609]: no field `o2` on type `idleResources<'_>`
- --> $DIR/resources-cfg.rs:58:21
- |
-58 | c.resources.o2;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
-
-error[E0609]: no field `o4` on type `idleResources<'_>`
- --> $DIR/resources-cfg.rs:59:21
- |
-59 | c.resources.o4;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
-
-error[E0609]: no field `s1` on type `idleResources<'_>`
- --> $DIR/resources-cfg.rs:60:21
- |
-60 | c.resources.s1;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
-
-error[E0609]: no field `s3` on type `idleResources<'_>`
- --> $DIR/resources-cfg.rs:61:21
- |
-61 | c.resources.s3;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
-
-error[E0609]: no field `o3` on type `uart0Resources<'_>`
- --> $DIR/resources-cfg.rs:68:21
- |
-68 | c.resources.o3;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
-
-error[E0609]: no field `s1` on type `uart0Resources<'_>`
- --> $DIR/resources-cfg.rs:69:21
- |
-69 | c.resources.s1;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
-
-error[E0609]: no field `s2` on type `uart0Resources<'_>`
- --> $DIR/resources-cfg.rs:70:21
- |
-70 | c.resources.s2;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
-
-error[E0609]: no field `s3` on type `uart0Resources<'_>`
- --> $DIR/resources-cfg.rs:71:21
- |
-71 | c.resources.s3;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
-
-error[E0609]: no field `s2` on type `uart1Resources<'_>`
- --> $DIR/resources-cfg.rs:76:21
- |
-76 | c.resources.s2;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
-
-error[E0609]: no field `o5` on type `uart1Resources<'_>`
- --> $DIR/resources-cfg.rs:77:21
- |
-77 | c.resources.o5;
- | ^^ unknown field
- |
- = note: available fields are: `__marker__`
diff --git a/ui/single/task-priority-too-high.rs b/ui/task-priority-too-high.rs
index caa7b8ee..b1cbfa94 100644
--- a/ui/single/task-priority-too-high.rs
+++ b/ui/task-priority-too-high.rs
@@ -3,8 +3,8 @@
#[rtic::app(device = lm3s6965)]
mod app {
#[init]
- fn init(_: init::Context) -> init::LateResources {
- init::LateResources {}
+ fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
+ (init::LateResources {}, init::Monotonics())
}
#[task(binds = GPIOA, priority = 1)]
diff --git a/ui/single/task-priority-too-high.stderr b/ui/task-priority-too-high.stderr
index 984d3fac..984d3fac 100644
--- a/ui/single/task-priority-too-high.stderr
+++ b/ui/task-priority-too-high.stderr