nrf: add new interrupt binding traits and macro.
This commit is contained in:
parent
a054891263
commit
42c13c8c3d
@ -13,6 +13,36 @@ pub mod _export {
|
||||
pub use embassy_macros::{cortex_m_interrupt as interrupt, cortex_m_interrupt_declare as declare};
|
||||
}
|
||||
|
||||
/// Interrupt handler trait.
|
||||
///
|
||||
/// Drivers that need to handle interrupts implement this trait.
|
||||
/// The user must ensure `on_interrupt()` is called every time the interrupt fires.
|
||||
/// Drivers must use use [`Binding`] to assert at compile time that the user has done so.
|
||||
pub trait Handler<I: Interrupt> {
|
||||
/// Interrupt handler function.
|
||||
///
|
||||
/// Must be called every time the `I` interrupt fires, synchronously from
|
||||
/// the interrupt handler context.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function must ONLY be called from the interrupt handler for `I`.
|
||||
unsafe fn on_interrupt();
|
||||
}
|
||||
|
||||
/// Compile-time assertion that an interrupt has been bound to a handler.
|
||||
///
|
||||
/// For the vast majority of cases, you should use the `bind_interrupts!`
|
||||
/// macro instead of writing `unsafe impl`s of this trait.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// By implementing this trait, you are asserting that you have arranged for `H::on_interrupt()`
|
||||
/// to be called every time the `I` interrupt fires.
|
||||
///
|
||||
/// This allows drivers to check bindings at compile-time.
|
||||
pub unsafe trait Binding<I: Interrupt, H: Handler<I>> {}
|
||||
|
||||
/// Implementation detail, do not use outside embassy crates.
|
||||
#[doc(hidden)]
|
||||
pub struct DynHandler {
|
||||
|
@ -95,14 +95,39 @@ pub mod wdt;
|
||||
#[cfg_attr(feature = "_nrf9160", path = "chips/nrf9160.rs")]
|
||||
mod chip;
|
||||
|
||||
pub use chip::EASY_DMA_SIZE;
|
||||
|
||||
pub mod interrupt {
|
||||
//! nRF interrupts for cortex-m devices.
|
||||
//! Interrupt definitions and macros to bind them.
|
||||
pub use cortex_m::interrupt::{CriticalSection, Mutex};
|
||||
pub use embassy_cortex_m::interrupt::*;
|
||||
|
||||
pub use crate::chip::irqs::*;
|
||||
|
||||
/// Macro to bind interrupts to handlers.
|
||||
///
|
||||
/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
|
||||
/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to
|
||||
/// prove at compile-time that the right interrupts have been bound.
|
||||
// developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`.
|
||||
#[macro_export]
|
||||
macro_rules! bind_interrupts {
|
||||
($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => {
|
||||
$vis struct $name;
|
||||
|
||||
$(
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn $irq() {
|
||||
$(
|
||||
<$handler as $crate::interrupt::Handler<$crate::interrupt::$irq>>::on_interrupt();
|
||||
)*
|
||||
}
|
||||
|
||||
$(
|
||||
unsafe impl $crate::interrupt::Binding<$crate::interrupt::$irq, $handler> for $name {}
|
||||
)*
|
||||
)*
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Reexports
|
||||
@ -111,7 +136,7 @@ pub mod interrupt {
|
||||
pub use chip::pac;
|
||||
#[cfg(not(feature = "unstable-pac"))]
|
||||
pub(crate) use chip::pac;
|
||||
pub use chip::{peripherals, Peripherals};
|
||||
pub use chip::{peripherals, Peripherals, EASY_DMA_SIZE};
|
||||
pub use embassy_cortex_m::executor;
|
||||
pub use embassy_cortex_m::interrupt::_export::interrupt;
|
||||
pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
|
||||
|
Loading…
Reference in New Issue
Block a user