title | author | theme | ||
---|---|---|---|---|
Rust on ESP32 |
milan <[email protected]> |
|
We'll be talking about Rust and ESP32. Let's do a quick poll.
- Who has written Rust before?
- Who has developed for MCUs before?
- Who has written Rust code for MCUs?
You need to know neither of these topics to follow.
esp32
?!rust
?!- Implementing distributed coordination with the Anti-Firefly Algorithm
We brought ~20 ESP32 MCU's.
The complete code is in the above repo and can be explored.
The presentation is in the same repo. Feel free to ask questions at any time. Q&A at the end for longer questions.
32-bit microprocessors by Espressif
RISC-V, 1-core 160 MHz
sometimes 4 MiB flash
Pin compatible with ESP8266
Xtensa, 2-core 240 MHz
4 MiB flash
The ecosystem is growing rapidly. See
Architecture | Support | |
---|---|---|
Bare ARM | Tier 2 | read "guaranteed to build" |
RISC-V | Tier 2 | (ESP32-C, -H, and -P series) |
AVR | Tier 3 | supported but untested |
Xtensa | Tier 3 | (ESP32 and ESP32-S series) |
Xtensa has open PRs in LLVM that need to be merged before official support can be improved.
Rust std
(standard) library
Supported with esp-idf
(layer between bare metal and program)
Higher level -> power usage
Rust core
library
(strict subset of std
)
Supported by esp-hal
, the Hardware Abstraction Layer
Runs on bare metal, no OS
No memory allocator -> No heap
Can be circumvented with custom allocators
We'll focus on this
#![no_std]
#![no_main]
use esp_backtrace as _; // panic handler
#[entry]
fn main() -> ! {
// setup code
loop {
// loop code
}
}
A rather contentious topic.
- Memory corruption can lead to hidden security issues and days to weeks of "blind" debugging.
A fast language that crashes all the time is like a supercar ... that crashes all the time.
~ noboilerplate.org
- C will be replaced by a memory safe language. (fight me)
- The Rust type system is an absolute joy to work with!
fn increment(_cs: &CriticalSection) {
// incrementing something
// must happen atomically
}
fn main() {
// compile time error
increment();
//^^^^^^^^^-- an argument is missing
// instead do
interrupt::free(|cs| increment(cs));
// critical section is dropped ---^ here
// because it is local to the closure
}
let array = [0u16; 1'000'000];
// use
let max = array
.iter()
.max()
.expect("The array is empty");
// instead of
let mut max = u16::MIN;
for i in 0..array.len() {
if array[i] > max {
max = array[i];
}
}
The compile times are so slow and the compiler is annoying.
The compile times are so slow and the compiler is annoying.
Let me present an alternative view:
Programming with the Rust compiler is like pair-programming with someone on the Rust Compiler Team.
impl Add for Vec1 {
type Output = Vec1;
fn add(self, other: Vec1) -> Vec1 {
Vec1(self.0 - other.0)
}
}
warning: suspicious use of `-` in `Add` impl
--> src/main.rs:9:21
|
9 | Vec1(self.0 - other.0)
| ^
pick random time_slot
loop once per round:
send beacon at time slot
update time_slot :=
predecessor
+ average(predecessor, successor)
+ interval