Module deferred_call

Module deferred_call 

Source
Expand description

Hardware-independent kernel interface for deferred calls.

This allows any struct in the kernel which implements DeferredCallClient to set and receive deferred calls, Tock’s version of software interrupts.

These can be used to implement long-running in-kernel algorithms or software devices that are supposed to work like hardware devices. Essentially, this allows the chip to handle more important interrupts, and lets a kernel component return the function call stack up to the scheduler, automatically being called again.

§Initialization

Before any DeferredCalls are created, the internal state used by the implementation must be initialized. Boards must initialize deferred calls by calling either initialize_deferred_call_state or initialize_deferred_call_state_unsafe. Depending on the hardware state available (i.e., atomic support), boards will only have one initialization routine available.

On boards that must use the unsafe version (initialize_deferred_call_state_unsafe), they must be careful to only call initialize_deferred_call_state_unsafe once from the main execution thread to meet the safety requirements.

§Usage

The DEFCALLS array size determines how many DeferredCalls may be registered. By default this is set to 32. To support more deferred calls, this file would need to be modified to use a larger variable for BITMASK (e.g. BITMASK could be a u64 and the array size increased to 64). If more than 32 deferred calls are created, the kernel will panic at the beginning of the kernel loop.

use kernel::deferred_call::{DeferredCall, DeferredCallClient};
use kernel::static_init;

// Don't use this! Use the actual `ThreadIdProvider` from your arch crate.
struct DummyThreadIdProvider {}
unsafe impl kernel::platform::chip::ThreadIdProvider for DummyThreadIdProvider {
    fn running_thread_id() -> usize { 0 }
}

// Initialize the deferred call mechanism.
#[cfg(target_has_atomic = "ptr")]
kernel::deferred_call::initialize_deferred_call_state::<DummyThreadIdProvider>();
#[cfg(not(target_has_atomic = "ptr"))]
unsafe { kernel::deferred_call::initialize_deferred_call_state_unsafe::<DummyThreadIdProvider>(); }


struct SomeCapsule {
    deferred_call: DeferredCall
}
impl SomeCapsule {
    pub fn new() -> Self {
        Self {
            deferred_call: DeferredCall::new(),
        }
    }
}
impl DeferredCallClient for SomeCapsule {
    fn handle_deferred_call(&self) {
        // Your action here
    }

    fn register(&'static self) {
        self.deferred_call.register(self);
    }
}

// main.rs or your component must register the capsule with its deferred
// call. This should look like:
let some_capsule = unsafe { static_init!(SomeCapsule, SomeCapsule::new()) };
some_capsule.register();

Structs§

DeferredCall

Traits§

DeferredCallClient
This trait should be implemented by clients which need to receive DeferredCalls.

Functions§

initialize_deferred_call_state
Initialize the static state used by deferred calls.
initialize_deferred_call_state_unsafe
Initialize the static state used by deferred calls.