Drone is an Embedded Operating System for writing real-time applications in Rust. It aims to bring modern development approaches without compromising performance into the world of embedded programming.
Quick Tour
- Getting Started
- Async/Await
- Dynamic Memory
- Memory-Mapped Registers
- Threads
- Generic Peripherals
- Logging
- Safety
cargo
takes development comfort to the next level,
and Drone extends its philosophy to the embedded world. If your
target chip and debug probe are supported by Drone, you can
flash your first program and get a feedback right away!
Each interrupt is an executor for async
tasks. Thanks to Rust's zero-cost asynchronous programming your
interrupt handlers look like a conventional synchronous code,
except they don't need separate stacks.
Drone includes a dynamic memory allocator that allows you to use
familiar
Rust's Box
, Vec
, String
, Arc
,
and other dynamic types. It is lock-free, deterministic, and has
a small code footprint, which makes it useful even on simplest
micro-controllers. The cost is that it requires tuning for each
particular application. Drone automates this by providing
utilities for collecting real-time allocator statistics and
calculating an optimized layout configuration.
Drone provides a rich API for working safely with memory-mapped
registers. An application starts with a set of zero-sized unique
tokens for all available registers. A token can have move or
copy semantics, can be shareable with atomic access or
non-shareable with non-atomic access, can be split into
individual register field tokens.
Drone uses interrupt-based preemptive priority scheduling, where
tasks with same priorities are executed cooperatively. An
application has a predefined number of threads corresponding to
hardware interrupts, but each thread can run dynamic number of
fibers.
Registers and individual register fields can be grouped into
peripheral blocks. Drone makes a great effort to abstract from
different instances of one peripheral type. Even if these
instances have minor differences.
Drone provides an abstract logging facade designed after ARM
Serial Wire Output. The output can be captured with a generic
USB-UART adapter. It has 32 multiplexed streams and supports
atomic packets up to 4 bytes. Familiar Rust macros
like print!
, eprint!
, dbg!
are mapped to reserved #0 and #1 ports that work as standard
output and standard error respectively.
Drone provides safe API for inherently unsafe low-level
operations. The only required unsafe function is the entry-point
located at src/bin.rs
, which is a separate
compilation unit. You can even write a whole micro-controller
firmware with #![forbid(unsafe_code)]
at the top
of src/lib.rs
.
Design Principles
-
Energy effective from the start. Drone encourages
interrupt-driven execution model.
-
Hard Real-Time. Drone relies on atomic operations instead
of using critical sections.
-
Fully preemptive multi-tasking with strict priorities. A
higher priority task takes precedence with minimal latency.
-
Highly concurrent. Multi-tasking is cheap and safe,
following Rust's Fearless Concurrency principle.
-
Message passing concurrency. Drone ships with
synchronization primitives out of the box.
-
Single stack by default. Drone concurrency primitives are
essentially stack-less state machines. But stackful tasks are
still supported.
-
Dynamic memory enabled. Drone lets you use convenient data
structures like mutable strings or vectors while still staying
deterministic and code efficient.
- Getting Started
- Async/Await
- Dynamic Memory
- Memory-Mapped Registers
- Threads
- Generic Peripherals
- Logging
- Safety
cargo
takes development comfort to the next level,
and Drone extends its philosophy to the embedded world. If your
target chip and debug probe are supported by Drone, you can
flash your first program and get a feedback right away!
Each interrupt is an executor for async
tasks. Thanks to Rust's zero-cost asynchronous programming your
interrupt handlers look like a conventional synchronous code,
except they don't need separate stacks.
Drone includes a dynamic memory allocator that allows you to use
familiar
Rust's Box
, Vec
, String
, Arc
,
and other dynamic types. It is lock-free, deterministic, and has
a small code footprint, which makes it useful even on simplest
micro-controllers. The cost is that it requires tuning for each
particular application. Drone automates this by providing
utilities for collecting real-time allocator statistics and
calculating an optimized layout configuration.
Drone provides a rich API for working safely with memory-mapped registers. An application starts with a set of zero-sized unique tokens for all available registers. A token can have move or copy semantics, can be shareable with atomic access or non-shareable with non-atomic access, can be split into individual register field tokens.
Drone uses interrupt-based preemptive priority scheduling, where tasks with same priorities are executed cooperatively. An application has a predefined number of threads corresponding to hardware interrupts, but each thread can run dynamic number of fibers.
Registers and individual register fields can be grouped into peripheral blocks. Drone makes a great effort to abstract from different instances of one peripheral type. Even if these instances have minor differences.
Drone provides an abstract logging facade designed after ARM
Serial Wire Output. The output can be captured with a generic
USB-UART adapter. It has 32 multiplexed streams and supports
atomic packets up to 4 bytes. Familiar Rust macros
like print!
, eprint!
, dbg!
are mapped to reserved #0 and #1 ports that work as standard
output and standard error respectively.
Drone provides safe API for inherently unsafe low-level
operations. The only required unsafe function is the entry-point
located at src/bin.rs
, which is a separate
compilation unit. You can even write a whole micro-controller
firmware with #![forbid(unsafe_code)]
at the top
of src/lib.rs
.
-
Energy effective from the start. Drone encourages interrupt-driven execution model.
-
Hard Real-Time. Drone relies on atomic operations instead of using critical sections.
-
Fully preemptive multi-tasking with strict priorities. A higher priority task takes precedence with minimal latency.
-
Highly concurrent. Multi-tasking is cheap and safe, following Rust's Fearless Concurrency principle.
-
Message passing concurrency. Drone ships with synchronization primitives out of the box.
-
Single stack by default. Drone concurrency primitives are essentially stack-less state machines. But stackful tasks are still supported.
-
Dynamic memory enabled. Drone lets you use convenient data structures like mutable strings or vectors while still staying deterministic and code efficient.