Running NuttX on ESP32 board

NuttX supports the Expressif ESP32 inclusive with SMP (Symmetric MultiProcessing) support, then I decided to post here the steps I followed to get it working:

Install esptool:

$ sudo pip install esptool

Install to toolchain:

You can download the pre-build toolchain:

Or: you can compile it from source code:

$ git clone -b xtensa-1.22.x
$ cd crosstool-NG
$ ./bootstrap && ./configure --prefix=$PWD && make install
$ ./ct-ng xtensa-esp32-elf
$ ./ct-ng build
$ chmod -R u+w builds/xtensa-esp32-elf
$ sudo cp -a builds/xtensa-esp32-elf/* /usr/local/

Now you can compile the NuttX:

$ mkdir ~/nuttxspace
$ cd ~/nuttxspace
$ git clone
$ git clone
$ cd nuttx
$ make distclean
$ ./tools/ esp32-core/nsh
$ make

The nuttx.bin generated is too big, you need to generate it from elf file (nuttx) :

$ --chip esp32 elf2image --flash_mode dio --flash_size 4MB -o ./nuttx.bin nuttx

You will need the bootloader.bin and the partitions, you can get it from hello word example. You need to clone and update the submodules of esp-idf (read the Get Started from above link), then:

$ cp -a esp-idf/examples/get-started/hello_world .
$ cd hello_world
$ make
$ cp build/bootloader/bootloader.bin ~/nuttxspace/nuttx/
$ cp build/partitions_singleapp.bin ~/nuttxspace/nuttx/partitions.bin

The files nuttx.bin, bootloader.bin and partitions.bin need to be flashed in the board. To do that first put the board in ROM Boot mode:

Press and hold the BOOT button of ESP32 board (IO0 pin will be put in low level) and press and release the RESET button. Now you can release the BOOT button.

This is the command to flash:

$ sudo --chip esp32-c3 --port /dev/ttyUSB0 --baud 921600 write_flash 0x0 ../esp-bins/bootloader-esp32c3.bin 0x8000 ../esp-bins/partition-table-esp32c3.bin 0x10000 nuttx.bin v3.0
Chip is ESP32D0WDQ6 (revision 0)
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Configuring flash size...
Auto-detected Flash size: 4MB
Flash params set to 0x0220
Compressed 19392 bytes to 11445...
Wrote 19392 bytes (11445 compressed) at 0x00001000 in 0.2 seconds (effective 901.6 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 82...
Wrote 3072 bytes (82 compressed) at 0x00008000 in 0.0 seconds (effective 10507.6 kbit/s)...
Hash of data verified.
Compressed 185024 bytes to 45527...
Wrote 185024 bytes (45527 compressed) at 0x00010000 in 2.1 seconds (effective 710.2 kbit/s)...
Hash of data verified.

Hard resetting...

Finally open minicom and just reset the board, you should get it:

$ minicom

Welcome to minicom 2.7

Compiled on Feb  7 2016, 13:37:27.
Port /dev/ttyUSB0, 15:40:48

Press CTRL-A Z for help on special keys

ets Jun  8 2016 00:22:57

ets Jun  8 2016 00:22:57

configsip: 0, SPIWP:0xee
mode:DIO, clock div:2
ho 0 tail 12 room 4
entry 0x40078fb4
I (31) boot: ESP-IDF v3.1-dev-162-geb659e4 2nd stage bootloader
I (31) boot: compile time 15:35:11
I (42) boot: Enabling RNG early entropy source...
I (42) boot: SPI Speed      : 40MHz
I (42) boot: SPI Mode       : DIO
I (45) boot: SPI Flash Size : 4MB
I (49) boot: Partition Table:
I (52) boot: ## Label            Usage          Type ST Offset   Length
I (60) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (67) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (75) boot:  2 factory          factory app      00 00 00010000 00100000
I (82) boot: End of partition table
I (86) esp_image: segment 0: paddr=0x00010020 vaddr=0x3ffb0df0 size=0x00054 (    84) load
I (95) esp_image: segment 1: paddr=0x0001007c vaddr=0x40080000 size=0x00400 (  1024) load
I (104) esp_image: segment 2: paddr=0x00010484 vaddr=0x40080400 size=0x00300 (   768) load
I (113) esp_image: segment 3: paddr=0x0001078c vaddr=0x400c0000 size=0x00000 (     0) load
I (122) esp_image: segment 4: paddr=0x00010794 vaddr=0x00000000 size=0x0f874 ( 63604) 
I (153) esp_image: segment 5: paddr=0x00020010 vaddr=0x3f400010 size=0x018e4 (  6372) map
I (155) esp_image: segment 6: paddr=0x000218fc vaddr=0x00000000 size=0x0e714 ( 59156) 
I (179) esp_image: segment 7: paddr=0x00030018 vaddr=0x400d0018 size=0x0d278 ( 53880) map
I (199) boot: Loaded app from partition at offset 0x10000
I (199) boot: Disabling RNG early entropy source...

NuttShell (NSH)
nsh> ?
help usage:  help [-v] []

  [           cmp         false       mkdir       rm          true        
  ?           dirname     free        mh          rmdir       uname       
  basename    dd          help        mount       set         umount      
  break       df          hexdump     mv          sh          unset       
  cat         echo        kill        mw          sleep       usleep      
  cd          exec        ls          ps          test        xd          
  cp          exit        mb          pwd         time        

Builtin Apps:

P.S.: If your board is rebooting, then disable the RTC watchdog in the bootloader.

15 thoughts on “Running NuttX on ESP32 board

  1. Not yet, Espressif didn’t release the agnostic library to use the ESP32 WiFi radio. The best option to use WiFi on NuttX is using some Broadcom FullMAC chip.

    1. Hi Alex, no idea! But I’m interested to help it happen. You can also try to contact Espressif and tell them can you want to use NuttX on ESP32 🙂 .

  2. Seria bom se ajudassem especificando alguns tipos de placas eu estou com a mach3 cinco portas estou perdido na identificação dos cabos que vem dos dribles.

    1. Yes, they are delaying to open-source the WIFI Stack. So my suggestion is: use a FullMAC chip like this used on Photon board, it works fine with NuttX. I hope Someday Espressif release the WiFi MAC libs as open-source!

  3. Hi. acassis

    I’m interested in Nuttx recently, so when I tried to build Nuttx following your tutorial, I got the following error yesterday :
    LD: nuttx
    xtensa-esp32-elf-ld: cannot open linker script file /home/kdm/nuttxspace/nuttx/boards/xtensa/esp32/esp32-core/scripts/esp32_out.ld: No such file or directory
    Makefile:143: recipe for target ‘nuttx’ failed
    make[1]: *** [nuttx] Error 1
    make[1]: directory ‘/home/kdm/nuttxspace/nuttx/arch/xtensa/src’ exit
    tools/Makefile.unix:483: recipe for target ‘pass2’ failed
    make: *** [pass2] Error 2

    Some idea?
    Best Regards

    1. Hi Domyung,
      It is very strange, in fact this “esp32_out.ld” never existed on NuttX, but the compilation never complain about it.

      So try to remove all LDSCRIPT1 from nuttx/boards/xtensa/esp32/esp32-core/scripts/Make.defs

      It should work! Also keep in mind that support to ESP32 on NuttX is minimal, only UART and GPIO.

      If you want to see the NuttX’s power it is better to you other microcontroller with full support.

      1. Hi, I’m trying to follow your instructions for compiling the toolchain, but it complains about not being able to find a usable python. Which version of the distro did you use to make this work?

      2. Hi Nigel,
        I used Ubuntu 18.04 at that time, but it should work on any distro. Did you install python 2.7 or python 3?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s