aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/checked.rs77
-rw-r--r--src/lib.rs2
2 files changed, 79 insertions, 0 deletions
diff --git a/src/checked.rs b/src/checked.rs
new file mode 100644
index 0000000..836890d
--- /dev/null
+++ b/src/checked.rs
@@ -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);
+ }
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index bf0b7bd..95aa8ba 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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};