mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-23 20:22:51 +01:00
split get in get / get_mut
This commit is contained in:
parent
00ef129f87
commit
01c8c3312d
1 changed files with 108 additions and 38 deletions
144
src/lib.rs
144
src/lib.rs
|
@ -34,6 +34,41 @@ unsafe fn task_priority() -> u8 {
|
||||||
hardware((*NVIC.get()).ipr[nr as usize].read())
|
hardware((*NVIC.get()).ipr[nr as usize].read())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
unsafe fn get_check(logical_ceiling: u8) {
|
||||||
|
let task_priority = task_priority();
|
||||||
|
let system_ceiling = hardware(cortex_m::register::basepri::read());
|
||||||
|
let resource_ceiling = logical_ceiling;
|
||||||
|
|
||||||
|
if resource_ceiling < task_priority {
|
||||||
|
panic!(
|
||||||
|
"bad ceiling value. task priority = {}, \
|
||||||
|
resource ceiling = {}",
|
||||||
|
task_priority,
|
||||||
|
resource_ceiling,
|
||||||
|
);
|
||||||
|
} else if resource_ceiling == task_priority {
|
||||||
|
// OK: safe to access the resource without locking in the
|
||||||
|
// task with highest priority
|
||||||
|
} else if resource_ceiling <= system_ceiling {
|
||||||
|
// OK: use within another resource critical section, where
|
||||||
|
// the locked resource has higher or equal ceiling
|
||||||
|
} else {
|
||||||
|
panic!(
|
||||||
|
"racy access to resource. \
|
||||||
|
task priority = {}, \
|
||||||
|
resource ceiling = {}, \
|
||||||
|
system ceiling = {}",
|
||||||
|
task_priority,
|
||||||
|
resource_ceiling,
|
||||||
|
system_ceiling,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
unsafe fn get_check(_: u8) {}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
unsafe fn lock_check(ceiling: u8) {
|
unsafe fn lock_check(ceiling: u8) {
|
||||||
let ceiling = hardware(ceiling);
|
let ceiling = hardware(ceiling);
|
||||||
|
@ -49,7 +84,7 @@ unsafe fn lock_check(ceiling: u8) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
unsafe fn lock_check(_ceiling: u8) {}
|
unsafe fn lock_check(_: u8) {}
|
||||||
|
|
||||||
// XXX Do we need memory / instruction / compiler barriers here?
|
// XXX Do we need memory / instruction / compiler barriers here?
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -149,9 +184,42 @@ where
|
||||||
unsafe { &mut *self.peripheral.get() }
|
unsafe { &mut *self.peripheral.get() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a mutable pointer to the wrapped value
|
/// Returns an immutable reference to the inner data without locking
|
||||||
pub fn get(&self) -> *mut P {
|
///
|
||||||
self.peripheral.get()
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// You must
|
||||||
|
///
|
||||||
|
/// - Preserve the "reference" rules. Don't create an immutable reference if
|
||||||
|
/// the current task already owns a mutable reference to the data.
|
||||||
|
///
|
||||||
|
/// - adhere to the Stack Resource Policy. You can
|
||||||
|
/// - Access the resource from the highest priority task.
|
||||||
|
/// - Access the resource from within a critical section that sets the
|
||||||
|
/// system ceiling to `C`.
|
||||||
|
pub unsafe fn get(&self) -> &'static P {
|
||||||
|
get_check(C::ceiling());
|
||||||
|
|
||||||
|
&*self.peripheral.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable reference to the inner data without locking
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// You must
|
||||||
|
///
|
||||||
|
/// - Preserve the "reference" rules. Don't create a mutable reference if
|
||||||
|
/// the current task already owns a reference to the data.
|
||||||
|
///
|
||||||
|
/// - adhere to the Stack Resource Policy. You can
|
||||||
|
/// - Access the resource from the highest priority task.
|
||||||
|
/// - Access the resource from within a critical section that sets the
|
||||||
|
/// system ceiling to `C`.
|
||||||
|
pub unsafe fn get_mut(&self) -> &'static mut P {
|
||||||
|
get_check(C::ceiling());
|
||||||
|
|
||||||
|
&mut *self.peripheral.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Locks the resource, preventing tasks with priority lower than `Ceiling`
|
/// Locks the resource, preventing tasks with priority lower than `Ceiling`
|
||||||
|
@ -259,41 +327,40 @@ where
|
||||||
unsafe { &mut *self.data.get() }
|
unsafe { &mut *self.data.get() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a mutable reference to the wrapped value
|
/// Returns an immutable reference to the inner data without locking
|
||||||
pub unsafe fn get(&self) -> &'static mut T {
|
///
|
||||||
match () {
|
/// # Safety
|
||||||
#[cfg(debug_assertions)]
|
///
|
||||||
() => {
|
/// You must
|
||||||
let task_priority = task_priority();
|
///
|
||||||
let system_ceiling =
|
/// - Preserve the "reference" rules. Don't create an immutable reference if
|
||||||
hardware(cortex_m::register::basepri::read());
|
/// the current task already owns a mutable reference to the data.
|
||||||
let resource_ceiling = C::ceiling();
|
///
|
||||||
|
/// - adhere to the Stack Resource Policy. You can
|
||||||
|
/// - Access the resource from the highest priority task.
|
||||||
|
/// - Access the resource from within a critical section that sets the
|
||||||
|
/// system ceiling to `C`.
|
||||||
|
pub unsafe fn get(&'static self) -> &'static T {
|
||||||
|
get_check(C::ceiling());
|
||||||
|
|
||||||
if resource_ceiling < task_priority {
|
&*self.data.get()
|
||||||
panic!("bad ceiling value. task priority = {}, \
|
|
||||||
resource ceiling = {}",
|
|
||||||
task_priority,
|
|
||||||
resource_ceiling);
|
|
||||||
} else if resource_ceiling == task_priority {
|
|
||||||
// OK: safe to access the resource without locking in the
|
|
||||||
// task with highest priority
|
|
||||||
} else if resource_ceiling <= system_ceiling {
|
|
||||||
// OK: use within another resource critical section, where
|
|
||||||
// the locked resource has higher or equal ceiling
|
|
||||||
} else {
|
|
||||||
panic!("racy access to resource. \
|
|
||||||
task priority = {}, \
|
|
||||||
resource ceiling = {}, \
|
|
||||||
system ceiling = {}",
|
|
||||||
task_priority,
|
|
||||||
resource_ceiling,
|
|
||||||
system_ceiling);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
/// Returns a mutable reference to the inner data without locking
|
||||||
#[cfg(not(debug_assertions))]
|
///
|
||||||
() => {}
|
/// # Safety
|
||||||
}
|
///
|
||||||
|
/// You must
|
||||||
|
///
|
||||||
|
/// - Preserve the "reference" rules. Don't create a mutable reference if
|
||||||
|
/// the current task already owns a reference to the data.
|
||||||
|
///
|
||||||
|
/// - adhere to the Stack Resource Policy. You can
|
||||||
|
/// - Access the resource from the highest priority task.
|
||||||
|
/// - Access the resource from within a critical section that sets the
|
||||||
|
/// system ceiling to `C`.
|
||||||
|
pub unsafe fn get_mut(&'static self) -> &'static mut T {
|
||||||
|
get_check(C::ceiling());
|
||||||
|
|
||||||
&mut *self.data.get()
|
&mut *self.data.get()
|
||||||
}
|
}
|
||||||
|
@ -365,7 +432,10 @@ pub fn logical(priority: u8) -> u8 {
|
||||||
/// Puts `interrupt` in the "to execute" queue
|
/// Puts `interrupt` in the "to execute" queue
|
||||||
///
|
///
|
||||||
/// This function has no effect if the interrupt was already queued
|
/// This function has no effect if the interrupt was already queued
|
||||||
pub fn queue<I>(interrupt: I) where I: Nr {
|
pub fn queue<I>(interrupt: I)
|
||||||
|
where
|
||||||
|
I: Nr,
|
||||||
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
// NOTE(safe) atomic write
|
// NOTE(safe) atomic write
|
||||||
(*NVIC.get()).set_pending(interrupt)
|
(*NVIC.get()).set_pending(interrupt)
|
||||||
|
|
Loading…
Reference in a new issue