Using ESP-IDF with RISC-V ESP32-C3 nodeMCU module on a Linux system

>NodeMCU ESP32-C3S”></a></p>
<h2 id=Table of Content

* Introduction
* Step 1, install dependencies
* Step 2, install ESP-IDF
* Step 3, setup working environment
* Step 4, test “Hello World” example
* Step 5, tune the target, if needed
* Step 6, flash the project
* Step 7, viewing the output
* Troubleshooting
** Invalid value for ‘{esp32|esp32s2}’: ‘esp32c3′ is not one of ‘esp32′, ‘esp32s2′
** libsodium/crypto_box/curve25519xchacha20poly1305/box_seal_curve25519xchacha20poly1305.c
** Flashing errors
*** Detection, power, and device that disappear
*** usbfs: interface 0 claimed by ch341 while ‘brltty’ sets config #1
** Problem with CA certificates bundle

Introduction

The list of existing ESP32-C3 SoC modules (with their specs) is very interesting, This one RISC-V core SoC has lower computing power than the ESP32-S3 (dual-core Xtensa ISA based, with a RISC-V co-processor core for “ultra low power” (ULP) mode), but RISC-V architecture is also far more efficient and will for sure have longer lifetime support and evolution due to its openness. ESP32-C3 use an RV32IMC (Integer, Multiplication/division and Compressed extensions) core.

I bought for my test a ESP-C3-32S-Kit on AliExpress (for ~3.4€). There is also an interesting option, where you can use really tiny 3~4 € ESP-C3-01M-Kit programmer interface/mother board, with a SoC included alone on a daughter (ESP32-C3M with an on PCB antenna). This allows, to flash several pads one only one programmer board. This reduce size of the needed system for final application to just the SoC and it’s power supply and peripherals. Pads of the SoC daughter board are wide enough to be easily soldered.

ESP-IDF is a tool to develop in C language on Espressif platforms, including ESP8266 and ESP32 series. It uses FreeRTOS free and open source embedded real-time OS for its SoCs. Sadly the official documentation for installing it is incomplete with the current state (November 2021) of GIT repository. Here is the mean to install a working ESP-IDF for this SoC series on Linux. This will be more compact and straight forward that the official with Linux+Windows installation.

About RISC-V more generally, I created this week a list of available Open Source RISC-V implementations, and open sources tools to build them or work with them.

Step 1, install dependencies

Instruction for Arch Linux, CentOS and Debian, based Linux systems:

* Debian/Ubuntu/…

sudo apt-get install git wget flex bison gperf python3 python3-pip python3-setuptools cmake \
  ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0

* CentOS

sudo yum -y update && sudo yum install git wget flex bison gperf python3 python3-pip python3-setuptools \
  cmake ninja-build ccache dfu-util libusbx

* Arch Linux/Manjaro/…

sudo pacman -S --needed gcc git make flex bison gperf python-pip cmake ninja ccache dfu-util libusb

Step 2, install ESP-IDF

This will take at least 1.2GB of disk space (size of the git clone at the time I write this article).

mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git

They didn’t mention, that 4.3 is required to use ESP32-C3. At the time I tried it, version 4.2 is currently (November 2021) the default branch, you can see the current version by this commands. Warning: This start the environment, so you will probably need to log again or simply start another shell to avoid problems when finishing the installation.:

cd ~/esp/esp-idf
. ./export.sh
idf.py --version

So you need to checkout the 4.3 branch to have a working version with ESP32-C3, and then update submodule to match the new version:

cd ~/esp/esp-idf
git checkout release/v4.3
git submodule update --init --recursive

Then you need to install some binaries/libs. Warning, it will create a ~/.expressif directory to place all downloaded files inside, don’t forget to create the directory + a link to a partition with enough place (about 1GB needed for all versions).

cd ~/esp/esp-idf
./install.sh esp32c3

After the installation, the following command is suggested to enter in the working (python pyenv) environment (don’t forget the first . and space)

Step 3, setup working environment

. ./export.sh

A message will be displayed that explain to you how to compile a program:

Done! You can now compile ESP-IDF projects.
Go to the project directory and run:

  idf.py build

They suggest in the documentation to add an alias to your .bashrc:

alias get_idf='. $HOME/esp/esp-idf/export.sh'

So you will only have to type get_idf to get ready to use it.

Step 4, test “Hello World” example

I would personally make it this way:

cd ~/esp/
mkdir tests
cd tests
cp -a ~/esp/esp-idf/examples/get-started/hello_world .
cd hello_world
idf.py set-target esp32c3

Errors possible, see:
* Invalid value for ‘{esp32|esp32s2}’: ‘esp32c3′ is not one of ‘esp32′, ‘esp32s2′
* libsodium/crypto_box/curve25519xchacha20poly1305/box_seal_curve25519xchacha20poly1305.c

Step 5, tune the target, if needed

You need now to use menuconfig if you want to setup some parameters, default one should just work fine.

idf.py menuconfig

This show you an interactive cli menu interface like for the Linux kernel, that allow you to tune some parameters. You don’t need to tune them for this test.

You can navigate with cursor keys, validate or enter submenus with enter, and quit them without modification with esc key. When you quit it, it will say you if you didn’t done any modification:

No changes to save (for '~/esp/test/hello_world/sdkconfig')

Step 5 build the project

Now as everything is setup, you only need to build the project, this could take some time, as it, at first time, compile, the whole embedded system:

idf.py build

It will end with a message displaying the location of the binary to be flashed and the instruction to type to flash it, the long explicit way and the short implicit way (I coloured them here):

Generated >/data/arc/esp/test/hello_world/build/hello-world.bin

Project build complete. To flash, run this command:
/home/popolon/.espressif/python_env/idf4.3_py3.9_env/bin/python ../../esp-idf/components/esptool_py/esptool/esptool.py -p (PORT) -b 460800 --before default_reset --after hard_reset --chip esp32c3  write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/hello-world.bin
or run 'idf.py -p (PORT) flash'

* Problem with CA certificates

Step 6, flash the project

If you didn’t have plugged your board in the USB port it’s the time to do. Then (by default white colour RGB led is enlighten. Type then the suggested command. I choose the short way here:

idf.py --port /dev/ttyUSB0 flash

It should now do the flashing sequence. I show only some important steps. In color you MAC address is given, it can be useful to detect if everything run fine.

Serial port /dev/ttyUSB0
Connecting....
Chip is ESP32-C3 (revision 3)
Features: Wi-Fi
Crystal is 40MHz
MAC: XX:XX:XX:XX:XX:XX
Uploading stub...
[...] <- lot of output
Writing at 0x00010000... (20 %)
[...] <- lot of output
Leaving...
Hard resetting via RTS pin...
Done

Read this if you have some troubles at flashing.

Step 7, viewing the output

You can connect to the board, still with its ttyUSB0 port, need to connect at speed 115200. I previously wrote an article about how to control a remote board, including serial

I use TinySerial here:

com /dev/ttyUSB0 115200

You can also use idf.py to monitor the output like this (idf.py monitor shortcuts and launching GDB with GDBStub:

idf.py -p /dev/ttyUSB0 monitor

In both case, you will see a booting sequence, an Hello World! some characteristics of your board, then a 10 seconds counter and a reboot. This is looping until you unplug or flash again the board.

Hello world!
This is esp32c3 chip with 1 CPU core(s), WiFi/BLE, silicon revision 3, 2MB external flash
Minimum free heap size: 327588 bytes
Restarting in 10 seconds...
Restarting in 9 seconds...
Restarting in 8 seconds...

You can quit by typing: the 2 keys ctrl-c followed then by a

Building, flashing and monitor can be combined by one command:
idf.py -p /dev/ttyUSB0 flash monitor

Troubleshooting

I don’t want to pollute too much the reading of the workflow and keep it as reference, so people can found answer when they encouter the same errors.

Invalid value for ‘{esp32|esp32s2}’: ‘esp32c3′ is not one of ‘esp32′, ‘esp32s2′

If you have the following error, you didn’t checkout the 4.3 branch at Step 2

Usage: /data/arc/esp/esp-idf/tools/idf.py set-target [OPTIONS] {esp32|esp32s2}
Try '/data/arc/esp/esp-idf/tools/idf.py set-target --help' for help.

Error: Invalid value for '{esp32|esp32s2}': 'esp32c3' is not one of 'esp32', 'esp32s2'.

libsodium/crypto_box/curve25519xchacha20poly1305/box_seal_curve25519xchacha20poly1305.c

If during the set-target you have the following error:

CMake Error at ~/esp/esp-idf/tools/cmake/component.cmake:475 (add_library):
  Cannot find source file:

    ~/esp/esp-idf/components/libsodium/libsodium/src/libsodium/crypto_box/curve25519xchacha20poly1305/box_seal_curve25519xchacha20poly1305.c

This mean you didn’t made the git submodules update in Step 2. So return in ~/esp/esp-idf and git submodule update.

You will then need to remove the hello_world directory and copy it again in tests: cd ~/esp/tests/; rm -R hello_word; cp -a ~/esp/esp-idf/examples/get-started/hello_world ..

Flashing errors

There are several problems possible for flashing part, most of them are about ttyUSB0 detection/usage.

Detection, power, and device that disappear

NodeMCU ESP32-C3S

First look if your board is detected by lsusb.

* If the device isn’t detected at all, verify if you USB wire is not a powering only wire. Try by connecting other USB devices, if all of them aren’t detected by the wire, this is probably the case, if you use a wire for your phone with the same kind of connector, try if it detected with it, then your board.

* Another case, a board that worked perfectly the first day, was not detected any more the second day. I looked at it with artisanal microscope using phone zoom + cheap lens, and seen a hair or wire, like on the detail picture at left, just above two pins of the USB connector. After removing it, the board work again.

* If the interface is displayed by lsusb but disappear when flashing it, try to disable power saving (autosuspend) for this device or all USB devices, lots of old mother boards have problems with USB devices power saving. Some mouses keep stuck, some flashable devices disappear, etc…

usbfs: interface 0 claimed by ch341 while ‘brltty’ sets config #1

If it fails with a long error message including around the 10th line:

FileNotFoundError: [Errno 2] No such file or directory: '/dev/ttyUSB0'

Then there is a problem with the USB detection in your system configuration.

You can dig in kernel message with dmesg | less then search for ttyUSB0 (just type /ttyUSB0 to found the problem.

In my case for example, the brtty (tty for braille) driver tried to get the serial device and then disconnected it:

[36767.028312] usb 1-1.6: ch341-uart converter now attached to ttyUSB0
[36767.252867] audit: type=1130 audit(1637441179.890:468): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=brltty-device@sys-devices-pci0000:00-0000:00:1a.0-usb1-1\x2d1-1\x2d1.6 comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[36767.878792] audit: type=1130 audit(1637441180.513:469): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=brltty@-sys-devices-pci0000:00-0000:00:1a.0-usb1-1\x2d1-1\x2d1.6 comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[36767.883002] usb 1-1.6: usbfs: interface 0 claimed by ch341 while 'brltty' sets config #1
[36767.883975] ch341-uart ttyUSB0: ch341-uart converter now disconnected from ttyUSB0
[36767.883998] ch341 1-1.6:1.0: device disconnected

You can in this case not the device id with the following command (the ID in the result is coloured here:

lsusb | grep CH340
Bus 001 Device 005: ID 1a86:7523 QinHeng Electronics CH340 serial converter

Then edit the 90-brltty-device.rules:

>code>sudo vi /usr/lib/udev/rules.d/90-brltty-device.rules

Search the line containing 1a86/7523 by typing /1a86/7523, then comment the line by adding a # at start:

#ENV{PRODUCT}=="1a86/7523/*", ENV{BRLTTY_BRAILLE_DRIVER}="bm", GOTO="brltty_usb_run"

save and quit by typing :x if you use vi/vim/nvim… and then reload udev rules by typing:

systemctl reload systemd-udevd

It should now be ok, by just unplugging and replugging the USB wire from your computer.

Generally all the kind of (tty)USB connection problem can be solved by tuning /etc/udev/rules.d/

Problem with CA certificates bundle

With the 4.2 version of ESP-IDF, some FAILED are thrown in relation with a x509_crt_bundle and cacrt_all.pem invalid certificate.

Updating the Certificate Bundle section has a link to himself as solution. ^^. Looks like the problem is on ESP-IF 4.2, 4.3 runs just fine, see install + upgrade process.

My system CA-certificates are already up to date but it want a specific version to put somewhere (not documented) to be able to push it on the board firmware. Ca-certificates, are certificates about CA (Certificate Authorities) that you need to be sure that this authorities are still be considered as valid. anyway ESP-IF 4.3 works just fine.