I wanted to share some experiments I did to run Julia on a ESP32 C3 using GPUCompiler and LLVM:
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 @seelengrab (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).