initial version of checked resources

This commit is contained in:
Jorge Aparicio 2017-04-07 17:34:06 -05:00
parent 759ac160db
commit 2ae638995c
2 changed files with 79 additions and 0 deletions

77
src/checked.rs Normal file
View file

@ -0,0 +1,77 @@
//! Safe, run-time checked resources
use core::marker::PhantomData;
use core::cell::UnsafeCell;
use cortex_m::interrupt;
use cortex_m::register::{basepri, basepri_max};
use Ceiling;
unsafe fn acquire(locked: &UnsafeCell<bool>, ceiling: u8) -> u8 {
interrupt::free(
|_| {
assert!(!*locked.get(), "resource already locked");
let old_basepri = basepri::read();
basepri_max::write(ceiling);
*locked.get() = true;
old_basepri
},
)
}
unsafe fn release(locked: &UnsafeCell<bool>, old_basepri: u8) {
interrupt::free(
|_| {
basepri::write(old_basepri);
*locked.get() = false;
},
);
}
/// A totally safe `Resource` that panics on misuse
pub struct Resource<T, C> {
_marker: PhantomData<C>,
data: UnsafeCell<T>,
locked: UnsafeCell<bool>,
}
impl<T, C> Resource<T, C>
where
C: Ceiling,
{
/// Creates a new `Resource` with ceiling `C`
pub const fn new(data: T) -> Resource<T, C> {
Resource {
_marker: PhantomData,
data: UnsafeCell::new(data),
locked: UnsafeCell::new(false),
}
}
/// Locks the resource, blocking tasks with priority equal or smaller than
/// the ceiling `C`
pub fn lock<F>(&'static self, f: F)
where
F: FnOnce(&T),
{
unsafe {
let old_basepri = acquire(&self.locked, C::ceiling());
f(&*self.data.get());
release(&self.locked, old_basepri);
}
}
/// Mutably locks the resource, blocking tasks with priority equal or
/// smaller than the ceiling `C`
pub fn lock_mut<F>(&'static self, f: F)
where
F: FnOnce(&mut T),
{
unsafe {
let old_basepri = acquire(&self.locked, C::ceiling());
f(&mut *self.data.get());
release(&self.locked, old_basepri);
}
}
}

View file

@ -10,6 +10,8 @@
extern crate cortex_m;
pub mod checked;
use cortex_m::ctxt::Context;
use cortex_m::interrupt::{CriticalSection, Nr};
use cortex_m::peripheral::{Peripheral, NVIC};