Skip to content
Snippets Groups Projects
Commit a94de6ba authored by Jorge Aparicio's avatar Jorge Aparicio
Browse files

wrap references to resources in static-ref's Ref/RefMut

to assert that they point to `static` data
parent 4d8d53a2
No related branches found
No related tags found
No related merge requests found
...@@ -11,6 +11,7 @@ syn = "0.11.10" ...@@ -11,6 +11,7 @@ syn = "0.11.10"
[dependencies] [dependencies]
cortex-m = "0.2.2" cortex-m = "0.2.2"
typenum = "1.7.0" typenum = "1.7.0"
static-ref = { git = "https://github.com/japaric/static-ref" }
[dev-dependencies] [dev-dependencies]
compiletest_rs = "0.2.5" compiletest_rs = "0.2.5"
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#![no_std] #![no_std]
extern crate cortex_m; extern crate cortex_m;
extern crate static_ref;
extern crate typenum; extern crate typenum;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
...@@ -16,6 +17,7 @@ use cortex_m::ctxt::Context; ...@@ -16,6 +17,7 @@ use cortex_m::ctxt::Context;
use cortex_m::interrupt::Nr; use cortex_m::interrupt::Nr;
#[cfg(not(thumbv6m))] #[cfg(not(thumbv6m))]
use cortex_m::register::{basepri, basepri_max}; use cortex_m::register::{basepri, basepri_max};
use static_ref::{Ref, RefMut};
use typenum::{Cmp, Equal, Unsigned}; use typenum::{Cmp, Equal, Unsigned};
#[cfg(not(thumbv6m))] #[cfg(not(thumbv6m))]
use typenum::{Greater, Less}; use typenum::{Greater, Less};
...@@ -64,12 +66,12 @@ impl<T, CEILING> Resource<T, C<CEILING>> { ...@@ -64,12 +66,12 @@ impl<T, CEILING> Resource<T, C<CEILING>> {
&'static self, &'static self,
_priority: &P<PRIORITY>, _priority: &P<PRIORITY>,
_system_ceiling: &'cs C<SCEILING>, _system_ceiling: &'cs C<SCEILING>,
) -> &'cs T ) -> Ref<'cs, T>
where where
SCEILING: GreaterThanOrEqual<CEILING>, SCEILING: GreaterThanOrEqual<CEILING>,
CEILING: GreaterThanOrEqual<PRIORITY>, CEILING: GreaterThanOrEqual<PRIORITY>,
{ {
unsafe { &*self.data.get() } unsafe { Ref::new(&*self.data.get()) }
} }
/// Claims the resource at the task with highest priority /// Claims the resource at the task with highest priority
...@@ -78,11 +80,11 @@ impl<T, CEILING> Resource<T, C<CEILING>> { ...@@ -78,11 +80,11 @@ impl<T, CEILING> Resource<T, C<CEILING>> {
pub fn claim<'task, PRIORITY>( pub fn claim<'task, PRIORITY>(
&'static self, &'static self,
_priority: &'task P<PRIORITY>, _priority: &'task P<PRIORITY>,
) -> &'task T ) -> Ref<'task, T>
where where
CEILING: Cmp<PRIORITY, Output = Equal>, CEILING: Cmp<PRIORITY, Output = Equal>,
{ {
unsafe { &*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
...@@ -90,11 +92,11 @@ impl<T, CEILING> Resource<T, C<CEILING>> { ...@@ -90,11 +92,11 @@ impl<T, CEILING> Resource<T, C<CEILING>> {
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>,
) -> &'task mut T ) -> RefMut<'task, T>
where where
CEILING: Cmp<PRIORITY, Output = Equal>, CEILING: Cmp<PRIORITY, Output = Equal>,
{ {
unsafe { &mut *self.data.get() } unsafe { RefMut::new(&mut *self.data.get()) }
} }
/// Locks the resource for the duration of the critical section `f` /// Locks the resource for the duration of the critical section `f`
...@@ -113,7 +115,7 @@ impl<T, CEILING> Resource<T, C<CEILING>> { ...@@ -113,7 +115,7 @@ impl<T, CEILING> Resource<T, C<CEILING>> {
f: F, f: F,
) -> R ) -> R
where where
F: FnOnce(&T, C<CEILING>) -> R, F: FnOnce(Ref<T>, C<CEILING>) -> R,
CEILING: Cmp<PRIORITY, Output = Greater> + Cmp<UMAX, Output = Less> CEILING: Cmp<PRIORITY, Output = Greater> + Cmp<UMAX, Output = Less>
+ Level, + Level,
{ {
...@@ -121,7 +123,8 @@ impl<T, CEILING> Resource<T, C<CEILING>> { ...@@ -121,7 +123,8 @@ impl<T, CEILING> Resource<T, C<CEILING>> {
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(&*self.data.get(), C { _marker: PhantomData }); let ret =
f(Ref::new(&*self.data.get()), C { _marker: PhantomData });
barrier!(); barrier!();
basepri::write(old_basepri); basepri::write(old_basepri);
ret ret
...@@ -141,7 +144,7 @@ impl<T, CEILING> Resource<T, C<CEILING>> { ...@@ -141,7 +144,7 @@ impl<T, CEILING> Resource<T, C<CEILING>> {
f: F, f: F,
) -> R ) -> R
where where
F: FnOnce(&mut T) -> R, F: FnOnce(RefMut<T>) -> R,
CEILING: Cmp<PRIORITY, Output = Greater> + Cmp<UMAX, Output = Less> CEILING: Cmp<PRIORITY, Output = Greater> + Cmp<UMAX, Output = Less>
+ Level, + Level,
{ {
...@@ -149,7 +152,7 @@ impl<T, CEILING> Resource<T, C<CEILING>> { ...@@ -149,7 +152,7 @@ impl<T, CEILING> Resource<T, C<CEILING>> {
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(&mut *self.data.get()); let ret = f(RefMut::new(&mut *self.data.get()));
barrier!(); barrier!();
basepri::write(old_basepri); basepri::write(old_basepri);
ret ret
...@@ -196,23 +199,23 @@ impl<Periph, CEILING> Peripheral<Periph, C<CEILING>> { ...@@ -196,23 +199,23 @@ impl<Periph, CEILING> Peripheral<Periph, C<CEILING>> {
&'static self, &'static self,
_priority: &P<PRIORITY>, _priority: &P<PRIORITY>,
_system_ceiling: &'cs C<SCEILING>, _system_ceiling: &'cs C<SCEILING>,
) -> &'cs Periph ) -> Ref<'cs, Periph>
where where
SCEILING: GreaterThanOrEqual<CEILING>, SCEILING: GreaterThanOrEqual<CEILING>,
CEILING: GreaterThanOrEqual<PRIORITY>, CEILING: GreaterThanOrEqual<PRIORITY>,
{ {
unsafe { &*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>,
) -> &'task Periph ) -> Ref<'task, Periph>
where where
CEILING: Cmp<PRIORITY, Output = Equal>, CEILING: Cmp<PRIORITY, Output = Equal>,
{ {
unsafe { &*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)
...@@ -223,7 +226,7 @@ impl<Periph, CEILING> Peripheral<Periph, C<CEILING>> { ...@@ -223,7 +226,7 @@ impl<Periph, CEILING> Peripheral<Periph, C<CEILING>> {
f: F, f: F,
) -> R ) -> R
where where
F: FnOnce(&Periph, C<CEILING>) -> R, F: FnOnce(Ref<Periph>, C<CEILING>) -> R,
CEILING: Cmp<PRIORITY, Output = Greater> + Cmp<UMAX, Output = Less> CEILING: Cmp<PRIORITY, Output = Greater> + Cmp<UMAX, Output = Less>
+ Level, + Level,
{ {
...@@ -231,7 +234,10 @@ impl<Periph, CEILING> Peripheral<Periph, C<CEILING>> { ...@@ -231,7 +234,10 @@ impl<Periph, CEILING> Peripheral<Periph, C<CEILING>> {
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(&*self.peripheral.get(), C { _marker: PhantomData }); let ret = f(
Ref::new(&*self.peripheral.get()),
C { _marker: PhantomData },
);
barrier!(); barrier!();
basepri::write(old_basepri); basepri::write(old_basepri);
ret ret
......
...@@ -8,26 +8,26 @@ static R1: Resource<i32, C2> = Resource::new(0); ...@@ -8,26 +8,26 @@ static R1: Resource<i32, C2> = Resource::new(0);
fn j1(mut prio: P2) { fn j1(mut prio: P2) {
// OK only one `&mut-` reference to the data // OK only one `&mut-` reference to the data
let r1: &mut i32 = R1.claim_mut(&mut prio); let r1 = R1.claim_mut(&mut prio);
} }
fn j2(prio: P2) { fn j2(prio: P2) {
// OK two `&-` references to the same data // OK two `&-` references to the same data
let r1: &i32 = R1.claim(&prio); let r1 = R1.claim(&prio);
let another_r1: &i32 = R1.claim(&prio); let another_r1 = R1.claim(&prio);
} }
fn j3(mut prio: P2) { fn j3(mut prio: P2) {
// CAN'T have a `&-` reference and a `&mut-` reference to the same data // CAN'T have a `&-` reference and a `&mut-` reference to the same data
let r1: &i32 = R1.claim(&prio); let r1 = R1.claim(&prio);
let another_r1: &mut i32 = R1.claim_mut(&mut prio); let another_r1 = R1.claim_mut(&mut prio);
//~^ error //~^ error
} }
fn j4(mut prio: P2) { fn j4(mut prio: P2) {
// CAN'T have two `&mut-` references to the same data // CAN'T have two `&mut-` references to the same data
let r1: &mut i32 = R1.claim_mut(&mut prio); let r1 = R1.claim_mut(&mut prio);
let another_r1: &mut i32 = R1.claim_mut(&mut prio); let another_r1 = R1.claim_mut(&mut prio);
//~^ error //~^ error
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment