Packaging qemu with support for esp32c3

Recently I’ve bought myself a Seeed Studio XIAO ESP32C3, and I eventually want to program it using Rust. I thought it would be nice to also be able to test the code with the usual CI runners so for that purpose I would like to emulate the ESP32C3 chip. Espressif maintains a fork of qemu that allows that: GitHub - espressif/qemu: Fork of QEMU with Espressif patches. See Wiki for details. so I wanted to package that version for use in my devShell (and later the automated tests).

I think I’ve succesfully built something with qemu: Build from espressif fork, configure for esp32c3 · NixOS/nixpkgs@243c455 · GitHub, but there are some things I could use some help with:

  1. Is this something I could/should upstream to nixpkgs, or is this too niche? The commit linked above modifies the existing qemu derivation quite a bit, based on https://github.com/espressif/esp-toolchain-docs/blob/42ffdfb70916ddebde2dad7c3452d7406299ebb6/qemu/esp32c3/README.md

  2. The build system uses Meson, which I’m not familiar with, but I managed to work around some subproject that Meson would try to download during the build by ‘manually’ prefetching the subproject repos. Is there are more idomatic nixpkgs way to do this?

  3. If I build my expression I get a qemu that seems to work (starts, doesn’t just crash immedately), but I have not been able to build a working image to run on it. I’m not sure if this means that the derivation is broken after all, or if my images are wrong. Any tips would be appreciated.

3 Likes

Looks like a good start. This is something I plan to work with, may I ask if you would share a repo of what you built?

You may upstream it by creating another file, maybe qemu-esp.nix, and qemu.overrideAttrs in it.

I don’t really have anything fit for public consumption yet, but as a first step I’m reproducing https://n8henrie.com/2023/09/compiling-rust-for-the-esp32-with-nix/ and trying to update it to current versions. I then would like to be able to put a simple ‘blink’ type program into qemu as a proof-of-concept.

1 Like

That is a very nice idea, and seems to work great, thanks for the advice! New state of my branch is on https://github.com/SFrijters/nixpkgs/tree/qemu-espressif .

1 Like

It looks like we’re trying to achieve something similar, but I’m still confused. Thanks for the tip.
(which I was try to run qemu for raspberry4B in nixos though qemu-patch-raspberry4, which I thought is quite hard to understand what exactly this repo has done)

For clarity: my plan / wish is to be able to

  • Cross compile C/C++/Rust code from x86_64-linux (and ideally aarch64-linux) to a riscv variant that works on an esp32c3 chip. This I can do for a physical chip using particular pinned versions of rust/nixpkgs but I’m not able to use current nixpkgs for example. That relates to the issue I linked.
  • Emulate said esp32c3 using qemu on x86_64-linux (and ideally aarch64-linux). That is what my PR is for. If this is not accepted into nixpkgs, I’ll create a flake repo for it.
  • Create a binary payload from step 1 (using e.g. espflash) to use in the emulator. I haven’t managed to find the correct incantation for that yet. The best result so far is getting qemu stuck in a boot loop.

If qemu-patch-raspberry4 is another qemu fork you will probably be able to use my PR as inspiration at least.

1 Like

I’ve created GitHub - SFrijters/nix-qemu-espressif: Nix flake for qemu with ESP32 and ESP32C3 support, built from the Espressif fork - for an example of use see https://github.com/SFrijters/nix-qemu-esp32c3-rust-example (I think getting it into nixpkgs is an uphill battle) and it now provides the new esp-develop-8.2.0-20240122 version.

2 Likes

A working example of Rust code being compiled for ESP32C3 and running on QEMU is now available at GitHub - SFrijters/nix-qemu-esp32c3-rust-example: An example / test for https://github.com/SFrijters/nix-qemu-espressif .

1 Like

For those still interested in this: I’ve found a less invasive way of working around the linker error that I encountered and the example code no longer patches nixpkgs, but just injects an additional cargoBuildFlag for the example package. So, we no longer need to rebuild the whole Rust stack, which is a big improvement imo.