Add embassy-cortex-m crate.

- Move Interrupt and InterruptExecutor from `embassy` to `embassy-cortex-m`.
- Move Unborrow from `embassy` to `embassy-hal-common` (nothing in `embassy` requires it anymore)
- Move PeripheralMutex from `embassy-hal-common` to `embassy-cortex-m`.
This commit is contained in:
Dario Nieuwenhuis
2022-06-11 05:08:57 +02:00
parent db344c2bda
commit 5085100df2
104 changed files with 814 additions and 460 deletions

View File

@ -1,571 +0,0 @@
use core::mem;
macro_rules! prio {
($name:ident, $mask:expr, ($($k:ident = $v:expr,)*)) => {
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum $name {
$($k = $v),*
}
impl From<u8> for $name {
fn from(priority: u8) -> Self {
unsafe { mem::transmute(priority & $mask) }
}
}
impl From<$name> for u8 {
fn from(p: $name) -> Self {
p as u8
}
}
};
}
#[rustfmt::skip]
prio!(Priority0, 0x00, (
P0 = 0x0,
));
#[rustfmt::skip]
prio!(Priority1, 0x80, (
P0 = 0x0,
P1 = 0x80,
));
#[rustfmt::skip]
prio!(Priority2, 0xc0, (
P0 = 0x0,
P1 = 0x40,
P2 = 0x80,
P3 = 0xc0,
));
#[rustfmt::skip]
prio!(Priority3, 0xe0, (
P0 = 0x0,
P1 = 0x20,
P2 = 0x40,
P3 = 0x60,
P4 = 0x80,
P5 = 0xa0,
P6 = 0xc0,
P7 = 0xe0,
));
#[rustfmt::skip]
prio!(Priority4, 0xf0, (
P0 = 0x0,
P1 = 0x10,
P2 = 0x20,
P3 = 0x30,
P4 = 0x40,
P5 = 0x50,
P6 = 0x60,
P7 = 0x70,
P8 = 0x80,
P9 = 0x90,
P10 = 0xa0,
P11 = 0xb0,
P12 = 0xc0,
P13 = 0xd0,
P14 = 0xe0,
P15 = 0xf0,
));
#[rustfmt::skip]
prio!(Priority5, 0xf8, (
P0 = 0x0,
P1 = 0x8,
P2 = 0x10,
P3 = 0x18,
P4 = 0x20,
P5 = 0x28,
P6 = 0x30,
P7 = 0x38,
P8 = 0x40,
P9 = 0x48,
P10 = 0x50,
P11 = 0x58,
P12 = 0x60,
P13 = 0x68,
P14 = 0x70,
P15 = 0x78,
P16 = 0x80,
P17 = 0x88,
P18 = 0x90,
P19 = 0x98,
P20 = 0xa0,
P21 = 0xa8,
P22 = 0xb0,
P23 = 0xb8,
P24 = 0xc0,
P25 = 0xc8,
P26 = 0xd0,
P27 = 0xd8,
P28 = 0xe0,
P29 = 0xe8,
P30 = 0xf0,
P31 = 0xf8,
));
#[rustfmt::skip]
prio!(Priority6, 0xfc, (
P0 = 0x0,
P1 = 0x4,
P2 = 0x8,
P3 = 0xc,
P4 = 0x10,
P5 = 0x14,
P6 = 0x18,
P7 = 0x1c,
P8 = 0x20,
P9 = 0x24,
P10 = 0x28,
P11 = 0x2c,
P12 = 0x30,
P13 = 0x34,
P14 = 0x38,
P15 = 0x3c,
P16 = 0x40,
P17 = 0x44,
P18 = 0x48,
P19 = 0x4c,
P20 = 0x50,
P21 = 0x54,
P22 = 0x58,
P23 = 0x5c,
P24 = 0x60,
P25 = 0x64,
P26 = 0x68,
P27 = 0x6c,
P28 = 0x70,
P29 = 0x74,
P30 = 0x78,
P31 = 0x7c,
P32 = 0x80,
P33 = 0x84,
P34 = 0x88,
P35 = 0x8c,
P36 = 0x90,
P37 = 0x94,
P38 = 0x98,
P39 = 0x9c,
P40 = 0xa0,
P41 = 0xa4,
P42 = 0xa8,
P43 = 0xac,
P44 = 0xb0,
P45 = 0xb4,
P46 = 0xb8,
P47 = 0xbc,
P48 = 0xc0,
P49 = 0xc4,
P50 = 0xc8,
P51 = 0xcc,
P52 = 0xd0,
P53 = 0xd4,
P54 = 0xd8,
P55 = 0xdc,
P56 = 0xe0,
P57 = 0xe4,
P58 = 0xe8,
P59 = 0xec,
P60 = 0xf0,
P61 = 0xf4,
P62 = 0xf8,
P63 = 0xfc,
));
#[rustfmt::skip]
prio!(Priority7, 0xfe, (
P0 = 0x0,
P1 = 0x2,
P2 = 0x4,
P3 = 0x6,
P4 = 0x8,
P5 = 0xa,
P6 = 0xc,
P7 = 0xe,
P8 = 0x10,
P9 = 0x12,
P10 = 0x14,
P11 = 0x16,
P12 = 0x18,
P13 = 0x1a,
P14 = 0x1c,
P15 = 0x1e,
P16 = 0x20,
P17 = 0x22,
P18 = 0x24,
P19 = 0x26,
P20 = 0x28,
P21 = 0x2a,
P22 = 0x2c,
P23 = 0x2e,
P24 = 0x30,
P25 = 0x32,
P26 = 0x34,
P27 = 0x36,
P28 = 0x38,
P29 = 0x3a,
P30 = 0x3c,
P31 = 0x3e,
P32 = 0x40,
P33 = 0x42,
P34 = 0x44,
P35 = 0x46,
P36 = 0x48,
P37 = 0x4a,
P38 = 0x4c,
P39 = 0x4e,
P40 = 0x50,
P41 = 0x52,
P42 = 0x54,
P43 = 0x56,
P44 = 0x58,
P45 = 0x5a,
P46 = 0x5c,
P47 = 0x5e,
P48 = 0x60,
P49 = 0x62,
P50 = 0x64,
P51 = 0x66,
P52 = 0x68,
P53 = 0x6a,
P54 = 0x6c,
P55 = 0x6e,
P56 = 0x70,
P57 = 0x72,
P58 = 0x74,
P59 = 0x76,
P60 = 0x78,
P61 = 0x7a,
P62 = 0x7c,
P63 = 0x7e,
P64 = 0x80,
P65 = 0x82,
P66 = 0x84,
P67 = 0x86,
P68 = 0x88,
P69 = 0x8a,
P70 = 0x8c,
P71 = 0x8e,
P72 = 0x90,
P73 = 0x92,
P74 = 0x94,
P75 = 0x96,
P76 = 0x98,
P77 = 0x9a,
P78 = 0x9c,
P79 = 0x9e,
P80 = 0xa0,
P81 = 0xa2,
P82 = 0xa4,
P83 = 0xa6,
P84 = 0xa8,
P85 = 0xaa,
P86 = 0xac,
P87 = 0xae,
P88 = 0xb0,
P89 = 0xb2,
P90 = 0xb4,
P91 = 0xb6,
P92 = 0xb8,
P93 = 0xba,
P94 = 0xbc,
P95 = 0xbe,
P96 = 0xc0,
P97 = 0xc2,
P98 = 0xc4,
P99 = 0xc6,
P100 = 0xc8,
P101 = 0xca,
P102 = 0xcc,
P103 = 0xce,
P104 = 0xd0,
P105 = 0xd2,
P106 = 0xd4,
P107 = 0xd6,
P108 = 0xd8,
P109 = 0xda,
P110 = 0xdc,
P111 = 0xde,
P112 = 0xe0,
P113 = 0xe2,
P114 = 0xe4,
P115 = 0xe6,
P116 = 0xe8,
P117 = 0xea,
P118 = 0xec,
P119 = 0xee,
P120 = 0xf0,
P121 = 0xf2,
P122 = 0xf4,
P123 = 0xf6,
P124 = 0xf8,
P125 = 0xfa,
P126 = 0xfc,
P127 = 0xfe,
));
#[rustfmt::skip]
prio!(Priority8, 0xff, (
P0 = 0x0,
P1 = 0x1,
P2 = 0x2,
P3 = 0x3,
P4 = 0x4,
P5 = 0x5,
P6 = 0x6,
P7 = 0x7,
P8 = 0x8,
P9 = 0x9,
P10 = 0xa,
P11 = 0xb,
P12 = 0xc,
P13 = 0xd,
P14 = 0xe,
P15 = 0xf,
P16 = 0x10,
P17 = 0x11,
P18 = 0x12,
P19 = 0x13,
P20 = 0x14,
P21 = 0x15,
P22 = 0x16,
P23 = 0x17,
P24 = 0x18,
P25 = 0x19,
P26 = 0x1a,
P27 = 0x1b,
P28 = 0x1c,
P29 = 0x1d,
P30 = 0x1e,
P31 = 0x1f,
P32 = 0x20,
P33 = 0x21,
P34 = 0x22,
P35 = 0x23,
P36 = 0x24,
P37 = 0x25,
P38 = 0x26,
P39 = 0x27,
P40 = 0x28,
P41 = 0x29,
P42 = 0x2a,
P43 = 0x2b,
P44 = 0x2c,
P45 = 0x2d,
P46 = 0x2e,
P47 = 0x2f,
P48 = 0x30,
P49 = 0x31,
P50 = 0x32,
P51 = 0x33,
P52 = 0x34,
P53 = 0x35,
P54 = 0x36,
P55 = 0x37,
P56 = 0x38,
P57 = 0x39,
P58 = 0x3a,
P59 = 0x3b,
P60 = 0x3c,
P61 = 0x3d,
P62 = 0x3e,
P63 = 0x3f,
P64 = 0x40,
P65 = 0x41,
P66 = 0x42,
P67 = 0x43,
P68 = 0x44,
P69 = 0x45,
P70 = 0x46,
P71 = 0x47,
P72 = 0x48,
P73 = 0x49,
P74 = 0x4a,
P75 = 0x4b,
P76 = 0x4c,
P77 = 0x4d,
P78 = 0x4e,
P79 = 0x4f,
P80 = 0x50,
P81 = 0x51,
P82 = 0x52,
P83 = 0x53,
P84 = 0x54,
P85 = 0x55,
P86 = 0x56,
P87 = 0x57,
P88 = 0x58,
P89 = 0x59,
P90 = 0x5a,
P91 = 0x5b,
P92 = 0x5c,
P93 = 0x5d,
P94 = 0x5e,
P95 = 0x5f,
P96 = 0x60,
P97 = 0x61,
P98 = 0x62,
P99 = 0x63,
P100 = 0x64,
P101 = 0x65,
P102 = 0x66,
P103 = 0x67,
P104 = 0x68,
P105 = 0x69,
P106 = 0x6a,
P107 = 0x6b,
P108 = 0x6c,
P109 = 0x6d,
P110 = 0x6e,
P111 = 0x6f,
P112 = 0x70,
P113 = 0x71,
P114 = 0x72,
P115 = 0x73,
P116 = 0x74,
P117 = 0x75,
P118 = 0x76,
P119 = 0x77,
P120 = 0x78,
P121 = 0x79,
P122 = 0x7a,
P123 = 0x7b,
P124 = 0x7c,
P125 = 0x7d,
P126 = 0x7e,
P127 = 0x7f,
P128 = 0x80,
P129 = 0x81,
P130 = 0x82,
P131 = 0x83,
P132 = 0x84,
P133 = 0x85,
P134 = 0x86,
P135 = 0x87,
P136 = 0x88,
P137 = 0x89,
P138 = 0x8a,
P139 = 0x8b,
P140 = 0x8c,
P141 = 0x8d,
P142 = 0x8e,
P143 = 0x8f,
P144 = 0x90,
P145 = 0x91,
P146 = 0x92,
P147 = 0x93,
P148 = 0x94,
P149 = 0x95,
P150 = 0x96,
P151 = 0x97,
P152 = 0x98,
P153 = 0x99,
P154 = 0x9a,
P155 = 0x9b,
P156 = 0x9c,
P157 = 0x9d,
P158 = 0x9e,
P159 = 0x9f,
P160 = 0xa0,
P161 = 0xa1,
P162 = 0xa2,
P163 = 0xa3,
P164 = 0xa4,
P165 = 0xa5,
P166 = 0xa6,
P167 = 0xa7,
P168 = 0xa8,
P169 = 0xa9,
P170 = 0xaa,
P171 = 0xab,
P172 = 0xac,
P173 = 0xad,
P174 = 0xae,
P175 = 0xaf,
P176 = 0xb0,
P177 = 0xb1,
P178 = 0xb2,
P179 = 0xb3,
P180 = 0xb4,
P181 = 0xb5,
P182 = 0xb6,
P183 = 0xb7,
P184 = 0xb8,
P185 = 0xb9,
P186 = 0xba,
P187 = 0xbb,
P188 = 0xbc,
P189 = 0xbd,
P190 = 0xbe,
P191 = 0xbf,
P192 = 0xc0,
P193 = 0xc1,
P194 = 0xc2,
P195 = 0xc3,
P196 = 0xc4,
P197 = 0xc5,
P198 = 0xc6,
P199 = 0xc7,
P200 = 0xc8,
P201 = 0xc9,
P202 = 0xca,
P203 = 0xcb,
P204 = 0xcc,
P205 = 0xcd,
P206 = 0xce,
P207 = 0xcf,
P208 = 0xd0,
P209 = 0xd1,
P210 = 0xd2,
P211 = 0xd3,
P212 = 0xd4,
P213 = 0xd5,
P214 = 0xd6,
P215 = 0xd7,
P216 = 0xd8,
P217 = 0xd9,
P218 = 0xda,
P219 = 0xdb,
P220 = 0xdc,
P221 = 0xdd,
P222 = 0xde,
P223 = 0xdf,
P224 = 0xe0,
P225 = 0xe1,
P226 = 0xe2,
P227 = 0xe3,
P228 = 0xe4,
P229 = 0xe5,
P230 = 0xe6,
P231 = 0xe7,
P232 = 0xe8,
P233 = 0xe9,
P234 = 0xea,
P235 = 0xeb,
P236 = 0xec,
P237 = 0xed,
P238 = 0xee,
P239 = 0xef,
P240 = 0xf0,
P241 = 0xf1,
P242 = 0xf2,
P243 = 0xf3,
P244 = 0xf4,
P245 = 0xf5,
P246 = 0xf6,
P247 = 0xf7,
P248 = 0xf8,
P249 = 0xf9,
P250 = 0xfa,
P251 = 0xfb,
P252 = 0xfc,
P253 = 0xfd,
P254 = 0xfe,
P255 = 0xff,
));

View File

@ -5,11 +5,11 @@
pub(crate) mod fmt;
pub mod drop;
pub mod interrupt;
mod macros;
pub mod peripheral;
pub mod ratio;
pub mod ring_buffer;
mod unborrow;
pub use unborrow::Unborrow;
/// Low power blocking wait loop using WFE/SEV.
pub fn low_power_wait_until(mut condition: impl FnMut() -> bool) {

View File

@ -16,7 +16,7 @@ macro_rules! peripherals {
}
$(#[$cfg])?
unsafe impl embassy::util::Unborrow for $name {
unsafe impl $crate::Unborrow for $name {
type Target = $name;
#[inline]
unsafe fn unborrow(self) -> $name {
@ -80,7 +80,7 @@ macro_rules! unborrow {
#[macro_export]
macro_rules! unsafe_impl_unborrow {
($type:ident) => {
unsafe impl ::embassy::util::Unborrow for $type {
unsafe impl $crate::Unborrow for $type {
type Target = $type;
#[inline]
unsafe fn unborrow(self) -> Self::Target {

View File

@ -1,134 +0,0 @@
use core::marker::PhantomData;
use core::mem::MaybeUninit;
use cortex_m::peripheral::scb::VectActive;
use cortex_m::peripheral::{NVIC, SCB};
use embassy::interrupt::{Interrupt, InterruptExt};
/// A type which can be used as state with `PeripheralMutex`.
///
/// It needs to be `Send` because `&mut` references are sent back and forth between the 'thread' which owns the `PeripheralMutex` and the interrupt,
/// and `&mut T` is only `Send` where `T: Send`.
pub trait PeripheralState: Send {
type Interrupt: Interrupt;
fn on_interrupt(&mut self);
}
pub struct StateStorage<S>(MaybeUninit<S>);
impl<S> StateStorage<S> {
pub const fn new() -> Self {
Self(MaybeUninit::uninit())
}
}
pub struct PeripheralMutex<'a, S: PeripheralState> {
state: *mut S,
_phantom: PhantomData<&'a mut S>,
irq: S::Interrupt,
}
/// Whether `irq` can be preempted by the current interrupt.
pub(crate) fn can_be_preempted(irq: &impl Interrupt) -> bool {
match SCB::vect_active() {
// Thread mode can't preempt anything.
VectActive::ThreadMode => false,
// Exceptions don't always preempt interrupts,
// but there isn't much of a good reason to be keeping a `PeripheralMutex` in an exception anyway.
VectActive::Exception(_) => true,
VectActive::Interrupt { irqn } => {
#[derive(Clone, Copy)]
struct NrWrap(u16);
unsafe impl cortex_m::interrupt::InterruptNumber for NrWrap {
fn number(self) -> u16 {
self.0
}
}
NVIC::get_priority(NrWrap(irqn.into())) < irq.get_priority().into()
}
}
}
impl<'a, S: PeripheralState> PeripheralMutex<'a, S> {
/// Create a new `PeripheralMutex` wrapping `irq`, with `init` initializing the initial state.
///
/// Registers `on_interrupt` as the `irq`'s handler, and enables it.
pub fn new(
irq: S::Interrupt,
storage: &'a mut StateStorage<S>,
init: impl FnOnce() -> S,
) -> Self {
if can_be_preempted(&irq) {
panic!("`PeripheralMutex` cannot be created in an interrupt with higher priority than the interrupt it wraps");
}
let state_ptr = storage.0.as_mut_ptr();
// Safety: The pointer is valid and not used by anyone else
// because we have the `&mut StateStorage`.
unsafe { state_ptr.write(init()) };
irq.disable();
irq.set_handler(|p| unsafe {
// Safety: it's OK to get a &mut to the state, since
// - We checked that the thread owning the `PeripheralMutex` can't preempt us in `new`.
// Interrupts' priorities can only be changed with raw embassy `Interrupts`,
// which can't safely store a `PeripheralMutex` across invocations.
// - We can't have preempted a with() call because the irq is disabled during it.
let state = &mut *(p as *mut S);
state.on_interrupt();
});
irq.set_handler_context(state_ptr as *mut ());
irq.enable();
Self {
irq,
state: state_ptr,
_phantom: PhantomData,
}
}
pub fn with<R>(&mut self, f: impl FnOnce(&mut S) -> R) -> R {
self.irq.disable();
// Safety: it's OK to get a &mut to the state, since the irq is disabled.
let state = unsafe { &mut *self.state };
let r = f(state);
self.irq.enable();
r
}
/// Returns whether the wrapped interrupt is currently in a pending state.
pub fn is_pending(&self) -> bool {
self.irq.is_pending()
}
/// Forces the wrapped interrupt into a pending state.
pub fn pend(&self) {
self.irq.pend()
}
/// Forces the wrapped interrupt out of a pending state.
pub fn unpend(&self) {
self.irq.unpend()
}
/// Gets the priority of the wrapped interrupt.
pub fn priority(&self) -> <S::Interrupt as Interrupt>::Priority {
self.irq.get_priority()
}
}
impl<'a, S: PeripheralState> Drop for PeripheralMutex<'a, S> {
fn drop(&mut self) {
self.irq.disable();
self.irq.remove_handler();
// safety:
// - we initialized the state in `new`, so we know it's initialized.
// - the irq is disabled, so it won't preempt us while dropping.
unsafe { self.state.drop_in_place() }
}
}

View File

@ -0,0 +1,60 @@
/// Unsafely unborrow an owned singleton out of a `&mut`.
///
/// It is intended to be implemented for owned peripheral singletons, such as `USART3` or `AnyPin`.
/// Unborrowing an owned `T` yields the same `T`. Unborrowing a `&mut T` yields a copy of the T.
///
/// This allows writing HAL drivers that either own or borrow their peripherals, but that don't have
/// to store pointers in the borrowed case.
///
/// Safety: this trait can be used to copy non-Copy types. Implementors must not cause
/// immediate UB when copied, and must not cause UB when copies are later used, provided they
/// are only used according the [`Self::unborrow`] safety contract.
///
pub unsafe trait Unborrow {
/// Unborrow result type
type Target;
/// Unborrow a value.
///
/// Safety: This returns a copy of a singleton that's normally not
/// copiable. The returned copy must ONLY be used while the lifetime of `self` is
/// valid, as if it were accessed through `self` every time.
unsafe fn unborrow(self) -> Self::Target;
}
unsafe impl<'a, T: Unborrow> Unborrow for &'a mut T {
type Target = T::Target;
unsafe fn unborrow(self) -> Self::Target {
T::unborrow(core::ptr::read(self))
}
}
macro_rules! unsafe_impl_unborrow_tuples {
($($t:ident),+) => {
unsafe impl<$($t),+> Unborrow for ($($t),+)
where
$(
$t: Unborrow<Target = $t>
),+
{
type Target = ($($t),+);
unsafe fn unborrow(self) -> Self::Target {
self
}
}
};
}
unsafe_impl_unborrow_tuples!(A, B);
unsafe_impl_unborrow_tuples!(A, B, C);
unsafe_impl_unborrow_tuples!(A, B, C, D);
unsafe_impl_unborrow_tuples!(A, B, C, D, E);
unsafe_impl_unborrow_tuples!(A, B, C, D, E, F);
unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G);
unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H);
unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I);
unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I, J);
unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I, J, K);
unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I, J, K, L);