A C compiler targeting the ULP coprocessor on the ESP32 chip. It is based on the lcc compiler written by David Hanson and Chris Fraser. The code-generator for the ULP was written by Jason Fuller (me), and all bugs are mine.
- Download https://github.com/jasonful/lcc/raw/master/ulpcc.zip and extract to a directory of your choosing
- set the ULPCCDIR environment variable to the directory you extracted to.
- set IDF_PATH to where you installed the ESP IDF. (If you do not have it installed on your Windows machine, install it from here.)
- set PATH=%PATH%;%ULPCCDIR%\bin
- cd ~
- git clone https://github.com/jasonful/lcc.git
- cd lcc
- source ~/lcc/ulpcc/doc/lccenv.sh
- buildlcc
ulpcc foo.c
will generate foo.S- Build foo.S as you normally would a hand-written .S file.
- Globals in foo.c are exported with a ulp_ prefix just like .globals in a foo.S.
- Floating point
- Signed arithmetic. Despite what some parts of the documentation may imply, the ULP coprocessor has no support for signed arithmetic.
This means you should always useunsigned int
(orunsigned
) instead ofint
. - Division, multiplication, mod
- Function calls. Without a stack pointer, and only having 4 registers to play with, implementing this will take some thought. For now, hopefully this won't be a problem since most ULP programs are pretty short.
- Strings. The ULP coprocessor cannot access individual bytes.
- Arrays of structures. Calculating offsets requires multiplication, which is not supported.
You can call the following ULP instructions as if they were functions:
adc
, halt
, i2c_rd
, i2c_wr
, reg_rd
, reg_wr
, sleep
, tsens
, wait
, wake
.
Pseudo-functions that take parameters must take constants (not expressions) because the machine instructions take constants.
See %ULPCCDIR%\inc\ulp_c.h for details.
You can also call the pseudo-function include
with a numeric argument. For example:
include (1);
will generate .include "1.S"
in the .S file, allowing you to include assembly code from other files.
- The compiler automatically inserts a
halt
at the end of entry(). - When something is not supported, I try to generate a friendly error message in the .S file.
- If you get an error like
ulp_main.elf section '.text' will not fit in region 'ram'
you will need to increase the space reserved for ULP code by modifying CONFIG_ULP_COPROC_RESERVE_MEM in your sdkconfig file. I believe the max is 8192.
Report bugs to https://github.com/jasonful/lcc/issues