mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-24 04:32:52 +01:00
270 lines
7.8 KiB
Text
270 lines
7.8 KiB
Text
|
#![feature(prelude_import)]
|
||
|
//! examples/optlock.rs
|
||
|
|
||
|
#![deny(unsafe_code)]
|
||
|
#![deny(warnings)]
|
||
|
#![no_main]
|
||
|
#![no_std]
|
||
|
#[prelude_import]
|
||
|
use core::prelude::v1::*;
|
||
|
#[macro_use]
|
||
|
extern crate core;
|
||
|
#[macro_use]
|
||
|
extern crate compiler_builtins;
|
||
|
|
||
|
use cortex_m_semihosting::debug;
|
||
|
use lm3s6965::Interrupt;
|
||
|
use panic_semihosting as _;
|
||
|
use rtfm::Exclusive;
|
||
|
|
||
|
#[allow(non_snake_case)]
|
||
|
fn init(_: init::Context) {
|
||
|
rtfm::pend(Interrupt::GPIOA);
|
||
|
}
|
||
|
#[allow(non_snake_case)]
|
||
|
fn gpioa(
|
||
|
// when omitted priority is assumed to be `1`
|
||
|
mut c: gpioa::Context,
|
||
|
) {
|
||
|
use rtfm::Mutex as _;
|
||
|
// the lower priority task requires a critical section to access the data
|
||
|
c.resources.shared.lock(
|
||
|
// data can only be modified within this critical section (closure)
|
||
|
|
||
|
// GPIOB will *not* run right now due to the critical section
|
||
|
|
||
|
// hprintln!("B - shared = {}", *shared).unwrap();
|
||
|
|
||
|
// GPIOC does not contend for `shared` so it's allowed to run now
|
||
|
|shared| {
|
||
|
*shared += 1;
|
||
|
rtfm::pend(Interrupt::GPIOB);
|
||
|
rtfm::pend(Interrupt::GPIOC);
|
||
|
},
|
||
|
);
|
||
|
|
||
|
// critical section is over: GPIOB can now start
|
||
|
|
||
|
debug::exit(debug::EXIT_SUCCESS);
|
||
|
}
|
||
|
#[allow(non_snake_case)]
|
||
|
fn gpiob(mut c: gpiob::Context) {
|
||
|
use rtfm::Mutex as _;
|
||
|
// higher priority task, with critical section
|
||
|
c.resources.shared.lock(|shared| {
|
||
|
*shared += 1;
|
||
|
});
|
||
|
}
|
||
|
#[allow(non_snake_case)]
|
||
|
fn gpioc(c: gpioc::Context) {
|
||
|
use rtfm::Mutex as _;
|
||
|
// highest priority task with critical section
|
||
|
// we wrap resource.shared into an Exclusive
|
||
|
let mut exclusive = Exclusive(c.resources.shared);
|
||
|
// we can access through both lock ...
|
||
|
exclusive.lock(|shared| {
|
||
|
*shared += 1;
|
||
|
});
|
||
|
// and deref, i.e., non-orthogonal design
|
||
|
*exclusive += 1;
|
||
|
}
|
||
|
#[allow(non_snake_case)]
|
||
|
#[doc = "Initialization function"]
|
||
|
pub mod init {
|
||
|
#[doc = r" Execution context"]
|
||
|
pub struct Context {
|
||
|
#[doc = r" Core (Cortex-M) peripherals"]
|
||
|
pub core: rtfm::export::Peripherals,
|
||
|
}
|
||
|
impl Context {
|
||
|
#[inline(always)]
|
||
|
pub unsafe fn new(core: rtfm::export::Peripherals) -> Self {
|
||
|
Context { core }
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
mod resources {
|
||
|
use rtfm::export::Priority;
|
||
|
#[allow(non_camel_case_types)]
|
||
|
pub struct shared<'a> {
|
||
|
priority: &'a Priority,
|
||
|
}
|
||
|
impl<'a> shared<'a> {
|
||
|
#[inline(always)]
|
||
|
pub unsafe fn new(priority: &'a Priority) -> Self {
|
||
|
shared { priority }
|
||
|
}
|
||
|
#[inline(always)]
|
||
|
pub unsafe fn priority(&self) -> &Priority {
|
||
|
self.priority
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#[allow(non_snake_case)]
|
||
|
#[doc = "Resources `gpioa` has access to"]
|
||
|
pub struct gpioaResources<'a> {
|
||
|
pub shared: resources::shared<'a>,
|
||
|
}
|
||
|
#[allow(non_snake_case)]
|
||
|
#[doc = "Hardware task"]
|
||
|
pub mod gpioa {
|
||
|
#[doc(inline)]
|
||
|
pub use super::gpioaResources as Resources;
|
||
|
#[doc = r" Execution context"]
|
||
|
pub struct Context<'a> {
|
||
|
#[doc = r" Resources this task has access to"]
|
||
|
pub resources: Resources<'a>,
|
||
|
}
|
||
|
impl<'a> Context<'a> {
|
||
|
#[inline(always)]
|
||
|
pub unsafe fn new(priority: &'a rtfm::export::Priority) -> Self {
|
||
|
Context {
|
||
|
resources: Resources::new(priority),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#[allow(non_snake_case)]
|
||
|
#[doc = "Resources `gpiob` has access to"]
|
||
|
pub struct gpiobResources<'a> {
|
||
|
pub shared: resources::shared<'a>,
|
||
|
}
|
||
|
#[allow(non_snake_case)]
|
||
|
#[doc = "Hardware task"]
|
||
|
pub mod gpiob {
|
||
|
#[doc(inline)]
|
||
|
pub use super::gpiobResources as Resources;
|
||
|
#[doc = r" Execution context"]
|
||
|
pub struct Context<'a> {
|
||
|
#[doc = r" Resources this task has access to"]
|
||
|
pub resources: Resources<'a>,
|
||
|
}
|
||
|
impl<'a> Context<'a> {
|
||
|
#[inline(always)]
|
||
|
pub unsafe fn new(priority: &'a rtfm::export::Priority) -> Self {
|
||
|
Context {
|
||
|
resources: Resources::new(priority),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#[allow(non_snake_case)]
|
||
|
#[doc = "Resources `gpioc` has access to"]
|
||
|
pub struct gpiocResources<'a> {
|
||
|
pub shared: &'a mut u32,
|
||
|
}
|
||
|
#[allow(non_snake_case)]
|
||
|
#[doc = "Hardware task"]
|
||
|
pub mod gpioc {
|
||
|
#[doc(inline)]
|
||
|
pub use super::gpiocResources as Resources;
|
||
|
#[doc = r" Execution context"]
|
||
|
pub struct Context<'a> {
|
||
|
#[doc = r" Resources this task has access to"]
|
||
|
pub resources: Resources<'a>,
|
||
|
}
|
||
|
impl<'a> Context<'a> {
|
||
|
#[inline(always)]
|
||
|
pub unsafe fn new(priority: &'a rtfm::export::Priority) -> Self {
|
||
|
Context {
|
||
|
resources: Resources::new(priority),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#[doc = r" Implementation details"]
|
||
|
const APP: () = {
|
||
|
#[doc = r" Always include the device crate which contains the vector table"]
|
||
|
use lm3s6965 as _;
|
||
|
#[allow(non_upper_case_globals)]
|
||
|
static mut shared: u32 = 0;
|
||
|
impl<'a> rtfm::Mutex for resources::shared<'a> {
|
||
|
type T = u32;
|
||
|
#[inline(always)]
|
||
|
fn lock<R>(&mut self, f: impl FnOnce(&mut u32) -> R) -> R {
|
||
|
#[doc = r" Priority ceiling"]
|
||
|
const CEILING: u8 = 3u8;
|
||
|
unsafe {
|
||
|
rtfm::export::lock(
|
||
|
&mut shared,
|
||
|
self.priority(),
|
||
|
CEILING,
|
||
|
lm3s6965::NVIC_PRIO_BITS,
|
||
|
f,
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#[allow(non_snake_case)]
|
||
|
#[no_mangle]
|
||
|
unsafe fn GPIOA() {
|
||
|
const PRIORITY: u8 = 1u8;
|
||
|
crate::gpioa(gpioa::Context::new(&rtfm::export::Priority::new(PRIORITY)));
|
||
|
}
|
||
|
impl<'a> gpioaResources<'a> {
|
||
|
#[inline(always)]
|
||
|
unsafe fn new(priority: &'a rtfm::export::Priority) -> Self {
|
||
|
gpioaResources {
|
||
|
shared: resources::shared::new(priority),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#[allow(non_snake_case)]
|
||
|
#[no_mangle]
|
||
|
unsafe fn GPIOB() {
|
||
|
const PRIORITY: u8 = 2u8;
|
||
|
crate::gpiob(gpiob::Context::new(&rtfm::export::Priority::new(PRIORITY)));
|
||
|
}
|
||
|
impl<'a> gpiobResources<'a> {
|
||
|
#[inline(always)]
|
||
|
unsafe fn new(priority: &'a rtfm::export::Priority) -> Self {
|
||
|
gpiobResources {
|
||
|
shared: resources::shared::new(priority),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#[allow(non_snake_case)]
|
||
|
#[no_mangle]
|
||
|
unsafe fn GPIOC() {
|
||
|
const PRIORITY: u8 = 3u8;
|
||
|
crate::gpioc(gpioc::Context::new(&rtfm::export::Priority::new(PRIORITY)));
|
||
|
}
|
||
|
impl<'a> gpiocResources<'a> {
|
||
|
#[inline(always)]
|
||
|
unsafe fn new(priority: &'a rtfm::export::Priority) -> Self {
|
||
|
gpiocResources {
|
||
|
shared: &mut shared,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#[no_mangle]
|
||
|
unsafe extern "C" fn main() -> ! {
|
||
|
rtfm::export::interrupt::disable();
|
||
|
let mut core: rtfm::export::Peripherals = core::mem::transmute(());
|
||
|
let _ = [(); ((1 << lm3s6965::NVIC_PRIO_BITS) - 1u8 as usize)];
|
||
|
core.NVIC.set_priority(
|
||
|
lm3s6965::Interrupt::GPIOA,
|
||
|
rtfm::export::logical2hw(1u8, lm3s6965::NVIC_PRIO_BITS),
|
||
|
);
|
||
|
rtfm::export::NVIC::unmask(lm3s6965::Interrupt::GPIOA);
|
||
|
let _ = [(); ((1 << lm3s6965::NVIC_PRIO_BITS) - 2u8 as usize)];
|
||
|
core.NVIC.set_priority(
|
||
|
lm3s6965::Interrupt::GPIOB,
|
||
|
rtfm::export::logical2hw(2u8, lm3s6965::NVIC_PRIO_BITS),
|
||
|
);
|
||
|
rtfm::export::NVIC::unmask(lm3s6965::Interrupt::GPIOB);
|
||
|
let _ = [(); ((1 << lm3s6965::NVIC_PRIO_BITS) - 3u8 as usize)];
|
||
|
core.NVIC.set_priority(
|
||
|
lm3s6965::Interrupt::GPIOC,
|
||
|
rtfm::export::logical2hw(3u8, lm3s6965::NVIC_PRIO_BITS),
|
||
|
);
|
||
|
rtfm::export::NVIC::unmask(lm3s6965::Interrupt::GPIOC);
|
||
|
core.SCB.scr.modify(|r| r | 1 << 1);
|
||
|
let late = init(init::Context::new(core.into()));
|
||
|
rtfm::export::interrupt::enable();
|
||
|
loop {
|
||
|
rtfm::export::wfi()
|
||
|
}
|
||
|
}
|
||
|
};
|