mirror of
https://github.com/rtic-rs/rtic.git
synced 2025-12-18 22:05:37 +01:00
WIP
This commit is contained in:
parent
754f041ae0
commit
8723c6d45b
41 changed files with 1974 additions and 2851 deletions
55
examples/async-after.rs
Normal file
55
examples/async-after.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#![allow(warnings)]
|
||||
// #![deny(unsafe_code)]
|
||||
// #![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m;
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
// extern crate panic_abort;
|
||||
extern crate panic_itm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use core::mem;
|
||||
|
||||
use cortex_m::asm;
|
||||
use cortex_m::peripheral::{DWT, ITM};
|
||||
use rtfm::{app, Resource};
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
free_interrupts: [EXTI1],
|
||||
|
||||
tasks: {
|
||||
exti0: {
|
||||
interrupt: EXTI0,
|
||||
async_after: [a],
|
||||
},
|
||||
|
||||
a: {},
|
||||
},
|
||||
}
|
||||
|
||||
const S: u32 = 8_000_000;
|
||||
|
||||
#[inline(always)]
|
||||
fn init(mut ctxt: init::Context) -> init::LateResources {
|
||||
init::LateResources {}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn idle(ctxt: idle::Context) -> ! {
|
||||
loop {
|
||||
asm::wfi();
|
||||
}
|
||||
}
|
||||
|
||||
fn exti0(mut ctxt: exti0::Context) {
|
||||
ctxt.async.a.post(&mut ctxt.threshold, 1 * S, ());
|
||||
}
|
||||
|
||||
fn a(ctxt: a::Context) {
|
||||
asm::bkpt();
|
||||
}
|
||||
57
examples/async.rs
Normal file
57
examples/async.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#![allow(warnings)]
|
||||
// #![deny(unsafe_code)]
|
||||
// #![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m;
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
// extern crate panic_abort;
|
||||
extern crate panic_itm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use core::mem;
|
||||
|
||||
use cortex_m::asm;
|
||||
use cortex_m::peripheral::{DWT, ITM};
|
||||
use rtfm::{app, Resource};
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
init: {
|
||||
async: [a],
|
||||
},
|
||||
|
||||
free_interrupts: [EXTI1],
|
||||
|
||||
tasks: {
|
||||
exti0: {
|
||||
interrupt: EXTI0,
|
||||
async: [a],
|
||||
},
|
||||
|
||||
a: {},
|
||||
},
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn init(mut ctxt: init::Context) -> init::LateResources {
|
||||
init::LateResources {}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn idle(ctxt: idle::Context) -> ! {
|
||||
loop {
|
||||
asm::wfi();
|
||||
}
|
||||
}
|
||||
|
||||
fn exti0(mut ctxt: exti0::Context) {
|
||||
ctxt.async.a.post(&mut ctxt.threshold, ());
|
||||
}
|
||||
|
||||
fn a(ctxt: a::Context) {
|
||||
asm::bkpt();
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use rtfm::{app, Threshold};
|
||||
|
||||
pub struct Foo;
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
resources: {
|
||||
static CO_OWNED: Foo = Foo;
|
||||
static ON: Foo = Foo;
|
||||
static OWNED: Foo = Foo;
|
||||
static SHARED: Foo = Foo;
|
||||
},
|
||||
|
||||
idle: {
|
||||
resources: [OWNED, SHARED],
|
||||
},
|
||||
|
||||
tasks: {
|
||||
SYS_TICK: {
|
||||
path: sys_tick,
|
||||
resources: [CO_OWNED, ON, SHARED],
|
||||
},
|
||||
|
||||
TIM2: {
|
||||
enabled: false,
|
||||
path: tim2,
|
||||
priority: 1,
|
||||
resources: [CO_OWNED],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
fn init(_p: ::init::Peripherals, _r: ::init::Resources) {}
|
||||
|
||||
fn idle(_t: &mut Threshold, _r: ::idle::Resources) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn sys_tick(_t: &mut Threshold, _r: SYS_TICK::Resources) {}
|
||||
|
||||
fn tim2(_t: &mut Threshold, _r: TIM2::Resources) {}
|
||||
33
examples/empty.rs
Normal file
33
examples/empty.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#![allow(warnings)]
|
||||
// #![deny(unsafe_code)]
|
||||
// #![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m;
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
// extern crate panic_abort;
|
||||
extern crate panic_itm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use core::mem;
|
||||
|
||||
use cortex_m::asm;
|
||||
use rtfm::{app, Resource};
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn init(mut ctxt: init::Context) -> init::LateResources {
|
||||
init::LateResources {}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn idle(ctxt: idle::Context) -> ! {
|
||||
loop {
|
||||
asm::wfi();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
//! A showcase of the `app!` macro syntax
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use rtfm::{app, Threshold};
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
resources: {
|
||||
static CO_OWNED: u32 = 0;
|
||||
static ON: bool = false;
|
||||
static OWNED: bool = false;
|
||||
static SHARED: bool = false;
|
||||
},
|
||||
|
||||
init: {
|
||||
// This is the path to the `init` function
|
||||
//
|
||||
// `init` doesn't necessarily has to be in the root of the crate
|
||||
path: main::init,
|
||||
},
|
||||
|
||||
idle: {
|
||||
// This is a path to the `idle` function
|
||||
//
|
||||
// `idle` doesn't necessarily has to be in the root of the crate
|
||||
path: main::idle,
|
||||
resources: [OWNED, SHARED],
|
||||
},
|
||||
|
||||
tasks: {
|
||||
SYS_TICK: {
|
||||
path: sys_tick,
|
||||
// If omitted priority is assumed to be 1
|
||||
// priority: 1,
|
||||
resources: [CO_OWNED, ON, SHARED],
|
||||
},
|
||||
|
||||
TIM2: {
|
||||
// Tasks are enabled, between `init` and `idle`, by default but they
|
||||
// can start disabled if `false` is specified here
|
||||
enabled: false,
|
||||
path: tim2,
|
||||
priority: 1,
|
||||
resources: [CO_OWNED],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
mod main {
|
||||
use rtfm::{self, Resource, Threshold};
|
||||
|
||||
pub fn init(_p: ::init::Peripherals, _r: ::init::Resources) {}
|
||||
|
||||
pub fn idle(t: &mut Threshold, mut r: ::idle::Resources) -> ! {
|
||||
loop {
|
||||
*r.OWNED != *r.OWNED;
|
||||
|
||||
if *r.OWNED {
|
||||
if r.SHARED.claim(t, |shared, _| *shared) {
|
||||
rtfm::wfi();
|
||||
}
|
||||
} else {
|
||||
r.SHARED.claim_mut(t, |shared, _| *shared = !*shared);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn sys_tick(_t: &mut Threshold, mut r: SYS_TICK::Resources) {
|
||||
*r.ON = !*r.ON;
|
||||
|
||||
*r.CO_OWNED += 1;
|
||||
}
|
||||
|
||||
fn tim2(_t: &mut Threshold, mut r: TIM2::Resources) {
|
||||
*r.CO_OWNED += 1;
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
//! Working with resources in a generic fashion
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use rtfm::{app, Resource, Threshold};
|
||||
use stm32f103xx::{SPI1, GPIOA};
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
resources: {
|
||||
static GPIOA: GPIOA;
|
||||
static SPI1: SPI1;
|
||||
},
|
||||
|
||||
tasks: {
|
||||
EXTI0: {
|
||||
path: exti0,
|
||||
priority: 1,
|
||||
resources: [GPIOA, SPI1],
|
||||
},
|
||||
|
||||
EXTI1: {
|
||||
path: exti1,
|
||||
priority: 2,
|
||||
resources: [GPIOA, SPI1],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
fn init(p: init::Peripherals) -> init::LateResources {
|
||||
init::LateResources {
|
||||
GPIOA: p.device.GPIOA,
|
||||
SPI1: p.device.SPI1,
|
||||
}
|
||||
}
|
||||
|
||||
fn idle() -> ! {
|
||||
loop {
|
||||
rtfm::wfi();
|
||||
}
|
||||
}
|
||||
|
||||
// A generic function that uses some resources
|
||||
fn work<G, S>(t: &mut Threshold, gpioa: &G, spi1: &S)
|
||||
where
|
||||
G: Resource<Data = GPIOA>,
|
||||
S: Resource<Data = SPI1>,
|
||||
{
|
||||
gpioa.claim(t, |_gpioa, t| {
|
||||
// drive NSS low
|
||||
|
||||
spi1.claim(t, |_spi1, _| {
|
||||
// transfer data
|
||||
});
|
||||
|
||||
// drive NSS high
|
||||
});
|
||||
}
|
||||
|
||||
// This task needs critical sections to access the resources
|
||||
fn exti0(t: &mut Threshold, r: EXTI0::Resources) {
|
||||
work(t, &r.GPIOA, &r.SPI1);
|
||||
}
|
||||
|
||||
// This task has direct access to the resources
|
||||
fn exti1(t: &mut Threshold, r: EXTI1::Resources) {
|
||||
work(t, &r.GPIOA, &r.SPI1);
|
||||
}
|
||||
42
examples/interrupt.rs
Normal file
42
examples/interrupt.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#![allow(warnings)]
|
||||
// #![deny(unsafe_code)]
|
||||
// #![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m;
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
// extern crate panic_abort;
|
||||
extern crate panic_itm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use core::mem;
|
||||
|
||||
use cortex_m::asm;
|
||||
use cortex_m::peripheral::{DWT, ITM};
|
||||
use rtfm::{app, Resource};
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
tasks: {
|
||||
exti0: {
|
||||
interrupt: EXTI0,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn init(mut ctxt: init::Context) -> init::LateResources {
|
||||
init::LateResources {}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn idle(ctxt: idle::Context) -> ! {
|
||||
loop {
|
||||
asm::wfi();
|
||||
}
|
||||
}
|
||||
|
||||
fn exti0(ctxt: exti0::Context) {}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
//! Demonstrates initialization of resources in `init`.
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use rtfm::{app, Threshold};
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
resources: {
|
||||
// Usually, resources are initialized with a constant initializer:
|
||||
static ON: bool = false;
|
||||
|
||||
// However, there are cases where this is not possible or not desired.
|
||||
// For example, there may not be a sensible value to use, or the type may
|
||||
// not be constructible in a constant (like `Vec`).
|
||||
//
|
||||
// While it is possible to use an `Option` in some cases, that requires
|
||||
// you to properly initialize it and `.unwrap()` it at every use. It
|
||||
// also consumes more memory.
|
||||
//
|
||||
// To solve this, it is possible to defer initialization of resources to
|
||||
// `init` by omitting the initializer. Doing that will require `init` to
|
||||
// return the values of all "late" resources.
|
||||
static IP_ADDRESS: u32;
|
||||
|
||||
// PORT is used by 2 tasks, making it a shared resource. This just tests
|
||||
// another internal code path and is not important for the example.
|
||||
static PORT: u16;
|
||||
},
|
||||
|
||||
idle: {
|
||||
// Test that late resources can be used in idle
|
||||
resources: [IP_ADDRESS],
|
||||
},
|
||||
|
||||
tasks: {
|
||||
SYS_TICK: {
|
||||
priority: 1,
|
||||
path: sys_tick,
|
||||
resources: [IP_ADDRESS, PORT, ON],
|
||||
},
|
||||
|
||||
EXTI0: {
|
||||
priority: 2,
|
||||
path: exti0,
|
||||
resources: [PORT],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The signature of `init` is now required to have a specific return type.
|
||||
fn init(_p: init::Peripherals, _r: init::Resources) -> init::LateResources {
|
||||
// `init::Resources` does not contain `IP_ADDRESS`, since it is not yet
|
||||
// initialized.
|
||||
//_r.IP_ADDRESS; // doesn't compile
|
||||
|
||||
// ...obtain value for IP_ADDRESS from EEPROM/DHCP...
|
||||
let ip_address = 0x7f000001;
|
||||
|
||||
init::LateResources {
|
||||
// This struct will contain fields for all resources with omitted
|
||||
// initializers.
|
||||
IP_ADDRESS: ip_address,
|
||||
PORT: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
||||
// Other tasks can access late resources like any other, since they are
|
||||
// guaranteed to be initialized when tasks are run.
|
||||
|
||||
r.IP_ADDRESS;
|
||||
}
|
||||
|
||||
fn exti0(_t: &mut Threshold, _r: EXTI0::Resources) {}
|
||||
|
||||
fn idle(_t: &mut Threshold, _r: idle::Resources) -> ! {
|
||||
loop {
|
||||
rtfm::wfi();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
//! Nesting claims and how the preemption threshold works
|
||||
//!
|
||||
//! If you run this program you'll hit the breakpoints as indicated by the
|
||||
//! letters in the comments: A, then B, then C, etc.
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use rtfm::{app, Resource, Threshold};
|
||||
use stm32f103xx::Interrupt;
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
resources: {
|
||||
static LOW: u64 = 0;
|
||||
static HIGH: u64 = 0;
|
||||
},
|
||||
|
||||
tasks: {
|
||||
EXTI0: {
|
||||
path: exti0,
|
||||
priority: 1,
|
||||
resources: [LOW, HIGH],
|
||||
},
|
||||
|
||||
EXTI1: {
|
||||
path: exti1,
|
||||
priority: 2,
|
||||
resources: [LOW],
|
||||
},
|
||||
|
||||
EXTI2: {
|
||||
path: exti2,
|
||||
priority: 3,
|
||||
resources: [HIGH],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
fn init(_p: init::Peripherals, _r: init::Resources) {}
|
||||
|
||||
fn idle() -> ! {
|
||||
// A
|
||||
rtfm::bkpt();
|
||||
|
||||
// Sets task `exti0` as pending
|
||||
//
|
||||
// Because `exti0` has higher priority than `idle` it will be executed
|
||||
// immediately
|
||||
rtfm::set_pending(Interrupt::EXTI0); // ~> exti0
|
||||
|
||||
loop {
|
||||
rtfm::wfi();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn exti0(t: &mut Threshold, EXTI0::Resources { mut LOW, mut HIGH }: EXTI0::Resources) {
|
||||
// Because this task has a priority of 1 the preemption threshold `t` also
|
||||
// starts at 1
|
||||
|
||||
// B
|
||||
rtfm::bkpt();
|
||||
|
||||
// Because `exti1` has higher priority than `exti0` it can preempt it
|
||||
rtfm::set_pending(Interrupt::EXTI1); // ~> exti1
|
||||
|
||||
// A claim creates a critical section
|
||||
LOW.claim_mut(t, |_low, t| {
|
||||
// This claim increases the preemption threshold to 2
|
||||
//
|
||||
// 2 is just high enough to not race with task `exti1` for access to the
|
||||
// `LOW` resource
|
||||
|
||||
// D
|
||||
rtfm::bkpt();
|
||||
|
||||
// Now `exti1` can't preempt this task because its priority is equal to
|
||||
// the current preemption threshold
|
||||
rtfm::set_pending(Interrupt::EXTI1);
|
||||
|
||||
// But `exti2` can, because its priority is higher than the current
|
||||
// preemption threshold
|
||||
rtfm::set_pending(Interrupt::EXTI2); // ~> exti2
|
||||
|
||||
// F
|
||||
rtfm::bkpt();
|
||||
|
||||
// Claims can be nested
|
||||
HIGH.claim_mut(t, |_high, _| {
|
||||
// This claim increases the preemption threshold to 3
|
||||
|
||||
// Now `exti2` can't preempt this task
|
||||
rtfm::set_pending(Interrupt::EXTI2);
|
||||
|
||||
// G
|
||||
rtfm::bkpt();
|
||||
});
|
||||
|
||||
// Upon leaving the critical section the preemption threshold drops back
|
||||
// to 2 and `exti2` immediately preempts this task
|
||||
// ~> exti2
|
||||
});
|
||||
|
||||
// Once again the preemption threshold drops but this time to 1. Now the
|
||||
// pending `exti1` task can preempt this task
|
||||
// ~> exti1
|
||||
}
|
||||
|
||||
fn exti1(_t: &mut Threshold, _r: EXTI1::Resources) {
|
||||
// C, I
|
||||
rtfm::bkpt();
|
||||
}
|
||||
|
||||
fn exti2(_t: &mut Threshold, _r: EXTI2::Resources) {
|
||||
// E, H
|
||||
rtfm::bkpt();
|
||||
}
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
//! An application with one task
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m;
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use cortex_m::peripheral::syst::SystClkSource;
|
||||
use rtfm::{app, Threshold};
|
||||
use stm32f103xx::GPIOC;
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
// Here data resources are declared
|
||||
//
|
||||
// Data resources are static variables that are safe to share across tasks
|
||||
resources: {
|
||||
// Declaration of resources looks exactly like declaration of static
|
||||
// variables
|
||||
static ON: bool = false;
|
||||
},
|
||||
|
||||
// Here tasks are declared
|
||||
//
|
||||
// Each task corresponds to an interrupt or an exception. Every time the
|
||||
// interrupt or exception becomes *pending* the corresponding task handler
|
||||
// will be executed.
|
||||
tasks: {
|
||||
// Here we declare that we'll use the SYS_TICK exception as a task
|
||||
SYS_TICK: {
|
||||
// Path to the task handler
|
||||
path: sys_tick,
|
||||
|
||||
// These are the resources this task has access to.
|
||||
//
|
||||
// The resources listed here must also appear in `app.resources`
|
||||
resources: [ON],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn init(mut p: init::Peripherals, r: init::Resources) {
|
||||
// `init` can modify all the `resources` declared in `app!`
|
||||
r.ON;
|
||||
|
||||
// power on GPIOC
|
||||
p.device.RCC.apb2enr.modify(|_, w| w.iopcen().enabled());
|
||||
|
||||
// configure PC13 as output
|
||||
p.device.GPIOC.bsrr.write(|w| w.bs13().set());
|
||||
p.device
|
||||
.GPIOC
|
||||
.crh
|
||||
.modify(|_, w| w.mode13().output().cnf13().push());
|
||||
|
||||
// configure the system timer to generate one interrupt every second
|
||||
p.core.SYST.set_clock_source(SystClkSource::Core);
|
||||
p.core.SYST.set_reload(8_000_000); // 1s
|
||||
p.core.SYST.enable_interrupt();
|
||||
p.core.SYST.enable_counter();
|
||||
}
|
||||
|
||||
fn idle() -> ! {
|
||||
loop {
|
||||
rtfm::wfi();
|
||||
}
|
||||
}
|
||||
|
||||
// This is the task handler of the SYS_TICK exception
|
||||
//
|
||||
// `_t` is the preemption threshold token. We won't use it in this program.
|
||||
//
|
||||
// `r` is the set of resources this task has access to. `SYS_TICK::Resources`
|
||||
// has one field per resource declared in `app!`.
|
||||
#[allow(unsafe_code)]
|
||||
fn sys_tick(_t: &mut Threshold, mut r: SYS_TICK::Resources) {
|
||||
// toggle state
|
||||
*r.ON = !*r.ON;
|
||||
|
||||
if *r.ON {
|
||||
// set the pin PC13 high
|
||||
// NOTE(unsafe) atomic write to a stateless register
|
||||
unsafe {
|
||||
(*GPIOC::ptr()).bsrr.write(|w| w.bs13().set());
|
||||
}
|
||||
} else {
|
||||
// set the pin PC13 low
|
||||
// NOTE(unsafe) atomic write to a stateless register
|
||||
unsafe {
|
||||
(*GPIOC::ptr()).bsrr.write(|w| w.br13().reset());
|
||||
}
|
||||
}
|
||||
}
|
||||
91
examples/periodic-payload.rs
Normal file
91
examples/periodic-payload.rs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
// # -Os
|
||||
// init
|
||||
// a(bl=8000000, now=8000180, input=0)
|
||||
// a(bl=16000000, now=16000180, input=1)
|
||||
// a(bl=24000000, now=24000180, input=2)
|
||||
//
|
||||
// # -O3
|
||||
// init
|
||||
// a(bl=8000000, now=8000168, input=0)
|
||||
// a(bl=16000000, now=16000168, input=1)
|
||||
// a(bl=24000000, now=24000168, input=2)
|
||||
|
||||
#![allow(warnings)]
|
||||
// #![deny(unsafe_code)]
|
||||
// #![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m;
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
// extern crate panic_abort;
|
||||
extern crate panic_itm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use core::mem;
|
||||
|
||||
use cortex_m::asm;
|
||||
use cortex_m::peripheral::{DWT, ITM};
|
||||
use rtfm::{app, Resource};
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
resources: {
|
||||
static ITM: ITM;
|
||||
},
|
||||
|
||||
init: {
|
||||
async_after: [a],
|
||||
},
|
||||
|
||||
free_interrupts: [EXTI0],
|
||||
|
||||
tasks: {
|
||||
a: {
|
||||
async_after: [a],
|
||||
input: u16,
|
||||
resources: [ITM],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const MS: u32 = 8_000;
|
||||
const S: u32 = 1_000 * MS;
|
||||
|
||||
#[inline(always)]
|
||||
fn init(mut ctxt: init::Context) -> init::LateResources {
|
||||
iprintln!(&mut ctxt.core.ITM.stim[0], "init");
|
||||
|
||||
ctxt.async.a.post(&mut ctxt.threshold, 1 * S, 0).ok();
|
||||
|
||||
init::LateResources { ITM: ctxt.core.ITM }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn idle(ctxt: idle::Context) -> ! {
|
||||
loop {
|
||||
asm::wfi();
|
||||
}
|
||||
}
|
||||
|
||||
fn a(mut ctxt: a::Context) {
|
||||
let now = DWT::get_cycle_count();
|
||||
let input = ctxt.input;
|
||||
|
||||
let bl = ctxt.baseline;
|
||||
let itm = ctxt.resources.ITM;
|
||||
iprintln!(
|
||||
&mut itm.stim[0],
|
||||
"a(bl={}, now={}, input={})",
|
||||
bl,
|
||||
now,
|
||||
input
|
||||
);
|
||||
|
||||
ctxt.async
|
||||
.a
|
||||
.post(&mut ctxt.threshold, 1 * S, input + 1)
|
||||
.ok();
|
||||
}
|
||||
130
examples/periodic-preemption-payload.rs
Normal file
130
examples/periodic-preemption-payload.rs
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
// # -Os
|
||||
// a(bl=16000000, now=16000248, input=0)
|
||||
// b(bl=24000000, now=24000251, input=0)
|
||||
// a(bl=32000000, now=32000248, input=1)
|
||||
// b(bl=48000000, now=48000283, input=1)
|
||||
// a(bl=48000000, now=48002427, input=2)
|
||||
// a(bl=64000000, now=64000248, input=3)
|
||||
// b(bl=72000000, now=72000251, input=2)
|
||||
// a(bl=80000000, now=80000248, input=4)
|
||||
// b(bl=96000000, now=96000283, input=3)
|
||||
// a(bl=96000000, now=96002427, input=5)
|
||||
|
||||
// # -O3
|
||||
// init
|
||||
// a(bl=16000000, now=16000231, input=0)
|
||||
// b(bl=24000000, now=24000230, input=0)
|
||||
// a(bl=32000000, now=32000231, input=1)
|
||||
// b(bl=48000000, now=48000259, input=1)
|
||||
// a(bl=48000000, now=48002397, input=2)
|
||||
// a(bl=64000000, now=64000231, input=3)
|
||||
// b(bl=72000000, now=72000230, input=2)
|
||||
// a(bl=80000000, now=80000231, input=4)
|
||||
// b(bl=96000000, now=96000259, input=3)
|
||||
// a(bl=96000000, now=96002397, input=5)
|
||||
|
||||
#![allow(warnings)]
|
||||
// #![deny(unsafe_code)]
|
||||
// #![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m;
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
// extern crate panic_abort;
|
||||
extern crate panic_itm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use core::mem;
|
||||
|
||||
use cortex_m::asm;
|
||||
use cortex_m::peripheral::{DWT, ITM};
|
||||
use rtfm::{app, Resource};
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
resources: {
|
||||
static ITM: ITM;
|
||||
},
|
||||
|
||||
init: {
|
||||
async_after: [a, b],
|
||||
},
|
||||
|
||||
free_interrupts: [EXTI0, EXTI1],
|
||||
|
||||
tasks: {
|
||||
a: {
|
||||
async_after: [a],
|
||||
input: u32,
|
||||
resources: [ITM],
|
||||
},
|
||||
|
||||
b: {
|
||||
async_after: [b],
|
||||
input: u32,
|
||||
priority: 2,
|
||||
resources: [ITM],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const MS: u32 = 8_000;
|
||||
const S: u32 = 1_000 * MS;
|
||||
|
||||
#[inline(always)]
|
||||
fn init(mut ctxt: init::Context) -> init::LateResources {
|
||||
iprintln!(&mut ctxt.core.ITM.stim[0], "init");
|
||||
|
||||
ctxt.async.a.post(&mut ctxt.threshold, 2 * S, 0).ok();
|
||||
ctxt.async.b.post(&mut ctxt.threshold, 3 * S, 0).ok();
|
||||
|
||||
init::LateResources { ITM: ctxt.core.ITM }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn idle(ctxt: idle::Context) -> ! {
|
||||
loop {
|
||||
asm::wfi();
|
||||
}
|
||||
}
|
||||
|
||||
fn a(mut ctxt: a::Context) {
|
||||
let now = DWT::get_cycle_count();
|
||||
|
||||
let input = ctxt.input;
|
||||
let bl = ctxt.baseline;
|
||||
ctxt.resources.ITM.claim_mut(&mut ctxt.threshold, |itm, _| {
|
||||
iprintln!(
|
||||
&mut itm.stim[0],
|
||||
"a(bl={}, now={}, input={})",
|
||||
bl,
|
||||
now,
|
||||
input
|
||||
);
|
||||
});
|
||||
|
||||
ctxt.async
|
||||
.a
|
||||
.post(&mut ctxt.threshold, 2 * S, input + 1)
|
||||
.ok();
|
||||
}
|
||||
|
||||
fn b(mut ctxt: b::Context) {
|
||||
let now = DWT::get_cycle_count();
|
||||
|
||||
let bl = ctxt.baseline;
|
||||
let input = ctxt.input;
|
||||
let t = &mut ctxt.threshold;
|
||||
iprintln!(
|
||||
&mut ctxt.resources.ITM.borrow_mut(t).stim[0],
|
||||
"b(bl={}, now={}, input={})",
|
||||
bl,
|
||||
now,
|
||||
input,
|
||||
);
|
||||
|
||||
ctxt.async.b.post(t, 3 * S, input + 1).ok();
|
||||
}
|
||||
117
examples/periodic-preemption.rs
Normal file
117
examples/periodic-preemption.rs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
// # -Os
|
||||
// init
|
||||
// a(bl=16000000, now=16000249)
|
||||
// b(bl=24000000, now=24000248)
|
||||
// a(bl=32000000, now=32000249)
|
||||
// b(bl=48000000, now=48000282)
|
||||
// a(bl=48000000, now=48001731)
|
||||
// a(bl=64000000, now=64000249)
|
||||
// b(bl=72000000, now=72000248)
|
||||
// a(bl=80000000, now=80000249)
|
||||
// b(bl=96000000, now=96000282)
|
||||
// a(bl=96000000, now=96001731)
|
||||
|
||||
// # -O3
|
||||
// init
|
||||
// a(bl=16000000, now=16000228)
|
||||
// b(bl=24000000, now=24000231)
|
||||
// a(bl=32000000, now=32000228)
|
||||
// b(bl=48000000, now=48000257)
|
||||
// a(bl=48000000, now=48001705)
|
||||
// a(bl=64000000, now=64000228)
|
||||
// b(bl=72000000, now=72000231)
|
||||
// a(bl=80000000, now=80000228)
|
||||
// b(bl=96000000, now=96000257)
|
||||
// a(bl=96000000, now=96001705)
|
||||
|
||||
#![allow(warnings)]
|
||||
// #![deny(unsafe_code)]
|
||||
// #![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m;
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
// extern crate panic_abort;
|
||||
extern crate panic_itm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use core::mem;
|
||||
|
||||
use cortex_m::asm;
|
||||
use cortex_m::peripheral::{DWT, ITM};
|
||||
use rtfm::{app, Resource};
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
resources: {
|
||||
static ITM: ITM;
|
||||
},
|
||||
|
||||
init: {
|
||||
async_after: [a, b],
|
||||
},
|
||||
|
||||
free_interrupts: [EXTI0, EXTI1],
|
||||
|
||||
tasks: {
|
||||
a: {
|
||||
async_after: [a],
|
||||
resources: [ITM],
|
||||
},
|
||||
|
||||
b: {
|
||||
async_after: [b],
|
||||
priority: 2,
|
||||
resources: [ITM],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const MS: u32 = 8_000;
|
||||
const S: u32 = 1_000 * MS;
|
||||
|
||||
#[inline(always)]
|
||||
fn init(mut ctxt: init::Context) -> init::LateResources {
|
||||
iprintln!(&mut ctxt.core.ITM.stim[0], "init");
|
||||
|
||||
ctxt.async.a.post(&mut ctxt.threshold, 2 * S, ()).ok();
|
||||
ctxt.async.b.post(&mut ctxt.threshold, 3 * S, ()).ok();
|
||||
|
||||
init::LateResources { ITM: ctxt.core.ITM }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn idle(ctxt: idle::Context) -> ! {
|
||||
loop {
|
||||
asm::wfi();
|
||||
}
|
||||
}
|
||||
|
||||
fn a(mut ctxt: a::Context) {
|
||||
let now = DWT::get_cycle_count();
|
||||
|
||||
let bl = ctxt.baseline;
|
||||
ctxt.resources.ITM.claim_mut(&mut ctxt.threshold, |itm, _| {
|
||||
iprintln!(&mut itm.stim[0], "a(bl={}, now={})", bl, now);
|
||||
});
|
||||
|
||||
ctxt.async.a.post(&mut ctxt.threshold, 2 * S, ()).ok();
|
||||
}
|
||||
|
||||
fn b(mut ctxt: b::Context) {
|
||||
let now = DWT::get_cycle_count();
|
||||
|
||||
let bl = ctxt.baseline;
|
||||
let t = &mut ctxt.threshold;
|
||||
iprintln!(
|
||||
&mut ctxt.resources.ITM.borrow_mut(t).stim[0],
|
||||
"b(bl={}, now={})",
|
||||
bl,
|
||||
now
|
||||
);
|
||||
|
||||
ctxt.async.b.post(t, 3 * S, ()).ok();
|
||||
}
|
||||
77
examples/periodic.rs
Normal file
77
examples/periodic.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
// # -Os
|
||||
// init
|
||||
// a(bl=8000000, now=8000180)
|
||||
// a(bl=16000000, now=16000180)
|
||||
//
|
||||
// # -O3
|
||||
// a(bl=8000000, now=8000168)
|
||||
// a(bl=16000000, now=16000168)
|
||||
|
||||
#![allow(warnings)]
|
||||
// #![deny(unsafe_code)]
|
||||
// #![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m;
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
// extern crate panic_abort;
|
||||
extern crate panic_itm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use core::mem;
|
||||
|
||||
use cortex_m::asm;
|
||||
use cortex_m::peripheral::{DWT, ITM};
|
||||
use rtfm::{app, Resource};
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
resources: {
|
||||
static ITM: ITM;
|
||||
},
|
||||
|
||||
init: {
|
||||
async_after: [a],
|
||||
},
|
||||
|
||||
free_interrupts: [EXTI0],
|
||||
|
||||
tasks: {
|
||||
a: {
|
||||
async_after: [a],
|
||||
resources: [ITM],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const MS: u32 = 8_000;
|
||||
const S: u32 = 1_000 * MS;
|
||||
|
||||
#[inline(always)]
|
||||
fn init(mut ctxt: init::Context) -> init::LateResources {
|
||||
iprintln!(&mut ctxt.core.ITM.stim[0], "init");
|
||||
|
||||
ctxt.async.a.post(&mut ctxt.threshold, 1 * S, ()).ok();
|
||||
|
||||
init::LateResources { ITM: ctxt.core.ITM }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn idle(ctxt: idle::Context) -> ! {
|
||||
loop {
|
||||
asm::wfi();
|
||||
}
|
||||
}
|
||||
|
||||
fn a(mut ctxt: a::Context) {
|
||||
let now = DWT::get_cycle_count();
|
||||
|
||||
let bl = ctxt.baseline;
|
||||
let itm = ctxt.resources.ITM;
|
||||
iprintln!(&mut itm.stim[0], "a(bl={}, now={})", bl, now);
|
||||
|
||||
ctxt.async.a.post(&mut ctxt.threshold, 1 * S, ()).ok();
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
//! Two tasks running at *different* priorities with access to the same resource
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use rtfm::{app, Resource, Threshold};
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
resources: {
|
||||
static COUNTER: u64 = 0;
|
||||
},
|
||||
|
||||
tasks: {
|
||||
// The `SYS_TICK` task has higher priority than `TIM2`
|
||||
SYS_TICK: {
|
||||
path: sys_tick,
|
||||
priority: 2,
|
||||
resources: [COUNTER],
|
||||
},
|
||||
|
||||
TIM2: {
|
||||
path: tim2,
|
||||
priority: 1,
|
||||
resources: [COUNTER],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
fn init(_p: init::Peripherals, _r: init::Resources) {
|
||||
// ..
|
||||
}
|
||||
|
||||
fn idle() -> ! {
|
||||
loop {
|
||||
rtfm::wfi();
|
||||
}
|
||||
}
|
||||
|
||||
fn sys_tick(_t: &mut Threshold, mut r: SYS_TICK::Resources) {
|
||||
// ..
|
||||
|
||||
// This task can't be preempted by `tim2` so it has direct access to the
|
||||
// resource data
|
||||
*r.COUNTER += 1;
|
||||
|
||||
// ..
|
||||
}
|
||||
|
||||
fn tim2(t: &mut Threshold, mut r: TIM2::Resources) {
|
||||
// ..
|
||||
|
||||
// As this task runs at lower priority it needs a critical section to
|
||||
// prevent `sys_tick` from preempting it while it modifies this resource
|
||||
// data. The critical section is required to prevent data races which can
|
||||
// lead to undefined behavior.
|
||||
r.COUNTER.claim_mut(t, |counter, _t| {
|
||||
// `claim_mut` creates a critical section
|
||||
*counter += 1;
|
||||
});
|
||||
|
||||
// ..
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
//! Safe creation of `&'static mut` references
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use rtfm::app;
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
resources: {
|
||||
static BUFFER: [u8; 16] = [0; 16];
|
||||
},
|
||||
|
||||
init: {
|
||||
resources: [BUFFER],
|
||||
},
|
||||
}
|
||||
|
||||
fn init(_p: init::Peripherals, r: init::Resources) {
|
||||
let _buf: &'static mut [u8; 16] = r.BUFFER;
|
||||
}
|
||||
|
||||
fn idle() -> ! {
|
||||
loop {
|
||||
rtfm::wfi();
|
||||
}
|
||||
}
|
||||
273
examples/tq.rs
273
examples/tq.rs
|
|
@ -1,273 +0,0 @@
|
|||
// #![deny(unsafe_code)]
|
||||
// #![deny(warnings)]
|
||||
#![allow(dead_code)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m;
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
extern crate panic_abort;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use core::cmp;
|
||||
|
||||
use cortex_m::peripheral::syst::SystClkSource;
|
||||
use cortex_m::peripheral::ITM;
|
||||
use rtfm::ll::{self, Consumer, FreeList, Instant, Node, Producer, RingBuffer, Slot, TaggedPayload,
|
||||
TimerQueue};
|
||||
use rtfm::{app, Resource, Threshold};
|
||||
use stm32f103xx::Interrupt;
|
||||
|
||||
const ACAP: usize = 4;
|
||||
|
||||
const MS: u32 = 8_000;
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
resources: {
|
||||
/* timer queue */
|
||||
static TQ: TimerQueue<Task, [TaggedPayload<Task>; ACAP]>;
|
||||
|
||||
/* a */
|
||||
// payloads w/ after
|
||||
static AN: [Node<i32>; ACAP] = unsafe { ll::uninitialized() };
|
||||
static AFL: FreeList<i32> = FreeList::new();
|
||||
|
||||
/* exti0 */
|
||||
static Q1: RingBuffer<TaggedPayload<Task1>, [TaggedPayload<Task1>; ACAP + 1], u8> =
|
||||
RingBuffer::u8();
|
||||
static Q1C: Consumer<'static, TaggedPayload<Task1>, [TaggedPayload<Task1>; ACAP + 1], u8>;
|
||||
static Q1P: Producer<'static, TaggedPayload<Task1>, [TaggedPayload<Task1>; ACAP + 1], u8>;
|
||||
},
|
||||
|
||||
init: {
|
||||
resources: [AN, Q1],
|
||||
},
|
||||
|
||||
tasks: {
|
||||
EXTI1: {
|
||||
path: exti1,
|
||||
resources: [TQ, AFL],
|
||||
priority: 1,
|
||||
|
||||
// async: [a],
|
||||
},
|
||||
|
||||
// dispatch interrupt
|
||||
EXTI0: {
|
||||
path: exti0,
|
||||
resources: [Q1C, AFL],
|
||||
priority: 3,
|
||||
},
|
||||
|
||||
// timer queue
|
||||
SYS_TICK: {
|
||||
path: sys_tick,
|
||||
resources: [TQ, Q1P],
|
||||
priority: 2,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
pub fn init(mut p: ::init::Peripherals, r: init::Resources) -> init::LateResources {
|
||||
// ..
|
||||
|
||||
/* executed after `init` end */
|
||||
p.core.DWT.enable_cycle_counter();
|
||||
unsafe { p.core.DWT.cyccnt.write(0) };
|
||||
p.core.SYST.set_clock_source(SystClkSource::Core);
|
||||
p.core.SYST.enable_counter();
|
||||
p.core.SYST.disable_interrupt();
|
||||
|
||||
// populate the free list
|
||||
for n in r.AN {
|
||||
r.AFL.push(Slot::new(n));
|
||||
}
|
||||
|
||||
let (q1p, q1c) = r.Q1.split();
|
||||
init::LateResources {
|
||||
TQ: TimerQueue::new(p.core.SYST),
|
||||
Q1C: q1c,
|
||||
Q1P: q1p,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn idle() -> ! {
|
||||
rtfm::set_pending(Interrupt::EXTI1);
|
||||
|
||||
loop {
|
||||
rtfm::wfi()
|
||||
}
|
||||
}
|
||||
|
||||
fn a(_t: &mut Threshold, bl: Instant, payload: i32) {
|
||||
unsafe {
|
||||
iprintln!(
|
||||
&mut (*ITM::ptr()).stim[0],
|
||||
"a(now={:?}, bl={:?}, payload={})",
|
||||
Instant::now(),
|
||||
bl,
|
||||
payload
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn exti1(t: &mut Threshold, r: EXTI1::Resources) {
|
||||
/* expansion */
|
||||
let bl = Instant::now();
|
||||
let mut async = a::Async::new(bl, r.TQ, r.AFL);
|
||||
/* end of expansion */
|
||||
|
||||
unsafe { iprintln!(&mut (*ITM::ptr()).stim[0], "EXTI0(bl={:?})", bl) }
|
||||
async.a(t, 100 * MS, 0).unwrap();
|
||||
async.a(t, 50 * MS, 1).unwrap();
|
||||
async.a(t, 75 * MS, 2).unwrap();
|
||||
async.a(t, 75 * MS + 1, 3).unwrap();
|
||||
}
|
||||
|
||||
/* auto generated */
|
||||
fn exti0(t: &mut Threshold, mut r: EXTI0::Resources) {
|
||||
while let Some(payload) = r.Q1C.dequeue() {
|
||||
match payload.tag() {
|
||||
Task1::a => {
|
||||
let (bl, payload, slot) = unsafe { payload.coerce() }.read();
|
||||
|
||||
r.AFL.claim_mut(t, |afl, _| afl.push(slot));
|
||||
|
||||
a(&mut unsafe { Threshold::new(3) }, bl, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn sys_tick(t: &mut Threshold, r: SYS_TICK::Resources) {
|
||||
#[allow(non_snake_case)]
|
||||
let SYS_TICK::Resources { mut Q1P, mut TQ } = r;
|
||||
|
||||
enum State<T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
Payload(TaggedPayload<T>),
|
||||
Baseline(Instant),
|
||||
Done,
|
||||
}
|
||||
|
||||
loop {
|
||||
let state = TQ.claim_mut(t, |tq, _| {
|
||||
if let Some(bl) = tq.queue.peek().map(|p| p.baseline()) {
|
||||
if Instant::now() >= bl {
|
||||
// message ready
|
||||
State::Payload(tq.queue.pop().unwrap())
|
||||
} else {
|
||||
// new timeout
|
||||
State::Baseline(bl)
|
||||
}
|
||||
} else {
|
||||
// empty queue
|
||||
tq.syst.disable_interrupt();
|
||||
State::Done
|
||||
}
|
||||
});
|
||||
|
||||
match state {
|
||||
State::Payload(p) => match p.tag() {
|
||||
Task::a => {
|
||||
Q1P.claim_mut(t, |q1p, _| q1p.enqueue_unchecked(p.retag(Task1::a)));
|
||||
rtfm::set_pending(Interrupt::EXTI0);
|
||||
}
|
||||
},
|
||||
State::Baseline(bl) => {
|
||||
const MAX: u32 = 0x00ffffff;
|
||||
|
||||
let diff = bl - Instant::now();
|
||||
|
||||
if diff < 0 {
|
||||
// message became ready
|
||||
continue;
|
||||
} else {
|
||||
TQ.claim_mut(t, |tq, _| {
|
||||
tq.syst.set_reload(cmp::min(MAX, diff as u32));
|
||||
tq.syst.clear_current();
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
State::Done => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tasks dispatched at a priority of 1
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Task1 {
|
||||
a,
|
||||
}
|
||||
|
||||
// All tasks
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Task {
|
||||
a,
|
||||
}
|
||||
|
||||
mod a {
|
||||
use cortex_m::peripheral::SCB;
|
||||
|
||||
use rtfm::ll::Instant;
|
||||
use rtfm::{Resource, Threshold};
|
||||
use Task;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub struct Async {
|
||||
// inherited baseline
|
||||
baseline: Instant,
|
||||
TQ: ::EXTI1::TQ,
|
||||
AFL: ::EXTI1::AFL,
|
||||
}
|
||||
|
||||
impl Async {
|
||||
#[allow(non_snake_case)]
|
||||
pub fn new(bl: Instant, TQ: ::EXTI1::TQ, AFL: ::EXTI1::AFL) -> Self {
|
||||
Async {
|
||||
baseline: bl,
|
||||
TQ,
|
||||
AFL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn a(&mut self, t: &mut Threshold, after: u32, payload: i32) -> Result<(), i32> {
|
||||
if let Some(slot) = self.AFL.claim_mut(t, |afl, _| afl.pop()) {
|
||||
let baseline = self.baseline;
|
||||
self.TQ.claim_mut(t, |tq, _| {
|
||||
if tq.queue.capacity() == tq.queue.len() {
|
||||
// full
|
||||
Err(payload)
|
||||
} else {
|
||||
let bl = baseline + after;
|
||||
if tq.queue
|
||||
.peek()
|
||||
.map(|head| bl < head.baseline())
|
||||
.unwrap_or(true)
|
||||
{
|
||||
tq.syst.enable_interrupt();
|
||||
// Set SYST pending
|
||||
unsafe { (*SCB::ptr()).icsr.write(1 << 26) }
|
||||
}
|
||||
|
||||
tq.queue.push(slot.write(bl, payload).tag(Task::a)).ok();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
} else {
|
||||
Err(payload)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
//! Two tasks running at the *same* priority with access to the same resource
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
extern crate stm32f103xx;
|
||||
|
||||
use rtfm::{app, Threshold};
|
||||
|
||||
app! {
|
||||
device: stm32f103xx,
|
||||
|
||||
resources: {
|
||||
static COUNTER: u64 = 0;
|
||||
},
|
||||
|
||||
// Both SYS_TICK and TIM2 have access to the `COUNTER` data
|
||||
tasks: {
|
||||
SYS_TICK: {
|
||||
path: sys_tick,
|
||||
resources: [COUNTER],
|
||||
},
|
||||
|
||||
TIM2: {
|
||||
path: tim2,
|
||||
resources: [COUNTER],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
fn init(_p: init::Peripherals, _r: init::Resources) {
|
||||
// ..
|
||||
}
|
||||
|
||||
fn idle() -> ! {
|
||||
loop {
|
||||
rtfm::wfi();
|
||||
}
|
||||
}
|
||||
|
||||
// As both tasks are running at the same priority one can't preempt the other.
|
||||
// Thus both tasks have direct access to the resource
|
||||
fn sys_tick(_t: &mut Threshold, mut r: SYS_TICK::Resources) {
|
||||
// ..
|
||||
|
||||
*r.COUNTER += 1;
|
||||
|
||||
// ..
|
||||
}
|
||||
|
||||
fn tim2(_t: &mut Threshold, mut r: TIM2::Resources) {
|
||||
// ..
|
||||
|
||||
*r.COUNTER += 1;
|
||||
|
||||
// ..
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
//! Minimal example with zero tasks
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
// IMPORTANT always include this feature gate
|
||||
#![feature(proc_macro)]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rtfm as rtfm; // IMPORTANT always do this rename
|
||||
extern crate stm32f103xx; // the device crate
|
||||
|
||||
// import the procedural macro
|
||||
use rtfm::app;
|
||||
|
||||
// This macro call indicates that this is a RTFM application
|
||||
//
|
||||
// This macro will expand to a `main` function so you don't need to supply
|
||||
// `main` yourself.
|
||||
app! {
|
||||
// this is the path to the device crate
|
||||
device: stm32f103xx,
|
||||
}
|
||||
|
||||
// The initialization phase.
|
||||
//
|
||||
// This runs first and within a *global* critical section. Nothing can preempt
|
||||
// this function.
|
||||
fn init(p: init::Peripherals) {
|
||||
// This function has access to all the peripherals of the device
|
||||
p.core.SYST;
|
||||
p.device.GPIOA;
|
||||
p.device.RCC;
|
||||
// ..
|
||||
}
|
||||
|
||||
// The idle loop.
|
||||
//
|
||||
// This runs after `init` and has a priority of 0. All tasks can preempt this
|
||||
// function. This function can never return so it must contain some sort of
|
||||
// endless loop.
|
||||
fn idle() -> ! {
|
||||
loop {
|
||||
// This puts the processor to sleep until there's a task to service
|
||||
rtfm::wfi();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue