Module cortex_m::ctxt [] [src]

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> = Local::new(Cell::new(false));

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.

Structs

Local

Data local to a context

Traits

Context

A token unique to a context