Enable the host feature in drone-core
masterIf you need to enable or extend the host feature for drone-core, configure your [features] section in Cargo.toml to include drone-core/host.
[features]
host = ["drone-core/host"]repository·master·Indexed 19 days ago
https://github.com/drone-os/drone-coreThe central crate for Drone, an Embedded Operating System, providing fundamental building blocks for the OS. It includes procedural macros for hardware abstraction such as register definitions (reg), peripheral mapping (periph), and bitfield manipulation (Bitfield). It also provides tools for memory management via the heap! macro, conditional compilation logic using CfgCond and CfgCondExt, and memory layout configuration through the override_layout! macro.
If you need to enable or extend the host feature for drone-core, configure your [features] section in Cargo.toml to include drone-core/host.
[features]
host = ["drone-core/host"]To use drone-core in your project, add it to your Cargo.toml dependencies. Note that while the current repository version is v0.14.3, the documentation example uses v0.15.0.
[dependencies]
drone-core = { version = "0.15.0" }The LinkedList<T> is a singly-linked list where each element is wrapped in a Node<T>.
LinkedList<T>: Manages the head pointer using atomic operations to ensure thread safety (lock-free). It handles the high-level logic of pushing, popping, and iterating.Node<T>: A #[repr(C)] structure containing the actual value: T and a raw pointer next to the subsequent node.When using high-level methods like push(data), the list automatically allocates a Node on the heap using Box. When using pop(), the list takes ownership of the node, extracts the value, and deallocates the node memory automatically.
A critical section is a block of code that is protected from being interrupted. In drone-core, you can create a critical section using the Interrupts struct. This disables all interrupts for the current CPU upon creation and re-enables them (restoring the previous state) when the instance is dropped. Critical sections can be nested.
Warning: Priority Inversion Hazard
On devices using XIP (eXecute In Place) for flash memory (like the RP2040), a cache miss during a critical section can prevent higher-priority interrupts from executing while the cache loads. To mitigate this, enable the xip cargo feature. This moves Interrupts::paused to a .time_critical link section that is copied to RAM at startup. When using the xip feature, ensure you do not access XIP memory regions inside the critical section.
use drone_core::platform::Interrupts;
let mut x = 0;
{
// Creating an instance of `Interrupts` disables interrupts.
// Interrupts are re-enabled when `_critical` is dropped at the end of the scope.
let _critical = Interrupts::pause();
x += 1;
}
// Interrupts are now enabled again
dbg!(x);The communication between the asynchronous session and the synchronous fiber is mediated by In and Out types.
In<Cmd, ReqRes>)A union representing what is sent into the fiber. It can be either:
cmd: A command to be executed by the ProcLoop.req_res: The result of a previously made request.Out<Req, CmdRes>)An enum representing what the fiber yields back to the session:
Req(Req): The fiber is requesting a resource or action, suspending itself until the request is answered.CmdRes(CmdRes): The fiber has completed the current command and is returning the result.When you acquire a lock via lock() or try_lock(), you receive a MutexGuard. This guard implements Deref and DerefMut, allowing you to access the underlying data directly. The lock is automatically released when the guard is dropped (RAII).
Warning: If you do not use the returned guard, the mutex will be immediately unlocked.
The CfgCond struct is used to represent and generate conditional compilation attributes (#[cfg(...)]) based on feature-based configurations. It supports representing logical combinations of clauses, specifically handling any conditions and generating the appropriate Rust TokenStream for attributes.
Key behaviors:
#[cfg(any(...))] or #[cfg(not(any(...)))] attributes via the .attrs() method..add_clause().Fiber stream rings allow a fiber running in one thread to yield data to a stream that can be consumed in another thread. This is achieved by attaching a fiber to a ThrToken (like a thread token) and using ring buffer methods to bridge the data flow.
There are two primary overflow behaviors when the underlying ring buffer is full:
Additionally, you can choose between:
T directly via FiberStreamRing<T>.Result<T, E> via TryFiberStreamRing<T, E>, which allows the fiber to signal errors.!Send, use the _factory variants which take a closure to instantiate the fiber within the target thread.The periph macro automatically generates a large set of traits and types based on the identifiers provided in the macro input. Understanding these naming patterns is essential for interacting with the generated code.
For a block BlockName, a register RegName, and a variant VarName:
BlockNameRegName (CamelCase).BlockNameRegNameOpt (if Option is used).BlockNameRegNameExt (if Option is used).BlockNameRegNameVal.UBlockNameRegName (Unsafe/Unrestricted)SBlockNameRegName (Shared)CBlockNameRegName (Critical/Constrained)Opt suffixes if Option is used, e.g., UBlockNameRegNameOpt).For a field FieldName within a register:
BlockNameRegNameFieldName (CamelCase).BlockNameRegNameFieldNameOpt (if Option is used).BlockNameRegNameFieldNameExt (if Option is used).UBlockNameRegNameFieldNameSBlockNameRegNameFieldNameCBlockNameRegNameFieldNameOpt suffixes if Option is used).fn field_name(&self) -> &T::UFieldName).UBlockNameRegNameFieldNameFields, SBlockNameRegNameFieldNameFields, and CBlockNameRegNameFieldNameFields.If you are developing for a host environment (rather than an embedded target), you can add or extend the host feature in your Cargo.toml.
[features]
host = ["drone-core/host"]Streams are not necessarily active by default. To avoid unnecessary processing, check if a stream is explicitly enabled by a debug probe using is_enabled(). It is highly recommended to wrap write operations in this check.
use drone_core::stream;
let stream_id = 11;
if stream::Stream::new(stream_id).is_enabled() {
stream::write_str(stream_id, "hello there!\n");
}use drone_core::stream;
if stream::Stream::new(11).is_enabled() {
stream::write_str(11, "hello there!\n");
}To use drone-core in your project, add it to your Cargo.toml dependencies. Note that the current version in this file is 0.15.0.
[dependencies]
drone-core = { version = "0.15.0" }