mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-29 15:04:32 +01:00
old style claim using unsafe sell and manual check
This commit is contained in:
parent
4e6818eb2c
commit
a568afaf27
1 changed files with 252 additions and 1 deletions
253
src/lib.rs
253
src/lib.rs
|
@ -10,7 +10,7 @@ extern crate cortex_m;
|
||||||
extern crate static_ref;
|
extern crate static_ref;
|
||||||
extern crate typenum;
|
extern crate typenum;
|
||||||
|
|
||||||
use core::cell::UnsafeCell;
|
use core::cell::{Cell, UnsafeCell};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use cortex_m::ctxt::Context;
|
use cortex_m::ctxt::Context;
|
||||||
|
@ -28,6 +28,8 @@ pub use cortex_m::asm::{bkpt, wfi};
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use cortex_m::peripheral::NVIC;
|
pub use cortex_m::peripheral::NVIC;
|
||||||
|
|
||||||
|
use typenum::type_operators::*;
|
||||||
|
|
||||||
macro_rules! barrier {
|
macro_rules! barrier {
|
||||||
() => {
|
() => {
|
||||||
asm!(""
|
asm!(""
|
||||||
|
@ -57,6 +59,36 @@ impl<T, C> Resource<T, C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
enum State {
|
||||||
|
Free,
|
||||||
|
// Locked,
|
||||||
|
LockedMut,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A resource
|
||||||
|
pub struct Res<T, CEILING> {
|
||||||
|
_ceiling: PhantomData<CEILING>,
|
||||||
|
_state: Cell<State>,
|
||||||
|
//_state: State,
|
||||||
|
data: UnsafeCell<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, C> Res<T, C> {
|
||||||
|
/// Creates a new resource with ceiling `C`
|
||||||
|
pub const fn new(data: T) -> Self
|
||||||
|
where
|
||||||
|
C: Ceiling,
|
||||||
|
{
|
||||||
|
Res {
|
||||||
|
_ceiling: PhantomData,
|
||||||
|
_state: Cell::new(State::Free),
|
||||||
|
// _state: State::Free,
|
||||||
|
data: UnsafeCell::new(data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T, CEILING> Resource<T, C<CEILING>> {
|
impl<T, CEILING> Resource<T, C<CEILING>> {
|
||||||
/// Borrows the resource for the duration of another resource's critical
|
/// Borrows the resource for the duration of another resource's critical
|
||||||
/// section
|
/// section
|
||||||
|
@ -99,6 +131,88 @@ impl<T, CEILING> Resource<T, C<CEILING>> {
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Locks the resource for the duration of the critical section `f`
|
||||||
|
///
|
||||||
|
/// For the duration of the critical section, tasks whose priority level is
|
||||||
|
/// smaller than or equal to the resource `CEILING` will be prevented from
|
||||||
|
/// preempting the current task.
|
||||||
|
///
|
||||||
|
/// Within this critical section, resources with ceiling equal to or smaller
|
||||||
|
/// than `CEILING` can be borrowed at zero cost. See
|
||||||
|
/// [Resource.borrow](struct.Resource.html#method.borrow).
|
||||||
|
#[cfg(not(thumbv6m))]
|
||||||
|
pub fn mock<R, PRIOTASK, CURRCEIL, F>(
|
||||||
|
&'static self,
|
||||||
|
_prio: &P<PRIOTASK>,
|
||||||
|
_curr_ceil: &C<CURRCEIL>,
|
||||||
|
f: F,
|
||||||
|
) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(Ref<T>, &C<<CEILING as Max<CURRCEIL>>::Output>) -> R,
|
||||||
|
PRIOTASK: Unsigned,
|
||||||
|
CURRCEIL: Unsigned,
|
||||||
|
CEILING: GreaterThanOrEqual<PRIOTASK> + Max<CURRCEIL> + Level + Unsigned,
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
let c1 = <CURRCEIL>::to_u8();
|
||||||
|
let c2 = <CEILING>::to_u8();
|
||||||
|
if c2 > c1 {
|
||||||
|
let old_basepri = basepri::read();
|
||||||
|
basepri_max::write(<CEILING>::hw());
|
||||||
|
barrier!();
|
||||||
|
let ret =
|
||||||
|
f(Ref::new(&*self.data.get()), &C { _marker: PhantomData });
|
||||||
|
barrier!();
|
||||||
|
basepri::write(old_basepri);
|
||||||
|
ret
|
||||||
|
} else {
|
||||||
|
f(Ref::new(&*self.data.get()), &C { _marker: PhantomData })
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Locks the resource for the duration of the critical section `f`
|
||||||
|
///
|
||||||
|
/// For the duration of the critical section, tasks whose priority level is
|
||||||
|
/// smaller than or equal to the resource `CEILING` will be prevented from
|
||||||
|
/// preempting the current task.
|
||||||
|
///
|
||||||
|
/// Within this critical section, resources with ceiling equal to or smaller
|
||||||
|
/// than `CEILING` can be borrowed at zero cost. See
|
||||||
|
/// [Resource.borrow](struct.Resource.html#method.borrow).
|
||||||
|
#[cfg(not(thumbv6m))]
|
||||||
|
pub fn claim<R, PRIOTASK, CURRCEIL, F>(
|
||||||
|
&'static self,
|
||||||
|
_prio: &P<PRIOTASK>,
|
||||||
|
_curr_ceil: &C<CURRCEIL>,
|
||||||
|
f: F,
|
||||||
|
) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(Ref<T>, &C<<CEILING as Max<CURRCEIL>>::Output>) -> R,
|
||||||
|
PRIOTASK: Unsigned,
|
||||||
|
CURRCEIL: Unsigned,
|
||||||
|
CEILING: GreaterThanOrEqual<PRIOTASK> + Max<CURRCEIL> + Level + Unsigned,
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
let c1 = <CURRCEIL>::to_u8();
|
||||||
|
let c2 = <CEILING>::to_u8();
|
||||||
|
if c2 > c1 {
|
||||||
|
let old_basepri = basepri::read();
|
||||||
|
basepri_max::write(<CEILING>::hw());
|
||||||
|
barrier!();
|
||||||
|
let ret =
|
||||||
|
f(Ref::new(&*self.data.get()), &C { _marker: PhantomData });
|
||||||
|
barrier!();
|
||||||
|
basepri::write(old_basepri);
|
||||||
|
ret
|
||||||
|
} else {
|
||||||
|
f(Ref::new(&*self.data.get()), &C { _marker: PhantomData })
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T, C> Sync for Resource<T, C>
|
unsafe impl<T, C> Sync for Resource<T, C>
|
||||||
|
@ -107,6 +221,142 @@ where
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// re-implementation of the original claim API
|
||||||
|
impl<T, CEILING> Res<T, C<CEILING>> {
|
||||||
|
/// Locks the resource for the duration of the critical section `f`
|
||||||
|
///
|
||||||
|
/// For the duration of the critical section, tasks whose priority level is
|
||||||
|
/// smaller than or equal to the resource `CEILING` will be prevented from
|
||||||
|
/// preempting the current task.
|
||||||
|
///
|
||||||
|
/// Within this critical section, resources with ceiling equal to or smaller
|
||||||
|
/// than `CEILING` can be borrowed at zero cost. See
|
||||||
|
/// [Resource.borrow](struct.Resource.html#method.borrow).
|
||||||
|
#[cfg(not(thumbv6m))]
|
||||||
|
pub fn claim<R, PRIOTASK, CURRCEIL, F>(
|
||||||
|
&'static self,
|
||||||
|
_prio: &P<PRIOTASK>,
|
||||||
|
_curr_ceil: &C<CURRCEIL>,
|
||||||
|
f: F,
|
||||||
|
) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(Ref<T>, &C<<CEILING as Max<CURRCEIL>>::Output>) -> R,
|
||||||
|
PRIOTASK: Unsigned,
|
||||||
|
CURRCEIL: Unsigned,
|
||||||
|
CEILING: GreaterThanOrEqual<PRIOTASK> + Max<CURRCEIL> + Level + Unsigned,
|
||||||
|
{
|
||||||
|
|
||||||
|
match self._state.get() {
|
||||||
|
State::LockedMut => panic!("Resource already locked)"),
|
||||||
|
_ => unsafe {
|
||||||
|
let c1 = <CURRCEIL>::to_u8();
|
||||||
|
let c2 = <CEILING>::to_u8();
|
||||||
|
if c2 > c1 {
|
||||||
|
let old_basepri = basepri::read();
|
||||||
|
basepri_max::write(<CEILING>::hw());
|
||||||
|
barrier!();
|
||||||
|
let s = self._state.get();
|
||||||
|
self._state.set(State::LockedMut);
|
||||||
|
barrier!();
|
||||||
|
|
||||||
|
let ret = f(
|
||||||
|
Ref::new(&*self.data.get()),
|
||||||
|
&C { _marker: PhantomData },
|
||||||
|
);
|
||||||
|
|
||||||
|
barrier!();
|
||||||
|
self._state.set(s);
|
||||||
|
barrier!();
|
||||||
|
basepri::write(old_basepri);
|
||||||
|
ret
|
||||||
|
} else {
|
||||||
|
let s = self._state.get();
|
||||||
|
self._state.set(State::LockedMut);
|
||||||
|
barrier!();
|
||||||
|
|
||||||
|
let ret = f(
|
||||||
|
Ref::new(&*self.data.get()),
|
||||||
|
&C { _marker: PhantomData },
|
||||||
|
);
|
||||||
|
|
||||||
|
barrier!();
|
||||||
|
self._state.set(s);
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Locks the resource for the duration of the critical section `f`
|
||||||
|
///
|
||||||
|
/// For the duration of the critical section, tasks whose priority level is
|
||||||
|
/// smaller than or equal to the resource `CEILING` will be prevented from
|
||||||
|
/// preempting the current task.
|
||||||
|
///
|
||||||
|
/// Within this critical section, resources with ceiling equal to or smaller
|
||||||
|
/// than `CEILING` can be borrowed at zero cost. See
|
||||||
|
/// [Resource.borrow](struct.Resource.html#method.borrow).
|
||||||
|
#[cfg(not(thumbv6m))]
|
||||||
|
pub fn claim_mut<R, PRIOTASK, CURRCEIL, F>(
|
||||||
|
&'static self,
|
||||||
|
_prio: &P<PRIOTASK>,
|
||||||
|
_curr_ceil: &C<CURRCEIL>,
|
||||||
|
f: F,
|
||||||
|
) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut T, &C<<CEILING as Max<CURRCEIL>>::Output>) -> R,
|
||||||
|
PRIOTASK: Unsigned,
|
||||||
|
CURRCEIL: Unsigned,
|
||||||
|
CEILING: GreaterThanOrEqual<PRIOTASK> + Max<CURRCEIL> + Level + Unsigned,
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
match self._state.get() {
|
||||||
|
State::Free => {
|
||||||
|
let c1 = <CURRCEIL>::to_u8();
|
||||||
|
let c2 = <CEILING>::to_u8();
|
||||||
|
if c2 > c1 {
|
||||||
|
let old_basepri = basepri::read();
|
||||||
|
basepri_max::write(<CEILING>::hw());
|
||||||
|
barrier!();
|
||||||
|
self._state.set(State::LockedMut);
|
||||||
|
barrier!();
|
||||||
|
|
||||||
|
let ret = f(
|
||||||
|
&mut *self.data.get(),
|
||||||
|
&C { _marker: PhantomData },
|
||||||
|
);
|
||||||
|
|
||||||
|
barrier!();
|
||||||
|
self._state.set(State::Free);
|
||||||
|
barrier!();
|
||||||
|
basepri::write(old_basepri);
|
||||||
|
ret
|
||||||
|
} else {
|
||||||
|
self._state.set(State::LockedMut);
|
||||||
|
barrier!();
|
||||||
|
|
||||||
|
let ret = f(
|
||||||
|
&mut *self.data.get(),
|
||||||
|
&C { _marker: PhantomData },
|
||||||
|
);
|
||||||
|
|
||||||
|
barrier!();
|
||||||
|
self._state.set(State::Free);
|
||||||
|
ret
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("Resource already locked)"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T, C> Sync for Res<T, C>
|
||||||
|
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
|
||||||
|
@ -223,6 +473,7 @@ where
|
||||||
nvic.set_pending(task);
|
nvic.set_pending(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// A type-level ceiling
|
/// A type-level ceiling
|
||||||
pub struct C<T> {
|
pub struct C<T> {
|
||||||
_marker: PhantomData<T>,
|
_marker: PhantomData<T>,
|
||||||
|
|
Loading…
Reference in a new issue