37 comments

[ 4.9 ms ] story [ 109 ms ] thread
Impressive job remaining so fast as the fore, Espressif & friends. The chips have been great & the software keeps improving.
I hope development continues and gets merged, their Rust support is what made me chose their S3 instead of something else
Same, I recently picked up a bunch of S2s on the premise of their Rust support. Really just hoping for no_std async I2C at this point.
Isn't there a bunch of embassy based async stuff in esp-rs?
Good question! As far as I can tell from the docs, it looks like I2C is still synchronous [1], but this will be my first async embedded Rust project, so I'm still unfamiliar with the general shape and functionality of things.

For comparison, things like WiFi are definitely async [2]

[1] https://docs.rs/esp32s2-hal/latest/esp32s2_hal/i2c/index.htm...

[2] https://github.com/esp-rs/esp-wifi/blob/main/examples-esp32s...

In esp-hal, they offer both sync and async I2C implementations, depending on what works best for an application. Since the async implementation is gated by a feature, it may not show up in the docs you linked.

Async implementation: https://github.com/esp-rs/esp-hal/blob/main/esp-hal-common/s...

You can also see the async feature mentioned here: https://docs.rs/crate/esp32s2-hal/latest/features

There is a very brief example of using async i2c here: https://github.com/esp-rs/esp-hal/blob/main/esp32s3-hal/exam... (you can see that it is using `lis3dh_async`, which requires async i2c)

Not specific to the ESP platforms, but Embassy offers a more useful example of async i2c here: https://github.com/embassy-rs/embassy/blob/main/examples/rp/... (and it would work the same on ESP)

If there's something missing in Embassy, hop onto the Matrix and chat about it. Dario and company are about as responsive and pleasant to speak to as one could find in the OSS world.
The C3 RISC v seems to lead the xtensa architecture.
"Lead" in what way? Is a single-core 160MHz C3 (RISC-V) actually faster than the dual core 240MHz ESP-S3 (Xtensa)?

I like the idea of using a more standard architecture, which should have better toolchain support. The C3 “leads” in that aspect. So, I would probably choose the C3 in most cases... but depending on the specific application, the Xtensa cores still seem to have advantages for now.

Fwiw, I use both. I really like both. I said c3 leads was my own experience following this community.

As it was explained RISC v has better support because it's open and can be emulated with qemi/llvm/wasm whereas xtensa cannot. Espressif has tried to address this as a licensee, but they don't own xtensa is owned by Tensilica Inc which is owned by cadence.

Cadence has not allowed details of the JTAG to be published. Because details of xtensa aren't open source licensed. This makes things such as the openocd debugger, probe rs etc aren't as good, and this situation is unlikely to change.

Debuggers are nice.

I'm working on the esp32 c3 embassy-rs support this weekend. I personally prefer the RISCv because I think it is easier to emulate and not need to flash a physical device , this means Dev work can move faster with better tests.

Just my opinion.

Yeah the C3 is slower than s-series, burns more power. I also miss the twai/can bus support in the C3 series.

Long term RISCv might cost less, and I think it will get new features faster.

I think it is cheaper to develop for RISCv. RISCv thanks to its outstanding qemu support means it is quickly becoming the reference standard for nascent "brand new" embedded capabilities.

MicroPython offers a great alternative to memory-safe ESP32 programming. It is a battle tested option with a great REPL and many optimization, including the native and Viper code emitters that are quite fast. It has so many available primitives and access to the hardware that if you wish you can write even the drivers for your peripherals directly in Python.
MicroPython isn't a great choice for these chips, you often want the minimal power consumption since you often run on battery, and MicroPython is extremely slow. https://youtu.be/u9UfKTOcYNs?si=ZiDxe_jsXfauOzR6.
The ESP chips are barely power efficient enough to run on battery with C.

Like, honestly, I'd not put anything but compiled languages without some sort of runtime on those chips except if I have something like "update an eink display twice a day" use cases.

I'm trying to make a natural gas usage live monitoring, I reused a single use e-cig battery (that is rechargeable). From calculation it should last at least a year in deep sleep.
>The ESP chips are barely power efficient enough to run on battery with C.

Incorrect, Esp32-s3 uses 8 micro amps in deep sleep.

8uA is still large compared to some other options. I work on medical implants that average 15uA while actively sensing biological signals 24hr/day. This includes the analog front end hardware to condition the signals as well. 8uA of deep sleep current would be a non starter.
and your devices probably don't cost $3 on aliexpress, right?
Wow that’s amazing what components are some of those?
How much does power usage of computation tend to matter in microcontroller applications? Vs "sleep" state power usage and being smart about waking up.
You do realise that there are two architecture xtensa & RISC v. RISC v isn't as power efficient.

The xtensa super low power mode can deep sleep, wake on timer or external interrupt, and (based on duty cycle) probably run for year or more on a 9v battery.

Micropython is similar in performance to Arduino on esp32. Poor Async, around 10x slower than rust and much harder to do Async, etc. Possibly better for beginners, but even that won't be true in another year thanks to projects like embassy-rs

Rust and C have similar compiled performance. The difference is rust Dev on esp32 is easier to target with other architectures, also rust will probably be a bit easier to detect & debug any crashes during design making it a lower cost to develop than C equivalent (because C is more permissive, it's easier to make accident mistakes)

I respectfully disagree, after performing many months of tests with the same application I wrote both in C and in MicroPython, both in battery-powered devices (you can find it on Github: FreakWAN). Moreover, when battery usage is really important, the main factor is the standby power usage. Anyway the device will only wake-up briefly to do a few things and shut it down again. It is unlikely you do heavy computations inside the device for the moments it is awake, you mostly do things like I/O with sensors and communication. So MicroPython is absolutely viable.
Without numbers and sensible tests that allow us to compare this in a systematic manner, neither of your manage to make a strong case for your position.

That being said, my professional opinion is that Python on MCUs is a dead end. The only attraction I can see is that people who aren't comfortable with C have an easier time programming microcontrollers. And to be very direct: I really, really would not hire someone who is uncomfortable with C to program MCUs.

I think Rust is the right direction to move in for MCUs. Low power devices are getting faster and now have more RAM, Flash and onboard goodies. That means they are going to do more stuff and more sophisticated stuff. They'll get more "responsibility". Which means that more will be asked of programmers in an industry that isn't exactly known for good software design.

Rust is a step towards better helping programmers write better software. It is a step towards helping developers write software with much larger footprints and deal with project scale. It has a compiler that can help you and there are more and more tools that help you verify code for correctness. This is important when you a) write code for a constrained environment and b) write code that may interact directly with the physical world.

This is the _opposite_ of going in the direction of Python. We don't need less rigor and discipline. We need a lot more rigor and discipline.

We also need better tooling. C/C++ compilers are stuck in the past and make for brittle and messy build systems. The fact that Python is often used to automate embedded SDKs and RTOS doesn't exactly make things better. A lot of time is wasted every year on trying to deal with the fact that Python isn't a compiled language and thus keeps breaking whenever some configuration changes. Python isn't even suitable for writing stable tooling.

Rust has much better tooling.

I don't doubt that there are people who are happy with micropython. Good. Go be happy. But it is not what the industry needs (or even uses) for embedded development.

it's funny that when "discipline and rigor" is advocated for, the underlying premise is basically "pain builds character".
Quite the opposite.

You can essentially choose what kind of pain you want. On one hand you can have the pain of having to work with a compiler and toolchain that aims to eliminate problems early by requiring you to be more consistent and more correct. On the other hand you can choose to deal with the pain later - as your errors and inconsistencies come back to haunt you later. Or if you are a professional: have to invent your own consistency and error checks through extensive testing. Not that I would expect rigorous test from someone who chooses to avoid compilers that can help them write higher quality code.

It is a lot more painful to have to deal with errors later, than it is to deal with them as you write the code. Not least in terms of financial pain and risk. For a lot of embedded systems "just updating the software" isn't always easy, it usually carries significant risk, and it isn't always even possible depending on how something is deployed.

Or to express the above with fewer words: you can choose between pain now and pain later.

As for tooling: using an interpreted language like Python means that it will only work for as long as the runtime environment is in a particular state. That all the right libraries are available in the right versions, and even the language runtime itself. Thousands upon thousands of files splattered across your filesystem. Every update of any part of the environment risking you suddenly have to spend days figuring out how to get things to work again.

Brittle toolchains are a pain. Don't waste time on things that lead to brittle toolchains.

I see a lot of hobbyists downplaying this online. I don't see a lot of people who work on this full time downplaying it. Be it people I know at MCU manufacturers who have to support customers or companies that manufacture devices and have large teams of embedded developers who regularly have to waste time because every new release means weeks of getting builds to behave somewhat predictably and reproducibly.

Having more modern compilers and tooling that can be relied upon isn't about more pain. It is about considerably less pain. If dealing with a compiler that is strict is too much pain for you, then embedded programming probably isn't for you. Because having lax compilers (or no compiler) means you'll learn about your mistakes when it is quite possibly too late to do anything about them.

C/C++ are not very nice languages if you want to ensure quality. Python gives you a sense of productivity over C/C++, but it provides no added benefit in terms of quality and de-risking. Rather the opposite because even the meager discipline a C/C++ compiler gives you is more than what Python gives you.

Fortunely there are lots of companies out there in the industry, many of which have more open minded folks regarding what toolchains to use.

Those that decide to be stuck in C, might one day wake up and realise the world has moved on without asking for permission.

I think the jury's still out on whether Rust will make it long term. Even if all the technology checks out, the project can easily be mismanaged into the ground. We've already seen hints of that.

Outside of C/C++ and Rust (seeing that MicroPython is irrelevant, as per your comment), what other options will be viable going into the future?

You are probably right about Rust: it has challenges that seems to make a lot of people want to keep it at arms length. Viability isn't just about technical fitness, but also about momentum, community size, pace and having sensible "taste makers" that teach the community good design and programming practices.

At the moment I don't see any viable alternatives. Rust has a good sized community AND people have been working on embedded use of it for many years already. It took a lot of work to get there. For an alternative to be viable it would have to achieve at least what Rust has achieved so far.

What will ultimately determine if Rust becomes the new go-to language for embedded programming is the community forming around embedded Rust projects.

Ruby is a good example of the power of a community trying to solve a given problem. I think Ruby would not have made it if it were not for Rails. Ruby started out as an interesting language with an atrociously bad runtime and ratty standard library. Yet it Rails had a community that vastly outperformed the qualities of the language/runtime it was based on.

Perhaps embedded programming is where Rust will ultimately make such a huge difference the application of Rust becomes greater than Rust itself. Perhaps a Rust based RTOS, and a sensible approach to how embedded software is structured, modularized, and designed may be the thing that becomes greater than the language itself?

Linux & Microsoft win 11 both support native drivers in rust.

Rust is a great (possibly best) way to build wasm. Wasm is extremely powerful.

Name one language to do both secure blockchain smart contracts, & device drivers, and embedded systems.

And it can use pyo3/maturing to expose code to python. Many significant python libraries are rewriting into rust. Clang/llvm targets means that rust can go anywhere C or C++ can go, including very esoteric systems.

I don't think the jury is out, it just doesn't have mainstream corporate penetration yet, it may never have that and that's fine.

Rust community can/will write bindings to anything, there is no need for other options, people don't realise how powerful rusts polyglot approach is.

Consider this - you may just have had the Rust kool-aid and you don't even realize certain fallacies. Also, you say wasm is extremely powerful - but is it as useful as it is powerful? Is it the future? I doubt that as well.
> I really, really would not hire someone who is uncomfortable with C to program MCUs.

I was under the impression Espressif was aimed at DIYers, prototypers, etc. looking to move fast and optimize later.

I'm a C guy myself, but I think you're looking at this wrong. There is no blessed stack. It's about tradeoffs.

That’s kind of like assuming AVR chips were only for hobbyists because you’re only familiar with the Arduino. And assuming that what hobbyists do has to be how the embedded industry works.

I’m looking at this from the point of view of someone who runs a company that does about 2-3 custom MCU based design per year, and spends at least 30% of our software development effort on embedded. We don’t write firmware in C because it is fun, but because we don’t actually have any real choice.

But please, do tell me that I’m looking at this wrong when I say that I’d rather not write software that controls machines that can kill people in C.

No one is telling you what language to use for your purposes. Just trying to point out that not everyone has the same purposes, and therefore may correctly draw different conclusions.
You might want to figure out what actual challenges professional firmware developers face before you start assuming how they "correctly" draw conclusions.
(comment deleted)
Perhaps worth including the date that was in the original title (29-09-2023), since this is a regular quarterly update.
I'm 99% sure I included it in the original submission, I think it was edited out.