mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-26 05:29:38 +01:00
30d6327001
with the upcoming version of heapless we are able to initialize all internal queues in const context removing the need for late initialization this commit also removes the "nightly" feature because all the optimization provided by it are now enabled by default
139 lines
2.9 KiB
Rust
139 lines
2.9 KiB
Rust
//! IMPLEMENTATION DETAILS. DO NOT USE ANYTHING IN THIS MODULE
|
|
|
|
use core::{cell::Cell, u8};
|
|
|
|
#[cfg(armv7m)]
|
|
use cortex_m::register::basepri;
|
|
pub use cortex_m::{
|
|
asm::wfi, interrupt, peripheral::scb::SystemHandler, peripheral::syst::SystClkSource,
|
|
peripheral::Peripherals,
|
|
};
|
|
use heapless::spsc::SingleCore;
|
|
pub use heapless::{consts, i, spsc::Queue};
|
|
|
|
#[cfg(feature = "timer-queue")]
|
|
pub use crate::tq::{NotReady, TimerQueue};
|
|
|
|
pub type FreeQueue<N> = Queue<u8, N, u8, SingleCore>;
|
|
pub type ReadyQueue<T, N> = Queue<(T, u8), N, u8, SingleCore>;
|
|
|
|
#[cfg(armv7m)]
|
|
#[inline(always)]
|
|
pub fn run<F>(priority: u8, f: F)
|
|
where
|
|
F: FnOnce(),
|
|
{
|
|
if priority == 1 {
|
|
// if the priority of this interrupt is `1` then BASEPRI can only be `0`
|
|
f();
|
|
unsafe { basepri::write(0) }
|
|
} else {
|
|
let initial = basepri::read();
|
|
f();
|
|
unsafe { basepri::write(initial) }
|
|
}
|
|
}
|
|
|
|
#[cfg(not(armv7m))]
|
|
#[inline(always)]
|
|
pub fn run<F>(_priority: u8, f: F)
|
|
where
|
|
F: FnOnce(),
|
|
{
|
|
f();
|
|
}
|
|
|
|
// Newtype over `Cell` that forbids mutation through a shared reference
|
|
pub struct Priority {
|
|
inner: Cell<u8>,
|
|
}
|
|
|
|
impl Priority {
|
|
#[inline(always)]
|
|
pub unsafe fn new(value: u8) -> Self {
|
|
Priority {
|
|
inner: Cell::new(value),
|
|
}
|
|
}
|
|
|
|
// these two methods are used by `lock` (see below) but can't be used from the RTFM application
|
|
#[inline(always)]
|
|
fn set(&self, value: u8) {
|
|
self.inner.set(value)
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn get(&self) -> u8 {
|
|
self.inner.get()
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn assert_send<T>()
|
|
where
|
|
T: Send,
|
|
{
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn assert_sync<T>()
|
|
where
|
|
T: Sync,
|
|
{
|
|
}
|
|
|
|
#[cfg(armv7m)]
|
|
#[inline(always)]
|
|
pub unsafe fn lock<T, R>(
|
|
ptr: *mut T,
|
|
priority: &Priority,
|
|
ceiling: u8,
|
|
nvic_prio_bits: u8,
|
|
f: impl FnOnce(&mut T) -> R,
|
|
) -> R {
|
|
let current = priority.get();
|
|
|
|
if current < ceiling {
|
|
if ceiling == (1 << nvic_prio_bits) {
|
|
priority.set(u8::MAX);
|
|
let r = interrupt::free(|_| f(&mut *ptr));
|
|
priority.set(current);
|
|
r
|
|
} else {
|
|
priority.set(ceiling);
|
|
basepri::write(logical2hw(ceiling, nvic_prio_bits));
|
|
let r = f(&mut *ptr);
|
|
basepri::write(logical2hw(current, nvic_prio_bits));
|
|
priority.set(current);
|
|
r
|
|
}
|
|
} else {
|
|
f(&mut *ptr)
|
|
}
|
|
}
|
|
|
|
#[cfg(not(armv7m))]
|
|
#[inline(always)]
|
|
pub unsafe fn lock<T, R>(
|
|
ptr: *mut T,
|
|
priority: &Priority,
|
|
ceiling: u8,
|
|
_nvic_prio_bits: u8,
|
|
f: impl FnOnce(&mut T) -> R,
|
|
) -> R {
|
|
let current = priority.get();
|
|
|
|
if current < ceiling {
|
|
priority.set(u8::MAX);
|
|
let r = interrupt::free(|_| f(&mut *ptr));
|
|
priority.set(current);
|
|
r
|
|
} else {
|
|
f(&mut *ptr)
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn logical2hw(logical: u8, nvic_prio_bits: u8) -> u8 {
|
|
((1 << nvic_prio_bits) - logical) << (8 - nvic_prio_bits)
|
|
}
|