Rust on Microcontrollers: From Web Dev to Embedded Systems 🦀🔌
Rust on Microcontrollers: From Web Dev to Embedded Systems 🦀🔌
Hot take: If you can deploy to AWS, you can deploy to a $3 microcontroller! Rust makes embedded programming accessible to web developers like us - and it's actually FUN! 🎯
Coming from 7 years of Laravel and Node.js, my entire career was "server goes brrr, user gets JSON." The closest I got to hardware was SSHing into an EC2 instance. Memory constraints? Just scale vertically! Pointers? What are those?
Then my RF/SDR hobby got serious. I needed custom firmware for radio receivers, antenna controllers, and signal processors. The problem? Embedded C is terrifying. Segfaults in production? Bad. Segfaults on a satellite you can't debug? CATASTROPHIC! 🛰️
Enter Rust on embedded systems - and suddenly I could write microcontroller code with the same confidence as writing a Laravel controller! Let me show you why this is game-changing!
Wait, Rust Runs on WHAT? 🤯
Me, a web developer: "Rust needs what, 16MB to compile? How does it run on a chip with 32KB RAM?"
Rust: "Hold my crab emoji." 🦀
Here's the reality check: Rust compiles down to the SAME bare metal code as C. No runtime. No garbage collector. No Node.js event loop eating your precious kilobytes!
What you get:
- Runs on chips with as little as 16KB RAM
- Zero runtime overhead (unlike MicroPython/JavaScript)
- Memory safety (unlike C/C++)
- Same speed as C (but without the segfaults)
- No operating system required (bare metal baby!)
Real talk: I'm running Rust on an STM32 microcontroller that costs less than my morning coffee and has less RAM than a single Chrome tab. And it's FAST! ⚡
Why Web Devs Should Care About Embedded 🎯
"But I write APIs, why do I need microcontrollers?"
Funny story - I thought the same thing! Then I discovered:
1. IoT is Everywhere
Your smart thermostat? Probably running embedded code. That USB security key? Embedded. Your car's dashboard? DEFINITELY embedded!
The opportunity: Companies are desperate for devs who understand BOTH web APIs AND hardware. That combo is RARE and VALUABLE! 💰
2. Performance Intuition
Writing for a chip with 32KB RAM teaches you things no bootcamp ever will:
- Every byte matters
- Allocation is expensive
- Zero-copy is a lifestyle, not a pattern
- "Just add a library" isn't an option when you have 16KB total!
Translation: You become a better web developer by understanding constraints!
3. It's Actually Similar to Web Dev
Think about it:
- Embedded: Read sensor → Process data → Send to actuator
- Web API: Read request → Process data → Send response
Same flow, different hardware! 🔄
The Learning Curve (Spoiler: Easier Than You Think) 📈
Coming from Laravel/Node.js, here's what surprised me:
What's Familiar ✅
Cargo still works:
# In web dev
cargo add tokio axum
# In embedded
cargo add cortex-m embedded-hal
Same tool, different targets!
Code looks the same:
// This looks like normal Rust!
let mut led = pins.pa5.into_push_pull_output();
led.set_high(); // Turn LED on
If you know Rust, you're 80% there!
What's Different (But Not Scary) 🆕
No standard library - You use #![no_std] instead
- No
Vec,String,HashMap(unless you bring your own allocator) - Think: PHP without Laravel helpers - raw but powerful!
You think in hardware:
- "This pin is GPIO port A5"
- "UART runs at 115200 baud"
- "ADC samples at 1MHz"
Coming from web dev: Remember configuring nginx? Same energy! 🎵
My First Embedded Rust Project 🚀
For my RF hobby, I built an antenna rotator controller - a device that points my antenna at satellites.
The hardware:
- STM32F103 "Blue Pill" board ($2 from AliExpress)
- Stepper motor drivers
- GPS module
- OLED display
The code (simplified):
#![no_std]
#![no_main]
use cortex_m_rt::entry;
use stm32f1xx_hal::{pac, prelude::*};
#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let mut gpioc = dp.GPIOC.split();
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
loop {
led.toggle(); // Blink LED
cortex_m::asm::delay(8_000_000); // Wait ~1 second
}
}
What blew my mind:
- Compiler caught my GPIO pin configuration errors at BUILD TIME
- No null pointer exceptions possible
- Type system prevented me from mixing up UART1 and UART2 pins
- Same Rust I use for web APIs!
The Safety Story (This Is HUGE) 🛡️
Remember how Rust prevents data races in web apps? Same thing on hardware, but the stakes are HIGHER!
In C (the old way):
// Configure GPIO pin
GPIOA->MODER |= 0x01; // Uh... what mode is that?
// Did I shift the right bits? WHO KNOWS! 🤷
In Rust:
// Configure GPIO pin
let mut pin = pins.pa5.into_push_pull_output();
// Type: PushPullOutput - compiler KNOWS what this pin can do!
Why this matters:
- Can't use SPI pin as I2C (compiler error)
- Can't read from an output pin (compiler error)
- Can't access peripherals from multiple interrupts unsafely (compiler error)
Real example from my antenna controller: I tried to use a timer from both the main loop AND an interrupt handler. In C? Runtime crash. In Rust? Compiler error with suggestion to use a mutex! 🎯
Embedded Rust vs. Web Rust 🔄
Here's the mental model that clicked for me:
| Web Rust (with std) | Embedded Rust (no_std) |
|---|---|
Vec<T> |
Fixed arrays [T; N] |
String |
heapless::String<32> |
println!() |
defmt::info!() |
| Tokio async | embassy async |
| Error handling | panic = restart chip! |
The mindset shift: In web dev, we throw hardware at problems. In embedded, we solve problems with constraints! 🧠
Getting Started (The Practical Bits) 🛠️
What you need:
-
Hardware ($5-20 to start):
- STM32F103 "Blue Pill" (cheapest)
- ESP32-C3 (WiFi + Rust!)
- Raspberry Pi Pico (RP2040)
-
Debugger ($3-10):
- ST-Link V2 clone
- Or use the built-in USB on some boards!
-
Software (FREE):
# Install embedded Rust rustup target add thumbv7m-none-eabi # Install flash tool cargo install probe-rs --features cli # Clone a template git clone https://github.com/rust-embedded/cortex-m-quickstart
Your first program:
# Build for ARM Cortex-M
cargo build --release
# Flash to chip (like deploying to production!)
probe-rs run --chip STM32F103C8
Coming from web dev: Think of probe-rs run as git push heroku main but for hardware! 🚀
Common "WTF" Moments (And Solutions) 😅
1. "Why is my binary so big??"
Problem: 500KB binary for blinking an LED?!
Solution:
[profile.release]
opt-level = "z" # Optimize for size
lto = true # Link-time optimization
Result: 2KB binary! (Smaller than this blog post!) 📦
2. "How do I debug without println!()?"
Web dev instinct:
println!("Debug: {}", value); // ❌ Doesn't exist in no_std!
Embedded way:
defmt::info!("Debug: {}", value); // ✅ Logs over debug probe!
Bonus: defmt compresses logs at compile time. Your "Request processed" string? Just 1 byte on the wire! 🔥
3. "Where's my stack trace?"
The truth: Embedded panics look like this:
panicked at 'index out of bounds'
The fix: Use probe-rs debugger - it's actually BETTER than web debugging:
- Step through code
- Inspect registers
- Set breakpoints
- No browser DevTools tab crashes! 😂
Real-World Embedded Rust 🌍
Who's using this?
- Ferrous Systems: Automotive firmware
- Oxide Computer: Server firmware
- Amazon: Firecracker VMM
- My RF projects: Antenna controllers, SDR firmware, signal processors
Why they chose Rust:
- Memory safety (no recalls for buffer overflows!)
- Performance (same as C)
- Modern tooling (Cargo > Makefiles)
- Fearless concurrency (even on bare metal!)
Should YOU Learn Embedded Rust? 🤔
Learn it if:
- You want to understand how computers ACTUALLY work
- IoT projects sound fun
- You're tired of "it works on my machine" (try "it works on my chip!")
- You have an RF/electronics hobby (like me!)
- You want a skill that's rare and valuable
Maybe skip if:
- You're still learning web Rust (get comfortable first!)
- You have zero interest in hardware
- You just want to build CRUD apps (totally valid!)
My take: Even if you never ship embedded code professionally, learning it makes you a 10x better systems thinker! 🧠
Resources to Get Started 📚
- The Embedded Rust Book (free, excellent!)
- Discovery Book (hands-on tutorials)
- awesome-embedded-rust (GitHub repo)
- embedded.fm podcast (not Rust-specific, but great!)
Community:
- #embedded channel on Rust Discord (super helpful!)
- embedded-wg on GitHub
- Just ask - embedded Rust folks are NICE!
The Bottom Line 🎯
Coming from 7 years of Laravel/Node.js, I thought embedded programming was this arcane black magic reserved for electrical engineers. I was wrong!
Rust makes embedded accessible to web developers because:
- Same language - if you know Rust, you're halfway there
- Same tools - Cargo works everywhere
- Better safety - memory bugs caught at compile time
- Modern DX - no Makefiles, no weird IDE setup
- Active community - friendly and welcoming!
For my RF/SDR projects, Rust on microcontrollers means I can:
- Write firmware faster than C
- Debug issues at compile time, not runtime
- Deploy with confidence (no memory leaks!)
- Use modern language features (enums, traits, generics!)
The killer feature? I write ONE language for my entire signal processing pipeline:
- Embedded Rust on the radio receiver hardware
- Systems Rust for the SDR processing (gnuradio replacement)
- Web Rust (Axum) for the control API
- WASM Rust for the web interface
Same language. Different targets. Zero context switching! 🚀
Remember:
- Rust runs on $3 chips with 32KB RAM (seriously!)
- Same safety guarantees as desktop Rust (memory safe embedded!)
- Better DX than C (Cargo > Makefiles forever)
- Growing ecosystem (embedded-hal, embassy, probe-rs)
- Perfect for RF/SDR/IoT projects (my antenna controller proves it!)
Ready to flash some firmware? The hardware is cheaper than a pizza, and the skills are worth way more than a bootcamp certificate! 🦀✨
Want to connect? Find me on LinkedIn - always happy to chat about Rust, RF, or both!
Building something cool? Star my GitHub and share your embedded Rust projects!
Now go make some LEDs blink with memory safety! 🔌🦀