Compiling Julia code for a RISC-V ESP32 microcontroller

Alexander-Barth
Sat, 17 Jan 2026 09:42:33 +0000
Maker

I wanted to share some experiments I did to run Julia on a ESP32 C3 using GPUCompiler and LLVM:

Codeberg.org

ESP32RISCVCompiler

Experimental compiler for ESP32 c3 (RISC-V) for the julia language

This microcontrollers use the open RISC-V instruction set. The ESP32 family of microcontrollers are quite popular because they quite inexpensive and jet rather powerful (dual core processor, WiFi and Bluetooth).

Once you have a Julia build with RISC-V enabled as LLVM target, GPUCompiler.jl can generate an object file with the compiled Julia code. I wrapped some functions from the Arduino API to manipulate the GPIO (General-Purpose Input/Output) pins and write to serial output. As it is done typically in Arduino sketches, there is a Julia function for setup() and one for loop() (both part of a Julia module). A single object file with these functions is then linked against the ESP32 IDF framework from the manufacturer of these microcontrollers.

What I got to work is quite basic like blinking a led, write to serial output. The most complex example that I got working is to control a led strip.

Only a tiny subset of Julia can be used however (no global variables, no heap allocation: no strings or arrays..). When I try to use global variable, the memory adresses of the host are stored into the RISC-V binary.

A work-around to access some global variables like the global Serial object is to create a function that returns it adress in LLVM IR. But for global variables declared by the user, this is more difficult to do.

I learned a lot from the post of @Sukera (Running Julia baremetal on an Arduino) on Julia on Arduino, which works also for WASM (GitHub - Alexander-Barth/FluidSimDemo-WebAssembly) .

Any ideas how to handle module-level global variable such as a reference to an Int32 would be quite helpful (when cross-compiling).

11 posts - 4 participants

Read full topic