Documentation/risc-v/esp32c2: add ESP32-C2 and ESP8684-DevKitM pages
Some checks failed
MemBrowse Memory Report / changes-filter (push) Waiting to run
MemBrowse Memory Report / load-targets (push) Waiting to run
MemBrowse Memory Report / identical (push) Blocked by required conditions
MemBrowse Memory Report / analyze (push) Blocked by required conditions
Build Documentation / build-html (push) Has been cancelled

Document the chip (toolchain, Simple Boot, peripherals, MCUBoot) and
the DevKitM-1 board (pinout, headers, RGB, existing defconfigs),
including vendor figures.

Assisted-by: Cursor:Grok 4.6
Signed-off-by: Marcio Ribeiro <marcio.ribeiro@espressif.com>
This commit is contained in:
Marcio Ribeiro 2026-09-17 13:56:19 -03:00 • committed by Alan C. Assis
parent c1affc5923
commit 2d5ef658ee
6 changed files with 1304 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 MiB

View file

@ -0,0 +1,669 @@
=================
ESP8684-DevKitM-1
=================
.. tags:: chip:esp32c2, chip:esp8684, arch:risc-v, vendor:espressif
ESP8684-DevKitM-1 is an entry-level development board based on ESP8684-MINI-1,
a general-purpose module with 1 MB/2 MB/4 MB SPI flash. The module uses the
ESP32-C2 SoC and integrates Wi-Fi and Bluetooth LE. You can find the board
schematic
`here <https://dl.espressif.com/dl/schematics/esp8684-devkitm-1-schematics_V1.1.pdf>`_
and the vendor user guide
`here <https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32c2/esp8684-devkitm-1/user_guide.html>`__.
Most of the I/O pins are broken out to the pin headers on both sides for easy
interfacing. Developers can either connect peripherals with jumper wires or
mount ESP8684-DevKitM-1 on a breadboard.
Toolchain, flashing and the serial console are described in the
:doc:`ESP32-C2 chip documentation <../../index>`.
.. figure:: esp8684-devkitm-1-v1.1-isometric.png
:alt: ESP8684-DevKitM-1 Board Layout
:figclass: align-center
ESP8684-DevKitM-1 with ESP8684-MINI-1 module
The block diagram below presents the main components of the ESP8684-DevKitM-1.
.. figure:: esp8684-devkitm-1-v0.1-block-diagram.png
:alt: ESP8684-DevKitM-1 Electrical Block Diagram
:figclass: align-center
ESP8684-DevKitM-1 Electrical Block Diagram
Hardware Components
-------------------
.. figure:: esp8684-devkitm-1-v1.1-annotated-photo.png
:alt: ESP8684-DevKitM-1 Hardware Components
:figclass: align-center
ESP8684-DevKitM-1 Hardware Components
===================== ========================================================
Key Component Description
===================== ========================================================
ESP8684-MINI-1 Wi-Fi and Bluetooth LE module with PCB antenna and
on-board SPI flash (1 MB/2 MB/4 MB). Typical XTAL is
26 MHz.
5 V to 3.3 V LDO Converts USB or 5 V header power to 3.3 V.
5 V Power On LED Turns on when USB power is connected.
Pin Headers All available GPIO pins broken out on J1 and J3.
Boot Button Download button. Hold **Boot** and press **Reset** to
enter Firmware Download mode.
Micro-USB Port Power supply and USB-to-UART communication.
Reset Button Restarts the system (connected to CHIP_EN).
USB-to-UART Bridge Single USB-to-UART bridge, up to 3 Mbps.
RGB LED On v1.1: discrete RGB LED on GPIO0 (R), GPIO1 (G) and
GPIO8 (B). On v1.0: addressable RGB LED on GPIO8 only.
===================== ========================================================
This board has no USB-Serial-JTAG port on the SoC. Console and flashing use
the on-board USB-to-UART bridge.
Buttons and LEDs
================
Board Buttons
-------------
There are two buttons labeled Boot and RST. The RST button is not available
to software. It pulls the chip enable line that doubles as a reset line.
The BOOT button is connected to GPIO9. On reset it is used as a strapping
pin to determine whether the chip boots normally or into the serial
bootloader. After reset, however, the BOOT button can be used for software
input.
Board LEDs
----------
There is one on-board LED that indicates the presence of USB power.
The RGB LED mapping depends on the hardware revision:
* **v1.1 (current):** discrete RGB LED driven by GPIO0 (red), GPIO1 (green)
and GPIO8 (blue). This is the mapping used by NuttX
(``LED_RED``, ``LED_GREEN`` and ``LED_BLUE`` in ``board.h``).
* **v1.0:** addressable RGB LED driven only by GPIO8.
Both revisions are available on the market. See
`Hardware Revision Details <https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32c2/esp8684-devkitm-1/user_guide.html#hardware-revision-details>`_.
GPIO8 and GPIO9 are also strapping pins of the ESP8684 chip.
Power Supply
============
There are three mutually exclusive ways to provide power to the board:
* Micro-USB port (default, recommended)
* 5V and G (GND) pins
* 3V3 and G (GND) pins
Use a USB 2.0 cable (Standard-A to Micro-B) that carries data lines.
Charge-only cables will not enumerate the USB-to-UART bridge and cannot be
used to flash the board.
Pin Mapping
===========
.. figure:: esp8684-devkitm-1-pinout_v1.1.png
:alt: ESP8684-DevKitM-1 pin layout
:figclass: align-center
ESP8684-DevKitM-1 Pin Layout
Default NuttX pin assignments for this board:
============= ========== =========================================
ESP8684 Pin Signal Notes
============= ========== =========================================
GPIO20 U0TXD UART0 TX (serial console)
GPIO19 U0RXD UART0 RX (serial console)
GPIO9 BOOT Strapping pin; user button after reset
GPIO0 LED Red RGB LED (v1.1); ADC1_CH0
GPIO1 LED Green RGB LED (v1.1); ADC1_CH1
GPIO8 LED Blue RGB LED (v1.1) / WS2812 (v1.0); strapping
GPIO6 I2C0 SCL Default I2C clock
GPIO5 I2C0 SDA Default I2C data; ADC2_CH0
GPIO7 SPI2 MOSI Default SPI2 MOSI (FSPID)
GPIO2 SPI2 MISO Default SPI2 MISO (FSPIQ); LEDC PWM ch0
GPIO10 SPI2 CS Default SPI2 chip select
GPIO6 SPI2 CLK Default SPI2 clock (shared with I2C SCL)
============= ========== =========================================
**J1**
===== ========== =========================================
Pin Signal Notes
===== ========== =========================================
1 G Ground
2 3V3 3.3 V power supply
3 3V3 3.3 V power supply
4 GPIO2 ADC1_CH2, FSPIQ
5 GPIO3 ADC1_CH3
6 G Ground
7 RST CHIP_EN; High: enable; Low: power off
8 G Ground
9 GPIO0 ADC1_CH0, LED Red (v1.1)
10 GPIO1 ADC1_CH1, LED Green (v1.1)
11 GPIO10 FSPICS0
12 G Ground
13 5V 5 V power supply
14 5V 5 V power supply
15 G Ground
===== ========== =========================================
**J3**
===== ========== =========================================
Pin Signal Notes
===== ========== =========================================
1 G Ground
2 TX GPIO20, U0TXD
3 RX GPIO19, U0RXD
4 G Ground
5 GPIO9 Strapping pin, BOOT button
6 GPIO8 Strapping pin, LED Blue (v1.1)
7 G Ground
8 GPIO7 FSPID, MTDO
9 GPIO6 FSPICLK, MTCK
10 GPIO5 ADC2_CH0, FSPIWP, MTDI
11 GPIO4 ADC1_CH4, FSPIHD, MTMS
12 G Ground
13 GPIO18
14 G Ground
15 G Ground
===== ========== =========================================
GPIO8 and GPIO9 are strapping pins. Their level at reset selects boot and
download mode. See the
`ESP8684 Datasheet <https://www.espressif.com/sites/default/files/documentation/esp8684_datasheet_en.pdf>`_
section *Strapping Pins*.
Configurations
==============
All of the configurations presented below can be tested by running the following commands::
$ ./tools/configure.sh esp8684-devkitm:<config_name>
$ make flash ESPTOOL_PORT=/dev/ttyUSB0 -j
Where ``<config_name>`` is the name of board configuration you want to use,
i.e.: nsh, buttons, wifi...
Then use a serial console terminal like ``picocom`` configured to 115200 8N1.
adc
---
The ``adc`` configuration enables the ADC driver and the ADC example application.
ADC Unit 1 is registered to ``/dev/adc0`` with channels 0, 1, 2 and 3 enabled by default.
Currently, the ADC operates in oneshot mode.
More ADC channels can be enabled or disabled in ``ADC Configuration`` menu.
This example shows channels 0 and 1 connected to 3.3 V and channels 2 and 3 to GND (all readings
show in units of mV)::
nsh> adc -n 1
adc_main: g_adcstate.count: 1
adc_main: Hardware initialized. Opening the ADC device: /dev/adc0
Sample:
1: channel: 0 value: 2900
2: channel: 1 value: 2900
3: channel: 2 value: 0
4: channel: 3 value: 0
ble
---
This configuration is used to enable the Bluetooth Low Energy (BLE) of
the ESP32-C2 chip.
To test it, just run the following commands below.
Confirm that bnep interface exist::
nsh> ifconfig
bnep0 Link encap:UNSPEC at DOWN
inet addr:0.0.0.0 DRaddr:0.0.0.0 Mask:0.0.0.0
Get basic information from it::
nsh> bt bnep0 info
Device: bnep0
BDAddr: 86:f7:03:09:41:4d
Flags: 0000
Free: 20
ACL: 20
SCO: 0
Max:
ACL: 24
SCO: 0
MTU:
ACL: 70
SCO: 0
Policy: 0
Type: 0
Start the scanning process::
nsh> bt bnep0 scan start
Wait a little bit before stopping it.
Then after some minutes stop it::
nsh> bt bnep0 scan stop
Get the list of BLE devices found around you::
nsh> bt bnep0 scan get
Scan result:
1. addr: d7:c4:e6:xx:xx:xx type: 0
rssi: -62
response type: 4
advertiser data: 10 09 4d 69 20 XX XX XX XX XX XX XX XX XX XX 20 e
nsh>
bmp180
------
This configuration enables the use of the BMP180 pressure sensor over I2C.
You can check that the sensor is working by using the ``bmp180`` application::
nsh> bmp180
Pressure value = 91531
Pressure value = 91526
Pressure value = 91525
buttons
-------
This configuration shows the use of the buttons subsystem. It can be used by executing
the ``buttons`` application and pressing the ``BOOT`` button on the board::
nsh> buttons
buttons_main: Starting the button_daemon
buttons_main: button_daemon started
button_daemon: Running
button_daemon: Opening /dev/buttons
button_daemon: Supported BUTTONs 0x01
nsh> Sample = 1
Sample = 0
crypto
------
This configuration enables support for the cryptographic hardware and
the ``/dev/crypto`` device file. Currently, we are supporting SHA-1,
and SHA-256 algorithms using hardware.
To test hardware acceleration, you can use `hmac` example and following output
should look like this::
nsh> hmac
...
hmac sha1 success
hmac sha1 success
hmac sha1 success
hmac sha256 success
hmac sha256 success
hmac sha256 success
efuse
-----
This configuration demonstrates the use of the eFuse driver. It can be accessed
through the ``/dev/efuse`` device file.
Virtual eFuse mode can be used by enabling `CONFIG_ESPRESSIF_EFUSE_VIRTUAL`
option to prevent possible damages on chip.
The following snippet demonstrates how to read MAC address:
.. code-block:: C
int fd;
int ret;
uint8_t mac[6];
struct efuse_param_s param;
struct efuse_desc_s mac_addr =
{
.bit_offset = 1,
.bit_count = 48
};
const efuse_desc_t* desc[] =
{
&mac_addr,
NULL
};
param.field = desc;
param.size = 48;
param.data = mac;
fd = open("/dev/efuse", O_RDONLY);
ret = ioctl(fd, EFUSEIOC_READ_FIELD, &param);
To find offset and count variables for related eFuse,
please refer to Espressif's Technical Reference Manuals.
gpio
----
This is a test for the GPIO driver. It uses GPIO1 and GPIO2 as outputs and
GPIO9 as an interrupt pin.
At the nsh, we can turn the outputs on and off with the following::
nsh> gpio -o 1 /dev/gpio0
nsh> gpio -o 1 /dev/gpio1
nsh> gpio -o 0 /dev/gpio0
nsh> gpio -o 0 /dev/gpio1
We can use the interrupt pin to send a signal when the interrupt fires::
nsh> gpio -w 14 /dev/gpio2
The pin is configured as a rising edge interrupt, so after issuing the
above command, connect it to 3.3V.
To use dedicated gpio for controlling multiple gpio pin at the same time
or having better response time, you need to enable
`CONFIG_ESPRESSIF_DEDICATED_GPIO` option. Dedicated GPIO is suitable
for faster response times required applications like simulate serial/parallel
interfaces in a bit-banging way.
After this option enabled GPIO4 and GPIO5 pins are ready to used as dedicated GPIO pins
as input/output mode. These pins are for example, you can use any pin up to 8 pins for
input and 8 pins for output for dedicated gpio.
To write and read data from dedicated gpio, you need to use
`write` and `read` calls.
The following snippet demonstrates how to read/write to dedicated GPIO pins:
.. code-block:: C
int fd = open("/dev/dedic_gpio0", O_RDWR);
int rd_val = 0;
int wr_mask = 0xffff;
int wr_val = 3;
while(1)
{
write(fd, &wr_val, wr_mask);
if (wr_val == 0)
{
wr_val = 3;
}
else
{
wr_val = 0;
}
read(fd, &rd_val, sizeof(uint32_t));
printf("rd_val: %d", rd_val);
}
i2c
---
This configuration can be used to scan and manipulate I2C devices.
You can scan for all I2C devices using the following command::
nsh> i2c dev 0x00 0x7f
Default pins are GPIO6 (SCL) and GPIO5 (SDA).
To use slave mode, you can enable `ESPRESSIF_I2C0_SLAVE_MODE` option.
To use slave mode driver following snippet demonstrates how write to i2c bus
using slave driver:
.. code-block:: C
#define ESP_I2C_SLAVE_PATH "/dev/i2cslv0"
int main(int argc, char *argv[])
{
int i2c_slave_fd;
int ret;
uint8_t buffer[5] = {0xAA};
i2c_slave_fd = open(ESP_I2C_SLAVE_PATH, O_RDWR);
ret = write(i2c_slave_fd, buffer, 5);
close(i2c_slave_fd);
}
mcuboot_nsh
-----------
This configuration is the same as the ``nsh`` configuration, but it generates the application
image in a format that can be used by MCUboot. It also makes the ``make bootloader`` command to
build the MCUboot bootloader image using the Espressif HAL.
See :ref:`MCUBoot C2` for flash-layout limits on 2 MB modules. NuttX MCUBoot
support for ESP32-C2 is still in progress; there is no ``mcuboot_update_agent``
configuration for this board.
nsh
---
Basic configuration to run the NuttShell (nsh).
ostest
------
This is the NuttX test at ``apps/testing/ostest`` that is run against all new
architecture ports to assure a correct implementation of the OS.
pwm
---
This configuration demonstrates the use of PWM through LEDC channel 0,
which defaults to GPIO2. To test it, just execute the ``pwm`` application::
nsh> pwm
pwm_main: starting output with frequency: 10000 duty: 00008000
pwm_main: stopping output
random
------
This configuration shows the use of the ESP32-C2's True Random Number Generator.
To test it, just run ``rand`` to get 32 randomly generated bytes::
nsh> rand
Reading 8 random numbers
Random values (0x3ffe0b00):
0000 98 b9 66 a2 a2 c0 a2 ae 09 70 93 d1 b5 91 86 c8 ..f......p......
0010 8f 0e 0b 04 29 64 21 72 01 92 7c a2 27 60 6f 90 ....)d!r..|.'`o.
romfs
-----
This configuration demonstrates the use of ROMFS (Read-Only Memory File System) to provide
automated system initialization and startup scripts. ROMFS allows embedding a read-only
filesystem directly into the NuttX binary, which is mounted at ``/etc`` during system startup.
**What ROMFS provides:**
* **System initialization script** (``/etc/init.d/rc.sysinit``): Executed after board bring-up
* **Startup script** (``/etc/init.d/rcS``): Executed after system init, typically used to start applications
**Default behavior:**
When this configuration is used, NuttX will:
1. Create a read-only RAM disk containing the ROMFS filesystem
2. Mount the ROMFS at ``/etc``
3. Execute ``/etc/init.d/rc.sysinit`` during system initialization
4. Execute ``/etc/init.d/rcS`` for application startup
**Customizing startup scripts:**
The startup scripts are located in:
``boards/risc-v/esp32c2/common/src/etc/init.d/``
* ``rc.sysinit`` - System initialization script
* ``rcS`` - Application startup script
To customize these scripts:
1. **Edit the script files** in ``boards/risc-v/esp32c2/common/src/etc/init.d/``
2. **Add your initialization commands** using any NSH-compatible commands
**Example customizations:**
* **rc.sysinit** - Set up system services, mount additional filesystems, configure network.
* **rcS** - Start your application, launch daemons, configure peripherals. This is executed after the rc.sysinit script.
Example output::
*** Booting NuttX ***
[...]
rc.sysinit is called!
rcS file is called!
NuttShell (NSH) NuttX-12.8.0
nsh> ls /etc/init.d
/etc/init.d:
.
..
rc.sysinit
rcS
rtc
---
This configuration demonstrates the use of the RTC driver through alarms.
You can set an alarm, check its progress and receive a notification after it expires::
nsh> alarm 10
alarm_daemon started
alarm_daemon: Running
Opening /dev/rtc0
Alarm 0 set in 10 seconds
nsh> alarm -r
Opening /dev/rtc0
Alarm 0 is active with 10 seconds to expiration
nsh> alarm_daemon: alarm 0 received
The ESP32-C2 has no RTC retention memory, so the saved time does not
survive deep sleep.
sdmmc_spi
---------
This configuration is used to mount a FAT/FAT32 SD Card into the OS' filesystem.
It uses SPI to communicate with the SD Card, defaulting to SPI2.
The SD slot number, SPI port number and minor number can be modified in ``Application Configuration → NSH Library``.
To access the card's files, make sure ``/dev/mmcsd0`` exists and then execute the following commands::
nsh> ls /dev
/dev:
console
mmcsd0
null
ttyS0
zero
nsh> mount -t vfat /dev/mmcsd0 /mnt
This will mount the SD Card to ``/mnt``. Now, you can use the SD Card as a normal filesystem.
For example, you can read a file and write to it::
nsh> ls /mnt
/mnt:
hello.txt
nsh> cat /mnt/hello.txt
Hello World
nsh> echo 'NuttX RTOS' >> /mnt/hello.txt
nsh> cat /mnt/hello.txt
Hello World!
NuttX RTOS
nsh>
spi
---
This configuration enables the support for the SPI driver.
You can test it by connecting MOSI and MISO pins which are GPIO7 and GPIO2
by default to each other and running the ``spi`` example::
nsh> spi exch -b 2 "AB"
Sending: AB
Received: AB
If SPI peripherals are already in use you can also use bitbang driver which is a
software implemented SPI peripheral by enabling `CONFIG_ESPRESSIF_SPI_BITBANG`
option.
spiflash
--------
This config tests the external SPI that comes with the ESP8684-MINI-1 module
connected through SPI1.
By default a SmartFS file system is selected.
Once booted you can use the following commands to mount the file system::
nsh> mksmartfs /dev/smart0
nsh> mount -t smartfs /dev/smart0 /mnt
The storage partition defaults to offset ``0x110000`` and size ``0xf0000``
on 2 MB flash so that it fits after the application image.
temperature_sensor
------------------
This configuration enables the on-chip temperature sensor driver. The sensor is
exposed through the uORB interface and can be read with the ``sensortest``
utility::
nsh> sensortest temp
tickless
--------
This configuration enables the support for tickless scheduler mode.
timers
------
This configuration tests the general purpose timer. The ESP32-C2 has a
single timer group. It adds driver support, registers the timer as a device
and includes the timer example.
To test it, just run the following::
nsh> timer -d /dev/timer0
watchdog
--------
This configuration tests the watchdog timers. It includes the MWDT of the
single timer group, adds driver support, registers the WDT as a device and
includes the watchdog example application.
To test it, just run the following command::
nsh> wdog -i /dev/watchdog0
wifi
----
Enables Wi-Fi support. You can define your credentials this way::
$ make menuconfig
-> Application Configuration
-> Network Utilities
-> Network initialization (NETUTILS_NETINIT [=y])
-> WAPI Configuration
Or if you don't want to keep it saved in the firmware you can do it
at runtime::
nsh> wapi psk wlan0 mypasswd 3
nsh> wapi essid wlan0 myssid 1
nsh> renew wlan0
.. tip:: Please refer to :ref:`ESP32 Wi-Fi Station Mode <esp32_wi-fi_sta>`
for more information.

View file

@ -0,0 +1,635 @@
.. _esp32c2:
==================
Espressif ESP32-C2
==================
The ESP32-C2 (also sold as ESP8684) is a highly integrated, low-power SoC
with a RISC-V core. It supports 2.4 GHz Wi-Fi 4 (802.11b/g/n) and
Bluetooth 5 (LE).
* Internal Memory
- 576 KB ROM
- 272 KB SRAM (16 KB can be configured as cache)
- No RTC retention SRAM (saved RTC time does not survive deep sleep)
* External Memory
- SPI flash in the module (typically 1 MB, 2 MB or 4 MB)
* Connectivity
- 2.4 GHz Wi-Fi
- Bluetooth Low Energy 5
* GPIO
- 14 user GPIOs (GPIO0–GPIO10, GPIO18–GPIO20)
* Clock
- Main XTAL is 26 MHz on ESP8684-MINI-1 modules (40 MHz is also supported)
ESP32-C2 Toolchain
==================
A generic RISC-V toolchain can be used to build ESP32-C2 projects. It's recommended to use the same
toolchain used by NuttX CI. Please refer to the Docker
`container <https://github.com/apache/nuttx/tree/master/tools/ci/docker/linux/Dockerfile>`_ and
check for the current compiler version being used. For instance:
.. code-block::
###############################################################################
# Build image for tool required by RISCV builds
###############################################################################
FROM nuttx-toolchain-base AS nuttx-toolchain-riscv
# Download the latest RISCV GCC toolchain prebuilt by xPack
RUN mkdir riscv-none-elf-gcc && \
curl -s -L "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz" \
| tar -C riscv-none-elf-gcc --strip-components 1 -xz
It uses the xPack's prebuilt toolchain based on GCC 13.2.0-2.
Installing
----------
First, create a directory to hold the toolchain:
.. code-block:: console
$ mkdir -p /path/to/your/toolchain/riscv-none-elf-gcc
Download and extract toolchain:
.. code-block:: console
$ curl -s -L "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz" \
| tar -C /path/to/your/toolchain/riscv-none-elf-gcc --strip-components 1 -xz
Add the toolchain to your `PATH`:
.. code-block:: console
$ echo "export PATH=/path/to/your/toolchain/riscv-none-elf-gcc/bin:$PATH" >> ~/.bashrc
You can edit your shell's rc files if you don't use bash.
Building and flashing NuttX
===========================
Installing esptool
------------------
Make sure that ``esptool.py`` is installed and up-to-date.
This tool is used to convert the ELF to a compatible ESP32-C2 image and to flash the image into the board.
It can be installed with: ``pip install esptool>=4.8.1``.
.. warning::
Installing ``esptool.py`` may required a Python virtual environment on newer systems.
This will be the case if the ``pip install`` command throws an error such as:
``error: externally-managed-environment``.
If you are not familiar with virtual environments, refer to `Managing esptool on virtual environment`_ for instructions on how to install ``esptool.py``.
Bootloader and partitions
-------------------------
NuttX can boot the ESP32-C2 directly using the so-called "Simple Boot".
An externally-built 2nd stage bootloader is not required in this case as all
functions required to boot the device are built within NuttX. Simple boot does not
require any specific configuration (it is selectable by default if no other
2nd stage bootloader is used).
If features like `Flash Encryption`_ are required, an externally-built
2nd stage bootloader is needed. The MCUBoot bootloader is built using
the ``make bootloader`` command. This command generates the firmware in the
``nuttx`` folder. The ``ESPTOOL_BINDIR`` is used in the ``make flash`` command
to specify the path to the bootloader. For compatibility among other SoCs and
future options of 2nd stage bootloaders, the commands ``make bootloader`` and
the ``ESPTOOL_BINDIR`` option (for the ``make flash``) can be used even if no
externally-built 2nd stage bootloader is being built (they will be ignored if
Simple Boot is used, for instance)::
$ make bootloader
.. note::
MCUBoot support for ESP32-C2 on NuttX is still in progress. The
``mcuboot_nsh`` board configuration can build an MCUBoot-format image,
but there is no ``mcuboot_update_agent`` configuration yet. The default
MCUBoot slot map in Kconfig assumes at least 4 MB of flash and does
**not** fit the 2 MB modules used on many ESP8684-DevKitM-1 boards.
.. note:: It is recommended that if this is the first time you are using the board with NuttX to
perform a complete SPI FLASH erase.
.. code-block:: console
$ esptool.py erase_flash
Building and Flashing
---------------------
This is a two-step process where the first step converts the ELF file into an ESP32-C2 compatible binary
and the second step flashes it to the board. These steps are included in the build system and it is
possible to build and flash the NuttX firmware simply by running::
$ make flash ESPTOOL_PORT=<port> ESPTOOL_BINDIR=./
where:
* ``ESPTOOL_PORT`` is typically ``/dev/ttyUSB0`` or similar.
* ``ESPTOOL_BINDIR=./`` is the path of the externally-built 2nd stage bootloader and the partition table (if applicable): when built using the ``make bootloader``, these files are placed into ``nuttx`` folder.
* ``ESPTOOL_BAUD`` is able to change the flash baud rate if desired.
The ESP32-C2 port defaults to **2 MB** flash and **60 MHz** flash clock.
Flashing NSH Example
--------------------
This example shows how to build and flash the ``nsh`` defconfig for the ESP8684-DevKitM-1 board::
$ cd nuttx
$ make distclean
$ ./tools/configure.sh esp8684-devkitm:nsh
$ make -j$(nproc)
When the build is complete, the firmware can be flashed to the board using the command::
$ make -j$(nproc) flash ESPTOOL_PORT=<port> ESPTOOL_BINDIR=./
where ``<port>`` is the serial port where the board is connected::
$ make flash ESPTOOL_PORT=/dev/ttyUSB0 ESPTOOL_BINDIR=./
CP: nuttx.hex
MKIMAGE: NuttX binary
esptool.py -c esp32c2 elf2image --ram-only-header -fs 2MB -fm dio -ff 60m -o nuttx.bin nuttx
[...]
Generated: nuttx.bin
esptool.py -c esp32c2 -p /dev/ttyUSB0 -b 921600 write_flash -fs 2MB -fm dio -ff 60m 0x0000 nuttx.bin
[...]
Hard resetting via RTS pin...
Now opening the serial port with a terminal emulator should show the NuttX console::
$ picocom -b 115200 /dev/ttyUSB0
NuttShell (NSH) NuttX-12.8.0
nsh> uname -a
NuttX 12.8.0 ... risc-v esp8684-devkitm
The USB-to-UART bridge on the DevKit exposes UART0. The default UART0 pins
are GPIO20 (TX) and GPIO19 (RX). Use a USB cable that carries data lines;
charge-only cables will not enumerate the bridge.
Building with CMake
-------------------
General CMake usage (out-of-tree build, ``menuconfig`` target, and so on) is described in
:doc:`/quickstart/compiling_cmake`. The ESP32-C2 common arch enables post-build steps that
produce ``nuttx.bin`` (and related images) under the **CMake binary directory**; the build
log also prints suggested ``esptool.py`` command lines for your layout.
Example (NuttX shell defconfig, Ninja generator)::
$ cd nuttx
$ cmake -B build -DBOARD_CONFIG=esp8684-devkitm:nsh -GNinja
$ cmake --build build
To reconfigure the tree after changing options (same as other NuttX CMake boards)::
$ cmake --build build -t menuconfig
$ cmake --build build
Persistent HAL cache (``NXTMPDIR``)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Pass ``-DNXTMPDIR=ON`` at **configure** time to reuse a persistent clone of the
``esp-hal-3rdparty`` repository under ``nuttx/../nxtmpdir/esp-hal-3rdparty``. CMake checks
the expected revision; if it does not match, the cache directory is refreshed. This cuts
repeat configure/build time when the HAL checkout would otherwise be re-fetched into the
binary directory.
Example::
$ cmake -B build -DBOARD_CONFIG=esp8684-devkitm:nsh -DNXTMPDIR=ON -GNinja
$ cmake --build build
MCUBoot: building the 2nd-stage bootloader (``-t bootloader``)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For configurations that use MCUboot, build the bootloader the same way as
with Make, but via the CMake target::
$ cmake --build build -t bootloader
The image is installed as ``mcuboot-esp32c2.bin`` in the NuttX **source** directory (not
inside ``build/``).
.. note::
Flashing paths differ from the pure-Make flow: the application image is under your CMake
build directory (for example ``build/nuttx.bin``), while MCUboot binaries live next to
``nuttx`` sources.
Target flashing (``-t flash``)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
After a successful CMake build, you can flash the chip with the ``flash`` custom target.
This is the CMake-side equivalent of the Make ``FLASH`` logic in
``tools/espressif/Config.mk``.
**Serial port:** you must set ``ESPTOOL_PORT`` to a non-empty value (for example
``/dev/ttyUSB0``). If it is unset or empty, the flash step fails.
Example::
$ export ESPTOOL_PORT=/dev/ttyUSB0
$ cmake --build build -t flash
Or for a single invocation::
$ ESPTOOL_PORT=/dev/ttyUSB0 cmake --build build -t flash
Debugging
=========
This section describes debugging techniques for the ESP32-C2.
Debugging with ``openocd`` and ``gdb``
--------------------------------------
Espressif uses a specific version of OpenOCD to support ESP32-C2: `openocd-esp32 <https://github.com/espressif/openocd-esp32>`_.
Please check `Building OpenOCD from Sources <https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/api-guides/jtag-debugging/index.html#jtag-debugging-building-openocd>`_
for more information on how to build OpenOCD for ESP32-C2.
The ESP32-C2 does **not** integrate a USB-to-JTAG adapter. An external JTAG
adapter is required and can be connected as follows:
============ ===========
ESP32-C2 Pin JTAG Signal
============ ===========
GPIO4 TMS
GPIO5 TDI
GPIO6 TCK
GPIO7 TDO
============ ===========
These pins are also the default MTMS / MTDI / MTCK / MTDO strapping functions
on the ESP8684-DevKitM-1 header.
OpenOCD can then be used::
openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32c2-ftdi.cfg
Once OpenOCD is running, you can use GDB to connect to it and debug your application::
riscv-none-elf-gdb -x gdbinit nuttx
whereas the content of the ``gdbinit`` file is::
target remote :3333
set remote hardware-watchpoint-limit 2
mon reset halt
flushregs
monitor reset halt
thb nsh_main
c
.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``.
.. note::
``appimage_offset`` should be set to ``0x0`` when ``Simple Boot`` is used. For MCUboot, this value should be set to
``CONFIG_ESPRESSIF_OTA_PRIMARY_SLOT_OFFSET`` (``0x20000`` by default).
Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques.
Stack Dump and Backtrace Dump
-----------------------------
NuttX has a feature to dump the stack of a task and to dump the backtrace of it (and of all
the other tasks). This feature is useful to debug the system when it is not behaving as expected,
especially when it is crashing.
In order to enable this feature, the following options must be enabled in the NuttX configuration:
``CONFIG_SCHED_BACKTRACE``, ``CONFIG_DEBUG_SYMBOLS`` and, optionally, ``CONFIG_ALLSYMS``.
.. note::
The first two options enable the backtrace dump. The third option enables the backtrace dump
with the associated symbols, but increases the size of the generated NuttX binary.
Espressif also provides a tool to translate the backtrace dump into a human-readable format.
This tool is called ``btdecode.sh`` and is available at ``tools/espressif/btdecode.sh`` of NuttX
repository.
.. note::
This tool is not necessary if ``CONFIG_ALLSYMS`` is enabled. In this case, the backtrace dump
contains the function names.
Save a crash dump that contains ``sched_dumpstack`` lines to a file and decode it with::
./tools/espressif/btdecode.sh esp32c2 /tmp/backtrace.txt
Peripheral Support
==================
The following list indicates the state of peripherals' support in NuttX:
=========== ======= ====================
Peripheral Support NOTES
=========== ======= ====================
ADC Yes Oneshot
AES Yes
Bluetooth Yes
CAN/TWAI No
DMA Yes
eFuse Yes Also virtual mode supported
GPIO Yes Dedicated GPIO supported
HMAC No
I2C Yes Master and Slave mode supported
I2S Yes
LED/PWM Yes
RMT Yes
RNG Yes
RSA No
RTC Yes No RTC retention SRAM
SHA Yes
SPI Yes
SPIFLASH Yes
SPIRAM No
Timers Yes One timer group
UART Yes
USB Serial No No USB-Serial-JTAG on this SoC
Watchdog Yes
Wi-Fi Yes WPA3-SAE supported
=========== ======= ====================
Analog-to-digital converter (ADC)
---------------------------------
Two ADC units are available for the ESP32-C2:
* ADC1 with 5 channels.
* ADC2 with 1 channel. **This unit is not implemented.**
Those units are independent and can be used simultaneously. During bringup, GPIOs for selected channels are
configured automatically to be used as ADC inputs.
If available, ADC calibration is automatically applied (see
`this page <https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/api-reference/peripherals/adc_calibration.html>`__ for more details).
Otherwise, a simple conversion is applied based on the attenuation and resolution.
The ADC unit is accessible using the ADC character driver, which returns data for the enabled channels.
The ADC1 unit can be enabled in the menu :menuselection:`System Type --> Peripheral Support --> Analog-to-digital converter (ADC)`.
Then, it can be customized in the menu :menuselection:`System Type --> ADC Configuration`, which includes operating mode, gain and channels.
========== ===========
Channel ADC1 GPIO
========== ===========
0 0
1 1
2 2
3 3
4 4
========== ===========
ADC2 channel 0 is GPIO5.
.. warning:: Maximum measurable voltage may saturate around 2900 mV.
.. _MCUBoot C2:
MCUBoot
=======
The ESP32-C2 can use MCUBoot as a 2nd stage bootloader. NuttX integration is
still marked as in progress upstream (see
`MCUBoot Espressif port <https://docs.mcuboot.com/readme-espressif.html>`__).
The ``esp8684-devkitm:mcuboot_nsh`` configuration produces an MCUBoot-compatible
application image and enables ``make bootloader``. There is no
``mcuboot_update_agent`` defconfig for this board yet.
.. warning::
Default MCUBoot Kconfig offsets (primary ``0x20000``, secondary ``0x170000``,
scratch ``0x2C0000``, optional storage ``0x300000``) assume **4 MB or more**
of flash. ESP8684-DevKitM-1 boards commonly ship with **2 MB**. Using those
defaults on 2 MB flash will place partitions past the end of the device.
Override ``ESPRESSIF_OTA_*`` and ``ESPRESSIF_STORAGE_MTD_*`` before enabling
MCUBoot on 2 MB parts.
For Simple Boot on 2 MB flash, the storage MTD defaults to offset ``0x110000``
and size ``0xf0000``.
Flash Encryption
----------------
Flash encryption is intended for encrypting the contents of the ESP32-C2's off-chip flash memory. Once this feature is enabled,
firmware is flashed as plaintext, and then the data is encrypted in place on the first boot. As a result, physical readout
of flash will not be sufficient to recover most flash contents.
The current state of flash encryption for ESP32-C2 allows the use of Virtual E-Fuses and development mode, which permit users to evaluate and test the firmware before making definitive changes such as burning E-Fuses.
Flash encryption supports the following features:
.. list-table::
:header-rows: 1
* - Feature
- Description
* - **Flash Encryption with Virtual E-Fuses**
- Use flash encryption without burning E-Fuses. Default selection when flash encryption is enabled.
* - **Flash Encryption in Development mode**
- Allows reflashing an encrypted device by appending the ``--encrypt`` argument to the ``esptool.py write_flash`` command. This is done automatically if ``ESPRESSIF_SECURE_FLASH_ENC_FLASH_DEVICE_ENCRYPTED`` is set.
* - **Flash Encryption in Release mode**
- Does not allow reflashing the device. This is a permanent setting.
* - **Flash Encryption key**
- A user-generated key is required by default. Alternatively, a device-generated key is possible, but it will not be recoverable by the user (not recommended). See ``ESPRESSIF_SECURE_FLASH_ENC_USE_HOST_KEY``.
* - **Encrypted MTD Partition**
- If SPI Flash is enabled, an empty user MTD partition will be automatically encrypted on first flash.
.. note::
It is **strongly suggested** to read the following before working on flash encryption:
- `MCUBoot Flash Encryption <https://docs.mcuboot.com/readme-espressif.html#flash-encryption>`_
- `General E-Fuse documentation <https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/api-reference/system/efuse.html>`_
- `Flash Encryption Relevant E-Fuses <https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/security/flash-encryption.html#relevant-efuses>`_
ESP32-C2 Secure Boot V2 uses **ECDSA**, not RSA.
Flash Encryption Requirements
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Flash encryption requires burning E-Fuses to enable it on chip. This is not a reversible operation and should be done with caution.
There is, however, a way to test the flash encryption by simulating them on flash.
Build System Features
'''''''''''''''''''''
The build system contains some safeguards to avoid accidentally burning E-Fuses and automations for convenience. Those are summarized below:
1. A yellow warning will show up during build alerting that flash encryption is enabled (same for Virtual E-Fuses).
2. If ``ESPRESSIF_SECURE_FLASH_ENC_USE_HOST_KEY`` is set, build will fail if the flash encryption key is not found.
3. If SPI Flash is enabled, the user MTD partition is automatically encrypted with the provided encryption key.
4. ``make flash`` command will prompt the user for confirmation before burning the E-Fuse, if Virtual E-Fuses are disabled.
Simulating Flash Encryption with Virtual E-Fuses
'''''''''''''''''''''''''''''''''''''''''''''''''
It is highly recommended to use this method for testing the flash encryption before actually burning the E-Fuses.
The E-Fuses are stored in flash and persist between reboots. No real E-Fuses are changed.
To enable virtual E-Fuses for flash encryption testing, open ``menuconfig`` and:
1. Enable flash encryption on boot on: :menuselection:`System Type --> Bootloader and Image Configuration`
2. Verify Virtual E-Fuses are enabled (this is done by default): :menuselection:`System Type --> Peripheral Support --> E-Fuse support`
Actual encryption and burning E-Fuses
'''''''''''''''''''''''''''''''''''''
E-Fuses are burned by esptool and the bootloader on the first boot after flashing with encryption enabled.
This process is automated on NuttX build system.
.. warning:: Burning E-Fuses is NOT a reversible operation and should be done with caution.
To build a firmware with E-Fuse support and flash encryption enabled, open ``menuconfig`` and:
1. Enable flash encryption on boot on: :menuselection:`System Type --> Bootloader and Image Configuration`
2. Disable Virtual E-Fuses :menuselection:`System Type --> Peripheral Support --> E-Fuse support`
3. Check usage mode is Development (this allows reflashing, while Release mode does not).
.. note:: If using development mode of flash encryption (see menuconfig and documentation above), it is still possible to re-flash the device with esptool by
setting ``ESPRESSIF_SECURE_FLASH_ENC_FLASH_DEVICE_ENCRYPTED`` which adds ``--encrypt`` argument to the ``esptool.py write_flash`` command.
This will apply the burned encryption key to the image while flashing.
Flash Allocation for MCUBoot
----------------------------
When MCUBoot is enabled, the **default** Kconfig layout is the same as on other
Espressif RISC-V chips (4 MB class). Do not use it unchanged on 2 MB flash.
**Default flash layout (MCUBoot enabled, 4 MB+)**
.. list-table::
:header-rows: 1
:widths: 40 20 20
:align: left
* - Region
- Offset
- Size
* - Bootloader
- 0x000000
- 64KB
* - E-Fuse Virtual (see Note)
- 0x010000
- 64KB
* - Primary Application Slot (/dev/ota0)
- 0x020000
- 1.4MB
* - Secondary Application Slot (/dev/ota1)
- 0x170000
- 1.4MB
* - Scratch Partition (/dev/otascratch)
- 0x2C0000
- 256KB
* - Storage MTD (optional)
- 0x300000
- 1MB
* - Available Flash
- 0x400000+
- Remaining
.. raw:: html
<div style="clear: both"></div>
**Note**: The E-Fuse Virtual region is optional and only used when
``ESPRESSIF_EFUSE_VIRTUAL_KEEP_IN_FLASH`` is enabled. However, this 64KB
location is always allocated in the memory layout to prevent accidental
erasure during board flashing operations, ensuring data preservation if
virtual E-Fuses are later enabled.
The key KConfig options that control this layout:
- ``ESPRESSIF_OTA_PRIMARY_SLOT_OFFSET`` (default: 0x20000)
- ``ESPRESSIF_OTA_SECONDARY_SLOT_OFFSET`` (default: 0x170000)
- ``ESPRESSIF_OTA_SLOT_SIZE`` (default: 0x150000)
- ``ESPRESSIF_OTA_SCRATCH_OFFSET`` (default: 0x2C0000)
- ``ESPRESSIF_OTA_SCRATCH_SIZE`` (default: 0x40000)
- ``ESPRESSIF_STORAGE_MTD_OFFSET`` (default: 0x300000 when MCUBoot enabled)
- ``ESPRESSIF_STORAGE_MTD_SIZE`` (default: 0x100000)
For MCUBoot operation:
- The **Primary Slot** contains the currently running application
- The **Secondary Slot** receives OTA updates
- The **Scratch Partition** is used by MCUBoot for image swapping during updates
- MCUBoot manages image validation, confirmation, and rollback functionality
_`Managing esptool on virtual environment`
==========================================
This section describes how to install ``esptool``, ``imgtool`` or any other Python packages in a
proper environment.
Normally, a Linux-based OS would already have Python 3 installed by default. Up to a few years ago,
you could simply call ``pip install`` to install packages globally. However, this is no longer recommended
as it can lead to conflicts between packages and versions. The recommended way to install Python packages
is to use a virtual environment.
A virtual environment is a self-contained directory that contains a Python installation for a particular
version of Python, plus a number of additional packages. You can create a virtual environment for each
project you are working on, and install the required packages in that environment.
Two alternatives are explained below, you can select any one of those.
Using pipx (recommended)
------------------------
``pipx`` is a tool that makes it easy to install Python packages in a virtual environment. To install
``pipx``, you can run the following command (using apt as example)::
$ apt install pipx
Once you have installed ``pipx``, you can use it to install Python packages in a virtual environment. For
example, to install the ``esptool`` package, you can run the following command::
$ pipx install esptool
This will create a new virtual environment in the ``~/.local/pipx/venvs`` directory, which contains the
``esptool`` package. You can now use the ``esptool`` command as normal, and so will the build system.
Make sure to run ``pipx ensurepath`` to add the ``~/.local/bin`` directory to your ``PATH``. This will
allow you to run the ``esptool`` command from any directory.
Using venv (alternative)
------------------------
To create a virtual environment, you can use the ``venv`` module, which is included in the Python standard
library. To create a virtual environment, you can run the following command::
$ python3 -m venv myenv
This will create a new directory called ``myenv`` in the current directory, which contains a Python
installation and a copy of the Python standard library. To activate the virtual environment, you can run
the following command::
$ source myenv/bin/activate
This will change your shell prompt to indicate that you are now working in the virtual environment. You can
now install packages using ``pip``. For example, to install the ``esptool`` package, you can run the following
command::
$ pip install esptool
This will install the ``esptool`` package in the virtual environment. You can now use the ``esptool`` command as
normal. When you are finished working in the virtual environment, you can deactivate it by running the following
command::
$ deactivate
This will return your shell prompt to its normal state. You can reactivate the virtual environment at any time by
running the ``source myenv/bin/activate`` command again. You can also delete the virtual environment by deleting
the directory that contains it.
Supported Boards
================
.. toctree::
:glob:
:maxdepth: 1
boards/*/*