aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jorge Aparicio <japaricious@gmail.com> 2017-03-11 20:54:10 -0500
committerGravatar Jorge Aparicio <japaricious@gmail.com> 2017-03-11 20:54:10 -0500
commit511d3c90107b4ae5c1b952bbd4597254f39b3474 (patch)
treeb922143c0fa29015737536f16e67b93a70e07237 /src
parente1a67e7a238f5814028956af421636759888d740 (diff)
downloadcortex-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.rs93
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;