diff options
author | 2017-03-11 20:54:10 -0500 | |
---|---|---|
committer | 2017-03-11 20:54:10 -0500 | |
commit | 511d3c90107b4ae5c1b952bbd4597254f39b3474 (patch) | |
tree | b922143c0fa29015737536f16e67b93a70e07237 /src | |
parent | e1a67e7a238f5814028956af421636759888d740 (diff) | |
download | cortex-m-511d3c90107b4ae5c1b952bbd4597254f39b3474.tar.gz cortex-m-511d3c90107b4ae5c1b952bbd4597254f39b3474.tar.zst cortex-m-511d3c90107b4ae5c1b952bbd4597254f39b3474.zip |
add documentation to the ctxt module
Diffstat (limited to 'src')
-rw-r--r-- | src/ctxt.rs | 93 |
1 files changed, 92 insertions, 1 deletions
diff --git a/src/ctxt.rs b/src/ctxt.rs index 4650ff6..05e578b 100644 --- a/src/ctxt.rs +++ b/src/ctxt.rs @@ -1,4 +1,95 @@ -//! Interrupt / Exception context +//! Interrupt / Exception context local data +//! +//! The main use case is safely adding state to exception / interrupt handlers. +//! +//! This is done in two stages, first you define a token that will appear in the +//! interrupt handler signature; each handler will have its unique token. This +//! token must be zero sized type because interrupt handlers' real signature is +//! `fn()` and it must also implement the `Context` trait. You must also make +//! sure that the token can't be constructed outside of the crate where it's +//! defined. +//! +//! ``` +//! // This must be in a library crate +//! /// Token unique to the TIM7 interrupt handler +//! pub struct Tim7 { _0: () } +//! +//! unsafe impl Context for Tim7 {} +//! ``` +//! +//! Then in the application one can pin data to the interrupt handler using +//! `Local`. +//! +//! ``` +//! // omitted: how to put this handler in the vector table +//! extern "C" fn tim7(ctxt: Tim7) { +//! static STATE: Local<Cell<bool>, Tim7> = Local::new(Cell::new(false)); +//! +//! let state = STATE.borrow(&ctxt); +//! +//! // toggle state +//! state.set(!state.get()); +//! +//! if state.get() { +//! // something +//! } else { +//! // something else +//! } +//! } +//! ``` +//! +//! Note that due to the uniqueness of tokens, other handlers won't be able to +//! access context local data. (Given that you got the signatures right) +//! +//! ``` +//! static TIM3_DATA: Local<Cell<bool>, Tim3> +//! +//! extern "C" fn tim3(ctxt: Tim3) { +//! let data = TIM3_DATA.borrow(&ctxt); +//! } +//! +//! extern "C" fn tim4(ctxt: Tim4) { +//! //let data = TIM3_DATA.borrow(&ctxt); +//! // ^ wouldn't work +//! } +//! ``` +//! +//! To have the application use these tokenized function signatures, you can +//! define, in a library, a `Handlers` struct that represents the vector table: +//! +//! ``` +//! #[repr(C)] +//! pub struct Handlers { +//! tim1: extern "C" fn(Tim1), +//! tim2: extern "C" fn(Tim2), +//! tim3: extern "C" fn(Tim3), +//! tim4: extern "C" fn(Tim4), +//! .. +//! } +//! +//! pub const DEFAULT_HANDLERS: Handlers = Handlers { +//! tim1: default_handler, +//! tim2: default_handler, +//! tim3: default_handler, +//! tim4: default_handler, +//! .. +//! } +//! ``` +//! +//! Then have the user use that `struct` to register the interrupt handlers: +//! +//! ``` +//! extern "C" fn tim3(ctxt: Tim3) { .. } +//! +//! // override the TIM3 interrupt handler +//! #[no_mangle] +//! static _INTERRUPTS: Handlers = Handlers { +//! tim3: tim3, ..DEFAULT_HANDLERS +//! }; +//! ``` +//! +//! This pattern is implemented for exceptions in this crate. See +//! `exception::Handlers` and `exception::DEFAULT_HANDLERS`. use core::marker::PhantomData; use core::cell::UnsafeCell; |