ESP32

Implementation for Espressif ESP32 MCUs. More...

Detailed Description

Implementation for Espressif ESP32 MCUs.

Author
Gunar Schorcht gunar.nosp@m.@sch.nosp@m.orcht.nosp@m..net

RIOT-OS on ESP32 boards

<a name="esp32_toc"> Table of Contents </a>

  1. Overview
  2. Short Configuration Reference
  3. MCU ESP32
    1. Features of ESP32
    2. Features Supported by RIOT-OS
    3. Limitations of the RIOT-port
  4. Toolchain
    1. RIOT Docker Toolchain (riotdocker)
    2. Manual Toolchain Installation
  5. Flashing the Device
    1. Toolchain Usage
    2. Compile Options
    3. Flash Modes
    4. ESP-IDF Heap Implementation
  6. Common Peripherals
    1. GPIO pins
    2. ADC Channels
    3. DAC Channels
    4. I2C Interfaces
    5. PWM Channels
    6. SPI Interfaces
    7. Timers
    8. RTT Implementation
    9. UART Interfaces
    10. CAN Interfaces
    11. Power Management
    12. Other Peripherals
  7. Special On-board Peripherals
    1. SPI RAM Modules
    2. SPIFFS Device
  8. Network Interfaces
    1. Ethernet MAC Network Interface
    2. WiFi Network Interface
    3. WiFi SoftAP Network Interface
    4. ESP-NOW Network Interface
    5. Other Network Devices
  9. Application-Specific Configurations
    1. Make Variable CONFIGS
    2. Application-Specific Board Configuration
    3. Application-Specific Driver Configuration
  10. Debugging
    1. JTAG Debugging
    2. QEMU Mode and GDB

<a name="esp32_overview"> Overview </a>  [<a href="#esp32_toc">TOC</a>]

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.

<a name="esp32_short_configuration_reference"> Short Configuration Reference </a>  [<a href="#esp32_toc">TOC</a>]

The following table gives a short reference of all board configuration parameters used by the ESP32 port in alphabetical order.

Parameter Short Description Type*
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 VSPI HSPI 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 VSPI HSPI 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 USEMODULE and DISABLE_MODULE.

Module Default Short description
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_32k not used use RTC timer with external 32.768 kHz crystal as RTT
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_ap not used enable the WiFi SoftAP network device
esp_wifi_enterprise not used enable the Wifi network device in WPA2 enterprise mode

<a name=esp32_mcu_esp32> MCU ESP32 </a>  [<a href="#esp32_toc">TOC</a>]

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.

<a name=esp32_features> Features of ESP32 </a>  [<a href="#esp32_toc">TOC</a>]

The key features of ESP32 are:

MCU ESP32 Supported by RIOT
Vendor Espressif
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
yes
yes
yes
ROM 448 kByte yes
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
yes
yes
yes
yes
yes
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
I2Cs 2 yes
SPIs 4 yes (2)
UARTs 3 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
CAN version 2.0 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
Documents Datasheet
Technical Reference


Note
Even if used ESP32 SoC is a dual-core version, RIOT-OS uses only one core.

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.

Most common modules used by ESP32 boards are the ESP32-WROOM-32 and ESP32-WROVER.

<a name="esp32_supported_features"> Features Supported by RIOT-OS </a>  [<a href="#esp32_toc">TOC</a>]

The RIOT-OS for ESP32 SoCs supports the following features at the moment:

<a name="esp32_limitations"> Limitations of the RIOT port </a>  [<a href="#esp32_toc">TOC</a>]

The implementation of RIOT-OS for ESP32 SOCs has the following limitations at the moment:

<a name="esp32_toolchain"> Toolchain <a>

Following software components are required for compilation:

There are two options to install the Toolchain:

<a name="esp32_riot_docker_toolchain"> RIOT Docker Toolchain (riotdocker) </a>  [<a href="#esp32_toc">TOC</a>]

The easiest way to use install the toolchain is the RIOT Docker image riotdocker. The compilation process using Docker consists of two steps

  1. making the RIOT application in Docker with command make BOARD= ...
  2. flashing the RIOT application on the host computer with command 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 BUILD_IN_DOCKER variable:

BUILD_IN_DOCKER=1 make BOARD=... flash

<a name="esp32_preparing_the_environment"> Preparing the Environment </a>  [<a href="#esp32_toc">TOC</a>]

Using RIOT Docker requires at least the following 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:

sudo apt-get install docker.io

For information on how to install esptool.py, see section Installation of esptool.py.

<a name="esp32_generating_docker_image"> Generating a riotdocker Image </a>  [<a href="#esp32_toc">TOC</a>]

A 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:

git clone https://github.com/gschorcht/riotdocker-Xtensa-ESP.git
cd riotdocker-Xtensa-ESP
git checkout esp32_only
docker build -t riotbuild .

A 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:

cd /path/to/RIOT
docker run -i -t --privileged -v /dev:/dev -u $UID -v $(pwd):/data/riotbuild riotbuild
Note
RIOT's root directory /path/to/RIOT becomes visible as the home directory of the riotbuild user 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.

<a name="esp32_using_existing_docker_image"> Using an Existing riotdocker Image </a>  [<a href="#esp32_toc">TOC</a>]

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 RIOT-Xtensa-ESP32-toolchain using

cd /path/to/RIOT
docker run -i -t --privileged -v /dev:/dev -u $UID -v $(pwd):/data/riotbuild schorcht/riotbuild_esp32

or the riot/riotbuild Docker image (size is about 1.5 GB) which contains the toolchains for all platforms using

cd /path/to/RIOT
docker run -i -t --privileged -v /dev:/dev -u $UID -v $(pwd):/data/riotbuild riot/riotbuild

<a name="esp32_flashing_using_docker"> Make Process with Docker Image </a>  [<a href="#esp32_toc">TOC</a>]

Using Docker, the make process consists of the following two steps:

  1. making the RIOT binary within a RIOT Docker image
  2. flashing the RIOT binary using a flasher program on the host system

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:

make BOARD=esp32-esp-12x -C tests/shell ...

This will generate a RIOT binary in ELF format.

Note
You can't use the flash target 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.

make flash-only BOARD=esp32-esp-12x -C tests/shell

<a name="esp32_manual_toolchain_installation"> Manual Toolchain Installation </a>  [<a href="#esp32_toc">TOC</a>]

A more difficult way to install the toolchain is the manual installation of required components as described below.

Note
To use the precompiled toolchain the following packages (Debian/Ubuntu) have to be installed:
build-essential cppcheck coccinelle curl doxygen git graphviz make pcregrep python python-serial python3 python3-flake8 unzip wget

<a name="esp32_installation_of_xtensa_gcc"> Installation of Xtensa GCC compiler suite </a>  [<a href="#esp32_toc">TOC</a>]

Xtensa GCC compiler for ESP32 can be downloaded and installed as precompiled binary archive from GitHub.

mkdir -p $HOME/esp
cd $HOME/esp
git clone https://github.com/gschorcht/xtensa-esp32-elf.git

Once the compiler is installed you can add the binary directory to your PATH variable.

export PATH=$PATH:$HOME/esp/xtensa-esp32-elf/bin

<a name="esp32_installation_of_esp_idf"> Installation of ESP-IDF (Espressif IoT Development Framework) </a>  [<a href="#esp32_toc">TOC</a>]

ESP-IDF, the official SDK from Espressif, can be downloaded and installed as GIT repository.

cd $HOME/esp
git clone https://github.com/espressif/esp-idf.git
cd esp-idf
git checkout f198339ec09e90666150672884535802304d23ec
git submodule init
git submodule update
Note
Please take care to checkout correct branches which were used for the port. Newer versions might also work but were not tested.

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 ESP32_SDK_DIR accordingly.

export ESP32_SDK_DIR=$HOME/esp/esp-idf

<a name="esp32_installation_of_esptool"> Installation of <tt>esptool.py</tt> (ESP flash programmer tool) </a>  [<a href="#esp32_toc">TOC</a>]

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 pip

sudo pip install pyserial

or the package manager of your OS, for example on Debian/Ubuntu systems:

apt install python-pyserial

For more information on esptool.py, please refer to the git repository.

<a name="esp32_flashing_the_device"> Flashing the Device </a>  [<a href="#esp32_toc">TOC</a>]

<a name="esp32_toolchain_usage"> Toolchain Usage </a>  [<a href="#esp32_toc">TOC</a>]

Once you have installed all required components, you should have the following directories.

/path/to/esp/esp-idf
/path/to/esp/xtensa-esp32-elf

To use the toolchain and optionally the SDK, please check that your environment variables are set correctly to

export ESP32_SDK_DIR=/path/to/esp/esp-idf
export PATH=$PATH:/path/to/esp/xtensa-esp32-elf/bin

To compile an application for an ESP32 board, change to RIOT's root directory and execute the make command, e.g.,

make flash BOARD=esp32-generic -C tests/shell [Compile Options]

where the BOARD variable specifies the generic ESP32 board definition and option -C the directory of application.

<a name="esp32_compile_options"> Compile Options </a>  [<a href="#esp32_toc">TOC</a>]

The compilation process can be controlled by a number of variables for the make command:

Option Values Default Description
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:

Module Description
esp_eth Enable the Ethernet MAC (EMAC) interface as netdev network device, see section Ethernet Network Interface.
esp_gdb Enable the compilation with debug information for debugging with QEMU and GDB (QEMU=1) or via JTAG interface with OpenOCD.
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 netdev network device, see section ESP-NOW Network Interface.
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 netdev network device in WPA2 personal mode, see section WiFi Network Interface.
esp_wifi_ap Enable the built-in WiFi SoftAP module as netdev network device, see section WiFi SoftAP Network Interface.
esp_wifi_enterprise Enable the built-in WiFi module as netdev network device in WPA2 enterprise mode, see section WiFi Network Interface.

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:

USEMODULE += esp_spiffs

Modules can be also be activated temporarily at the command line when calling the make command:

USEMODULE="esp_spiffs" make BOARD=...

<a name="esp32_flash_modes"> Flash Modes </a>  [<a href="#esp32_toc">TOC</a>]

The 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 (dio and dout) or 4 data lines (qio and qout) for addressing and data access. For each data line, one GPIO is required. Therefore, using qio or 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 dio or dout to keep GPIO9 and GPIO10 free for other purposes.

For more information about these flash modes, refer the documentation of esptool.py.

<a name="esp32_esp_log_module"> Log output </a>  [<a href="#esp32_toc">TOC</a>]

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.

When the 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:

I (663) [main_trampoline] main(): This is RIOT! (Version: 2019.10-devel-437-gf506a)

Either the 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,

LOG_ERROR("error message");

generates a log message in which the name of the calling function is used as tag. With

LOG_TAG_ERROR("mod", "error message");

a log message with string mod in the tag is generated.

The 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.

<a name="esp32_esp_idf_heap_implementation"> ESP-IDF Heap Implementation </a>  [<a href="#esp32_toc">TOC</a>]

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:

USEMODULE += esp_heap
Note
ESP-IDF heap implementation is used by default, when the following modules are used: esp_spi_ram

<a name="esp32_peripherals"> Common Peripherals </a>  [<a href="#esp32_toc">TOC</a>]

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.

<a name="esp32_gpio_pins"> GPIO pins </a>  [<a href="#esp32_toc">TOC</a>]

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
GPIO1 In/Out - yes UART0 TxD Console
GPIO2 In/Out yes yes Touch sensor Bootstrapping, pulled down
GPIO3 In/Out - yes UART0 RxD Console
GPIO4 In/Out yes yes Touch sensor -
GPIO5 In/Out - yes - -
GPIO6 In/Out - yes Flash SD_CLK -
GPIO7 In/Out - yes Flash SD_DATA0 -
GPIO8 In/Out - yes Flash SD_DATA1 -
GPIO9 In/Out - yes Flash SD_DATA2 only in qoutand qiomode, see section Flash Modes
GPIO10 In/Out - yes Flash SD_DATA3 only in qoutand qiomode, see section Flash Modes
GPIO11 In/Out - yes Flash SD_CMD -
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
GPIO18 In/Out - yes - -
GPIO19 In/Out - yes - -
GPIO21 In/Out - yes - -
GPIO22 In/Out - yes - -
GPIO23 In/Out - yes - -
GPIO25 In/Out yes yes DAC1 -
GPIO26 In/Out yes yes DAC2 -
GPIO27 In/Out yes yes Touch sensor -
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
GPIO34 In yes - VDET -
GPIO35 In yes - VDET -
GPIO36 In yes - SENSOR_VP -
GPIO37 In yes - SENSOR_CAPP usually not broken out
GPIO38 In yes - SENSOR_CAPN usually not broken out
GPIO39 In yes - SENSOR_VN -

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.

Note
GPIOs that can be used as ADC channels are also available as low power digital inputs/outputs in deep sleep mode.

GPIO0, GPIO2 are bootstrapping pins which are used to boot ESP32 in different modes:

GPIO0 GPIO2 Mode
1 X boot in FLASH mode to boot the firmware from flash (default mode)
0 0 boot in UART mode for flashing the firmware
Note
GPIO2 becomes the SPI MISO signal for boards that use the HSPI interface as SD-Card interface in 4-bit SD mode. On these boards all signals of the SD-Card interface are pulled up. Because of the bootstrapping functionality of GPIO2, it can become necessary to either press the Boot button, remove the SD card or remove the peripheral hardware to flash RIOT.

<a name="esp32_adc_channels"> ADC Channels </a>  [<a href="#esp32_toc">TOC</a>]

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.

Note
  • GPIO37 and GPIO38 are usually not broken out on ESP32 boards and can not be used therefore.
  • ADC2 is used by the WiFi module. The GPIOs connected to ADC2 are therefore not available as ADC channels if the modules esp_wifi or esp_now are used.

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.

Example:

#define ADC_GPIOS { GPIO0, GPIO2, GPIO4 }

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.

Note
  • ADC_GPIOS must 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.
  • As long as the GPIOs listed in ADC_GPIOS are not initialized as ADC channels with the adc_init function, they can be used for other purposes.

For each ADC line, an attenuation of the input signal can be defined separately with the adc_set_attenuationfunction.

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:

Attenuation Voltage Range Symbol
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
Note
The reference voltage Vref can vary from device to device in the range of 1.0V and 1.2V. The Vref of a device can be read with the adc_vref_to_gpio25 function at GPIO 25.
extern int adc_vref_to_gpio25 (void);

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.

<a name="esp32_dac_channels"> DAC Channels </a>  [<a href="#esp32_toc">TOC</a>]

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.

Example:

#define DAC_GPIOS { GPIO25, GPIO26 }

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.

Note
  • DAC_GPIOS must 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.
  • As long as the GPIOs listed in DAC_GPIOS are not initialized as DAC channels with the dac_init function, they can be used for other purposes.

<a name="esp32_i2c_interfaces"> I2C Interfaces </a>  [<a href="#esp32_toc">TOC</a>]

The ESP32 has two built-in I2C hardware interfaces that support I2C bus speed up to 400 kbps (I2C_SPEED_FAST).

The board-specific configuration of the I2C interface I2C_DEV(n) requires the definition of

where n can be 0 or 1. If they are not defined, the I2C interface I2C_DEV(n) is not used.

Example:

#define I2C0_SPEED I2C_SPEED_FAST
#define I2C0_SCL GPIO22
#define I2C0_SDA GPIO21
#define I2C1_SPEED I2C_SPEED_NORMAL
#define I2C1_SCL GPIO13
#define I2C1_SDA GPIO16
Note
The configuration of the I2C interfaces I2C_DEV(n) must be in continuous ascending order of n.

I2C_NUMOF is determined automatically from board-specific peripheral definitions of I2Cn_SPEED, I2Cn_SCK, and I2Cn_SDA.

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.

Device Signal Pin Symbol Remarks
I2C_DEV(0) SCL GPIO22 I2C0_SCL -
I2C_DEV(0) SDA GPIO21 I2C0_SDA -
Note
The GPIOs listed in the configuration are only initialized as I2C signals when the periph_i2c module 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

USEMODULE += esp_i2c_hw

to application's makefile. The Disadvantage of the software implementation is that it uses busy waiting.

Note
The hardware implementation seems to be very poor and faulty. I2C commands in the I2C command pipeline are sporadically not executed. A number of ACK errors and timeouts caused by protocol errors are the result. The hardware implementation is recommended only if they can be tolerated. Therefore, the software implementation is used by default.

<a name="esp32_pwm_channels"> PWM Channels </a>  [<a href="#esp32_toc">TOC</a>]

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 PWM_DEV(0) and PWM_DEV(1).

The GPIOs that can be used as PWM channels of RIOT's PWM devices are defined by the PWM0_GPIOS and PWM1_GPIOS macros in the board-specific peripheral configuration. This configuration can be changed by application specific configurations.

Example:

#define PWM0_GPIOS { GPIO9, GPIO10 }
#define PWM1_GPIOS { }

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.

Note
The definition of PWM0_GPIOS and PWM1_GPIOS can 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.

Note
As long as the GPIOs listed in PWM0_GPIOS and PMW1_GPIOS are not initialized as PWM channels with the pwm_init function, they are not allocated and can be used other purposes.

<a name="esp32_spi_interfaces"> SPI Interfaces </a>  [<a href="#esp32_toc">TOC</a>]

ESP32 integrates four SPI controllers:

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

where n can be 0 or 1. If they are not defined, the SPI interface SPI_DEV(n) is not used.

Example:

#define SPI0_CTRL VSPI
#define SPI0_SCK GPIO18 /* SCK Periphery */
#define SPI0_MISO GPIO19 /* MISO Periphery */
#define SPI0_MOSI GPIO23 /* MOSI Periphery */
#define SPI0_CS0 GPIO5 /* CS0 Periphery */
#define SPI1_CTRL HSPI
#define SPI1_SCK GPIO14 /* SCK Camera */
#define SPI1_MISO GPIO12 /* MISO Camera */
#define SPI1_MOSI GPIO13 /* MOSI Camera */
#define SPI1_CS0 GPIO15 /* CS0 Camera */

The pin configuration of VSPI interface and the HSPI interface can be changed by application specific configurations.

Note
  • The configuration of the SPI interfaces SPI_DEV(n) should be in continuous ascending order of n.
  • The order in which the interfaces VSPI and HSPI are used doesn't matter. For example, while one board may only use the HSPI interface as SPI_DEV(0), another board may use the VSPI interface as SPI_DEV(0) and the HSPI interface as SPI_DEV(1).
  • The GPIOs listed in the configuration are first initialized as SPI signals when the corresponding SPI interface is used by calling either the spi_init_cs function or the spi_acquire function. 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.
  • GPIO2 becomes the MISO signal in SPI mode on boards that use the HSPI as the SD card interface in 4-bit SD mode. Because of the bootstrapping functionality of the GPIO2, it can be necessary to either press the Boot button, remove the SD card or remove the peripheral hardware to flash RIOT.

SPI_NUMOF is determined automatically from the board-specific peripheral definitions of SPI_DEV(n).

The following table shows the pin configuration used for most boards, even though it can vary from board to board.

Device Signal Pin Symbol Remarks
VSPI SCK GPIO18 SPI0_SCK can be used for peripherals
VSPI MISO GPIO19 SPI0_MISO can be used for peripherals
VSPI MOSI GPIO23 SPI0_MOSI can be used for peripherals
VSPI CS0 GPIO18 SPI0_CS0 can be used for peripherals
HSPI SCK GPIO14 SPI1_SCK can be used for peripherals
HSPI MISO GPIO12 SPI1_MISO can be used for peripherals
HSPI MOSI GPIO13 SPI1_MOSI can be used for peripherals
HSPI CS0 GPIO15 SPI1_CS0 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 qio or qout mode)
FSPI SD3 GPIO10 - reserved for flash and PSRAM (only in qio or qout mode)

Some boards use the HSPI as SD-Card interface (SDIO) in 4-bit SD mode.

Device Pin SD 4-bit mode SPI mode
HSPI GPIO14 CLK SCK
HSPI GPIO15 CMD CS0
HSPI GPIO2 DAT0 MISO
HSPI GPIO4 DAT1 -
HSPI GPIO12 DAT2 -
HSPI GPIO13 DAT3 MOSI

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.

<a name="esp32_timers"> Timers </a>  [<a href="#esp32_toc">TOC</a>]

There are two different implementations for hardware timers.

By default, the hardware timer module is used. To use the hardware counter implementation, add

USEMODULE += esp_hw_counter

to application's makefile.

Timers are MCU built-in features and not board-specific. There is nothing to be configured.

<a name="esp32_rtt_counter"> RTT implementation </a>  [<a href="#esp32_toc">TOC</a>]

The RTT peripheral low-level driver provides a RTT (Real Time Timer) with a frequency of 32.768 kHz. It either uses the RTC hardware timer if an external 32.768 kHz crystal is connected to the ESP32 or the PLL-controlled 64-bit microsecond system timer to emulate the RTC timer.

Whether an external 32.768 kHz crystal is connected to the ESP32 is specified as a feature by the board definition using the pseudomodule esp_rtc_timer_32k. If the feature esp_rtc_timer_32k is defined but the external 32.768 kHz crystal is not recognized during startup, the PLL controlled 64 bit microsecond system timer is used to emulate the RTC timer.

The RTT is retained during light and deep sleep as well as during a restart. The RTC hardware timer is used for this purpose, regardless of whether an external 32.768 kHz crystal is connected to the ESP32 or the internal 150 kHz RC oscillator is used. All current timer values are saved in the RTC memory before entering a sleep mode or restart and are restored after when waking up or restarting.

Note
The RTT implementation is also used to implement a RTC (Real Time Clock) peripheral. For this purpose the module rt_rtc is automatically enabled when the feature periph_rtc is used.

<a name="esp32_uart_interfaces"> UART Interfaces </a>  [<a href="#esp32_toc">TOC</a>]

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.

The pin configuration of UART_DEV(1) and UART_DEV(2) are defined in board specific peripheral configuration by

where 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_TXD and 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.

Device Signal Pin Symbol Remarks
UART_DEV(0) TxD GPIO1 UART0_TXD cannot be changed
UART_DEV(0) RxD GPIO3 UART0_RXD cannot be changed
UART_DEV(1) TxD GPIO10 UART1_TXD optional, can be overridden
UART_DEV(1) RxD GPIO9 UART1_RXD optional, can be overridden
UART_DEV(2) TxD GPIO17 UART2_TXD optional, can be overridden
UART_DEV(2) RxD GPIO16 UART2_RXD optional, can be overridden

Example:

#define UART1_TXD GPIO10 /* UART_DEV(1) TxD */
#define UART1_RXD GPIO9 /* UART_DEV(1) RxD */

<a name="esp32_can_interfaces"> CAN Interfaces </a>  [<a href="#esp32_toc">TOC</a>]

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:

Note
  • ESP32 CAN does not support CAN-FD and is not CAN-FD tolerant.
  • ESP32 CAN does not support SJA1000's sleep mode and wake-up functionality.

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-RX and CAN-TX signals of the ESP32 into CAN_H and CAN_L bus signals, e.g., the MCP2551 or SN65HVD23X transceiver for compatibility with ISO 11898-2.

If module 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

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.

Device Signal Pin Symbol Remarks
CAN TX GPIO5 CAN_TX optional, can be overridden
CAN RX GPIO35 CAN_RX optional, can be overridden

Example:

#define CAN_TX GPIO10 /* CAN TX transceiver signal */
#define CAN_RX GPIO9 /* CAN RX transceiver signal */

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 Makefile.features

FEATURES_PROVIDED += periph_can # CAN peripheral interface

Otherwise, the application has to add the periph_can module in its makefile when needed.

<a name="esp32_power_management"> Power Management </a>  [<a href="#esp32_toc">TOC</a>]

Power Modes

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.

Using Power Modes

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_LIGHT_SLEEP or ESP_PM_DEEP_SLEEP as parameter. To exit from these modes, several wake-up sources can be used.

Wake-up Sources in <em>Light-sleep</em> Mode

Possible wake-up sources for the Light-sleep mode are:

Note
Since the digital core (MCU) is stalled during Light-sleep, it is not possible timers like periph_timer or xtimer as wake-up source.
Warning
Since only level interrupts are supported in Light-sleep mode, defined edge interrupts of type GPIO_RISING and GPIO_FALLING are implicitly mapped to GPIO_HIGH and GPIO_LOW, respectively, when entering Light-sleep mode.

Wake-up Sources in <em>Light-sleep</em> Mode

Possible Wake-up sources for the Deep-sleep mode are:

Note
RTC GPIOs are the GPIOs that are realized by the RTC unit and can also be used as ADC channels. See section GPIO pins and ADC Channels for more information.

Configuration

Several definitions can be used during compile time to configure the Light-sleep and the Deep-sleep mode:

Parameter Default Mode Description
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

In the following example the system shall be woken up from Deep-sleep if the pulled-up pin GPIO25 (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 (ESP_PM_WUP_UART0=6).

CFLAGS='-DESP_PM_WUP_PINS=GPIO25 -DESP_PM_WUP_LEVEL=ESP_PM_WUP_PINS_ALL_LOW \
-DESP_PM_WUP_UART0=6 -DESP_PM_GPIO_HOLD' \
make BOARD=esp32-wroom-32 -C tests/periph_pm

Saving Data in <em>Deep-sleep</em> Mode

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

For example:

static int _i_value __attribute__((section(".rtc.bss"))); /* set to 0 at power on */
static int _u_value __attribute__((section(".rtc.data"))) = 1; /* initialized */

<a name="esp32_other_peripherals"> Other Peripherals </a>  [<a href="#esp32_toc">TOC</a>]

The ESP32 port of RIOT also supports:

<a name="esp32_special_on_board_peripherals"> Special On-board Peripherals </a>  [<a href="#esp32_toc">TOC</a>]

<a name="esp32_spi_ram"> SPI RAM Modules</a>  [<a href="#esp32_toc">TOC</a>]

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.

USEMODULE += esp_spi_ram
Note
  • When the SPI RAM is enabled using the 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.
  • Enabling SPI RAM for modules that don't have SPI RAM may lead to boot problems for some modules. For others is simply throws an error message.

<a name="esp32_spiffs_device"> SPIFFS Device </a>  [<a href="#esp32_toc">TOC</a>]

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:

USEMODULE += esp_spiffs

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:

#define SPI_FLASH_DRIVE_START 0x200000

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 mtd0 alias MTD_0.

<a name="esp32_network_interfaces"> Network Interfaces </a>  [<a href="#esp32_toc">TOC</a>]

ESP32 provides different built-in possibilities to realize network devices:

<a name="esp32_ethernet_network_interface"> Ethernet MAC Network Interface </a>  [<a href="#esp32_toc">TOC</a>]

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 esp_eth a 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.

ifneq (,$(filter netdev_default,$(USEMODULE)))
USEMODULE += esp_eth
endif

Otherwise, the application has to add the esp_eth module in its makefile when needed.

Note
The board has to have one of the supported PHY modules to be able to use the Ethernet MAC module.

<a name="esp32_wifi_network_interface"> WiFi Network Interface </a>  [<a href="#esp32_toc">TOC</a>]

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.

WPA2 personal mode

To use the WiFi netdev driver in WPA2 personal mode with a preshared key (PSK), module esp_wifi has to be enabled.

USEMODULE += esp_wifi

Furthermore, the following configuration parameters have to be defined:

Parameter Default Description
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:

USEMODULE=esp_wifi \
CFLAGS='-DESP_WIFI_SSID=\"MySSID\" -DESP_WIFI_PASS=\"MyPassphrase\"' \
make -C examples/gnrc_networking BOARD=...
Note
  • Module esp_wifi is not enabled automatically when module netdev_default is used.
  • Leave 'ESP_WIFI_PASS' undefined to connect to an open WiFi access point.
  • The Wifi network interface (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.

WPA2 Enterprise Mode

To use the WiFi netdev driver in WPA2 enterprise mode with IEEE 802.1X/EAP authentication, module esp_wifi_enterprise has to be enabled.

USEMODULE += esp_wifi_enterprise

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:

Parameter Default Description
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:

USEMODULE=esp_wifi_enterprise \
CFLAGS='-DESP_WIFI_SSID=\"MySSID\" -DESP_WIFI_EAP_ID=\"anonymous\" -DESP_WIFI_EAP_USER=\"MyUserName\" -DESP_WIFI_EAP_PASS=\"MyPassphrase\"' \
make -C examples/gnrc_networking BOARD=...
Note
  • Since there is no possibility to add the CA certificate to the RIOT image, the verification of the AP certificate is not yet supported.
  • Module esp_wifi_enterprise is not enabled automatically when module netdev_default is used.
  • The Wifi network interface (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'.

<a name="esp32_wifi_ap_network_interface"> WiFi SoftAP Network Interface </a>  [<a href="#esp32_toc">TOC</a>]

The RIOT port for the ESP32 supports a netdev interface for the ESP32 WiFi SoftAP mode. Module esp_wifi_ap has to be enabled to use it.

The following parameters can be configured:

Parameter Default Description
ESP_WIFI_SSID "RIOT_AP" Static SSID definition for the SoftAP
ESP_WIFI_AP_PREFIX "RIOT_AP_" Optional prefix for dynamic SSID, if used, the node will create the SSID based on the prefix + mac address (e.g.: "RIOT_AP_aabbccddeeff"). This is disabled by default and ESP_WIFI_SSID is used, define this to enable the usage of the SSID prefix.
ESP_WIFI_PASS none The password for the WiFi SoftAP network interface. If no password is provided, the interface will be "open", otherwise it uses WPA2-PSK authentication mode.
ESP_WIFI_SSID_HIDDEN 0 Whether the SoftAP SSID should be hidden.
ESP_WIFI_MAX_CONN 4 The maximum number of connections for the SoftAP.
ESP_WIFI_BEACON_INTERVAL 100 The beacon interval time in milliseconds for the SoftAP.
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_ap module, can be done either in the makefile of the project or at make command line, for example:

USEMODULE=esp_wifi_ap \
CFLAGS='-DESP_WIFI_SSID=\"MySSID\" -DESP_WIFI_PASS=\"MyPassphrase\" -DESP_WIFI_MAX_CONN=1 \
make -C examples/gnrc_networking BOARD=...
Note
  • The esp_wifi_ap module is not used by default when netdev_default is used.
  • Supports open and WPA2-PSK authentication modes.
  • The ESP-NOW network interface and the WiFi SoftAP network interface can not be used simultaneously.
Warning
The SoftAP may or may not be at all reliable sometimes, this is a known problem with the Wi-Fi network interface, even on the official ESP-IDF. The problem is that the AP doesn't cache multicast data for connected stations, and if stations connected to the AP are power save enabled, they may experience multicast packet loss. This affects RIOT, because NDP relies on multicast packets to work correctly. Refer to the SDK documentation from Espressif on AP Sleep for more information.

<a name="esp32_esp_now_network_interface"> ESP-NOW Network Interface </a>  [<a href="#esp32_toc">TOC</a>]

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 esp_now a 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.

Note
Module esp_nowmodule is not enabled automatically if the netdev_default module is used. Instead, the application has to add the esp_now module in its makefile when needed.
USEMODULE += esp_now

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.

Parameter Default Description
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 uint8_t[16] and has to be exactly 16 bytes long.
Note
The ESP-NOW network interface (module esp_now) and the Wifi network interface (module esp_wifi or 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'.

<a name="esp32_other_network_devices"> Other Network Devices </a>  [<a href="#esp32_toc">TOC</a>]

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:

<a name="esp32_using_mrf24j40"> Using MRF24J40 (module <tt>mrf24j40</tt>) </a>  [<a href="#esp32_toc">TOC</a>]

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:

USEMODULE += mrf24j40

The driver parameters that have to be defined by the board configuration for the MRF24J40 driver module are:

Parameter Description
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.

Note
The reset signal of the MRF24J40 based network device can be connected with the ESP32 RESET/EN pin which is broken out on most boards. This keeps the GPIO free defined by MRF24J40_PARAM_RESET free for other purposes.

<a name="esp32_using_enc28j60"> Using ENC28J60 (module <tt>enc28j60</tt>) </a>  [<a href="#esp32_toc">TOC</a>]

To use ENC28J60 Ethernet modules as network device, the enc28j60 driver module has to be added to the makefile of the application:

USEMODULE += enc28j60

The parameters that have to be defined by board configuration for the ENC28J60 driver module are:

Parameter Description
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.

Note
The reset signal of the ENC28J60 based network device can be connected with the ESP32 RESET/EN pin which is broken out on most boards. This keeps the GPIO free defined by ENC28J60_PARAM_RESET free for other purposes.

<a name="esp32_application_specific_configurations"> Application-Specific Configurations </a>  [<a href="#esp32_toc">TOC</a>]

The board-specific configuration files board.h and 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:

<a name="esp32_config_make_variable"> Make Variable <tt>CFLAGS</tt> </a>  [<a href="#esp32_toc">TOC</a>]

Using the 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.

<a name="esp32_application_specific_board_configuration"> Application-Specific Board Configuration </a>  [<a href="#esp32_toc">TOC</a>]

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:

#ifdef CPU_ESP32
#define PWM0_CHANNEL_GPIOS { GPIO12, GPIO13, GPIO14, GPIO15 }
#endif
#include_next "board.h"

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 $APPDIR/Makefile.

INCLUDES += -I$(APPDIR)
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
#ifdef CPU_ESP32
...
#endif
#ifdef BOARD_ESP32_WROVER_KIT
...
#endif

<a name="esp32_application_specific_driver_configuration"> Application-Specific Driver Configuration </a>  [<a href="#esp32_toc">TOC</a>]

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:

#ifdef CPU_ESP32
#define LIS3DH_PARAM_INT2 (GPIO_PIN(0, 4))
#endif
#include_next "lis3dh_params.h"

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 $APPDIR/Makefile.

INCLUDES += -I$(APPDIR)

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:

#ifdef CPU_ESP32
...
#endif
#ifdef BOARD_ESP32_WROVER_KIT
...
#endif

<a name="esp32_debugging"> Debugging </a>  [<a href="#esp32_toc">TOC</a>]

<a name="esp32_jtag_debugging"> JTAG Debugging </a>  [<a href="#esp32_toc">TOC</a>]

ESP32 provides a JTAG interface at GPIOs 12 ... 15 for On-Chip Debugging.

ESP32 Pin ESP32 signal name JTAG Signal
CHIP_PU TRST_N
GPIO15 (MTDO) TDO
GPIO12 (MTDI) TDI
GPIO13 (MTCK) TCK
GPIO14 (MTMS) TMS
GND GND

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.

Note
When debugging, the GPIOs used for the JTAG interface must not be used for anything else.

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.

<a name="esp32_qemu_mode_and_gdb"> QEMU Mode and GDB </a>  [<a href="#esp32_toc">TOC</a>]

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 rom.bin and 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.

cd $HOME/src
git clone git://github.com/Ebiroll/qemu_esp32
cp qemu_esp32/bin/xtensa-esp32-elf-gdb $HOME/esp/xtensa-esp32-elf/bin/xtensa-esp32-elf-gdb.qemu
rm -rf qemu_esp32
git clone git://github.com/Ebiroll/qemu-xtensa-esp32
cd qemu-xtensa-esp32
./configure --disable-werror --prefix=$HOME/esp/qemu-esp32 --target-list=xtensa-softmmu,xtensaeb-softmmu
make install
cd ..; rm -rf qemu-xtensa-esp32 # optional

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

cd $HOME/src/RIOT-Xtensa-ESP/tests/shell/bin/esp32-generic
$HOME/esp/qemu-esp32/bin/qemu-system-xtensa -d guest_errors,unimp -cpu esp32 -M esp32 -m 4M -S -s > io.txt

where $HOME/src/RIOT-Xtensa-ESP is the root directory of RIOT and tests/shell is the application.

Note
QEMU starts always the files esp32flash.bin, rom.bin and rom1.bin in 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.

xtensa-esp32-elf-gdb.qemu $HOME/src/RIOT-Xtensa-ESP/tests/shell/bin/esp32-generic/tests_shell.elf

To start debugging, you have to connect to QEMU with command:

(gdb) target remote :1234
Note
QEMU for Xtensa ESP32 does not support interrupts. That is, once your application uses interrupts, e.g., timers, the application cannot be debugged using QEMU together with GDB.

Modules

 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.
 

Files

file  adc_arch.h
 Architecture specific ADC functions for ESP32.
 
file  adc_ctrl.h
 ADC controller functions used by ADC and DAC peripherals.
 
file  gpio_arch.h
 Architecture specific GPIO functions for ESP32.
 
file  irq_arch.h
 Implementation of the kernels irq interface.
 
file  periph_cpu.h
 CPU specific definitions and functions for peripheral handling.
 
file  rtt_arch.h
 Architecture specific RTT functions for ESP32.
 
file  sdk_conf.h
 SDK configuration compatible to the ESP-IDF.
 
file  syscalls.h
 Implementation of required system calls.
 
adc_vref_to_gpio25
int adc_vref_to_gpio25(void)
Output ADC reference voltage to GPIO25.
adc_t
unsigned int adc_t
Define default ADC type identifier.
Definition: adc.h:72
adc_attenuation_t
adc_attenuation_t
Attenuations that can be set for ADC lines.
Definition: adc_arch.h:33
adc_set_attenuation
int adc_set_attenuation(adc_t line, adc_attenuation_t atten)
Set the attenuation for the ADC line.