4

Ask HN: Has any Rust developer moved to embedded device programming?

 2 years ago
source link: https://news.ycombinator.com/item?id=32494606
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Ask HN: Has any Rust developer moved to embedded device programming?

Ask HN: Has any Rust developer moved to embedded device programming?
21 points by detuks 1 hour ago | hide | past | favorite | 18 comments
Hi! Was wondering if any Rust developer have moved to embedded land. Did you switch to C/C++ or stayed with Rust? What MCU did you work with? Any tips?

I have good understanding of Rust and soon will need to program ESP32 chip. Write a driver and and http/tcp api on it.

Currently I jave seen mixed messages about Rust in embedded. Ecosystem moves fast, but semms like old C/C++ devs stay with their lang. So I'm curious what Rust devs have to say abou it.

I've done some small embedded Rust applications on various STM32 and RP2040 boards. I've been doing embedded dev in C professionally for 7 years and Rust full-time for 2.5, mix or system and bare metal.

It's very hard to unlatch your brain from some of the common C/C++ embedded principles of static context variables and thinking of the hardware registers as "owned" memory, which you have to do in Rust. The auto-generated HAL crates aren't that great unless you're using the most common ones like stm32f4 or RP2040. Even then, it's hard to create a portable device driver without delving into generic-hell.

That all said, the ecosystem is moving fast, and a lot of my gripes above are just a product of the embedded rust ecosystem being very new in comparison to C. I do love rtic as a framework, and while I've given embassy a try I think it's trying to do too much aside from being a good async runtime, it should just focus on the runtime and not with stuff like creating its own entire HAL. Hubris and humility are fascinating but I just haven't gotten around to tinkering with them yet.

Lots of good tooling too, and the fact that most of your original C/C++ debugging tools are compatible with rust binaries is just the icing on the cake.

I know that there's the whole Ferrocene project, but until that produces results, stick with C if you're doing safety-critical applications, especially if they need to be certified

I started to explore the area, mostly arm based (rp2040 and STM) and a little bit of ESP32.

Tool chain wise:

ESP32 support is very recent and still based on the C tool chain and this makes it very fragile (you can break your environment easily and it is never clear how to recover except recompiling the entire tooolchain from 0)

Arm is a little better because the support is native.

The community is trying to make a generic embedded Hal platform API and implement it for specific devices. And it is pretty bad: almost no documentation, very few examples, tons of autogenerated code where you need to come back to the C world to understand the actual concepts.

Once you start to get going Rust is a blast to program in and the generated code is pretty efficient.

A small project I shared to help people starting on a raspberry pi clone (lilygo): https://github.com/gbin/rp2040-mandel-pico

I've been working in embedded for 5 years and am curious how rust could solve my biggest headaches:

* Managing build configurations - I use CMake to build a single application for multiple hardware platforms. This is accomplished almost exclusively through linking, e.g., a single header file "ble-ncp-driver.h" with multiple "ble-ncp-driver.cpp" files for each target platform. I call this the "fat driver" approach which has proven to be easier to work with than creating a UART abstraction or ADC abstraction. Does rust's package system address this?

* Automated device testing - fluid leaks are similar to bugs in software. They are systemic in nature and cannot be easily understood through static analysis. We spent equal time maintaining a test bench as product development.

* Preemptive operating systems - more trouble than they are worth. Often, devs get bogged down writing messages queues to pass items between task contexts and timing analysis requires detailed event tracing.

Given I don't see teams struggle with memory ownership (easy to do if you never, ever malloc), what else can rust bring to embedded dev?

s.gif
> Managing build configurations...

In terms of package management, you can apply rules to what crates you want to include; including specific platform constraints.

  [target.'cfg(target_os = "linux")'.dependencies]
  nix = "0.5"
On the code side it's pretty much the same as C++. You have a module that defines an interface and per-platform implementations that are included depending on a "configuration conditional check" #[cfg(target_os = "linux")] macro.

https://github.com/tokio-rs/mio/blob/c6b5f13adf67483d927b176...

s.gif
Regarding preemptive operating systems a lightweight solution is to use rtic.rs which I have found pretty great for my time critical applications
s.gif
> (easy to do if you never, ever malloc)

Not an embedded systems developer so an honest question. What do you do instead of malloc? Have a large array on stack and manage memory within that manually?

s.gif
Very small embedded systems tend to have a lot of short-lived items on the stack, and anything that lives longer then a function call exists in static memory at a fixed address. Memory pools are pretty common as well. Small systems tend to avoid a tradition heap, because they can get into trouble pretty easily.
s.gif
It's not just ownership, it's memory safety. I've worked in embedded development and I can't say I've never seen a segfault occur or worse, without an MMU, just random crashes and buggy behavior due to memory corruptions.
The Rust ESP32 ecosystem isn't as mature as STM32 unfortunately, I would be cautious about beginning a production ESP32 product written in Rust.

STM32s however are a different story... I'm using the stm32h7 microcontroller with Rust in a production product. Its really great.

Hopefully the ESP32 support matures sooner rather than later, which I think would be great for more Rust IoT uptake and Rust embedded as a whole.

I would love to see Rust become the defacto standard in embedded development.

I'm not a Rust-only developer, but a general systems programmer, and my foray into embedded is limited to a side project (see my profile), but no, I haven't switched to C/C++. Rust brings too much goodness to give it up.

Rust-embedded is an easy ecosystem to work with (if immature), and if you want more flexibility, Tock OS [0] is trying to cover that space (also immature, but I'm working on it).

[0] https://www.tockos.org/

Our company builds a wearable device using an NRF5x chip, and our firmware is written in C. We are moving to Rust for our newest device, in order to run graphical output and RT operations. It is looking pretty sweet!
s.gif
Not OP, also I don't know if is sarcasm or not, but Carbon is just too new, I would understand somehow if you asked about Zig, but isn't also mature enough.
Not exactly embedded but I'm writing an operating system kernel in Rust, having done so previously with C.

I love it so far. There are still some rough edges in the tooling, but overall I'm very happy. The resulting binaries are much larger than C projects, but I'm also opting into a lot of functionality you probably wouldn't always need in smaller environments.

s.gif
Can you name a few of those rough edges in the tooling? Thanks
s.gif
Right now struggling to separate out architecture-agnostic code and architecture-specific stuff in a way that can be switched out with `--target` and still undergo LTO as though it were all inlined.

Cargo recently got multi-target builds which is great, and makes this way less of a headache before (usually had to run cargo once per target, now it can do all of them at once).

The next challenge is packaging things up. Cargo gives you a hook for running things prior to the actual crate compilation (e.g. using it plus graphicsmagick to generate a bit font for the boot sequence rasterizer) but lacks the ability to run anything after the build, which means no development disk image building or any image checking can occur without a second command.

There's an open issue tracking this with countless use cases but the cargo team seems reluctant to "replace build systems" (which is ludicrous to me).

Not a Rust dev but I like the language. I've learned embedded over the last few years. I used to hate C and avoid it like the plague. On a good day now I kind of enjoy it, in some sick perverse twisted way. I'd say in general the embedded space is more project-centric in general thus new stacks are not at as significant a disadvantage as in backend land at the lower end of the project complexity and regulatory ingress spectrum. You will see gaps in terms of device driver availability and maturity and integration level with silicon vendor toolkits. However, since most projects do not use too much exotic hardware writing one or two I2C or SPI drivers won't take forever, you're probably OK to go Rust. But realistically, for complex stuff, you're going to run in to wall after wall that will eat time and money. If you can meld C/C++ and Rust in one binary or reach godlike device driver implementation status then you'll be relatively free of issues but while I'm sure that's possible once you're at the point where you're writing the whole stack you might be best to look for a job with a silicon vendor overhauling their toolkit for Rust support, since base library and code generation will help shift more product than any one shop. Try writing to TI/NXP/Renesas/STM/Freescale/Microchip/NXP/Atmel's HR department and asking for scope: I'd be surprised if you received zero interest.
s.gif
Applications are open for YC Winter 2023
Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search:

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK