Add more API docs for embassy-cortex-m and embassy-nrf

This commit is contained in:
Ulf Lilleengen
2022-06-23 12:59:18 +02:00
parent 6d3a652026
commit ca59c1ff35
8 changed files with 102 additions and 10 deletions

View File

@ -1,3 +1,4 @@
//! Executor specific to cortex-m devices.
use core::marker::PhantomData;
pub use embassy::executor::Executor;
@ -60,18 +61,18 @@ impl<I: Interrupt> InterruptExecutor<I> {
/// The executor keeps running in the background through the interrupt.
///
/// This returns a [`SendSpawner`] you can use to spawn tasks on it. A [`SendSpawner`]
/// is returned instead of a [`Spawner`] because the executor effectively runs in a
/// is returned instead of a [`Spawner`](embassy::executor::Spawner) because the executor effectively runs in a
/// different "thread" (the interrupt), so spawning tasks on it is effectively
/// sending them.
///
/// To obtain a [`Spawner`] for this executor, use [`Spawner::for_current_executor`] from
/// To obtain a [`Spawner`](embassy::executor::Spawner) for this executor, use [`Spawner::for_current_executor()`](embassy::executor::Spawner::for_current_executor()) from
/// a task running in it.
///
/// This function requires `&'static mut self`. This means you have to store the
/// Executor instance in a place where it'll live forever and grants you mutable
/// access. There's a few ways to do this:
///
/// - a [Forever](crate::util::Forever) (safe)
/// - a [Forever](embassy::util::Forever) (safe)
/// - a `static mut` (unsafe)
/// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
pub fn start(&'static mut self) -> SendSpawner {

View File

@ -1,3 +1,4 @@
//! Interrupt handling for cortex-m devices.
use core::{mem, ptr};
use atomic_polyfill::{compiler_fence, AtomicPtr, Ordering};
@ -29,8 +30,16 @@ unsafe impl cortex_m::interrupt::InterruptNumber for NrWrap {
}
}
/// Represents an interrupt type that can be configured by embassy to handle
/// interrupts.
pub unsafe trait Interrupt: Unborrow<Target = Self> {
/// Return the NVIC interrupt number for this interrupt.
fn number(&self) -> u16;
/// Steal an instance of this interrupt
///
/// # Safety
///
/// This may panic if the interrupt has already been stolen and configured.
unsafe fn steal() -> Self;
/// Implementation detail, do not use outside embassy crates.
@ -38,19 +47,55 @@ pub unsafe trait Interrupt: Unborrow<Target = Self> {
unsafe fn __handler(&self) -> &'static Handler;
}
/// Represents additional behavior for all interrupts.
pub trait InterruptExt: Interrupt {
/// Configure the interrupt handler for this interrupt.
///
/// # Safety
///
/// It is the responsibility of the caller to ensure the handler
/// points to a valid handler as long as interrupts are enabled.
fn set_handler(&self, func: unsafe fn(*mut ()));
/// Remove the interrupt handler for this interrupt.
fn remove_handler(&self);
/// Set point to a context that is passed to the interrupt handler when
/// an interrupt is pending.
///
/// # Safety
///
/// It is the responsibility of the caller to ensure the context
/// points to a valid handler as long as interrupts are enabled.
fn set_handler_context(&self, ctx: *mut ());
/// Enable the interrupt. Once enabled, the interrupt handler may
/// be called "any time".
fn enable(&self);
/// Disable the interrupt.
fn disable(&self);
/// Check if interrupt is being handled.
#[cfg(not(armv6m))]
fn is_active(&self) -> bool;
/// Check if interrupt is enabled.
fn is_enabled(&self) -> bool;
/// Check if interrupt is pending.
fn is_pending(&self) -> bool;
/// Set interrupt pending.
fn pend(&self);
/// Unset interrupt pending.
fn unpend(&self);
/// Get the priority of the interrupt.
fn get_priority(&self) -> Priority;
/// Set the interrupt priority.
fn set_priority(&self, prio: Priority);
}
@ -159,6 +204,7 @@ const PRIO_MASK: u8 = 0xfe;
#[cfg(feature = "prio-bits-8")]
const PRIO_MASK: u8 = 0xff;
/// The interrupt priority level.
#[cfg(feature = "prio-bits-0")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -167,6 +213,7 @@ pub enum Priority {
P0 = 0x0,
}
/// The interrupt priority level.
#[cfg(feature = "prio-bits-1")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -176,6 +223,7 @@ pub enum Priority {
P1 = 0x80,
}
/// The interrupt priority level.
#[cfg(feature = "prio-bits-2")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -187,6 +235,7 @@ pub enum Priority {
P3 = 0xc0,
}
/// The interrupt priority level.
#[cfg(feature = "prio-bits-3")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -202,6 +251,7 @@ pub enum Priority {
P7 = 0xe0,
}
/// The interrupt priority level.
#[cfg(feature = "prio-bits-4")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -225,6 +275,7 @@ pub enum Priority {
P15 = 0xf0,
}
/// The interrupt priority level.
#[cfg(feature = "prio-bits-5")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -264,6 +315,7 @@ pub enum Priority {
P31 = 0xf8,
}
/// The interrupt priority level.
#[cfg(feature = "prio-bits-6")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -335,6 +387,7 @@ pub enum Priority {
P63 = 0xfc,
}
/// The interrupt priority level.
#[cfg(feature = "prio-bits-7")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -470,6 +523,7 @@ pub enum Priority {
P127 = 0xfe,
}
/// The interrupt priority level.
#[cfg(feature = "prio-bits-8")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]

View File

@ -1,3 +1,4 @@
//! Embassy executor and interrupt handling specific to cortex-m devices.
#![no_std]
// This mod MUST go first, so that the others see its macros.

View File

@ -1,3 +1,4 @@
//! Peripheral interrupt handling specific to cortex-m devices.
use core::marker::PhantomData;
use core::mem::MaybeUninit;
@ -11,18 +12,25 @@ use crate::interrupt::{Interrupt, InterruptExt, Priority};
/// 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 {
/// The interrupt that is used for this peripheral.
type Interrupt: Interrupt;
/// 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.
fn on_interrupt(&mut self);
}
/// A type for storing the state of a peripheral that can be stored in a static.
pub struct StateStorage<S>(MaybeUninit<S>);
impl<S> StateStorage<S> {
/// Create a new instance for storing peripheral state.
pub const fn new() -> Self {
Self(MaybeUninit::uninit())
}
}
/// A type for a peripheral that keeps the state of a peripheral that can be accessed from thread mode and an interrupt handler in
/// a safe way.
pub struct PeripheralMutex<'a, S: PeripheralState> {
state: *mut S,
_phantom: PhantomData<&'a mut S>,
@ -87,6 +95,8 @@ impl<'a, S: PeripheralState> PeripheralMutex<'a, S> {
}
}
/// Access the peripheral state ensuring interrupts are disabled so that the state can be
/// safely accessed.
pub fn with<R>(&mut self, f: impl FnOnce(&mut S) -> R) -> R {
self.irq.disable();