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§
Traits§
- Deferred
Call Client - 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.