aboutsummaryrefslogtreecommitdiff
path: root/embassy-cortex-m/src
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2022-06-23 12:59:18 +0200
committerUlf Lilleengen <[email protected]>2022-06-23 13:17:56 +0200
commitca59c1ff3570474dc819c2d759c69c3a186ca5bc (patch)
tree22f96a5a03cdb43366e8bedf954cad13566328ca /embassy-cortex-m/src
parent6d3a652026d222bb0191c77406e1f4145a64c5f9 (diff)
Add more API docs for embassy-cortex-m and embassy-nrf
Diffstat (limited to 'embassy-cortex-m/src')
-rw-r--r--embassy-cortex-m/src/executor.rs7
-rw-r--r--embassy-cortex-m/src/interrupt.rs54
-rw-r--r--embassy-cortex-m/src/lib.rs1
-rw-r--r--embassy-cortex-m/src/peripheral.rs10
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.
1use core::marker::PhantomData; 2use core::marker::PhantomData;
2 3
3pub use embassy::executor::Executor; 4pub 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.
1use core::{mem, ptr}; 2use core::{mem, ptr};
2 3
3use atomic_polyfill::{compiler_fence, AtomicPtr, Ordering}; 4use 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.
32pub unsafe trait Interrupt: Unborrow<Target = Self> { 35pub 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.
41pub trait InterruptExt: Interrupt { 51pub 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")]
160const PRIO_MASK: u8 = 0xff; 205const 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.
1use core::marker::PhantomData; 2use core::marker::PhantomData;
2use core::mem::MaybeUninit; 3use 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`.
13pub trait PeripheralState: Send { 14pub 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.
18pub struct StateStorage<S>(MaybeUninit<S>); 23pub struct StateStorage<S>(MaybeUninit<S>);
19 24
20impl<S> StateStorage<S> { 25impl<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.
26pub struct PeripheralMutex<'a, S: PeripheralState> { 34pub 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