Implementation for Espressif ESP32 MCUs. More...
Implementation for Espressif ESP32 MCUs.
RIOT-Xtensa-ESP is a bare metal implementation of RIOT-OS for ESP32 SOCs which supports most features of RIOT-OS. The peripheral SPI and I2C interfaces allow to connect all external hardware modules supported by RIOT-OS, such as sensors and actuators. SPI interface can also be used to connect external IEEE802.15.4 modules to integrate ESP32 boards into a GNRC network.
Although the port does not use the official ESP-IDF (Espresso IoT Development Framework) SDK, it must be installed for compilation. The reason is that the port uses most of the ESP32 SOC definitions provided by the ESP-IDF header files. In addition, it needs the hardware abstraction library (libhal), and the ESP32 WiFi stack binary libraries which are part of the ESP-IDF SDK.
The following table gives a short reference of all board configuration parameters used by the ESP32 port in alphabetical order.
|ADC_GPIOS||GPIOs that can be used as ADC channels||m|
|CAN_TX||GPIO used as CAN transceiver TX signal||o|
|CAN_RX||GPIO used as CAN transceiver RX signal||o|
|DAC_GPIOS||GPIOs that can be used as DAC channels||m|
|I2C0_SPEED||Bus speed of I2C_DEV(0)||o|
|I2C0_SCL||GPIO used as SCL for I2C_DEV(0)||o|
|I2C0_SDA||GPIO used as SCL for I2C_DEV(0||o|
|I2C1_SPEED||Bus speed of I2C_DEV(1)||o|
|I2C1_SCL||GPIO used as SCL for I2C_DEV(1)||o|
|I2C1_SDA||GPIO used as SCL for I2C_DEV(1)||o|
|PWM0_GPIOS||GPIOs that can be used at channels of PWM_DEV(0)||o|
|PWM1_GPIOS||GPIOs that can be used at channels of PWM_DEV(1)||o|
|SPI0_CTRL||SPI Controller used for SPI_DEV(0), can be ||o|
|SPI0_SCK||GPIO used as SCK for SPI_DEV(0)||o|
|SPI0_MOSI||GPIO used as MOSI for SPI_DEV(0)||o|
|SPI0_MISO||GPIO used as MISO for SPI_DEV(0)||o|
|SPI0_CS0||GPIO used as default CS for SPI_DEV(0)||o|
|SPI1_CTRL||SPI Controller used for SPI_DEV(1), can be ||o|
|SPI1_SCK||GPIO used as SCK for SPI_DEV(1)||o|
|SPI1_MOSI||GPIO used as MOSI for SPI_DEV(1)||o|
|SPI1_MISO||GPIO used as MISO for SPI_DEV(1)||o|
|SPI1_CS0||GPIO used as default CS for SPI_DEV(1)||o|
|UART1_TXD||GPIO used as TxD for UART_DEV(1)||o|
|UART1_RXD||GPIO used as RxD for UART_DEV(1)||o|
|UART2_TXD||GPIO used as TxD for UART_DEV(2)||o|
|UART2_RXD||GPIO used as RxD for UART_DEV(2)||o|
*Type: m - mandatory, o - optional
The following table gives a short reference in alphabetical order of modules that can be enabled/disabled by board configurations and/or application's makefile using
|esp_eth||not used||enable the Ethernet MAC (EMAC) network device|
|esp_gdb||not used||enable the compilation with debug information for debugging|
|esp_hw_counter||not used||use hardware counters for RIOT timers|
|esp_i2c_hw||not used||use the i2C hardware implementation|
|esp_idf_heap||not used||enable ESP-IDF heap implementation|
|esp_log_colored||not used||enable colored log output|
|esp_log_startup||not used||enable additional startup information|
|esp_log_tagged||not used||add additional information to the log output|
|esp_now||not used||enable the ESP-NOW network device|
|esp_rtc_timer||not used||enable RTC hardware timer with internal 150 kHz RC oscillator|
|esp_rtc_timer_32k||not used||enable RTC hardware timer with external 32.768 kHz crystal.|
|esp_spi_ram||not used||enable SPI RAM|
|esp_spiffs||not used||enable SPIFFS for on-board flash memory|
|esp_wifi||not used||enable the Wifi network device in WPA2 personal mode|
|esp_wifi_enterprise||not used||enable the Wifi network device in WPA2 enterprise mode|
ESP32 is a low-cost, ultra-low-power, single or dual-core SoCs from Espressif Systems with integrated WiFi and dual-mode BT module. The processor core is based on the Tensilica Xtensa LX6 32-bit Controller Processor Core.
The key features of ESP32 are:
|MCU||ESP32||Supported by RIOT|
|Cores||1 or 2 x Tensilica Xtensa LX6||1 core|
|FPU||ULP - Ultra low power co-processor||no|
|RAM||520 kByte SRAM |
8 kByte slow RTC SRAM
8 kByte fast RTC SRAM
|Flash||512 kByte ... 16 MByte||yes|
|Frequency||240 MHz, 160 MHz, 80 MHz||yes|
|Power Consumption||68 mA @ 240 MHz |
44 mA @ 160 MHz (34 mA @ 160 MHz single core)
31 mA @ 80 MHz (25 mA @ 80 MHz single core)
800 uA in light sleep mode
10 uA in deep sleep mode
|Timers||4 x 64 bit||yes|
|ADCs||2 x SAR-ADC with up to 18 x 12 bit channels total||yes|
|DACs||2 x DAC with 8 bit||yes|
|GPIOs||34 (6 are only inputs, 18 are RTC GPIOs)||yes|
|WiFi||IEEE 802.11 b/g/n built in||yes|
|Bluetooth||v4.2 BR/EDR and BLE||no|
|Ethernet||MAC interface with dedicated DMA and IEEE 1588 support||yes|
|IR||up to 8 channels TX/RX||no|
|Motor PWM||2 devices x 6 channels||yes|
|LED PWM||16 channels||no|
|Crypto||Hardware acceleration of AES, SHA-2, RSA, ECC, RNG||no|
|Vcc||2.5 - 3.6 V|
Rather than using the ESP32 SoC directly, ESP32 boards use an ESP32 module from Espressif which integrates additionally to the SoC some key components, like SPI flash memory, SPI RAM, or crystal oscillator. Some of these components are optional. A good overview about available modules can be found in the Online documentation of ESP-IDF.
The RIOT-OS for ESP32 SoCs supports the following features at the moment:
The implementation of RIOT-OS for ESP32 SOCs has the following limitations at the moment:
Following software components are required for compilation:
There are two options to install the Toolchain:
The easiest way to use install the toolchain is the RIOT Docker image
riotdocker. The compilation process using Docker consists of two steps
make BOARD= ...
make flash-only BOARD=...
where step 2 requires that the ESP flash programmer
esptool.py is installed. Both steps can also be performed with a single command on the host system using the
Using RIOT Docker requires at least the following software:
Dockercontainer virtualization software
For information about installing Docker on your host, refer to the appropriate manuals for your operating system. For example, the easiest way to install Docker on the Ubuntu/Debian system is:
For information on how to install
esptool.py, see section Installation of
riotdocker fork that only installs the
RIOT-Xtensa-ESP32-toolchain is available at GitHub. After cloning this git repository, you can use branch
esp32_only to generate a Docker image with a size of "only" 990 MByte:
riotdocker version that contains the toolchains for all different RIOT platforms can be found at GitHub. However, the Docker image generated from the this Docker file has a size of about 1.5 GByte.
Once a Docker image has been created, it can be started with the following commands while in the RIOT root directory:
/path/to/RIOTbecomes visible as the home directory of the
riotbuilduser in the Docker image. That is, the output of compilations performed in RIOT Docker is also accessible on the host system.
Please refer the RIOT wiki on how to use the Docker image to compile RIOT OS.
Alternatively, an existing Docker image from Docker Hub can be used. You can either pull and start the schorcht/riotbuild_esp32 Docker image which only contains the
or the riot/riotbuild Docker image (size is about 1.5 GB) which contains the toolchains for all platforms using
Using Docker, the make process consists of the following two steps:
Once the RIOT Docker image has been started from RIOT's root directory, a RIOT application can be compiled inside the Docker using the make command as usual, for example:
This will generate a RIOT binary in ELF format.
flashtarget inside the Docker image.
The RIOT binary has to be flash outside docker on the host system. Since the Docker image was stared while in RIOT's root directory, the output of the compilations is also accessible on the host system. On the host system, the
flash-only target can then be used to flash the binary.
A more difficult way to install the toolchain is the manual installation of required components as described below.
Xtensa GCC compiler for ESP32 can be downloaded and installed as precompiled binary archive from GitHub.
Once the compiler is installed you can add the binary directory to your
ESP-IDF, the official SDK from Espressif, can be downloaded and installed as GIT repository.
Since we only use a few header files, ESP-IDF does not need to be compiled in any way. To use the installed ESP-IDF, just set the variable
esptool.py(ESP flash programmer tool) [TOC]
The RIOT port does not work with the
esptool.py ESP flasher program available on GitHub or as a package for your OS. Instead, a modified version is required.
To avoid the installation of the complete ESP-IDF SDK, for example, because RIOT Docker
riotdocker is used for compilation,
esptool.py has been extracted from the SDK and placed in RIOT's directory
dist/tools/esptool. For convenience, the build system uses always the version from this directory.
Therefore, it is not necessary to install
esptool.py explicitly. However
esptool.py depends on
pySerial which can be installed either using
or the package manager of your OS, for example on Debian/Ubuntu systems:
For more information on
esptool.py, please refer to the git repository.
Once you have installed all required components, you should have the following directories.
To use the toolchain and optionally the SDK, please check that your environment variables are set correctly to
To compile an application for an ESP32 board, change to RIOT's root directory and execute the make command, e.g.,
BOARD variable specifies the generic ESP32 board definition and option
-C the directory of application.
The compilation process can be controlled by a number of variables for the make command:
|CONFIGS||string||empty||Override default board and driver configurations, see section Application-Specific Configurations.|
|FLASH_MODE||dout, dio, qout, qio||dout||Set the flash mode, see section Flash Modes|
|PORT||/dev/*||/dev/ttyUSB0||Set the port for flashing the firmware.|
|QEMU||0, 1||0||Generate an image for QEMU, see section QEMU Mode and GDB.|
Optional features of ESP32 can be enabled by
USEMODULE definitions in the makefile of the application. These are:
|esp_eth||Enable the Ethernet MAC (EMAC) interface as |
|esp_gdb||Enable the compilation with debug information for debugging with QEMU and GDB (|
|esp_i2c_hw||Use the hardware I2C implementation, see section I2C Interfaces.|
|esp_idf_heap||Use the ESP-IDF heap implementation, see section ESP-IDF Heap Implementation.|
|esp_log_colored||Enable colored log output, see section Log output.|
|esp_log_startup||Enable additional startup information, see section Log output.|
|esp_log_tagged||Add additional information to the log output, see section Log output.|
|esp_now||Enable the built-in WiFi module with the ESP-NOW protocol as |
|esp_rtc_timer||Enable RTC hardware timer with internal 150 kHz RC oscillator.|
|esp_rtc_timer_32k||Enable RTC hardware timer with external 32.768 kHz crystal.|
|esp_spiffs||Enable the optional SPIFFS drive in on-board flash memory, see section SPIFFS Device.|
|esp_spi_ram||Enable the optional SPI RAM, see section SPI RAM Modules.|
|esp_wifi||Enable the built-in WiFi module as |
|esp_wifi_enterprise||Enable the built-in WiFi module as |
For example, to activate the a SPIFFS drive in on-board flash memory, the makefile of application has simply to add the
esp_spiffs module to
USEMODULE make variable:
Modules can be also be activated temporarily at the command line when calling the make command:
FLASH_MODE make command variable determines the mode that is used for flash access in normal operation.
The flash mode determines whether 2 data lines (
dout) or 4 data lines (
qout) for addressing and data access. For each data line, one GPIO is required. Therefore, using
qout increases the performance of SPI Flash data transfers, but uses two additional GPIOs (GPIO9 and GPIO10). That is, in this flash modes these GPIOs are not available for other purposes. If you can live with lower flash data transfer rates, you should always use
dout to keep GPIO9 and GPIO10 free for other purposes.
For more information about these flash modes, refer the documentation of esptool.py.
The RIOT port for ESP32 implements a log module with a bunch of macros to generate log output according to the interface as defined in system logging header. These macros support colored and tagged log output.
The colored log output is enabled by module
esp_log_colored. If colored log output is enabled, log messages are displayed in color according to their type: Error messages are displayed in red, warnings in yellow, information messages in green and all other message types in standard color.
esp_log_tagged module is used, all log messages are tagged with additional information: the type of message, the system time in ms, and the module or function in which the log message is generated. For example:
LOG_* macros as defined in system logging header or the tagged version
LOG_TAG_* of these macros can be used to produce tagged log output. If the
LOG_* macros are used, the function which generates the log message is used in the tag while a
tag parameter is used for the
LOG_TAG_* macros. For example,
generates a log message in which the name of the calling function is used as tag. With
a log message with string
mod in the tag is generated.
esp_log_startup module can be used to enable additional information about the boot process, the board configuration, the system configuration, the CPU used by the system, and the available heap. These information may help to detect problems during the startup. If the application does not start as expected, this module should be used.
ESP-IDF SDK provides a complex heap implementation that supports multiple heap segments in different memory areas such as DRAM, IRAM, and PSRAM. Whenever you want to use these memory areas as heap, you have to use the heap implementation from the ESP-IDF SDK. ESP-IDF heap is not used by default. To use it, it has to be enabled by the the makefile of the application:
ESP32 is an SoC and has a lot of peripherals that are not all supported by the RIOT port. This section describs the supported peripherals and how they have to be configured.
ESP32 has 34 GPIO pins, where only a subset can be used as output, as ADC channel, as DAC channel and as GPIOs in deep-sleep mode, the so-called RTC GPIOs. Some of them are used by special SoC components, e.g., as touch sensors. The following table gives a short overview.
|Pin||Type||ADC / RTC||PU / PD||Special function||Remarks|
|GPIO0||In/Out||yes||yes||Touch sensor||Bootstrapping, pulled up|
|GPIO2||In/Out||yes||yes||Touch sensor||Bootstrapping, pulled down|
|GPIO9||In/Out||-||yes||Flash SD_DATA2||only in |
|GPIO10||In/Out||-||yes||Flash SD_DATA3||only in |
|GPIO12||In/Out||yes||yes||MTDI / Touch sensor||JTAG interface / Bootstrapping, pulled down|
|GPIO13||In/Out||yes||yes||MTCK / Touch sensor||JTAG interface|
|GPIO14||In/Out||yes||yes||MTMS / Touch sensor||JTAG interface|
|GPIO15||In/Out||yes||yes||MTDO / Touch sensor||JTAG interface / Bootstrapping, pulled up|
|GPIO16||In/Out||-||yes||-||usually not available when SPI RAM is used|
|GPIO17||In/Out||-||yes||-||usually not available when SPI RAM is used|
|GPIO32||In/Out||yes||yes||XTAL32_P||can be used to connect an external 32 kHz crystal|
|GPIO33||In/Out||yes||-||XTAL32_N||can be used to connect an external 32 kHz crystal|
|GPIO37||In||yes||-||SENSOR_CAPP||usually not broken out|
|GPIO38||In||yes||-||SENSOR_CAPN||usually not broken out|
ADC: these pins can be used as ADC inputs
RTC: these pins are RTC GPIOs and can be used in deep-sleep mode
PU/PD: these pins have software configurable pull-up/pull-down functionality.
GPIO0, GPIO2 are bootstrapping pins which are used to boot ESP32 in different modes:
|1||X||boot in FLASH mode to boot the firmware from flash (default mode)|
|0||0||boot in UART mode for flashing the firmware|
ESP32 integrates two 12-bit ADCs (ADC1 and ADC2) capable of measuring up to 18 analog signals in total. Most of these ADC channels are either connected to a number of integrated sensors like a Hall sensors, touch sensors and a temperature sensor or can be connected with certain GPIOs. Integrated sensors are disabled in RIOT's implementation and are not accessible. Thus, up to 18 GPIOs, can be used as ADC inputs:
These GPIOs are realized by the RTC unit and are therefore also called RTC GPIOs or RTCIO GPIOs.
The GPIOs that can be used as ADC channels for a given board are defined by the
ADC_GPIOS macro in the board-specific peripheral configuration. This configuration can be changed by application-specific configurations.
The order of the listed GPIOs determines the mapping between the RIOT's ADC lines and the GPIOs. The maximum number of GPIOs in the list is
ADC_NUMOF_MAX which is defined to be 16.
ADC_NUMOF is determined automatically from
ADC_GPIOS list and must not be changed.
ADC_GPIOSmust be defined even if there are no GPIOs that could be used as ADC channels on the board. In this case, an empty list hast to be defined which just contains the curly braces.
adc_initfunction, they can be used for other purposes.
For each ADC line, an attenuation of the input signal can be defined separately with the
This results in different full ranges of the measurable voltage at the input. The attenuation can be set to 0 dB, 3 dB, 6 dB and 11 dB, with 11 dB being the standard attenuation. Since an ADC input is measured against a reference voltage Vref of 1.1 V, approximately the following measurement ranges are given when using a corresponding attenuation:
|0 dB||0 ... 1.1V (Vref)||ADC_ATTENUATION_0_DB|
|3 dB||0 ... 1.5V||ADC_ATTENUATION_3_DB|
|6 dB||0 ... 2.2V||ADC_ATTENUATION_6_DB|
|11 dB (default)||0 ... 3.3V||ADC_ATTENUATION_11_DB|
adc_vref_to_gpio25function at GPIO 25.
For that purpose GPIO25 is initialized automatically as ADC channel and is connected internally to Vref to measure the current voltage. Once the initialization is finished and the function returns with success, the current voltage can be read from GPIO25. The results of the ADC input can then be adjusted accordingly. The
adc_vref_to_gpio25 function can be used to determine the current voltage at ESP32.
ESP32 supports 2 DAC lines at GPIO25 and GPIO26. These DACs have a width of 8 bits and produce voltages in the range from 0 V to 3.3 V (VDD_A). The 16 bits DAC values given as parameter of function dac_set are down-scaled to 8 bit.
The GPIOs that can be used as DAC channels for a given board are defined by the
DAC_GPIOS macro in the board-specific peripheral configuration. This configuration can be changed by application-specific configurations.
The order of the listed GPIOs determines the mapping between the RIOT's DAC lines and the GPIOs. The maximum number of GPIOs in the list is
DAC_NUMOF_MAX which is defined to be 16.
DAC_NUMOF is determined automatically from
DAC_GPIOS list and must not be changed.
DAC_GPIOSmust be defined even if there are no GPIOs that could be used as DAC channels on the board. In this case, an empty list hast to be defined which just contains the curly braces.
DAC_GPIOSare not initialized as DAC channels with the
dac_initfunction, they can be used for other purposes.
The ESP32 has two built-in I2C hardware interfaces that support I2C bus speed up to 400 kbps (
The board-specific configuration of the I2C interface
I2C_DEV(n) requires the definition of
I2Cn_SPEED, the bus speed,
I2Cn_SCL, the GPIO used as SCL signal, and
I2Cn_SDA, the GPIO used as SDA signal,
n can be 0 or 1. If they are not defined, the I2C interface
I2C_DEV(n) is not used.
I2C_DEV(n)must be in continuous ascending order of n.
I2C_NUMOF is determined automatically from board-specific peripheral definitions of
The following table shows the default configuration of I2C interfaces used for a large number of boards. It can be changed by application-specific configurations.
periph_i2cmodule is used. Otherwise they are not allocated and can be used for other purposes.
Beside the I2C hardware implementation, a I2C bit-banging protocol software implementation can be used. This implementation allows bus speeds up to 1 Mbps (
I2C_SPEED_FAST_PLUS). It can be activated by adding
to application's makefile. The Disadvantage of the software implementation is that it uses busy waiting.
ESP supports two types of PWM generators
The PWM implementation uses the ESP32's high-speed MCPWM modules. Reason is that the LED PWM controller only supports resolutions of powers of two.
ESP32 has 2 MCPWM modules, each with up to 6 channels (
PWM_CHANNEL_NUM_DEV_MAX). Thus, the maximum number of PWM devices is 2 and the maximum total number of PWM channels is 12. These 2 MCPWM devices are used as RIOT PWM devices
The GPIOs that can be used as PWM channels of RIOT's PWM devices are defined by the
PWM1_GPIOS macros in the board-specific peripheral configuration. This configuration can be changed by application specific configurations.
The order of the listed GPIOs determines the mapping between RIOT's PWM channels and the GPIOs. Board definitions usually declare a number of GPIOs as PWM channels.
PWM1_GPIOScan be omitted or empty. In the latter case, they must at least contain the curly braces. The corresponding PWM device can not be used in this case.
PWM_NUMOF is determined automatically from the PWM0_GPIOS and PWM1_GPIOS definitions and must not be changed.
PMW1_GPIOSare not initialized as PWM channels with the
pwm_initfunction, they are not allocated and can be used other purposes.
ESP32 integrates four SPI controllers:
FSPIto external memories like flash and PSRAM
HSPIthat can be used for peripherals
VSPIthat can be used for peripherals
Thus, a maximum of two SPI controllers can be used as peripheral interfaces:
All SPI interfaces could be used in quad SPI mode, but RIOT's low level device driver doesn't support it.
The board-specific configuration of the SPI interface
SPI_DEV(n) requires the definition of
SPIn_CTRL, the SPI controller which is used for
SPI_DEV(n), can be
SPIn_SCK, the GPIO used as clock signal for
SPIn_MISO, the GPIO used as MISO signal for
SPIn_MOSI, the GPIO used as MOSI signal for
SPIn_CS0, the GPIO used as CS signal for
SPI_DEV(n)when the cs parameter in spi_acquire is
n can be 0 or 1. If they are not defined, the SPI interface
SPI_DEV(n) is not used.
The pin configuration of
VSPI interface and the
HSPI interface can be changed by application specific configurations.
SPI_DEV(n)should be in continuous ascending order of
HSPIare used doesn't matter. For example, while one board may only use the
SPI_DEV(0), another board may use the
spi_init_csfunction or the
spi_acquirefunction. That is, they are not allocated as SPI signals before and can be used for other purposes as long as the SPI interface is not used.
SPI_NUMOF is determined automatically from the board-specific peripheral definitions of
The following table shows the pin configuration used for most boards, even though it can vary from board to board.
|VSPI||SCK||GPIO18||can be used for peripherals|
|VSPI||MISO||GPIO19||can be used for peripherals|
|VSPI||MOSI||GPIO23||can be used for peripherals|
|VSPI||CS0||GPIO18||can be used for peripherals|
|HSPI||SCK||GPIO14||can be used for peripherals|
|HSPI||MISO||GPIO12||can be used for peripherals|
|HSPI||MOSI||GPIO13||can be used for peripherals|
|HSPI||CS0||GPIO15||can be used for peripherals|
|FSPI||SCK||GPIO6||-||reserved for flash and PSRAM|
|FSPI||CMD||GPIO11||-||reserved for flash and PSRAM|
|FSPI||SD0||GPIO7||-||reserved for flash and PSRAM|
|FSPI||SD1||GPIO8||-||reserved for flash and PSRAM|
|FSPI||SD2||GPIO9||-||reserved for flash and PSRAM (only in |
|FSPI||SD3||GPIO10||-||reserved for flash and PSRAM (only in |
Some boards use the HSPI as SD-Card interface (SDIO) in 4-bit SD mode.
|Device||Pin||SD 4-bit mode||SPI mode|
On these boards, all these signals are pulled up. This may cause flashing problems due to the bootstrap function of the GPIO2 pin, see section GPIO pins.
There are two different implementations for hardware timers.
By default, the hardware timer module is used. To use the hardware counter implementation, add
to application's makefile.
Timers are MCU built-in features and not board-specific. There is nothing to be configured.
The RTC hardware timer of the ESP32 can be clocked with either an external 32.768 kHz crystal or the internal adjustable 150 kHz RC oscillator. If the the external 32.768 kHz crystal is not available, the internal 150 kHz RC oscillator is used automatically. However, since this internal 150 kHz RC oscillator is not very accurate, the RTC low-level driver uses by default the PLL-controlled 64-bit microsecond system timer to emulate the RTC timer.
To allow the use of the RTC hardware timer for boards with an external 32 kHz crystal, the pseudomodules
esp_rtc_timer_32k can be used to control which timer is used by the RTC low-level driver as following:
If none of the modules above is enabled, the PLL-driven emulated RTC timer is used. In this case, the RTC hardware timer with the internal RC 150 kHz oscillator is only used in deep sleep mode and during a reset.
ESP32 supports up to three UART devices.
UART_DEV(0) has a fixed pin configuration and is always available. All ESP32 boards use it as standard configuration for the console.
UARTn_TXD, the GPIO used as TxD signal, and
UARTn_RXD, the GPIO used as RxD signal,
n can be 2 or 3. If they are not defined, the UART interface UART_DEV(n) is not used.
UART_NUMOF is determined automatically from the board-specific peripheral definitions of
UARTn_RXD and must not be changed.
The following default pin configuration of UART interfaces as used by a most boards can be overridden by the application, see section Application-Specific Configurations.
|UART_DEV(0)||TxD||GPIO1||cannot be changed|
|UART_DEV(0)||RxD||GPIO3||cannot be changed|
|UART_DEV(1)||TxD||GPIO10||optional, can be overridden|
|UART_DEV(1)||RxD||GPIO9||optional, can be overridden|
|UART_DEV(2)||TxD||GPIO17||optional, can be overridden|
|UART_DEV(2)||RxD||GPIO16||optional, can be overridden|
The ESP32 intregates a CAN controller which is compatible with the NXP SJA1000 CAN controller. Thus, it is CAN 2.0B specification compliant and supports two message formats:
As with the SJA1000, the ESP32 CAN controller provides only the data link layer and the physical layer signaling sublayer. Therefore, depending on physical layer requirements, an external transceiver module is required which converts the
CAN-TX signals of the ESP32 into
CAN_L bus signals, e.g., the MCP2551 or SN65HVD23X transceiver for compatibility with ISO 11898-2.
periph_can is used, the low-level CAN driver for the ESP32 CAN controller is enabled. It provides a CAN DLL device that can be used with RIOT's CAN protocol stack. It uses the ESP32 CAN controller in SJA1000 PeliCAN mode. Please refer the SJA1000 Datasheet for detailed information about the CAN controller and its programming.
The pin configuration of the CAN transceiver interface is usually defined in board specific peripheral configuration by
CAN_TX, the GPIO used as TX transceiver signal, and
CAN_RX, the GPIO used as RX transceiver signal.
If the pin configuration is not defined, the following default configuration is used which can be overridden by the application, see section Application-Specific Configurations.
|CAN||TX||GPIO5||optional, can be overridden|
|CAN||RX||GPIO35||optional, can be overridden|
If the board has an external transceiver module connected to the ESP32 on-board, module
periph_can should be provided as feature in board's
Otherwise, the application has to add the
periph_can module in its makefile when needed.
The RIOT port for the ESP32 implements RIOT's layered power management. It supports the following operating modes:
Since the peripherals are not working during Light-sleep/_Deep-sleep_, the CPU cannot be woken up by internal interrupt sources such as timers. Therefore, RIOT's layered power management can't select them as idle power mode. They are therefore blocked for normal operation. The application has to select them explicitly using the
pm_set function. RIOT's layered power management can only select either Modem-sleep or Active as the lowest unblocked mode.
But also in Modem-sleep or Active mode, the lowest possible power level is used. For this purpose, the Xtensa ISA instruction
waiti is used, which saves power by setting the current interrupt level, turning off the processor logic and waiting for an interrupt.
Modem-sleep mode and Active mode are the default operating modes dependent on whether the WiFi interface is used. They are selected automatically by the system.
To enter the Light-sleep or the Deep-sleep mode, function
pm_set has to be used with the according mode
ESP_PM_DEEP_SLEEP as parameter. To exit from these modes, several wake-up sources can be used.
Possible wake-up sources for the Light-sleep mode are:
xtimeras wake-up source.
GPIO_FALLINGare implicitly mapped to
GPIO_LOW, respectively, when entering Light-sleep mode.
Possible Wake-up sources for the Deep-sleep mode are:
Several definitions can be used during compile time to configure the Light-sleep and the Deep-sleep mode:
|ESP_PM_GPIO_HOLD||not defined||Deep||Hold GPIO output level if defined|
|ESP_PM_WUP_PINS||none||Deep||GPIOs used as wake-up source|
|ESP_PM_WUP_LEVEL||ESP_PM_WUP_PINS_ANY_HIGH||Deep||Level for wake-up pins to wake-up|
|ESP_PM_WUP_UART0||disabled||Light||Positive UART0 RxD signal edges to wake-up|
|ESP_PM_WUP_UART1||disabled||Light||Positive UART1 RxD signal edges to wake-up|
ESP_PM_GPIO_HOLDis defined, GPIOs hold their last output level when entering Deep-sleep mode. Please note that only RTC GPIOs can hold their output value in Deep-sleep mode.
ESP_PM_WUP_PINSspecifies either a single RTC GPIO or a comma separated list of RTC GPIOs that are used as wake-up source in Deep-sleep mode.
ESP_PM_WUP_LEVELspecifies the level for the wake-up pins in Deep-sleep mode:
ESP_PM_WUP_PINS_ANY_HIGH(default) - The system is woken up when any of the GPIOs specified in
ESP_PM_WUP_PINS_ALL_LOW- The system is woken up when all GPIOs specified in
ESP_PM_WUP_UART1define the number of positive edges of the RxD signal of the respective UART that are necessary to wake up the system in the Light-sleep mode. The value must be greater than 2, otherwise UART is not activated as wake-up source. The specified value is reduced by 2 so that
ESP_PM_WUP_UART1plus 2 is the number of positive edges required to wake up.
In the following example the system shall be woken up from Deep-sleep if the pulled-up pin
ESP_PM_WUP_PINS=GPIO25) goes LOW (
ESP_PM_WUP_LEVEL=ESP_PM_WUP_PINS_ALL_LOW). The last GPIO output values are held (
ESP_PM_GPIO_HOLD) in Deep-sleep mode. From Light-sleep the system can be woken up by any of the GPIOs defined as input with enabled interrupt or if the RxD signal of UART0 goes HIGH at least 4 times (
In Deep-sleep mode the SRAM is powered down. However, the slow RTC memory can be retained. Therefore, data that must be retained during Deep-sleep and the subsequent system restart, must be stored in the slow RTC memory. For that purpose, use
__attribute__((section(".rtc.bss")))to place uninitialized data in section
__attribute__((section(".rtc.data")))to place initialized data in section
The ESP32 port of RIOT also supports:
The ESP32 can use external SPI RAM connected through the FSPI interface. For example, all boards that use the ESP32-WROVER modules have already integrated such SPI RAM.
However, the external SPI RAM requires 4 data lines and thus can only be used in QOUT (quad output) or QIO (quad input/output) flash mode, which makes GPIO9 and GPIO10 unavailable for other purposes. Therefore, if needed, the SPI RAM must be explicitly enabled in the makefile of the application.
esp_spi_ram, the ESP32 uses four data lines to access the external SPI RAM in QOUT (quad output) flash mode. Therefore, GPIO9 and GPIO10 are used as SPI data lines and are not available for other purposes.
The RIOT port for ESP32 implements a MTD system drive
mtd0 using the on-board SPI flash memory. This MTD system drive can be used together with SPIFFS and VFS to realize a persistent file system.
To use the MTD system drive with SPIFFS, the
esp_spiffs module has to be enabled in the makefile of the application:
When SPIFFS is enabled, the MTD system drive is formatted with SPIFFS the first time the system is started. The start address of the MTD system drive in the SPI flash memory is defined by the board configuration:
If this start address is set to 0, as in the default board configuration, the first possible multiple of 0x100000 (1 MByte) will be used in the free SPI flash memory determined from the partition table.
Please refer file
$RIOTBASE/tests/unittests/test-spiffs/tests-spiffs.c for more information on how to use SPIFFS and VFS together with a MTD device
ESP32 provides different built-in possibilities to realize network devices:
ESP32 provides an Ethernet MAC layer module (EMAC) according to the IEEE 802.3 standard which can be used together with an external physical layer chip (PHY) to realize a 100/10 Mbps Ethernet interface. Supported PHY chips are the Microchip LAN8710/LAN8720 and the Texas Instruments TLK110.
The RIOT port for ESP32 realizes with module
netdev driver for the EMAC which uses RIOT's standard Ethernet interface.
If the board has one of the supported PHY layer chips connected to the ESP32, the
esp_eth module should be enabled by default in board's
Makefile.dep when module
netdev_default is used.
Otherwise, the application has to add the
esp_eth module in its makefile when needed.
The RIOT port for ESP32 implements a
netdev driver for the built-in WiFi interface. This
netdev driver supports WPA2 personal mode as well as WPA2 enterprise mode.
To use the WiFi
netdev driver in WPA2 personal mode with a preshared key (PSK), module
esp_wifi has to be enabled.
Furthermore, the following configuration parameters have to be defined:
|ESP_WIFI_SSID||"RIOT_AP"||SSID of the AP to be used.|
|ESP_WIFI_PASS||-||Passphrase used for the AP as clear text (max. 64 chars).|
|ESP_WIFI_STACKSIZE||THREAD_STACKSIZE_DEFAULT||Stack size used for the WiFi netdev driver thread.|
These configuration parameter definitions, as well as enabling the
esp_wifi module, can be done either in the makefile of the project or at make command line, for example:
esp_wifiis not enabled automatically when module
esp_wifi) and the ESP-NOW network interface (module
esp_now) can be used simultaneously, for example, to realize a border router for a mesh network which uses ESP-NOW.
To use the WiFi
netdev driver in WPA2 enterprise mode with IEEE 802.1X/EAP authentication, module
esp_wifi_enterprise has to be enabled.
It supports the following EAP authentication methods:
As inner (phase 2) EAP authentication method, only MSCHAPv2 is supported.
To use module
esp_wifi_enterprise with these authentication methods, the following configuration parameters have to be defined:
|ESP_WIFI_SSID||"RIOT_AP"||SSID of the AP to be used.|
|ESP_WIFI_EAP_ID||none||Optional anonymous identity used in phase 1 (outer) EAP authentication. If it is not defined, the user name defined for phase 2 (inner) EAP authentication is used as identity in phase 1.|
|ESP_WIFI_EAP_USER||none||User name used in phase 2 (inner) EAP authentication.|
|ESP_WIFI_EAP_PASS||none||Password used in phase 2 (inner) EAP authentication.|
|ESP_WIFI_STACKSIZE||THREAD_STACKSIZE_DEFAULT||Stack size used for the WiFi netdev driver thread.|
These configuration parameter definitions, as well as enabling the
esp_wifi module, can be done either in the makefile of the project or at make command line, for example:
esp_wifi_enterpriseis not enabled automatically when module
esp_wifi_enterprise) and the ESP-NOW network interface (module
esp_now) can be used simultaneously, for example, to realize a border router for a mesh network which uses ESP-NOW. In this case the ESP-NOW interface must use the same channel as the AP of the infrastructure WiFi network. All ESP-NOW nodes must therefore be compiled with the channel of the AP as value for the parameter 'ESP_NOW_CHANNEL'.
With ESP-NOW, the ESP32 provides a connectionless communication technology, featuring short packet transmission. It applies the IEEE802.11 Action Vendor frame technology, along with the IE function developed by Espressif, and CCMP encryption technology, realizing a secure, connectionless communication solution.
The RIOT port for ESP32 implements in module
netdev driver which uses ESP-NOW to provide a link layer interface to a meshed network of ESP32 nodes. In this network, each node can send short packets with up to 250 data bytes to all other nodes that are visible in its range.
esp_nowmodule is not enabled automatically if the
netdev_defaultmodule is used. Instead, the application has to add the
esp_nowmodule in its makefile when needed.
For ESP-NOW, ESP32 nodes are used in WiFi SoftAP + Station mode to advertise their SSID and become visible to other ESP32 nodes. The SSID of an ESP32 node is the concatenation of the prefix
RIOT_ESP_ with the MAC address of its SoftAP WiFi interface. The driver periodically scans all visible ESP32 nodes.
The following parameters are defined for ESP-NOW nodes. These parameters can be overridden by application-specific board configurations.
|ESP_NOW_SCAN_PERIOD||10000000UL||Defines the period in us at which an node scans for other nodes in its range. The default period is 10 s.|
|ESP_NOW_SOFT_AP_PASS||"ThisistheRIOTporttoESP"||Defines the passphrase as clear text (max. 64 chars) that is used for the SoftAP interface of ESP-NOW nodes. It has to be same for all nodes in one network.|
|ESP_NOW_CHANNEL||6||Defines the channel that is used as the broadcast medium by all nodes together.|
|ESP_NOW_KEY||NULL||Defines a key that is used for encrypted communication between nodes. If it is NULL, encryption is disabled. The key has to be of type |
esp_now) and the Wifi network interface (module
esp_wifi_enterprise) can be used simultaneously, for example, to realize a border router for a mesh network which uses ESP-NOW. In this case the ESP-NOW interface must use the same channel as the AP of the infrastructure WiFi network. All ESP-NOW nodes must therefore be compiled with the channel of the AP asvalue for the parameter 'ESP_NOW_CHANNEL'.
RIOT provides a number of driver modules for different types of network devices, e.g., IEEE 802.15.4 radio modules and Ethernet modules. The RIOT port for ESP32 has been tested with the following network devices:
To use MRF24J40 based IEEE 802.15.4 modules as network device, the
mrf24j40 driver module has to be added to the makefile of the application:
The driver parameters that have to be defined by the board configuration for the MRF24J40 driver module are:
|MRF24J40_PARAM_CS||GPIO used as CS signal|
|MRF24J40_PARAM_INT||GPIO used as interrupt signal|
|MRF24J40_PARAM_RESET||GPIO used as reset signal|
Since each board has different GPIO configurations, refer to the board documentation for the GPIOs recommended for the MRF24J40.
MRF24J40_PARAM_RESETfree for other purposes.
To use ENC28J60 Ethernet modules as network device, the
enc28j60 driver module has to be added to the makefile of the application:
The parameters that have to be defined by board configuration for the ENC28J60 driver module are:
|ENC28J60_PARAM_CS||GPIO used as CS signal|
|ENC28J60_PARAM_INT||GPIO used as interrupt signal|
|ENC28J60_PARAM_RESET||GPIO used as reset signal|
Since each board has different GPIO configurations, refer to the board documentation for the GPIOs recommended for the ENC28J60.
ENC28J60_PARAM_RESETfree for other purposes.
The board-specific configuration files
periph_conf.h as well well as the driver parameter configuration files
<driver>_params.h define the default configurations for peripherals and device driver modules. These are, for example, the GPIOs used, bus interfaces used or available bus speeds. Because there are many possible configurations and many different application requirements, these default configurations are usually only a compromise between different requirements.
Therefore, it is often necessary to change some of these default configurations for individual applications. For example, while many PWM channels are needed in one application, another application does not need PWM channels, but many ADC channels.
There are two ways to give the application the ability to change some of these default configurations:
CFLAGS make variable at the command line, board or driver parameter definitions can be overridden.
Example: ` CFLAGS='-DESP_LCD_PLUGGED_IN=1 -DLIS3DH_PARAM_INT2=GPIO4' `
When a larger number of board definitions needs be overridden, this approach becomes impractical. In that case, an application-specific board configuration file located in application directory can be used, see sections below.
To override default board configurations, simply create an application-specific board configuration file
$APPDIR/board.h in the source directory
$APPDIR of the application and add the definitions to be overridden. To force the preprocessor to include board's original
board.h after that, add the
include_next preprocessor directive as the last line.
For example to override the default definition of the GPIOs that are used as PWM channels, the application-specific board configuration file
$APPDIR/board.h could look like the following:
It is important to ensure that the application-specific board configuration
$APPDIR/board.h is included first. Insert the following line as the first line to the application makefile
Using the approach for overriding board configurations, the parameters of drivers that are typically defined in
drivers/<device>/include/<device>_params.h can be overridden. For that purpose just create an application-specific driver parameter file
$APPDIR/<device>_params.h in the source directory
$APPDIR of the application and add the definitions to be overridden. To force the preprocessor to include driver's original
<device>_params.h after that, add the
include_next preprocessor directive as the last line.
For example, to override a GPIO used for LIS3DH sensor, the application-specific driver parameter file
$APPDIR/<device>_params.h could look like the following:
It is important to ensure that the application-specific driver parameter file
$APPDIR/<device>_params.h is included first. Insert the following line as the first line to the application makefile
Please note:** To make such application-specific board configurations dependent on the ESP32 MCU or a particular ESP32 board, you should always enclose these definitions in the following constructs:
ESP32 provides a JTAG interface at GPIOs 12 ... 15 for On-Chip Debugging.
|ESP32 Pin||ESP32 signal name JTAG Signal|
This JTAG interface can be used with OpenOCD and GDB to debug your software on instruction level. When you compile your software with debugging information (module
esp_gdb) you can also debug on source code level as well.
Detailed information on how to configure the JTAG interface of the ESP32 and to setup of OpenOCD and GDB can be found in section JTAG Debugging in the ESP-IDF Programming Guide.
When you execute command
make flash with QEMU mode enabled (
QEMU=1), instead of loading the image to the target hardware, a binary image called
esp32flash.bin is created in the target directory. Furthermore, two ROM binary files
rom1.bin are copied to the target directory. This files file can then be used together with QEMU to debug the code in GDB.
The binary image can be compiled with debugging information using module
esp_gdb or optimized without debugging information (default). The latter one is the default. The version with debugging information can be debugged in source code while the optimized version can only be debugged in assembler mode.
To use QEMU, you have to install QEMU for Xtensa with ESP32 machine implementation as following.
Once the compilation has been finished, QEMU for Xtensa with ESP32 machine implementation should be available in
$HOME/esp/qemu-esp32 and you can change to your application target directory to start it in one terminal window , for example
$HOME/src/RIOT-Xtensa-ESP is the root directory of RIOT and
tests/shell is the application.
rom1.binin local directory. Therefore, Please make sure that you are in the correct destination directory before starting QEMU.
In the second terminal window, you can then start GDB and connect to the emulation for the example.
To start debugging, you have to connect to QEMU with command:
|ESP-NOW netdev interface|
|WiFi based ESP-NOW network device driver. |
|ESP-WiFi netdev interface|
|Network device driver for the ESP SoC WiFi interface. |
|ESP32 CAN controller|
|CAN controller driver for ESP32 (esp_can) |
|ESP32 Ethernet netdev interface|
|ESP32 ethernet network device driver. |
|ESP32 compile configurations|
|Compile-time configuration macros for ESP32 modules. |
|Architecture specific ADC functions for ESP32. |
|ADC controller functions used by ADC and DAC peripherals. |
|Architecture specific GPIO functions for ESP32. |
|Implementation of the kernels irq interface. |
|CPU specific definitions and functions for peripheral handling. |
|Architecture specific RTC functions for ESP32. |
|SDK configuration compatible to the ESP-IDF. |
|Implementation of required system calls. |