Rust on the ESP32 (2019)
mabez.dev
mabez.dev
One thing I haven’t quite figured out: a substantial number of onboard features are configurable at image build time, which then change the effective C libraries via preprocessor definitions. So, it doesn’t quite work to naively run bindgen on the header file once, and then embed that in a -sys crate and put it on crates.io
I think you can hand craft a -sys crate with all the appropriate config options as cargo features, but that seems both very time-consuming and likely to drift from the newest esp-idf versions. The alternative of running bindgen periodically (e.g. as part of the build process) works fine for one project, but then how do you publish reusable libraries online?
Its very tempting to try this due to the huge amount of resources the hardware has, but it is a huge amount of work. Just being able to access the registers isn't very valuable, the ESP is about Wifi, BT and I2S. If there are no ergonomic Rust APIs for those, why even bother?
Given that I decided to go a middle ground and use Nim with its new ARC (GC reference counting and move semantics). In theory it's less efficient than compile time Rust memory management but it works well in practice. Wrapping the C API is trivial and handles all of the C defines as well as writing in C, since it compiles down to it. And you can use any Nim or C libraries. It's surprisingly effective!
Except you still get data races from the C API's which Rust would likely help prevent. So it's cool to see someone toying with an xtensa llvm backend. I wish LLVM still fully supported a C backend so you could compile Rust to C and build that. Hopefully in the long run, more native rust libraries will exist for more full functionality embedded.
Rust might just be a leap too big and can only work in blank-slate scenarios.
"There is no hidden control flow, no hidden memory allocations, no preprocessor, and no macros."
Considering how much of the actual programming in embedded isn't so much programming in C but metaprogramming in C preprocessor I wonder if 1:1 replacing this with another language/conditional compile pair would really be smartest move. It could be very interesting to embrace the fact that you are writing a program that writes a program instead of pretending that it's all one language. Don't hide the two-stage nature of embedded development, radically rip them apart. The first stage could be so much more than an afterthought if you elevate it from macro replacement to a type-heavy behemoth like, I don't know, a Scala DSL tailored for generating target-specific C/Rust/whatever source from a template. A template that interleaves precompilation and target language, like C source already does, but with a proper language for the first stage instead of a glorified find/replace sequence. This would have to happen in the form of cross-pollination from the web world because they have decades of learning from mistakes in markup generating code and almost half as much in dealing with the ergonomics of anything-to-js transpilers.
I suspect that if you'd separate all the customary compile time logistics into its own, distinct preparatory stage it would be much easier to get different languages from the ubiquitous "a compiler backend exists, but..." to actual pragmatic usability.
Much of embedded programming is about coping with quirky hardware and nudging bits and bytes around. And coping with rather sloppily put together tooling that requires a lot of hand-cranking.
Introducing higher level languages doesn't really solve this. If anything, it would make things worse because it would focus attention where the problem isn't. Adding lots of complexity by adding transpilers for a bunch of languages just makes things more complex and does nothing to solve the actual problems.
(Slightly orthogonal: just look at how horrid Zephyr becomes due to Python-based build tools that keep breaking things with every release. Choosing Python actually made things worse because Python brings its own unmitigated problems. It screws up your day even before you get to do any programming)
Whew. I’m glad it wasn’t just me that thought this. Zephyr devs seem really blind to this. And the swap to CMake didn’t help things.
I think something that ties in with the target language and is aware of the syntax of the target language, like Rust macros, has many advantages. At the same time I do not know enough about Rust macros yet to tell if they are really powerful enough to help here.
There are blog posts exploring some of the use cases for them, but it depends a lot on what you want to do.
https://blogs.itemis.com/en/eclipse-mita-bringing-software-d...
Also declaring the index variable in a for loop like for(int i =0; i < 10; i++) is extremely helpful.
Those two alone are extremely beneficial.
And yes, C++ would be a better option, provided that up to date C++ compilers exist at all.
How good is the Rust support in Eclipse and Visual Studio?
Visual Studio should not be confused with Visual Studio Code. The latter has great Rust support.
If you want their buy-in into other toolchains, you need to meet them where they are.
It is mostly newcomers to the embedded programming scene that go on about tooling because they're used to better tooling from non-embedded development.
I think one should pay attention to the newcomers and try to learn from them.
Also, "embedded" is a massive field with very different cultures and needs.
https://github.com/lupyuen/pinetime-rust-mynewt
https://medium.com/swlh/sneak-peek-of-pinetime-smart-watch-a...
Although, I'm more interested in learning STM32 development, due to recommendations that it is far superior to ESP32 boards. Anyone have some tips on how to get started on this front as a hobby?
It may have changed since, but rust embedded definitely isn't hobbyist friendly unless the goal is to make things work, rather than to just make things.
I have the toolchain in a Docker container if you want to try it out.