From Lazarus wiki

Warning: The Xtensa support is highly experimental and prone to be broken. This description is work in progress.

So far Linux and Mac hosts only, currently most of the work concentrates on the ESP32 variant with the lx6 cores.



Native stable FPC must be installed and working on the system.

Install esp-idf based on the instructions given here:

Get Started (for Stable Release)

Follow the instructions to a least step 8 where you build the hello_word demo project.

copy all the freshly compiled .a files from the current project directory to a directory of your choice:

 mkdir ~/esp/xtensa-esp32-elf-libs 
 find . -path ./build/bootloader -prune -o -name "*.a" -exec cp {} ~/esp/xtensa-esp32-elf-libs \;
 find ~/esp/components -name "*.a" -exec cp {} ~/esp/xtensa-esp32-elf-libs \;


  • Make sure that you are in the directory where you have built the hello_world demo project when executing the find commands above.
  • One should not copy libraries from the project/build/bootloader directory, since these libraries do not contain full functionality.
  • Some of the required libraries are located in the esp-idf/components folder. Important to also copy the libraries in the ~/esp/esp-idf/components directory if the demo project was copied to outside the esp-idf directory.

Now you are ready to compile fpc and rtl.


export IDF_PATH=~/esp/esp-idf
source ~/esp/esp-idf/export.sh

to get the path and environment set (namely tools path and $IDF_PATH are needed)

Build FPC

Change into the fpc directory and run

 make FPC=fpc CPU_TARGET=xtensa OS_TARGET=freertos "CROSSOPT=-Cplx6 -XPxtensa-esp32-elf- -Cfhard" all -j

Tips & Tricks

If linking fails due to missing libraries, you can search them by (replace missing_symbol by the missing symbol):

 xtensa-esp32-elf-objdump -t ~/esp/xtensa-esp32-elf-libs/*.a | grep 'missing_symbol\|xtensa-esp32-elf-libs'

FPC doesn't automatically allocate heap space for this target. When using dynamic memory allocation remember to specify a heap size (for example -Ch1024).

Compile and run test program

Create a hello world program in the fpc dir and compile it with

 compiler/ppcrossxtensa -Furtl/units/xtensa-freertos/ -Tfreertos -XPxtensa-esp32-elf- -O3 -Wpesp32 -Fl~/esp/xtensa-esp32-elf-libs  -Fl~/.espressif/tools/xtensa-esp32-elf/esp-2019r2-8.2.0/xtensa-esp32-elf/xtensa-esp32-elf/lib/ hello

Get partition-table.bin and bootloader.bin from the hello_world example compiled above and copy them into the same dir as the compiled hello.bin

Flash with

 esptool.py -p /dev/ttyUSB0 -b 460800 --before default_reset --after hard_reset --chip esp32  write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x1000 bootloader.bin 0x8000 partition-table.bin 0x10000 hello.bin

Monitor the output with:

 idf_monitor.py  --port /dev/ttyUSB0 hello.elf


  • Once the bootloader and partition table has been flashed once one could also just flash the application only:
 esptool.py -p /dev/ttyUSB0 -b 460800 --before default_reset --after hard_reset --chip esp32  write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x10000 hello.bin
  • The maximum feasible baud rate depends on the USB-serial chip interfacing with the ESP32 chip, see this link. A baud rate of 921600 has worked successfully for flashing over a CP210x chip.


To use with QEMU

Build binutils

Get binutils-gdb sources, e.g. by

 git clone git://sourceware.org/git/binutils-gdb

Binutils 2.34 is known to work, so optionally do

 git checkout binutils-2_34

Copy https://github.com/FPK/binutils-xtensa-config/blob/master/lx6/xtensa-config.h into binutils-gdb/include to configure binutils for the CPU type support by FPC for xtensa-linux. This replaces the original file.

Configure and build binutils with

 ./configure --target=xtensa-linux --disable-gdb --disable-sim --disable-readline --disable-libdecnumber
 make -j `nproc`
 sudo make install

Build FPC

Get latest trunk and build it with:

 make FPC=fpc all -j "CROSSOPT=-Cfhard" OS_TARGET=linux CPU_TARGET=xtensa

Test FPC

Create a hello world in the FPC top level directory. Compile it with:

 compiler/ppcrossxtensa hello.pp -Tlinux -Furtl/units/xtensa-linux

Run it with:

 qemu-xtensa ./hello


Emulation and debugging using qemu (ESP32)

Install qemu (from source)

The official release of qemu supports the xtensa architecture but lacks support for the ESP32 and ESP8266 boards. To use qemu with ESP32 (ESP8266 support is not yet officially available) one can use Espressif's port of qemu (refer to this wiki for detail information: https://github.com/espressif/qemu/wiki).

Automated testing with qemu

For automated testing one needs to return an exit code from qemu to indicate the outcome of a test. One way to achieve this is to call the simcall instruction passing 1 in register a2 and the exit code in register a3:

 procedure qemu_exit(const exitcode: uint32); assembler; noreturn;
   mov  a3, a2   // copy exitcode value into a3
   movi a2, 1    // set a2 to 1 - exit request