diff options
| author | Ulf Lilleengen <[email protected]> | 2022-06-23 12:59:18 +0200 |
|---|---|---|
| committer | Ulf Lilleengen <[email protected]> | 2022-06-23 13:17:56 +0200 |
| commit | ca59c1ff3570474dc819c2d759c69c3a186ca5bc (patch) | |
| tree | 22f96a5a03cdb43366e8bedf954cad13566328ca /embassy-cortex-m | |
| parent | 6d3a652026d222bb0191c77406e1f4145a64c5f9 (diff) | |
Add more API docs for embassy-cortex-m and embassy-nrf
Diffstat (limited to 'embassy-cortex-m')
| -rw-r--r-- | embassy-cortex-m/src/executor.rs | 7 | ||||
| -rw-r--r-- | embassy-cortex-m/src/interrupt.rs | 54 | ||||
| -rw-r--r-- | embassy-cortex-m/src/lib.rs | 1 | ||||
| -rw-r--r-- | embassy-cortex-m/src/peripheral.rs | 10 |
4 files changed, 69 insertions, 3 deletions
diff --git a/embassy-cortex-m/src/executor.rs b/embassy-cortex-m/src/executor.rs index 34f3ec236..8c7f8cf9d 100644 --- a/embassy-cortex-m/src/executor.rs +++ b/embassy-cortex-m/src/executor.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Executor specific to cortex-m devices. | ||
| 1 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 2 | 3 | ||
| 3 | pub use embassy::executor::Executor; | 4 | pub use embassy::executor::Executor; |
| @@ -60,18 +61,18 @@ impl<I: Interrupt> InterruptExecutor<I> { | |||
| 60 | /// The executor keeps running in the background through the interrupt. | 61 | /// The executor keeps running in the background through the interrupt. |
| 61 | /// | 62 | /// |
| 62 | /// This returns a [`SendSpawner`] you can use to spawn tasks on it. A [`SendSpawner`] | 63 | /// This returns a [`SendSpawner`] you can use to spawn tasks on it. A [`SendSpawner`] |
| 63 | /// is returned instead of a [`Spawner`] because the executor effectively runs in a | 64 | /// is returned instead of a [`Spawner`](embassy::executor::Spawner) because the executor effectively runs in a |
| 64 | /// different "thread" (the interrupt), so spawning tasks on it is effectively | 65 | /// different "thread" (the interrupt), so spawning tasks on it is effectively |
| 65 | /// sending them. | 66 | /// sending them. |
| 66 | /// | 67 | /// |
| 67 | /// To obtain a [`Spawner`] for this executor, use [`Spawner::for_current_executor`] from | 68 | /// To obtain a [`Spawner`](embassy::executor::Spawner) for this executor, use [`Spawner::for_current_executor()`](embassy::executor::Spawner::for_current_executor()) from |
| 68 | /// a task running in it. | 69 | /// a task running in it. |
| 69 | /// | 70 | /// |
| 70 | /// This function requires `&'static mut self`. This means you have to store the | 71 | /// This function requires `&'static mut self`. This means you have to store the |
| 71 | /// Executor instance in a place where it'll live forever and grants you mutable | 72 | /// Executor instance in a place where it'll live forever and grants you mutable |
| 72 | /// access. There's a few ways to do this: | 73 | /// access. There's a few ways to do this: |
| 73 | /// | 74 | /// |
| 74 | /// - a [Forever](crate::util::Forever) (safe) | 75 | /// - a [Forever](embassy::util::Forever) (safe) |
| 75 | /// - a `static mut` (unsafe) | 76 | /// - a `static mut` (unsafe) |
| 76 | /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) | 77 | /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) |
| 77 | pub fn start(&'static mut self) -> SendSpawner { | 78 | pub fn start(&'static mut self) -> SendSpawner { |
diff --git a/embassy-cortex-m/src/interrupt.rs b/embassy-cortex-m/src/interrupt.rs index 72686b402..cd132076f 100644 --- a/embassy-cortex-m/src/interrupt.rs +++ b/embassy-cortex-m/src/interrupt.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Interrupt handling for cortex-m devices. | ||
| 1 | use core::{mem, ptr}; | 2 | use core::{mem, ptr}; |
| 2 | 3 | ||
| 3 | use atomic_polyfill::{compiler_fence, AtomicPtr, Ordering}; | 4 | use atomic_polyfill::{compiler_fence, AtomicPtr, Ordering}; |
| @@ -29,8 +30,16 @@ unsafe impl cortex_m::interrupt::InterruptNumber for NrWrap { | |||
| 29 | } | 30 | } |
| 30 | } | 31 | } |
| 31 | 32 | ||
| 33 | /// Represents an interrupt type that can be configured by embassy to handle | ||
| 34 | /// interrupts. | ||
| 32 | pub unsafe trait Interrupt: Unborrow<Target = Self> { | 35 | pub unsafe trait Interrupt: Unborrow<Target = Self> { |
| 36 | /// Return the NVIC interrupt number for this interrupt. | ||
| 33 | fn number(&self) -> u16; | 37 | fn number(&self) -> u16; |
| 38 | /// Steal an instance of this interrupt | ||
| 39 | /// | ||
| 40 | /// # Safety | ||
| 41 | /// | ||
| 42 | /// This may panic if the interrupt has already been stolen and configured. | ||
| 34 | unsafe fn steal() -> Self; | 43 | unsafe fn steal() -> Self; |
| 35 | 44 | ||
| 36 | /// Implementation detail, do not use outside embassy crates. | 45 | /// Implementation detail, do not use outside embassy crates. |
| @@ -38,19 +47,55 @@ pub unsafe trait Interrupt: Unborrow<Target = Self> { | |||
| 38 | unsafe fn __handler(&self) -> &'static Handler; | 47 | unsafe fn __handler(&self) -> &'static Handler; |
| 39 | } | 48 | } |
| 40 | 49 | ||
| 50 | /// Represents additional behavior for all interrupts. | ||
| 41 | pub trait InterruptExt: Interrupt { | 51 | pub trait InterruptExt: Interrupt { |
| 52 | /// Configure the interrupt handler for this interrupt. | ||
| 53 | /// | ||
| 54 | /// # Safety | ||
| 55 | /// | ||
| 56 | /// It is the responsibility of the caller to ensure the handler | ||
| 57 | /// points to a valid handler as long as interrupts are enabled. | ||
| 42 | fn set_handler(&self, func: unsafe fn(*mut ())); | 58 | fn set_handler(&self, func: unsafe fn(*mut ())); |
| 59 | |||
| 60 | /// Remove the interrupt handler for this interrupt. | ||
| 43 | fn remove_handler(&self); | 61 | fn remove_handler(&self); |
| 62 | |||
| 63 | /// Set point to a context that is passed to the interrupt handler when | ||
| 64 | /// an interrupt is pending. | ||
| 65 | /// | ||
| 66 | /// # Safety | ||
| 67 | /// | ||
| 68 | /// It is the responsibility of the caller to ensure the context | ||
| 69 | /// points to a valid handler as long as interrupts are enabled. | ||
| 44 | fn set_handler_context(&self, ctx: *mut ()); | 70 | fn set_handler_context(&self, ctx: *mut ()); |
| 71 | |||
| 72 | /// Enable the interrupt. Once enabled, the interrupt handler may | ||
| 73 | /// be called "any time". | ||
| 45 | fn enable(&self); | 74 | fn enable(&self); |
| 75 | |||
| 76 | /// Disable the interrupt. | ||
| 46 | fn disable(&self); | 77 | fn disable(&self); |
| 78 | |||
| 79 | /// Check if interrupt is being handled. | ||
| 47 | #[cfg(not(armv6m))] | 80 | #[cfg(not(armv6m))] |
| 48 | fn is_active(&self) -> bool; | 81 | fn is_active(&self) -> bool; |
| 82 | |||
| 83 | /// Check if interrupt is enabled. | ||
| 49 | fn is_enabled(&self) -> bool; | 84 | fn is_enabled(&self) -> bool; |
| 85 | |||
| 86 | /// Check if interrupt is pending. | ||
| 50 | fn is_pending(&self) -> bool; | 87 | fn is_pending(&self) -> bool; |
| 88 | |||
| 89 | /// Set interrupt pending. | ||
| 51 | fn pend(&self); | 90 | fn pend(&self); |
| 91 | |||
| 92 | /// Unset interrupt pending. | ||
| 52 | fn unpend(&self); | 93 | fn unpend(&self); |
| 94 | |||
| 95 | /// Get the priority of the interrupt. | ||
| 53 | fn get_priority(&self) -> Priority; | 96 | fn get_priority(&self) -> Priority; |
| 97 | |||
| 98 | /// Set the interrupt priority. | ||
| 54 | fn set_priority(&self, prio: Priority); | 99 | fn set_priority(&self, prio: Priority); |
| 55 | } | 100 | } |
| 56 | 101 | ||
| @@ -159,6 +204,7 @@ const PRIO_MASK: u8 = 0xfe; | |||
| 159 | #[cfg(feature = "prio-bits-8")] | 204 | #[cfg(feature = "prio-bits-8")] |
| 160 | const PRIO_MASK: u8 = 0xff; | 205 | const PRIO_MASK: u8 = 0xff; |
| 161 | 206 | ||
| 207 | /// The interrupt priority level. | ||
| 162 | #[cfg(feature = "prio-bits-0")] | 208 | #[cfg(feature = "prio-bits-0")] |
| 163 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | 209 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] |
| 164 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 210 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -167,6 +213,7 @@ pub enum Priority { | |||
| 167 | P0 = 0x0, | 213 | P0 = 0x0, |
| 168 | } | 214 | } |
| 169 | 215 | ||
| 216 | /// The interrupt priority level. | ||
| 170 | #[cfg(feature = "prio-bits-1")] | 217 | #[cfg(feature = "prio-bits-1")] |
| 171 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | 218 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] |
| 172 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 219 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -176,6 +223,7 @@ pub enum Priority { | |||
| 176 | P1 = 0x80, | 223 | P1 = 0x80, |
| 177 | } | 224 | } |
| 178 | 225 | ||
| 226 | /// The interrupt priority level. | ||
| 179 | #[cfg(feature = "prio-bits-2")] | 227 | #[cfg(feature = "prio-bits-2")] |
| 180 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | 228 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] |
| 181 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 229 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -187,6 +235,7 @@ pub enum Priority { | |||
| 187 | P3 = 0xc0, | 235 | P3 = 0xc0, |
| 188 | } | 236 | } |
| 189 | 237 | ||
| 238 | /// The interrupt priority level. | ||
| 190 | #[cfg(feature = "prio-bits-3")] | 239 | #[cfg(feature = "prio-bits-3")] |
| 191 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | 240 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] |
| 192 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 241 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -202,6 +251,7 @@ pub enum Priority { | |||
| 202 | P7 = 0xe0, | 251 | P7 = 0xe0, |
| 203 | } | 252 | } |
| 204 | 253 | ||
| 254 | /// The interrupt priority level. | ||
| 205 | #[cfg(feature = "prio-bits-4")] | 255 | #[cfg(feature = "prio-bits-4")] |
| 206 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | 256 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] |
| 207 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 257 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -225,6 +275,7 @@ pub enum Priority { | |||
| 225 | P15 = 0xf0, | 275 | P15 = 0xf0, |
| 226 | } | 276 | } |
| 227 | 277 | ||
| 278 | /// The interrupt priority level. | ||
| 228 | #[cfg(feature = "prio-bits-5")] | 279 | #[cfg(feature = "prio-bits-5")] |
| 229 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | 280 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] |
| 230 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 281 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -264,6 +315,7 @@ pub enum Priority { | |||
| 264 | P31 = 0xf8, | 315 | P31 = 0xf8, |
| 265 | } | 316 | } |
| 266 | 317 | ||
| 318 | /// The interrupt priority level. | ||
| 267 | #[cfg(feature = "prio-bits-6")] | 319 | #[cfg(feature = "prio-bits-6")] |
| 268 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | 320 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] |
| 269 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 321 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -335,6 +387,7 @@ pub enum Priority { | |||
| 335 | P63 = 0xfc, | 387 | P63 = 0xfc, |
| 336 | } | 388 | } |
| 337 | 389 | ||
| 390 | /// The interrupt priority level. | ||
| 338 | #[cfg(feature = "prio-bits-7")] | 391 | #[cfg(feature = "prio-bits-7")] |
| 339 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | 392 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] |
| 340 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 393 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -470,6 +523,7 @@ pub enum Priority { | |||
| 470 | P127 = 0xfe, | 523 | P127 = 0xfe, |
| 471 | } | 524 | } |
| 472 | 525 | ||
| 526 | /// The interrupt priority level. | ||
| 473 | #[cfg(feature = "prio-bits-8")] | 527 | #[cfg(feature = "prio-bits-8")] |
| 474 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | 528 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] |
| 475 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 529 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
diff --git a/embassy-cortex-m/src/lib.rs b/embassy-cortex-m/src/lib.rs index 143c56f39..680c2c8db 100644 --- a/embassy-cortex-m/src/lib.rs +++ b/embassy-cortex-m/src/lib.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Embassy executor and interrupt handling specific to cortex-m devices. | ||
| 1 | #![no_std] | 2 | #![no_std] |
| 2 | 3 | ||
| 3 | // This mod MUST go first, so that the others see its macros. | 4 | // This mod MUST go first, so that the others see its macros. |
diff --git a/embassy-cortex-m/src/peripheral.rs b/embassy-cortex-m/src/peripheral.rs index 5ff690831..6a03bfb9f 100644 --- a/embassy-cortex-m/src/peripheral.rs +++ b/embassy-cortex-m/src/peripheral.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Peripheral interrupt handling specific to cortex-m devices. | ||
| 1 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 2 | use core::mem::MaybeUninit; | 3 | use core::mem::MaybeUninit; |
| 3 | 4 | ||
| @@ -11,18 +12,25 @@ use crate::interrupt::{Interrupt, InterruptExt, Priority}; | |||
| 11 | /// It needs to be `Send` because `&mut` references are sent back and forth between the 'thread' which owns the `PeripheralMutex` and the interrupt, | 12 | /// It needs to be `Send` because `&mut` references are sent back and forth between the 'thread' which owns the `PeripheralMutex` and the interrupt, |
| 12 | /// and `&mut T` is only `Send` where `T: Send`. | 13 | /// and `&mut T` is only `Send` where `T: Send`. |
| 13 | pub trait PeripheralState: Send { | 14 | pub trait PeripheralState: Send { |
| 15 | /// The interrupt that is used for this peripheral. | ||
| 14 | type Interrupt: Interrupt; | 16 | type Interrupt: Interrupt; |
| 17 | |||
| 18 | /// The interrupt handler that should be invoked for the peripheral. Implementations need to clear the appropriate interrupt flags to ensure the handle will not be called again. | ||
| 15 | fn on_interrupt(&mut self); | 19 | fn on_interrupt(&mut self); |
| 16 | } | 20 | } |
| 17 | 21 | ||
| 22 | /// A type for storing the state of a peripheral that can be stored in a static. | ||
| 18 | pub struct StateStorage<S>(MaybeUninit<S>); | 23 | pub struct StateStorage<S>(MaybeUninit<S>); |
| 19 | 24 | ||
| 20 | impl<S> StateStorage<S> { | 25 | impl<S> StateStorage<S> { |
| 26 | /// Create a new instance for storing peripheral state. | ||
| 21 | pub const fn new() -> Self { | 27 | pub const fn new() -> Self { |
| 22 | Self(MaybeUninit::uninit()) | 28 | Self(MaybeUninit::uninit()) |
| 23 | } | 29 | } |
| 24 | } | 30 | } |
| 25 | 31 | ||
| 32 | /// A type for a peripheral that keeps the state of a peripheral that can be accessed from thread mode and an interrupt handler in | ||
| 33 | /// a safe way. | ||
| 26 | pub struct PeripheralMutex<'a, S: PeripheralState> { | 34 | pub struct PeripheralMutex<'a, S: PeripheralState> { |
| 27 | state: *mut S, | 35 | state: *mut S, |
| 28 | _phantom: PhantomData<&'a mut S>, | 36 | _phantom: PhantomData<&'a mut S>, |
| @@ -87,6 +95,8 @@ impl<'a, S: PeripheralState> PeripheralMutex<'a, S> { | |||
| 87 | } | 95 | } |
| 88 | } | 96 | } |
| 89 | 97 | ||
| 98 | /// Access the peripheral state ensuring interrupts are disabled so that the state can be | ||
| 99 | /// safely accessed. | ||
| 90 | pub fn with<R>(&mut self, f: impl FnOnce(&mut S) -> R) -> R { | 100 | pub fn with<R>(&mut self, f: impl FnOnce(&mut S) -> R) -> R { |
| 91 | self.irq.disable(); | 101 | self.irq.disable(); |
| 92 | 102 | ||
