Skip to content

Commit 511d3c9

Browse files
author
Jorge Aparicio
committed
add documentation to the ctxt module
1 parent e1a67e7 commit 511d3c9

File tree

1 file changed

+92
-1
lines changed

1 file changed

+92
-1
lines changed

src/ctxt.rs

+92-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,95 @@
1-
//! Interrupt / Exception context
1+
//! Interrupt / Exception context local data
2+
//!
3+
//! The main use case is safely adding state to exception / interrupt handlers.
4+
//!
5+
//! This is done in two stages, first you define a token that will appear in the
6+
//! interrupt handler signature; each handler will have its unique token. This
7+
//! token must be zero sized type because interrupt handlers' real signature is
8+
//! `fn()` and it must also implement the `Context` trait. You must also make
9+
//! sure that the token can't be constructed outside of the crate where it's
10+
//! defined.
11+
//!
12+
//! ```
13+
//! // This must be in a library crate
14+
//! /// Token unique to the TIM7 interrupt handler
15+
//! pub struct Tim7 { _0: () }
16+
//!
17+
//! unsafe impl Context for Tim7 {}
18+
//! ```
19+
//!
20+
//! Then in the application one can pin data to the interrupt handler using
21+
//! `Local`.
22+
//!
23+
//! ```
24+
//! // omitted: how to put this handler in the vector table
25+
//! extern "C" fn tim7(ctxt: Tim7) {
26+
//! static STATE: Local<Cell<bool>, Tim7> = Local::new(Cell::new(false));
27+
//!
28+
//! let state = STATE.borrow(&ctxt);
29+
//!
30+
//! // toggle state
31+
//! state.set(!state.get());
32+
//!
33+
//! if state.get() {
34+
//! // something
35+
//! } else {
36+
//! // something else
37+
//! }
38+
//! }
39+
//! ```
40+
//!
41+
//! Note that due to the uniqueness of tokens, other handlers won't be able to
42+
//! access context local data. (Given that you got the signatures right)
43+
//!
44+
//! ```
45+
//! static TIM3_DATA: Local<Cell<bool>, Tim3>
46+
//!
47+
//! extern "C" fn tim3(ctxt: Tim3) {
48+
//! let data = TIM3_DATA.borrow(&ctxt);
49+
//! }
50+
//!
51+
//! extern "C" fn tim4(ctxt: Tim4) {
52+
//! //let data = TIM3_DATA.borrow(&ctxt);
53+
//! // ^ wouldn't work
54+
//! }
55+
//! ```
56+
//!
57+
//! To have the application use these tokenized function signatures, you can
58+
//! define, in a library, a `Handlers` struct that represents the vector table:
59+
//!
60+
//! ```
61+
//! #[repr(C)]
62+
//! pub struct Handlers {
63+
//! tim1: extern "C" fn(Tim1),
64+
//! tim2: extern "C" fn(Tim2),
65+
//! tim3: extern "C" fn(Tim3),
66+
//! tim4: extern "C" fn(Tim4),
67+
//! ..
68+
//! }
69+
//!
70+
//! pub const DEFAULT_HANDLERS: Handlers = Handlers {
71+
//! tim1: default_handler,
72+
//! tim2: default_handler,
73+
//! tim3: default_handler,
74+
//! tim4: default_handler,
75+
//! ..
76+
//! }
77+
//! ```
78+
//!
79+
//! Then have the user use that `struct` to register the interrupt handlers:
80+
//!
81+
//! ```
82+
//! extern "C" fn tim3(ctxt: Tim3) { .. }
83+
//!
84+
//! // override the TIM3 interrupt handler
85+
//! #[no_mangle]
86+
//! static _INTERRUPTS: Handlers = Handlers {
87+
//! tim3: tim3, ..DEFAULT_HANDLERS
88+
//! };
89+
//! ```
90+
//!
91+
//! This pattern is implemented for exceptions in this crate. See
92+
//! `exception::Handlers` and `exception::DEFAULT_HANDLERS`.
293
394
use core::marker::PhantomData;
495
use core::cell::UnsafeCell;

0 commit comments

Comments
 (0)