Month: January 2021

Compiling NuttX to ESP32-C3

First you need to install the risc-v toolchain:

$ cd /tmp
$ wget https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14.tar.gz
$ tar xvf riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14.tar.gz
$ cd riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14
$ sudo cp -a * /usr/local/

Clone the nuttx and apps repositories:

$ mkdir ~/nuttxspace
$ cd ~/nuttxspace
$ git clone https://github.com/protobits/incubator-nuttx nuttx
$ git clone https://github.com/protobits/incubator-nuttx-apps apps

Configure the board:
$ cd nuttx
$ ./tools/configure.sh esp32c3-devkit:nsh

Compile:

$ make

Convert the NuttX ELF file:

$ esptool.py --chip esp32-c3 elf2image --flash_mode dio --flash_size 2MB -o ./nuttx.bin nuttx

Put the board in bootloader mode (press and hold Boot button and click on RST button, release Boot button)
Flash it:

$ sudo esptool.py --chip esp32-c3 --port /dev/ttyUSB0 --baud 921600 write_flash 0x10000 nuttx.bin

Poke-a-hole

Packaging structs needs some care, otherwise you can waste more memory than necessary. Fortunately there is a program called “pahole” that can help you to find these “holes” in your struct:

https://lwn.net/Articles/335942/

I run it against NuttX objects to spot some struct with holes, the good news is that NuttX doesn’t have much issues and in fact many of these holes in the structs are documented inside the struct.

The complete list for NuttX in the ESP32 can be found here: https://pastebin.com/raw/rVzZweJ7

How to install NuttX on BL602

As some of you know I work for Espressif porting NuttX to ESP32 family. We just started porting NuttX to ESP32-C3 (the RISC-V ESP32 chip) and then I decided to take a look at our competitor: the Bouffalo Labs BL602 RISC-V chip. Bouffalo Labs ported NuttX to their BL602 then I got a DT-BL10 DevKit from Aliexpress and tested it.

The compilation was straight forward, I just read the file nuttx/boards/risc-v/bl602/bl602evb/README.txt and followed the instructions.

First I installed the RISC-V toolchain:

$ cd /tmp
$ wget https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14.tar.gz
$ tar xvf riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14.tar.gz
$ cd riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14
$ sudo cp -a * /usr/local/

Then I cloned NuttX:

$ mkdir ~/nuttxspace
$ cd ~/nuttxspace
$ git clone https://github.com/apache/incubator-nuttx nuttx
$ git clone https://github.com/apache/incubator-nuttx-apps apps

And I entered inside it to configure NuttX:

$ cd ~/nuttxspace/nuttx
$ ./tools/configure.sh bl602evb:nsh
$ make menuconfig
Device Drivers --->
[*] Serial Driver Support --->
UART0 Configuration --->
(115200) BAUD rate // I changed from 2000000 to 115200

Note: I already had the kconfig tool needed by the menuconfig interface. Case you don’t have it yet, please install: $ sudo apt-get install kconfig-frontends

Next I compiled it executing the usual command:

$ make

If everything worked as expected you will get the file nuttx.bin:

$ ls -l nuttx.bin
-rwxrwxr-x 1 alan alan 71296 Jan 24 13:39 nuttx.bin

We just need to flash it in the board!

Install the blflash tool (note: you need the rust tools installed on your system, it uses the cargo building system)

$ git clone https://github.com/spacemeowx2/blflash
$ cd blflash/blflash
$ cargo install --path .

Before flashing the firmware you need to put your board in bootloader mode: press and hold the D8 button and then press and release the EN button, now you can release the D8 button.

Now just execute:

$ blflash flash ./nuttx.bin --port /dev/ttyUSB0
[INFO blflash::flasher] Start connection…
[TRACE blflash::flasher] 5ms send count 55
[TRACE blflash::flasher] handshake sent elapsed 196.675µs
[INFO blflash::flasher] Connection Succeed
[INFO blflash] Bootrom version: 1
[TRACE blflash] Boot info: BootInfo { len: 14, bootrom_version: 1, otp_info: [0, 0, 0, 0, 3, 0, 0, 0, 9e, 9b, 2, 42, e8, b4, 1b, 0] }
[INFO blflash::flasher] Sending eflash_loader…
[INFO blflash::flasher] Finished 2.552386428s 11.20KB/s
[TRACE blflash::flasher] 5ms send count 500
[TRACE blflash::flasher] handshake sent elapsed 5.261016ms
[INFO blflash::flasher] Entered eflash_loader
[INFO blflash::flasher] Skip segment addr: 0 size: 47504 sha256 matches
[INFO blflash::flasher] Skip segment addr: e000 size: 272 sha256 matches
[INFO blflash::flasher] Skip segment addr: f000 size: 272 sha256 matches
[INFO blflash::flasher] Erase flash addr: 10000 size: 351584
[INFO blflash::flasher] Program flash… f96f580021f71996b6fb88554c666aca1d1126a4ab0de0acfeef578caa26bd94
[INFO blflash::flasher] Program done 4.186647898s 82.02KB/s
[INFO blflash::flasher] Skip segment addr: 1f8000 size: 5671 sha256 matches
[INFO blflash] Success

Run your preferred serial console software (minicom, picocom, screen, etc), configure to use the port /dev/ttyUSB0 with baudrate 115220.

Press and release the EN button, you should see the NuttX terminal:

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

? echo help ls mh mv ps uname
cat free kill mb mount mw sleep usleep

Builtin Apps:
timer sh getprime hello nsh
nsh>

PS.: If you don’t want to install Rust on your system, you can try the blflash equivalent implemented on Python:

$ pip install bl60x-flash
$ export PATH=$PATH:$HOME/.local/bin
$ bl60x-flash /dev/ttyUSB0 ./nuttx.bin
Loading helper binary 21872 bytes @ 0x22010000 100%|█████████████████████████████████████████████| 21.9k/21.9k [00:00<00:00, 47.7kbyte/s]

Erased 351572 bytes @ 0x10000
Programming 351572 bytes @ 0x10000
100%|████████████████████████████████████████████████| 352k/352k [00:02<00:00, 128kbyte/s]
Verified by XIP SHA256 hash

PS2: Thanks Brennan for helping to figure out the baudrate issue.