aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJorge Aparicio <japaricious@gmail.com>2017-03-08 08:10:58 -0500
committerJorge Aparicio <japaricious@gmail.com>2017-03-08 08:10:58 -0500
commitd88a15fb2572419dbf80b1c30b3d29b312367813 (patch)
tree288edee9ef2d114cfc2459ef71310bfa07d837cb
parente56f8156bc0efe2a5d505c57514b0956d20329b4 (diff)
adapt to changes in cortex-m, verify the input of the `priority` function
-rw-r--r--Cargo.toml2
-rw-r--r--src/lib.rs166
2 files changed, 63 insertions, 105 deletions
diff --git a/Cargo.toml b/Cargo.toml
index c9d6f7b..c80cb41 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,5 +4,5 @@ version = "0.1.0"
authors = ["Jorge Aparicio <japaricious@gmail.com>"]
[dependencies.cortex-m]
-branch = "svd2rust"
+branch = "ng"
git = "https://github.com/japaric/cortex-m"
diff --git a/src/lib.rs b/src/lib.rs
index 6943b6e..e10b534 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,6 +2,8 @@
//!
//! NOTE ARMv6-M is not supported at the moment.
+#![deny(missing_docs)]
+#![deny(warnings)]
#![feature(asm)]
#![feature(const_fn)]
#![no_std]
@@ -12,146 +14,95 @@ const PRIORITY_BITS: u8 = 4;
extern crate cortex_m;
-use cortex_m::interrupt::CsToken;
+use cortex_m::interrupt::CsCtxt;
+use cortex_m::peripheral::Peripheral;
use cortex_m::register::{basepri, basepri_max};
use core::cell::UnsafeCell;
-use core::marker::PhantomData;
-// XXX why is this needed?
+// XXX Do we need memory / instruction / compiler barriers here?
#[inline(always)]
-fn compiler_barrier() {
- unsafe {
- asm!(""
- :
- :
- : "memory"
- : "volatile")
- }
-}
-
-// XXX why is this needed?
-#[inline(always)]
-fn memory_barrier() {
- unsafe {
- asm!("dsb
- isb"
- :
- :
- : "memory"
- : "volatile")
- }
+unsafe fn claim<T, R, F>(f: F, res: *const T, ceiling: u8) -> R
+ where F: FnOnce(&T) -> R
+{
+ let old_basepri = basepri::read();
+ basepri_max::write(ceiling);
+ let ret = f(&*res);
+ basepri::write(old_basepri);
+ ret
}
-pub struct Peripheral<T>
+/// A peripheral as a resource
+pub struct ResourceP<T>
where T: 'static
{
- _ty: PhantomData<&'static mut T>,
- address: usize,
+ peripheral: Peripheral<T>,
+ // NOTE NVIC-style priority ceiling
ceiling: u8,
}
-impl<T> Peripheral<T> {
- pub const unsafe fn new(address: usize, ceiling: u8) -> Self {
- Peripheral {
- _ty: PhantomData,
- address: address,
- ceiling: ceiling,
+impl<T> ResourceP<T> {
+ /// Wraps a `peripheral` into a `Resource`
+ ///
+ /// NOTE `ceiling` must be in the range `[1, 15]` (inclusive)
+ ///
+ /// # Unsafety
+ ///
+ /// - Do not create two resources that point to the same peripheral
+ pub const unsafe fn new(p: Peripheral<T>, ceiling: u8) -> Self {
+ ResourceP {
+ peripheral: p,
+ // NOTE elements 1 and 2 of the tuple are a poor man's const context
+ // range checker
+ ceiling: (priority(ceiling), ceiling - 1, ceiling + 240).0,
}
}
- pub fn claim<F, R>(&self, f: F) -> R
+ /// Claims the resource, blocking tasks with priority lower than `ceiling`
+ pub fn claim<R, F>(&'static self, f: F) -> R
where F: FnOnce(&T) -> R
{
- unsafe {
- let old_basepri = basepri::read();
- basepri_max::write(priority(self.ceiling));
- memory_barrier();
- let ret = f(&*(self.address as *const T));
- compiler_barrier();
- basepri::write(old_basepri);
- ret
- }
- }
-
- pub fn claim_mut<F, R>(&self, f: F) -> R
- where F: FnOnce(&mut T) -> R
- {
- unsafe {
- let old_basepri = basepri::read();
- basepri_max::write(priority(self.ceiling));
- memory_barrier();
- let ret = f(&mut *(self.address as *mut T));
- compiler_barrier();
- basepri::write(old_basepri);
- ret
- }
+ unsafe { claim(f, self.peripheral.get(), self.ceiling) }
}
- pub fn take<'a>(&self, _token: &'a CsToken) -> &'a T {
- unsafe {
- &*(self.address as *const T)
- }
- }
-
- pub fn take_mut<'a>(&self, _token: &'a CsToken) -> &'a mut T {
- unsafe {
- &mut *(self.address as *mut T)
- }
+ /// Borrows the resource for the duration of a critical section
+ pub fn borrow<'a>(&'static self, _ctxt: &'a CsCtxt) -> &'a T {
+ unsafe { &*self.peripheral.get() }
}
}
+unsafe impl<T> Sync for ResourceP<T> {}
+
+/// A resource
pub struct Resource<T> {
+ // NOTE NVIC-style priority ceiling
ceiling: u8,
data: UnsafeCell<T>,
}
impl<T> Resource<T> {
+ /// Initializes a resource
+ ///
+ /// NOTE `ceiling` must be in the range `[1, 15]`
pub const fn new(data: T, ceiling: u8) -> Self {
Resource {
- ceiling: ceiling,
+ // NOTE elements 1 and 2 of the tuple are a poor man's const context
+ // range checker
+ ceiling: (priority(ceiling), ceiling - 1, ceiling + 240).0,
data: UnsafeCell::new(data),
}
}
- pub fn claim<F, R>(&self, f: F) -> R
+ /// Claims the resource, blocking tasks with priority lower than `ceiling`
+ pub fn claim<F, R>(&'static self, f: F) -> R
where F: FnOnce(&T) -> R
{
- unsafe {
- let old_basepri = basepri::read();
- basepri_max::write(priority(self.ceiling));
- memory_barrier();
- let ret = f(&*self.data.get());
- compiler_barrier();
- basepri::write(old_basepri);
- ret
- }
+ unsafe { claim(f, self.data.get(), self.ceiling) }
}
- pub fn claim_mut<F, R>(&self, f: F) -> R
- where F: FnOnce(&mut T) -> R
- {
- unsafe {
- let old_basepri = basepri::read();
- basepri_max::write(priority(self.ceiling));
- memory_barrier();
- let ret = f(&mut *self.data.get());
- compiler_barrier();
- basepri::write(old_basepri);
- ret
- }
- }
-
- pub fn take<'a>(&self, _token: &'a CsToken) -> &'a T {
- unsafe {
- &*self.data.get()
- }
- }
-
- pub fn take_mut<'a>(&self, _token: &'a CsToken) -> &'a mut T {
- unsafe {
- &mut *self.data.get()
- }
+ /// Borrows the resource for the duration of a critical section
+ pub fn borrow<'cs>(&self, _ctxt: &'cs CsCtxt) -> &'cs T {
+ unsafe { &*self.data.get() }
}
}
@@ -164,7 +115,14 @@ unsafe impl<T> Sync for Resource<T> {}
/// With NVIC priorities, `32` has LOWER priority than `16`. (Also, NVIC
/// priorities encode the actual priority in the highest bits of a byte so
/// priorities like `1` and `2` aren't actually different)
-// TODO review the handling of extreme values
+///
+/// NOTE `logical` must be in the range `[1, 15]` (inclusive)
pub const fn priority(logical: u8) -> u8 {
- ((1 << PRIORITY_BITS) - logical) << (8 - PRIORITY_BITS)
+ // NOTE elements 1 and 2 of the tuple are a poor man's const context range
+ // checker
+ (((1 << PRIORITY_BITS) - logical) << (8 - PRIORITY_BITS),
+ logical - 1,
+ logical + 240)
+ .0
+
}