mirror of
https://github.com/rtic-rs/rtic.git
synced 2025-12-16 12:55:23 +01:00
rtfm! macro take 2
This commit is contained in:
parent
2bf5401439
commit
86a360a396
27 changed files with 1367 additions and 2237 deletions
|
|
@ -1,16 +0,0 @@
|
|||
extern crate compiletest_rs as compiletest;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use compiletest::common::Mode;
|
||||
|
||||
#[test]
|
||||
fn cfail() {
|
||||
let mut config = compiletest::default_config();
|
||||
config.mode = Mode::CompileFail;
|
||||
config.src_base = PathBuf::from(format!("tests/cfail"));
|
||||
config.target_rustcflags =
|
||||
Some("-L target/debug -L target/debug/deps ".to_string());
|
||||
|
||||
compiletest::run_tests(&config);
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use rtfm::{C1, C2, C3, C4, C5, P2, Resource, T2};
|
||||
|
||||
static R1: Resource<i32, C4> = Resource::new(0);
|
||||
static R2: Resource<i32, C3> = Resource::new(0);
|
||||
static R3: Resource<i32, C4> = Resource::new(0);
|
||||
static R4: Resource<i32, C5> = Resource::new(0);
|
||||
static R5: Resource<i32, C1> = Resource::new(0);
|
||||
static R6: Resource<i32, C2> = Resource::new(0);
|
||||
|
||||
fn j1(prio: P2, thr: T2) {
|
||||
thr.raise(
|
||||
&R1, |thr| {
|
||||
// NOTE PT = Preemption Threshold, TP = Task Priority
|
||||
|
||||
// CAN access a resource with ceiling RC when PT > RC
|
||||
let r2 = R2.access(&prio, thr);
|
||||
|
||||
// CAN access a resource with ceiling RC when PT == RC
|
||||
let r3 = R3.access(&prio, thr);
|
||||
|
||||
// CAN'T access a resource with ceiling RC when PT < RC
|
||||
let r4 = R4.access(&prio, thr);
|
||||
//~^ error
|
||||
|
||||
// CAN'T access a resource with ceiling RC when RC < TP
|
||||
let r5 = R5.access(&prio, thr);
|
||||
//~^ error
|
||||
|
||||
// CAN access a resource with ceiling RC when RC == tP
|
||||
let r6 = R6.access(&prio, thr);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use rtfm::{C2, C3, P0, P2, Resource, T2};
|
||||
|
||||
static R1: Resource<(), C3> = Resource::new(());
|
||||
|
||||
fn j1(prio: P2, thr: T2) {
|
||||
let t3 = thr.raise(
|
||||
&R1, |thr| {
|
||||
// forbidden: ceiling token can't outlive the critical section
|
||||
thr //~ error
|
||||
}
|
||||
);
|
||||
|
||||
// Would be bad: lockless access to a resource with ceiling = 3
|
||||
let r2 = R1.access(&prio, t3);
|
||||
}
|
||||
|
||||
fn j2(prio: P0) {
|
||||
let c16 = rtfm::atomic(
|
||||
|c16| {
|
||||
// forbidden: ceiling token can't outlive the critical section
|
||||
c16 //~ error
|
||||
},
|
||||
);
|
||||
|
||||
// Would be bad: lockless access to a resource with ceiling = 16
|
||||
let r1 = R1.access(&prio, c16);
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use rtfm::{CMax, C2, P1, P2, P3, PMax, Resource, T1, T2, T3, TMax};
|
||||
|
||||
static R1: Resource<i32, C2> = Resource::new(0);
|
||||
|
||||
// You don't need to raise the ceiling to access a resource with ceiling equal
|
||||
// to the task priority.
|
||||
fn j1(prio: P2, thr: T2) {
|
||||
thr.raise(&R1, |_| {});
|
||||
//~^ error
|
||||
|
||||
// OK
|
||||
let r1 = R1.access(&prio, &thr);
|
||||
}
|
||||
|
||||
// You CAN access a resource with ceiling C from a task with priority P if C > P
|
||||
// if you raise the preemption threshold first
|
||||
fn j2(prio: P1, thr: T1) {
|
||||
// OK
|
||||
thr.raise(&R1, |thr| { let r1 = R1.access(&prio, thr); })
|
||||
}
|
||||
|
||||
static R2: Resource<i32, CMax> = Resource::new(0);
|
||||
|
||||
// Tasks with priority less than P16 can't access a resource with ceiling CMax
|
||||
fn j4(prio: P1, thr: T1) {
|
||||
thr.raise(&R2, |thr| {});
|
||||
//~^ error
|
||||
}
|
||||
|
||||
// Only tasks with priority P16 can directly access a resource with ceiling CMax
|
||||
fn j5(prio: PMax, thr: TMax) {
|
||||
// OK
|
||||
let r2 = R2.access(&prio, &thr);
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
// error-pattern: has already been defined
|
||||
|
||||
#![feature(used)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use rtfm::{P0, P1, T0, TMax};
|
||||
use device::interrupt::Exti0;
|
||||
|
||||
peripherals!(device, {
|
||||
GPIOA: Peripheral {
|
||||
register_block: Gpioa,
|
||||
ceiling: C1,
|
||||
},
|
||||
// WRONG: peripheral alias
|
||||
GPIOA: Peripheral {
|
||||
register_block: Gpioa,
|
||||
ceiling: C2,
|
||||
},
|
||||
});
|
||||
|
||||
tasks!(device, {});
|
||||
|
||||
fn init(_: P0, _: &TMax) {}
|
||||
|
||||
fn idle(_: P0, _: T0) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn j1(_task: Exti0, _prio: P1) {}
|
||||
|
||||
// fake device crate
|
||||
extern crate core;
|
||||
extern crate cortex_m;
|
||||
|
||||
mod device {
|
||||
use cortex_m::peripheral::Peripheral;
|
||||
|
||||
pub const GPIOA: Peripheral<Gpioa> = unsafe { Peripheral::new(0x0) };
|
||||
|
||||
pub struct Gpioa;
|
||||
|
||||
pub mod interrupt {
|
||||
use cortex_m::interrupt::Nr;
|
||||
|
||||
extern "C" fn default_handler<T>(_: T) {}
|
||||
|
||||
pub struct Handlers {
|
||||
pub Exti0: extern "C" fn(Exti0),
|
||||
}
|
||||
|
||||
pub struct Exti0;
|
||||
|
||||
pub enum Interrupt {
|
||||
Exti0,
|
||||
}
|
||||
|
||||
unsafe impl Nr for Interrupt {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub const DEFAULT_HANDLERS: Handlers =
|
||||
Handlers { Exti0: default_handler };
|
||||
}
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
// error-pattern: symbol `GPIOA` is already defined
|
||||
|
||||
#![feature(const_fn)]
|
||||
#![feature(used)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use rtfm::{P0, P1, T0, TMax};
|
||||
use device::interrupt::Exti0;
|
||||
|
||||
peripherals!(device, {
|
||||
GPIOA: Peripheral {
|
||||
register_block: Gpioa,
|
||||
ceiling: C1,
|
||||
},
|
||||
});
|
||||
|
||||
mod foo {
|
||||
// WRONG: peripheral alias
|
||||
peripherals!(device, {
|
||||
GPIOA: Peripheral {
|
||||
register_block: Gpioa,
|
||||
ceiling: C2,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
tasks!(device, {});
|
||||
|
||||
fn init(_: P0, _: &TMax) {}
|
||||
|
||||
fn idle(_: P0, _: T0) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn j1(_task: Exti0, _prio: P1) {}
|
||||
|
||||
// fake device crate
|
||||
extern crate core;
|
||||
extern crate cortex_m;
|
||||
|
||||
mod device {
|
||||
use cortex_m::peripheral::Peripheral;
|
||||
|
||||
pub const GPIOA: Peripheral<Gpioa> = unsafe { Peripheral::new(0x0) };
|
||||
|
||||
pub struct Gpioa;
|
||||
|
||||
pub mod interrupt {
|
||||
use cortex_m::interrupt::Nr;
|
||||
|
||||
extern "C" fn default_handler<T>(_: T) {}
|
||||
|
||||
pub struct Handlers {
|
||||
pub Exti0: extern "C" fn(Exti0),
|
||||
}
|
||||
|
||||
pub struct Exti0;
|
||||
|
||||
pub enum Interrupt {
|
||||
Exti0,
|
||||
}
|
||||
|
||||
unsafe impl Nr for Interrupt {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub const DEFAULT_HANDLERS: Handlers =
|
||||
Handlers { Exti0: default_handler };
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use rtfm::{C2, P1, P3, Resource, T1, T3};
|
||||
|
||||
static R1: Resource<i32, C2> = Resource::new(0);
|
||||
|
||||
fn j1(prio: P1, thr: T1) {
|
||||
thr.raise(
|
||||
&R1, |thr| {
|
||||
let r1 = R1.access(&prio, thr);
|
||||
|
||||
// `j2` preempts this critical section
|
||||
rtfm::request(j2);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
fn j2(_task: Task, prio: P3, thr: T3) {
|
||||
rtfm::atomic(
|
||||
|thr| {
|
||||
// OK C2 (R1's ceiling) <= T16 (preemption threshold)
|
||||
// BAD C2 (R1's ceiling) < P3 (j2's priority)
|
||||
let r1 = R1.access(&prio, &thr);
|
||||
//~^ error
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// glue
|
||||
extern crate cortex_m;
|
||||
|
||||
use cortex_m::ctxt::Context;
|
||||
use cortex_m::interrupt::Nr;
|
||||
|
||||
struct Task;
|
||||
|
||||
unsafe impl Context for Task {}
|
||||
unsafe impl Nr for Task {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use rtfm::{C2, C4, P1, P3, Resource, T1, T3};
|
||||
|
||||
static R1: Resource<i32, C2> = Resource::new(0);
|
||||
static R2: Resource<i32, C4> = Resource::new(0);
|
||||
|
||||
fn j1(prio: P1, thr: T1) {
|
||||
thr.raise(
|
||||
&R1, |thr| {
|
||||
let r1 = R1.access(&prio, thr);
|
||||
|
||||
// `j2` preempts this critical section
|
||||
rtfm::request(j2);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
fn j2(_task: Task, prio: P3, thr: T3) {
|
||||
thr.raise(
|
||||
&R2, |thr| {
|
||||
// OK C2 (R1's ceiling) <= T4 (preemption threshold)
|
||||
// BAD C2 (R1's ceiling) < P3 (j2's priority)
|
||||
let r1 = R1.access(&prio, thr);
|
||||
//~^ error
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// glue
|
||||
extern crate cortex_m;
|
||||
|
||||
use cortex_m::ctxt::Context;
|
||||
use cortex_m::interrupt::Nr;
|
||||
|
||||
struct Task;
|
||||
|
||||
unsafe impl Context for Task {}
|
||||
unsafe impl Nr for Task {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use rtfm::{C2, CMax, P1, P3, Resource, T1, T3};
|
||||
|
||||
static R1: Resource<i32, C2> = Resource::new(0);
|
||||
|
||||
// You CAN'T use `raise` to lower the preemption level
|
||||
fn j1(prio: P3, thr: T3) {
|
||||
thr.raise(&R1, |thr| {});
|
||||
//~^ error
|
||||
}
|
||||
|
||||
static R2: Resource<i32, CMax> = Resource::new(0);
|
||||
|
||||
// You CAN'T `raise` the preemption level to the maximum
|
||||
fn j2(prio: P1, thr: T1) {
|
||||
thr.raise(&R2, |thr| {});
|
||||
//~^ error
|
||||
|
||||
// Instead use `rtfm::atomic` to access a resource with ceiling C16
|
||||
rtfm::atomic(|thr| {
|
||||
let r2 = R2.access(&prio, thr);
|
||||
});
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
// error-pattern: expected struct `typenum::Equal`, found struct `typenum::Greater`
|
||||
|
||||
#![feature(used)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use rtfm::{P0, P1, T0, T1, TMax};
|
||||
use device::interrupt::Exti0;
|
||||
|
||||
// WRONG: Tasks can't have a priority of 0.
|
||||
// Only idle and init can have a priority of 0.
|
||||
tasks!(device, {
|
||||
j1: Task {
|
||||
interrupt: Exti0,
|
||||
priority: P0,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
fn init(_: P0, _: &TMax) {}
|
||||
|
||||
fn idle(_: P0, _: T0) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn j1(_task: Exti0, _prio: P1, _thr: T1) {}
|
||||
|
||||
// fake device crate
|
||||
extern crate core;
|
||||
extern crate cortex_m;
|
||||
|
||||
mod device {
|
||||
pub mod interrupt {
|
||||
use cortex_m::ctxt::Context;
|
||||
use cortex_m::interrupt::Nr;
|
||||
|
||||
extern "C" fn default_handler<T>(_: T) {}
|
||||
|
||||
pub struct Handlers {
|
||||
pub Exti0: extern "C" fn(Exti0),
|
||||
pub Exti1: extern "C" fn(Exti1),
|
||||
pub Exti2: extern "C" fn(Exti2),
|
||||
}
|
||||
|
||||
pub struct Exti0;
|
||||
pub struct Exti1;
|
||||
pub struct Exti2;
|
||||
|
||||
pub enum Interrupt {
|
||||
Exti0,
|
||||
Exti1,
|
||||
Exti2,
|
||||
}
|
||||
|
||||
unsafe impl Nr for Interrupt {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti0 {}
|
||||
|
||||
unsafe impl Nr for Exti0 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti1 {}
|
||||
|
||||
unsafe impl Nr for Exti1 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti2 {}
|
||||
|
||||
unsafe impl Nr for Exti2 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub const DEFAULT_HANDLERS: Handlers = Handlers {
|
||||
Exti0: default_handler,
|
||||
Exti1: default_handler,
|
||||
Exti2: default_handler,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
// error-pattern: field `Exti0` specified more than once
|
||||
|
||||
#![feature(used)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use rtfm::{P0, P1, P2, T0, T1, T2, TMax};
|
||||
use device::interrupt::{Exti0, Exti1};
|
||||
|
||||
// WRONG: Two tasks mapped to the same interrupt handler
|
||||
tasks!(device, {
|
||||
j1: Task {
|
||||
interrupt: Exti0,
|
||||
priority: P1,
|
||||
enabled: true,
|
||||
},
|
||||
j2: Task {
|
||||
interrupt: Exti0,
|
||||
priority: P2,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
fn init(_: P0, _: &TMax) {}
|
||||
|
||||
fn idle(_: P0, _: T0) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn j1(_task: Exti0, _prio: P1, _thr: T1) {}
|
||||
|
||||
fn j2(_task: Exti0, _prio: P2, _thr: T2) {}
|
||||
|
||||
// fake device crate
|
||||
extern crate core;
|
||||
extern crate cortex_m;
|
||||
|
||||
mod device {
|
||||
pub mod interrupt {
|
||||
use cortex_m::ctxt::Context;
|
||||
use cortex_m::interrupt::Nr;
|
||||
|
||||
extern "C" fn default_handler<T>(_: T) {}
|
||||
|
||||
pub struct Handlers {
|
||||
pub Exti0: extern "C" fn(Exti0),
|
||||
pub Exti1: extern "C" fn(Exti1),
|
||||
pub Exti2: extern "C" fn(Exti2),
|
||||
}
|
||||
|
||||
pub struct Exti0;
|
||||
pub struct Exti1;
|
||||
pub struct Exti2;
|
||||
|
||||
pub enum Interrupt {
|
||||
Exti0,
|
||||
Exti1,
|
||||
Exti2,
|
||||
}
|
||||
|
||||
unsafe impl Nr for Interrupt {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti0 {}
|
||||
|
||||
unsafe impl Nr for Exti0 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti1 {}
|
||||
|
||||
unsafe impl Nr for Exti1 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti2 {}
|
||||
|
||||
unsafe impl Nr for Exti2 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub const DEFAULT_HANDLERS: Handlers = Handlers {
|
||||
Exti0: default_handler,
|
||||
Exti1: default_handler,
|
||||
Exti2: default_handler,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
// error-pattern: mismatched types
|
||||
|
||||
#![feature(used)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use device::interrupt::Exti0;
|
||||
use rtfm::{P0, P1, T0, T1, TMax};
|
||||
|
||||
tasks!(device, {
|
||||
j1: Task {
|
||||
interrupt: Exti0,
|
||||
priority: P1,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
fn init(_: P0, _: &TMax) {}
|
||||
|
||||
// WRONG. `idle` must have signature `fn(P0, C0) -> !`
|
||||
fn idle(_: P0, _: T0) {}
|
||||
|
||||
fn j1(_task: Exti0, _prio: P1, _thr: T1) {}
|
||||
|
||||
// fake device crate
|
||||
extern crate core;
|
||||
extern crate cortex_m;
|
||||
|
||||
mod device {
|
||||
pub mod interrupt {
|
||||
use cortex_m::ctxt::Context;
|
||||
use cortex_m::interrupt::Nr;
|
||||
|
||||
extern "C" fn default_handler<T>(_: T) {}
|
||||
|
||||
pub struct Handlers {
|
||||
pub Exti0: extern "C" fn(Exti0),
|
||||
pub Exti1: extern "C" fn(Exti1),
|
||||
pub Exti2: extern "C" fn(Exti2),
|
||||
}
|
||||
|
||||
pub struct Exti0;
|
||||
pub struct Exti1;
|
||||
pub struct Exti2;
|
||||
|
||||
pub enum Interrupt {
|
||||
Exti0,
|
||||
Exti1,
|
||||
Exti2,
|
||||
}
|
||||
|
||||
unsafe impl Nr for Interrupt {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti0 {}
|
||||
|
||||
unsafe impl Nr for Exti0 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti1 {}
|
||||
|
||||
unsafe impl Nr for Exti1 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti2 {}
|
||||
|
||||
unsafe impl Nr for Exti2 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub const DEFAULT_HANDLERS: Handlers = Handlers {
|
||||
Exti0: default_handler,
|
||||
Exti1: default_handler,
|
||||
Exti2: default_handler,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
// error-pattern: mismatched types
|
||||
|
||||
#![feature(used)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use rtfm::{P0, P1, T0, T1, TMax};
|
||||
use device::interrupt::Exti0;
|
||||
|
||||
tasks!(device, {
|
||||
j1: Task {
|
||||
interrupt: Exti0,
|
||||
priority: P1,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
// WRONG. `init` must have signature `fn(P0, &TMax)`
|
||||
fn init(_: P0, _: &T1) {}
|
||||
|
||||
fn idle(_: P0, _: T0) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn j1(_task: Exti0, _prio: P1, _thr: T1) {}
|
||||
|
||||
// fake device crate
|
||||
extern crate core;
|
||||
extern crate cortex_m;
|
||||
|
||||
mod device {
|
||||
pub mod interrupt {
|
||||
use cortex_m::ctxt::Context;
|
||||
use cortex_m::interrupt::Nr;
|
||||
|
||||
extern "C" fn default_handler<T>(_: T) {}
|
||||
|
||||
pub struct Handlers {
|
||||
pub Exti0: extern "C" fn(Exti0),
|
||||
pub Exti1: extern "C" fn(Exti1),
|
||||
pub Exti2: extern "C" fn(Exti2),
|
||||
}
|
||||
|
||||
pub struct Exti0;
|
||||
pub struct Exti1;
|
||||
pub struct Exti2;
|
||||
|
||||
pub enum Interrupt {
|
||||
Exti0,
|
||||
Exti1,
|
||||
Exti2,
|
||||
}
|
||||
|
||||
unsafe impl Nr for Interrupt {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti0 {}
|
||||
|
||||
unsafe impl Nr for Exti0 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti1 {}
|
||||
|
||||
unsafe impl Nr for Exti1 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti2 {}
|
||||
|
||||
unsafe impl Nr for Exti2 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub const DEFAULT_HANDLERS: Handlers = Handlers {
|
||||
Exti0: default_handler,
|
||||
Exti1: default_handler,
|
||||
Exti2: default_handler,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
// error-pattern: mismatched types
|
||||
|
||||
#![feature(used)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use device::interrupt::Exti0;
|
||||
use rtfm::{P0, P1, P2, T0, T1, T2, TMax};
|
||||
|
||||
tasks!(device, {
|
||||
j1: Task {
|
||||
interrupt: Exti0,
|
||||
priority: P1,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
fn init(_: P0, _: &TMax) {}
|
||||
|
||||
fn idle(_: P0, _: T0) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
// Wrong priority token. Declared P1, got P2
|
||||
fn j1(_task: Exti0, _prio: P2, _thr: T2) {}
|
||||
|
||||
// fake device crate
|
||||
extern crate core;
|
||||
extern crate cortex_m;
|
||||
|
||||
mod device {
|
||||
pub mod interrupt {
|
||||
use cortex_m::ctxt::Context;
|
||||
use cortex_m::interrupt::Nr;
|
||||
|
||||
extern "C" fn default_handler<T>(_: T) {}
|
||||
|
||||
pub struct Handlers {
|
||||
pub Exti0: extern "C" fn(Exti0),
|
||||
pub Exti1: extern "C" fn(Exti1),
|
||||
pub Exti2: extern "C" fn(Exti2),
|
||||
}
|
||||
|
||||
pub struct Exti0;
|
||||
pub struct Exti1;
|
||||
pub struct Exti2;
|
||||
|
||||
pub enum Interrupt {
|
||||
Exti0,
|
||||
Exti1,
|
||||
Exti2,
|
||||
}
|
||||
|
||||
unsafe impl Nr for Interrupt {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti0 {}
|
||||
|
||||
unsafe impl Nr for Exti0 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti1 {}
|
||||
|
||||
unsafe impl Nr for Exti1 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti2 {}
|
||||
|
||||
unsafe impl Nr for Exti2 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub const DEFAULT_HANDLERS: Handlers = Handlers {
|
||||
Exti0: default_handler,
|
||||
Exti1: default_handler,
|
||||
Exti2: default_handler,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
// error-pattern: mismatched types
|
||||
|
||||
#![feature(used)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use device::interrupt::{Exti0, Exti1};
|
||||
use rtfm::{P0, P1, T0, T1, TMax};
|
||||
|
||||
tasks!(device, {
|
||||
j1: Task {
|
||||
interrupt: Exti0,
|
||||
priority: P1,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
fn init(_: P0, _: &TMax) {}
|
||||
|
||||
fn idle(_: P0, _: T0) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
// Wrong task token. Declared Exti0, got Exti1
|
||||
fn j1(_task: Exti1, _prio: P1, _thr: T1) {}
|
||||
|
||||
// fake device crate
|
||||
extern crate core;
|
||||
extern crate cortex_m;
|
||||
|
||||
mod device {
|
||||
pub mod interrupt {
|
||||
use cortex_m::ctxt::Context;
|
||||
use cortex_m::interrupt::Nr;
|
||||
|
||||
extern "C" fn default_handler<T>(_: T) {}
|
||||
|
||||
pub struct Handlers {
|
||||
pub Exti0: extern "C" fn(Exti0),
|
||||
pub Exti1: extern "C" fn(Exti1),
|
||||
pub Exti2: extern "C" fn(Exti2),
|
||||
}
|
||||
|
||||
pub struct Exti0;
|
||||
pub struct Exti1;
|
||||
pub struct Exti2;
|
||||
|
||||
pub enum Interrupt {
|
||||
Exti0,
|
||||
Exti1,
|
||||
Exti2,
|
||||
}
|
||||
|
||||
unsafe impl Nr for Interrupt {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti0 {}
|
||||
|
||||
unsafe impl Nr for Exti0 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti1 {}
|
||||
|
||||
unsafe impl Nr for Exti1 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti2 {}
|
||||
|
||||
unsafe impl Nr for Exti2 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub const DEFAULT_HANDLERS: Handlers = Handlers {
|
||||
Exti0: default_handler,
|
||||
Exti1: default_handler,
|
||||
Exti2: default_handler,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
// error-pattern: mismatched types
|
||||
|
||||
#![feature(used)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use rtfm::{C2, P0, P1, T0, T2, TMax};
|
||||
use device::interrupt::Exti0;
|
||||
|
||||
tasks!(device, {
|
||||
j1: Task {
|
||||
interrupt: Exti0,
|
||||
priority: P1,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
fn init(_: P0, _: &TMax) {}
|
||||
|
||||
fn idle(_: P0, _: T0) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
// Wrong ceiling token. `prio` and `thr` must match in levels
|
||||
fn j1(_task: Exti0, _prio: P1, _thr: T2) {}
|
||||
|
||||
// fake device crate
|
||||
extern crate core;
|
||||
extern crate cortex_m;
|
||||
|
||||
mod device {
|
||||
pub mod interrupt {
|
||||
use cortex_m::ctxt::Context;
|
||||
use cortex_m::interrupt::Nr;
|
||||
|
||||
extern "C" fn default_handler<T>(_: T) {}
|
||||
|
||||
pub struct Handlers {
|
||||
pub Exti0: extern "C" fn(Exti0),
|
||||
pub Exti1: extern "C" fn(Exti1),
|
||||
pub Exti2: extern "C" fn(Exti2),
|
||||
}
|
||||
|
||||
pub struct Exti0;
|
||||
pub struct Exti1;
|
||||
pub struct Exti2;
|
||||
|
||||
pub enum Interrupt {
|
||||
Exti0,
|
||||
Exti1,
|
||||
Exti2,
|
||||
}
|
||||
|
||||
unsafe impl Nr for Interrupt {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti0 {}
|
||||
|
||||
unsafe impl Nr for Exti0 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti1 {}
|
||||
|
||||
unsafe impl Nr for Exti1 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti2 {}
|
||||
|
||||
unsafe impl Nr for Exti2 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub const DEFAULT_HANDLERS: Handlers = Handlers {
|
||||
Exti0: default_handler,
|
||||
Exti1: default_handler,
|
||||
Exti2: default_handler,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
#![feature(const_fn)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
#![feature(used)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cortex_m_rtfm as rtfm;
|
||||
|
||||
use core::cell::RefCell;
|
||||
|
||||
use rtfm::{C2, Local, P0, P1, P2, Resource, T0, T1, T2, TMax};
|
||||
use device::interrupt::{Exti0, Exti1};
|
||||
|
||||
tasks!(device, {
|
||||
t1: Task {
|
||||
interrupt: Exti0,
|
||||
priority: P1,
|
||||
enabled: true,
|
||||
},
|
||||
t2: Task {
|
||||
interrupt: Exti1,
|
||||
priority: P2,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
fn init(_: P0, _: &TMax) {}
|
||||
|
||||
fn idle(_: P0, _: T0) -> ! {
|
||||
rtfm::request(t1);
|
||||
rtfm::request(t1);
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
static CHANNEL: Resource<RefCell<Option<Exti0>>, C2> = {
|
||||
//~^ error: Send
|
||||
Resource::new(RefCell::new(None))
|
||||
};
|
||||
|
||||
static LOCAL: Local<i32, Exti0> = Local::new(0);
|
||||
|
||||
fn t1(mut task: Exti0, ref priority: P1, ref threshold: T1) {
|
||||
// First run
|
||||
static FIRST: Local<bool, Exti0> = Local::new(true);
|
||||
|
||||
let first = *FIRST.borrow(&task);
|
||||
|
||||
if first {
|
||||
// toggle
|
||||
*FIRST.borrow_mut(&mut task) = false;
|
||||
}
|
||||
|
||||
if first {
|
||||
threshold.raise(
|
||||
&CHANNEL, move |threshold| {
|
||||
let channel = CHANNEL.access(priority, threshold);
|
||||
|
||||
// BAD: give up task token
|
||||
*channel.borrow_mut() = Some(task);
|
||||
}
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let _local = LOCAL.borrow_mut(&mut task);
|
||||
|
||||
// ..
|
||||
|
||||
// `t2` will preempt `t1`
|
||||
rtfm::request(t2);
|
||||
|
||||
// ..
|
||||
|
||||
// `LOCAL` mutably borrowed up to this point
|
||||
}
|
||||
|
||||
fn t2(_task: Exti1, ref priority: P2, ref threshold: T2) {
|
||||
let channel = CHANNEL.access(priority, threshold);
|
||||
let mut channel = channel.borrow_mut();
|
||||
|
||||
if let Some(mut other_task) = channel.take() {
|
||||
// BAD: `t2` has access to `t1`'s task token
|
||||
// so it can now mutably access local while `t1` is also using it
|
||||
let _local = LOCAL.borrow_mut(&mut other_task);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// fake device crate
|
||||
extern crate core;
|
||||
extern crate cortex_m;
|
||||
|
||||
mod device {
|
||||
pub mod interrupt {
|
||||
use cortex_m::ctxt::Context;
|
||||
use cortex_m::interrupt::Nr;
|
||||
|
||||
extern "C" fn default_handler<T>(_: T) {}
|
||||
|
||||
pub struct Handlers {
|
||||
pub Exti0: extern "C" fn(Exti0),
|
||||
pub Exti1: extern "C" fn(Exti1),
|
||||
pub Exti2: extern "C" fn(Exti2),
|
||||
}
|
||||
|
||||
pub struct Exti0;
|
||||
pub struct Exti1;
|
||||
pub struct Exti2;
|
||||
|
||||
pub enum Interrupt {
|
||||
Exti0,
|
||||
Exti1,
|
||||
Exti2,
|
||||
}
|
||||
|
||||
unsafe impl Nr for Interrupt {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Context for Exti0 {}
|
||||
|
||||
unsafe impl Nr for Exti0 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl !Send for Exti0 {}
|
||||
|
||||
unsafe impl Context for Exti1 {}
|
||||
|
||||
unsafe impl Nr for Exti1 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl !Send for Exti1 {}
|
||||
|
||||
unsafe impl Context for Exti2 {}
|
||||
|
||||
unsafe impl Nr for Exti2 {
|
||||
fn nr(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl !Send for Exti2 {}
|
||||
|
||||
pub const DEFAULT_HANDLERS: Handlers = Handlers {
|
||||
Exti0: default_handler,
|
||||
Exti1: default_handler,
|
||||
Exti2: default_handler,
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue