mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-25 21:19:35 +01:00
adapt to changes in cortex-m, verify the input of the priority
function
This commit is contained in:
parent
e56f8156bc
commit
d88a15fb25
2 changed files with 63 additions and 105 deletions
|
@ -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"
|
||||
|
|
166
src/lib.rs
166
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")
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// XXX why is this needed?
|
||||
#[inline(always)]
|
||||
fn memory_barrier() {
|
||||
unsafe {
|
||||
asm!("dsb
|
||||
isb"
|
||||
:
|
||||
:
|
||||
: "memory"
|
||||
: "volatile")
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
unsafe { claim(f, self.peripheral.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.address as *mut T));
|
||||
compiler_barrier();
|
||||
basepri::write(old_basepri);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue