pub interface to logical2hw and hw2logical

This commit is contained in:
pln 2017-04-17 18:40:56 +02:00
parent a94de6bafc
commit dad3a1f520

View file

@ -47,8 +47,7 @@ pub struct Resource<T, CEILING> {
impl<T, C> Resource<T, C> { impl<T, C> Resource<T, C> {
/// Creates a new resource with ceiling `C` /// Creates a new resource with ceiling `C`
pub const fn new(data: T) -> Self pub const fn new(data: T) -> Self
where where C: Ceiling
C: Ceiling,
{ {
Resource { Resource {
_ceiling: PhantomData, _ceiling: PhantomData,
@ -62,14 +61,12 @@ impl<T, CEILING> Resource<T, C<CEILING>> {
/// section /// section
/// ///
/// This operation is zero cost and doesn't impose any additional blocking /// This operation is zero cost and doesn't impose any additional blocking
pub fn borrow<'cs, PRIORITY, SCEILING>( pub fn borrow<'cs, PRIORITY, SCEILING>(&'static self,
&'static self,
_priority: &P<PRIORITY>, _priority: &P<PRIORITY>,
_system_ceiling: &'cs C<SCEILING>, _system_ceiling: &'cs C<SCEILING>)
) -> Ref<'cs, T> -> Ref<'cs, T>
where where SCEILING: GreaterThanOrEqual<CEILING>,
SCEILING: GreaterThanOrEqual<CEILING>, CEILING: GreaterThanOrEqual<PRIORITY>
CEILING: GreaterThanOrEqual<PRIORITY>,
{ {
unsafe { Ref::new(&*self.data.get()) } unsafe { Ref::new(&*self.data.get()) }
} }
@ -77,24 +74,18 @@ impl<T, CEILING> Resource<T, C<CEILING>> {
/// Claims the resource at the task with highest priority /// Claims the resource at the task with highest priority
/// ///
/// This operation is zero cost and doesn't impose any additional blocking /// This operation is zero cost and doesn't impose any additional blocking
pub fn claim<'task, PRIORITY>( pub fn claim<'task, PRIORITY>(&'static self, _priority: &'task P<PRIORITY>) -> Ref<'task, T>
&'static self, where CEILING: Cmp<PRIORITY, Output = Equal>
_priority: &'task P<PRIORITY>,
) -> Ref<'task, T>
where
CEILING: Cmp<PRIORITY, Output = Equal>,
{ {
unsafe { Ref::new(&*self.data.get()) } unsafe { Ref::new(&*self.data.get()) }
} }
/// Like [Resource.claim](struct.Resource.html#method.claim) but returns a /// Like [Resource.claim](struct.Resource.html#method.claim) but returns a
/// `&mut-` reference /// `&mut-` reference
pub fn claim_mut<'task, PRIORITY>( pub fn claim_mut<'task, PRIORITY>(&'static self,
&'static self, _priority: &'task mut P<PRIORITY>)
_priority: &'task mut P<PRIORITY>, -> RefMut<'task, T>
) -> RefMut<'task, T> where CEILING: Cmp<PRIORITY, Output = Equal>
where
CEILING: Cmp<PRIORITY, Output = Equal>,
{ {
unsafe { RefMut::new(&mut *self.data.get()) } unsafe { RefMut::new(&mut *self.data.get()) }
} }
@ -109,22 +100,15 @@ impl<T, CEILING> Resource<T, C<CEILING>> {
/// than `CEILING` can be borrowed at zero cost. See /// than `CEILING` can be borrowed at zero cost. See
/// [Resource.borrow](struct.Resource.html#method.borrow). /// [Resource.borrow](struct.Resource.html#method.borrow).
#[cfg(not(thumbv6m))] #[cfg(not(thumbv6m))]
pub fn lock<R, PRIORITY, F>( pub fn lock<R, PRIORITY, F>(&'static self, _priority: &P<PRIORITY>, f: F) -> R
&'static self, where F: FnOnce(Ref<T>, C<CEILING>) -> R,
_priority: &P<PRIORITY>, CEILING: Cmp<PRIORITY, Output = Greater> + Cmp<UMAX, Output = Less> + Level
f: F,
) -> R
where
F: FnOnce(Ref<T>, C<CEILING>) -> R,
CEILING: Cmp<PRIORITY, Output = Greater> + Cmp<UMAX, Output = Less>
+ Level,
{ {
unsafe { unsafe {
let old_basepri = basepri::read(); let old_basepri = basepri::read();
basepri_max::write(<CEILING>::hw()); basepri_max::write(<CEILING>::hw());
barrier!(); barrier!();
let ret = let ret = f(Ref::new(&*self.data.get()), C { _marker: PhantomData });
f(Ref::new(&*self.data.get()), C { _marker: PhantomData });
barrier!(); barrier!();
basepri::write(old_basepri); basepri::write(old_basepri);
ret ret
@ -138,15 +122,9 @@ impl<T, CEILING> Resource<T, C<CEILING>> {
/// resource that has ceiling equal `CEILING`. This constraint is required /// resource that has ceiling equal `CEILING`. This constraint is required
/// to preserve Rust aliasing rules. /// to preserve Rust aliasing rules.
#[cfg(not(thumbv6m))] #[cfg(not(thumbv6m))]
pub fn lock_mut<R, PRIORITY, F>( pub fn lock_mut<R, PRIORITY, F>(&'static self, _priority: &mut P<PRIORITY>, f: F) -> R
&'static self, where F: FnOnce(RefMut<T>) -> R,
_priority: &mut P<PRIORITY>, CEILING: Cmp<PRIORITY, Output = Greater> + Cmp<UMAX, Output = Less> + Level
f: F,
) -> R
where
F: FnOnce(RefMut<T>) -> R,
CEILING: Cmp<PRIORITY, Output = Greater> + Cmp<UMAX, Output = Less>
+ Level,
{ {
unsafe { unsafe {
let old_basepri = basepri::read(); let old_basepri = basepri::read();
@ -160,32 +138,25 @@ impl<T, CEILING> Resource<T, C<CEILING>> {
} }
} }
unsafe impl<T, C> Sync for Resource<T, C> unsafe impl<T, C> Sync for Resource<T, C> where C: Ceiling {}
where
C: Ceiling,
{
}
/// A hardware peripheral as a resource /// A hardware peripheral as a resource
pub struct Peripheral<P, CEILING> pub struct Peripheral<P, CEILING>
where where P: 'static
P: 'static,
{ {
peripheral: cortex_m::peripheral::Peripheral<P>, peripheral: cortex_m::peripheral::Peripheral<P>,
_ceiling: PhantomData<CEILING>, _ceiling: PhantomData<CEILING>,
} }
impl<P, C> Peripheral<P, C> impl<P, C> Peripheral<P, C>
where where C: Ceiling
C: Ceiling,
{ {
/// Assigns a ceiling `C` to the `peripheral` /// Assigns a ceiling `C` to the `peripheral`
/// ///
/// # Safety /// # Safety
/// ///
/// You MUST not create two resources that point to the same peripheral /// You MUST not create two resources that point to the same peripheral
pub const unsafe fn new(peripheral: cortex_m::peripheral::Peripheral<P>,) pub const unsafe fn new(peripheral: cortex_m::peripheral::Peripheral<P>) -> Self {
-> Self {
Peripheral { Peripheral {
_ceiling: PhantomData, _ceiling: PhantomData,
peripheral: peripheral, peripheral: peripheral,
@ -195,49 +166,37 @@ where
impl<Periph, CEILING> Peripheral<Periph, C<CEILING>> { impl<Periph, CEILING> Peripheral<Periph, C<CEILING>> {
/// See [Resource.borrow](./struct.Resource.html#method.borrow) /// See [Resource.borrow](./struct.Resource.html#method.borrow)
pub fn borrow<'cs, PRIORITY, SCEILING>( pub fn borrow<'cs, PRIORITY, SCEILING>(&'static self,
&'static self,
_priority: &P<PRIORITY>, _priority: &P<PRIORITY>,
_system_ceiling: &'cs C<SCEILING>, _system_ceiling: &'cs C<SCEILING>)
) -> Ref<'cs, Periph> -> Ref<'cs, Periph>
where where SCEILING: GreaterThanOrEqual<CEILING>,
SCEILING: GreaterThanOrEqual<CEILING>, CEILING: GreaterThanOrEqual<PRIORITY>
CEILING: GreaterThanOrEqual<PRIORITY>,
{ {
unsafe { Ref::new(&*self.peripheral.get()) } unsafe { Ref::new(&*self.peripheral.get()) }
} }
/// See [Resource.claim](./struct.Resource.html#method.claim) /// See [Resource.claim](./struct.Resource.html#method.claim)
pub fn claim<'task, PRIORITY>( pub fn claim<'task, PRIORITY>(&'static self,
&'static self, _priority: &'task P<PRIORITY>)
_priority: &'task P<PRIORITY>, -> Ref<'task, Periph>
) -> Ref<'task, Periph> where CEILING: Cmp<PRIORITY, Output = Equal>
where
CEILING: Cmp<PRIORITY, Output = Equal>,
{ {
unsafe { Ref::new(&*self.peripheral.get()) } unsafe { Ref::new(&*self.peripheral.get()) }
} }
/// See [Resource.lock](./struct.Resource.html#method.lock) /// See [Resource.lock](./struct.Resource.html#method.lock)
#[cfg(not(thumbv6m))] #[cfg(not(thumbv6m))]
pub fn lock<R, PRIORITY, F>( pub fn lock<R, PRIORITY, F>(&'static self, _priority: &P<PRIORITY>, f: F) -> R
&'static self, where F: FnOnce(Ref<Periph>, C<CEILING>) -> R,
_priority: &P<PRIORITY>, CEILING: Cmp<PRIORITY, Output = Greater> + Cmp<UMAX, Output = Less> + Level
f: F,
) -> R
where
F: FnOnce(Ref<Periph>, C<CEILING>) -> R,
CEILING: Cmp<PRIORITY, Output = Greater> + Cmp<UMAX, Output = Less>
+ Level,
{ {
unsafe { unsafe {
let old_basepri = basepri::read(); let old_basepri = basepri::read();
basepri_max::write(<CEILING>::hw()); basepri_max::write(<CEILING>::hw());
barrier!(); barrier!();
let ret = f( let ret = f(Ref::new(&*self.peripheral.get()),
Ref::new(&*self.peripheral.get()), C { _marker: PhantomData });
C { _marker: PhantomData },
);
barrier!(); barrier!();
basepri::write(old_basepri); basepri::write(old_basepri);
ret ret
@ -245,18 +204,13 @@ impl<Periph, CEILING> Peripheral<Periph, C<CEILING>> {
} }
} }
unsafe impl<T, C> Sync for Peripheral<T, C> unsafe impl<T, C> Sync for Peripheral<T, C> where C: Ceiling {}
where
C: Ceiling,
{
}
/// A global critical section /// A global critical section
/// ///
/// No task can preempt this critical section /// No task can preempt this critical section
pub fn critical<R, F>(f: F) -> R pub fn critical<R, F>(f: F) -> R
where where F: FnOnce(CMAX) -> R
F: FnOnce(CMAX) -> R,
{ {
let primask = ::cortex_m::register::primask::read(); let primask = ::cortex_m::register::primask::read();
::cortex_m::interrupt::disable(); ::cortex_m::interrupt::disable();
@ -274,9 +228,8 @@ where
/// Requests the execution of a `task` /// Requests the execution of a `task`
pub fn request<T, P>(_task: fn(T, P)) pub fn request<T, P>(_task: fn(T, P))
where where T: Context + Nr,
T: Context + Nr, P: Priority
P: Priority,
{ {
let nvic = unsafe { &*NVIC.get() }; let nvic = unsafe { &*NVIC.get() };
@ -310,8 +263,7 @@ pub struct P<T> {
} }
impl<T> P<T> impl<T> P<T>
where where T: Level
T: Level,
{ {
#[doc(hidden)] #[doc(hidden)]
pub fn hw() -> u8 { pub fn hw() -> u8 {
@ -342,10 +294,22 @@ pub unsafe trait Level {
/// DO NOT IMPLEMENT THIS TRAIT YOURSELF /// DO NOT IMPLEMENT THIS TRAIT YOURSELF
pub unsafe trait Priority {} pub unsafe trait Priority {}
fn logical2hw(logical: u8) -> u8 {
/// Convert a logical priority to a shifted hardware prio
/// as used by the NVIC and basepri registers
/// Notice, wrapping causes a panic due to u8
pub fn logical2hw(logical: u8) -> u8 {
((1 << PRIORITY_BITS) - logical) << (8 - PRIORITY_BITS) ((1 << PRIORITY_BITS) - logical) << (8 - PRIORITY_BITS)
} }
/// Convert a shifted hardware prio to a logical priority
/// as used by the NVIC and basepri registers
/// Notice, wrapping causes a panic due to u8
pub fn hw2logical(hw: u8) -> u8 {
(1 << PRIORITY_BITS) - (hw >> (8 - PRIORITY_BITS))
}
/// Priority 0, the lowest priority /// Priority 0, the lowest priority
pub type P0 = P<::typenum::U0>; pub type P0 = P<::typenum::U0>;