Moving to a RTOS on the RP2040
MicroPython and “Do You Even Need an RTOS?”
- Several commenters report success using MicroPython with async/await for “real‑time enough” applications (steppers, LEDs, buttons) on RP2040/ESP32.
- Hardware peripherals (PIO, timers, RMT, interrupts) can offload precise timing from Python, making cooperative multitasking viable for moderate step rates.
- Some argue that for many projects (e.g., PTZ controller) this is simpler and more productive than adopting a full RTOS or large C codebase.
Rust, Embassy, RTIC, Hubris
- Multiple people are moving RP2040 projects to Rust with the Embassy async framework; they find it removes much of the need for an RTOS while giving memory safety.
- RTIC is seen as simple and lightweight but currently single‑core for RP2040 and harder to modularize; Embassy has its own async‑focused HALs and better ergonomics.
- Advice: start with
rp2040-hal, add Embassy/RTIC once task management becomes painful. - Hubris is mentioned as an attractive Rust microkernel for more structured systems; Embassy is suggested for tighter memory budgets.
RTOS Options: FreeRTOS, Zephyr, ThreadX, NuttX, Others
- FreeRTOS is considered a de facto standard, especially when SOC vendors ship it and related stacks.
- ThreadX (now open source) is praised for elegance and a POSIX layer; PX5 and RIOT are noted but proprietary cost or niche status limit appeal.
- Zephyr fully supports RP2040; some say it’s easy and powerful with integrated stacks (e.g., Bluetooth, mcuboot/OTA).
- Others find Zephyr bloated, slow to build, and confusing, especially for tightly constrained OEM firmware.
- NuttX and ChibiOS are mentioned positively but with weaker or problematic RP2040 support.
Zephyr’s Hardware Abstractions vs Minimalism
- One camp values Zephyr’s cross‑SOC abstractions, central Bluetooth and OTA story, and “less hacky Arduino” feel for prototypes.
- Another camp (focused on shipping, cost‑sensitive devices) prefers minimal, self‑written HALs over heavy vendor abstractions, citing control, footprint, and predictability.
- Consensus: SOC‑vendor choices often drive RTOS selection in practice.
Printf, I/O, and Concurrency Pitfalls
- The original article’s
printfproblems are attributed to toolchain/newlib/heap issues, non‑reentrantprintf, and calling it from multiple threads. - Suggestions include: per‑thread buffers, avoiding dynamic allocation, message‑passing logs through a single thread, Pico SDK’s pluggable stdio, UART interrupts, RTT via debuggers, and careful newlib configuration.
- Several emphasize that “printf not working” is usually not an RTOS bug but a C library and concurrency design issue.
Tooling, Python vs Native, and Reproducibility
- Strong criticism of Python‑based build tooling for embedded: version skew, dependency mess, non‑reproducible setups.
- Advocates prefer statically linked tools (C/C++/Rust/Go) and integrated managers like Cargo; Rust +
rustupis highlighted as particularly smooth for RP2040 flashing. - Others defend container/VM‑based toolchains (or CI‑built artifacts) for reproducibility, though some report USB/integration friction and container bloat.
PLCs vs Microcontrollers
- For deterministic industrial control, some favor PLCs (Codesys/Twincat, EtherCAT ecosystems) over DIY RTOS setups; they “just work” together with strong real‑time guarantees.
- Counterpoints note PLC cost, proprietary ecosystems, and poor integration with non‑industrial systems; for low‑volume or hobby gear, microcontrollers remain attractive.
Rolling Your Own Scheduler
- A few contributors bypass RTOSes entirely by implementing simple green‑thread or timer‑callback schedulers on Cortex‑M, sometimes by hooking Pico SDK macros.
- They report these lightweight approaches are sufficient for polling sensors, control loops, and basic multitasking, and avoid RTOS complexity—though without strong guarantees.