Expand description
§The mnemos kernel
The mnemos kernel is implemented as a library, with platform-specific code depending on the kernel library and producing the final binary.
§The “kernelspace” entry point
At the moment, the kernel requires some “entry point” code, more or less the main()
function
that runs when the system boots, to perform any system-specific initialization.
This entry point code is responsible for setting up any hardware or subsystems that exist outside the kernel (or are required by any kernel services), as well as starting and running the kernel itself.
§Setting up the Allocator
Before creating the kernel, a MnemosAlloc instance must be registered as a GlobalAlloc, and if the UnderlyingAllocator requires initialization, it must occur before creating the kernel.
The kernel will be allocated using the provided allocator.
§Creating the kernel
The allocator and any kernel settings are provided to the kernel constructor. The kernel will allocate itself, and return an owned kernel entity.
After creation, the executor is not running yet.
§Initialization phase
After creating the kernel, we need to register kernel services, which are expected to act as drivers for various system components.
Since we are not running the executor yet, the kernel provides an interface,
Kernel::initialize()
, which takes a future and spawns it on the executor. Futures added with
initialize
still do not run until the later “running” phase.
Right now, it is generally suggested you use one or more initialize
calls to register all (initial) kernel services.
§Running mode
Once everything is prepared and initialized, the startup code is expected to call
Kernel::tick()
repeatedly. On each call to tick:
- The allocator frees any synchronously dropped allocations, making them available for asynchronous allocation
- The async executor is polled
AT THE MOMENT, there is no indication of whether all tasks are blocked, which could be use to inform whether we should put the CPU into some kind of sleep mode until a hardware event (like a timer or DMA transaction) is triggered, and an async task has potentially been awoken.
§Not covered: “userspace”
At the moment, there is SOME concept of a userspace, which interacts with the kernel via a
bidirectional IPC ringbuffer. Space for this ringbuffer is allocated when calling
Kernel::new()
. Additionally this ringbuffer is polled on each call to tick
, after freeing
allocations and before calling tick
on the scheduler.
This is an artifact of how mnemos 0.1 worked, where there was a single userspace executor that existed and interacted with the kernel executor.
As of 2023-05-30, I don’t think this is the right abstraction for multiple userspace processes. The pieces that exist currently are likely to be removed or reworked heavily before they are usable, and should be considered nonfunctional at the moment.
Re-exports§
pub use embedded_hal_async;
pub use maitake;
pub use mnemos_alloc;
pub use tracing;
Modules§
- Kernel Communications Interfaces
- Daemons
- fmt 🔒
- Mnemos Services
Structs§
- Settings for all services spawned by default.