add critical, a global critical section

This commit is contained in:
Jorge Aparicio 2017-04-13 23:52:02 -05:00
parent 46baa7ea70
commit 398a5ebc5c
2 changed files with 26 additions and 21 deletions

View file

@ -93,7 +93,7 @@ fn main() {
let u = Ident::new(format!("U{}", (1 << bits))); let u = Ident::new(format!("U{}", (1 << bits)));
tokens.push( tokens.push(
quote! { quote! {
#[doc(hidden)] /// Maximum ceiling
pub type CMAX = C<::typenum::#u>; pub type CMAX = C<::typenum::#u>;
/// Maximum priority level /// Maximum priority level

View file

@ -22,8 +22,6 @@ pub use cortex_m::asm::wfi;
#[doc(hidden)] #[doc(hidden)]
pub use cortex_m::peripheral::NVIC; pub use cortex_m::peripheral::NVIC;
#[doc(hidden)]
pub use cortex_m::interrupt::free;
macro_rules! barrier { macro_rules! barrier {
() => { () => {
@ -128,13 +126,7 @@ where
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(&*self.data.get(), C { _marker: PhantomData });
&*self.data.get(),
C {
_0: (),
_marker: PhantomData,
},
);
barrier!(); barrier!();
basepri::write(old_basepri); basepri::write(old_basepri);
ret ret
@ -252,13 +244,7 @@ where
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(&*self.peripheral.get(), C { _marker: PhantomData });
&*self.peripheral.get(),
C {
_0: (),
_marker: PhantomData,
},
);
barrier!(); barrier!();
basepri::write(old_basepri); basepri::write(old_basepri);
ret ret
@ -272,6 +258,27 @@ where
{ {
} }
/// A global critical section
///
/// No task can preempt this critical section
pub fn critical<R, F>(f: F) -> R
where
F: FnOnce(CMAX) -> R,
{
let primask = ::cortex_m::register::primask::read();
::cortex_m::interrupt::disable();
let r = f(C { _marker: PhantomData });
// If the interrupts were active before our `disable` call, then re-enable
// them. Otherwise, keep them disabled
if primask.is_active() {
::cortex_m::interrupt::enable();
}
r
}
/// Requests the execution of the task `task` /// Requests the execution of the task `task`
pub fn request<T, P>(_task: fn(T, P)) pub fn request<T, P>(_task: fn(T, P))
where where
@ -301,13 +308,11 @@ where
/// A type-level ceiling /// A type-level ceiling
pub struct C<T> { pub struct C<T> {
_0: (),
_marker: PhantomData<T>, _marker: PhantomData<T>,
} }
/// A type-level priority /// A type-level priority
pub struct P<T> { pub struct P<T> {
_0: (),
_marker: PhantomData<T>, _marker: PhantomData<T>,
} }
@ -358,8 +363,8 @@ macro_rules! tasks {
$($task:ident: ($Interrupt:ident, $P:ident),)* $($task:ident: ($Interrupt:ident, $P:ident),)*
}) => { }) => {
fn main() { fn main() {
$crate::free(|_| { $crate::critical(|cmax| {
init(unsafe { ::core::ptr::read(0x0 as *const $crate::CMAX )}); init(cmax);
set_priorities(); set_priorities();
enable_tasks(); enable_tasks();
}); });