RIOT-OS port for Espressif's ESP8266 / ESP8285 MCUs. More...
RIOT-OS port for Espressif's ESP8266 / ESP8285 MCUs.
There are two implementations that can be used:
The non-SDK version produces a much smaller code size than the SDK version and is more efficient in execution because it does not need to run additional SDK functions to keep the SDK system alive.
The non-SDK version is probably the best choice if you do not need the built-in WiFi module, for example, when you plan to connect an IEEE 802.15.4 radio module to the MCU for communication.
By default, the non-SDK version is compiled. To compile the SDK version, add
USE_SDK=1 to the make command line, e.g.,
For more information about the make command variables, see section Compile Options.
ESP8266 is a low-cost, ultra-low-power, single-core SoCs with an integrated WiFi module from Espressif Systems. The processor core is based on the Tensilica Xtensa Diamond Standard 106Micro 32-bit Controller Processor Core, which Espressif calls L106. The key features of ESP8266 are:
|Cores||1 x Tensilica Xtensa LX106|
|RAM||80 kByte user-data RAM |
32 kByte instruction RAM
32 kByte instruction cache
16 kByte EST system-data RAM
|Flash||512 kByte ... 16 MByte|
|Frequency||80 MHz or 160 MHz|
|Power Consumption||70 mA in normal operating mode |
20 uA in deep sleep mode
|Timers||1 x 32 bit|
|ADCs||1 x 10 bit (1 channel)|
|I2Cs||2 (software implementation)|
|UARTs||1 (console) + 1 transmit-only|
|WiFi||IEEE 802.11 b/g/n built in|
|Vcc||2.5 - 3.6 V|
|Technical Reference||Technical Reference|
To compile RIOT for The ESP8266 SoC, the following software components are required:
You have the following options to install the Toolchain:
esptool.py, see section RIOT Docker Toolchain (riotdocker)
The easiest way to use the toolchain is Docker.
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:
The ESP Flasher tool
esptool.py is available at GitHub. To install the tool, either Python 2.7 or Python 3.4 or later must be installed. The latest stable version of
esptool.py can be installed with
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 the git repository
Please make sure that
esptool.py is in your
riotdocker fork that only installs the
RIOT-Xtensa-ESP8266-toolchain is available at GitHub. After cloning this git repository, you can use branch
esp8266_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_esp8266 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.
You can get a precompiled version of the whole toolchain from the GIT repository RIOT-Xtensa-ESP8266-toolchain. This repository contains the precompiled toolchain including all libraries that are necessary to compile RIOT-OS for ESP8266.
To install the toolchain use the following commands:
After the installation, all components of the toolchain are installed in directory
/opt/esp. Of course, you can use any other location for the installation.
To use the toolchain, you have to add the path of the binaries to your
PATH variable according to your toolchain location
/path/to/toolchain/ is the directory you selected for the installation of the toolchain. For the default installation in
/opt/esp this would be:
Furthermore, you have to set variables
ESP8266_NEWLIB_DIR according to the location of the toolchain.
If you have used
/opt/esp as installation directory, it is not necessary to set these variables since makefiles use them as default directories.
The most difficult way to install the toolchain is the manual installation of required components as described below.
esp-open-sdk is directly installed inside its source directory. Therefore, change directly to the target directory of the toolchain to build it.
If you plan to use the SDK version of the RIOT port and to use the SDK as part of esp-open-sdk, simply build its standalone version.
If you only plan to use the non-SDK version of the RIOT port or if you want to use one of Espressif's original SDKs, it is enough to build the toolchain.
Once compilation has been finished, the toolchain is available in
$PWD/xtensa-lx106-elf/bin. To use it, set the
PATH variable accordingly.
If you have compiled the standalone version of esp-open-sdk and you plan to use this SDK version, set additionally the
First, set the target directory for the installation.
Please take care, to use the newlib-c version that was modified for esp-open-rtos since it includes
Once you have cloned the GIT repository, build and install it with following commands.
If you plan to use the SDK version of the RIOT port and if you want to use one of Espressif's original SDKs, you have to install it.
First, download the ESP8266_NONOS_SDK version 2.1.0 from the Espressif web site. Probably other version might also work. However, RIOT port is tested with version 2.1.0.
Once you have downloaded it, you can install it with following commands.
To use the installed SDK, set variable
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
The compilation process can be controlled by a number of variables for the make command:
|ENABLE_GDB||0, 1||0||Enable compilation with debug information for debugging with QEMU (|
|FLASH_MODE||dout, dio, qout, qio||dout||Set the flash mode, please take care with your module, see section Flash Modes|
|PORT||/dev/ttyUSBx||/dev/*||Set the USB port for flashing the firmware|
|QEMU||0, 1||0||Generate an image for QEMU, see section QEMU Mode and GDB.|
|USE_SDK||0, 1||0||Compile the SDK version (|
Optional features of ESP8266 can be enabled by
USEMODULE definitions in the makefile of the application. These are:
|esp_gdb||Enable the compilation with debug information, which is equivalent to using |
|esp_sdk||Enable the SDK version, which is equivalent to using |
|esp_spiffs||Enable the SPIFFS drive in on-board flash memory|
|esp_sw_timer||Enable software timer implementation, implies the setting |
For example, to activate the 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 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.
dout, ESP8285 modules have to be always flashed in
doutmode. The default flash mode is
The flash memory of ESP8266 can be erased completely with following command:
address depends on ESP8266 chip version.
|Chip version||Module examples|
|512 kByte||0x07c000||ESP-01, ESP-03, ESP-07, etc.|
|1 MByte||0x0fc000||ESP8285-based modules like Wemos D1 mini lite, PSF-A85, some ESP-01, ESP-03 etc.|
|4 MByte||0x3fc000||ESP-12E, NodeMCU devkit 1.0, WeMos D1 mini|
|16 MByte||0xffc000||WeMos D1 mini pro (USE 0x07c000!)|
ESP8266 has 17 GPIO pins, which are all digital pins. Some of them can not be used at all or have bootstrapping capabilities and are therefore not available on all boards.
|GPIO0||usually pulled up|
|GPIO2||usually pulled up|
|GPIO9||Flash SPI in |
|GPIO10||Flash SPI in |
|GPIO15||usually pulled down|
|GPIO16||RTC pin and wake up signal in deep sleep mode|
GPIO0, GPIO2, and GPIO15 are bootstrapping pins which are used to boot ESP8266 in different modes:
|1||X||X||boot in SDIO mode to start OCD|
|0||0||1||boot in UART mode for flashing the firmware|
|0||1||1||boot in FLASH mode to boot the firmware from flash (default mode)|
ESP8266 has one dedicated ADC pin with a resolution of 10 bits. This ADC pin can measure voltages in the range of 0 V ... 1.1 V.
ESP8266 provides two hardware SPI interfaces:
Even though FSPI (or simply SPI) is a normal SPI interface, it is not possible to use it for peripherals. HSPI is therefore the only usable SPI interface available for peripherals as RIOT's
The pin configuration of the HSPI interface
SPI_DEV(0) is fixed. The only pin definition that can be overridden by an application-specific board configuration is the CS signal defined by
|Signal of HSPI||Pin|
|CS||GPIOn with n = 0, 2, 4, 5, 15, 16 (additionally 9, 10 in |
When the SPI is enabled using module
periph_spi, these GPIOs cannot be used for any other purpose. GPIOs 0, 2, 4, 5, 15, and 16 can be used as CS signal. In
dout flash modes (see section Flash Modes), GPIOs 9 and 10 can also be used as CS signal.
Since the ESP8266 does not or only partially support the I2C in hardware, I2C interfaces are realized as bit-banging protocol in software. The maximum usable bus speed is therefore
I2C_SPEED_FAST_PLUS. The maximum number of buses that can be defined is 2,
Number of I2C buses (
I2C_NUMOF) and used GPIO pins (
x stands for the bus device
x) have to be defined in the board-specific peripheral configuration in
$BOARD/periph_conf.h. Furthermore, the default I2C bus speed (
I2Cx_SPEED) that is used for bus
x has to be defined.
In the following example, only one I2C bus is defined:
A configuration with two I2C buses would look like the following:
All these configurations can be overridden by an application-specific board configuration.
The hardware implementation of ESP8266 PWM supports only frequencies as power of two. Therefore, a software implementation of one PWM device (
PWM_DEV(0)) with up to 8 PWM channels (
PWM_CHANNEL_NUM_MAX) is used.
GPIOs that can be used as channels of the PWM device
PWM_DEV(0) are defined by
PWM0_CHANNEL_GPIOS. By default, GPIOs 2, 4 and 5 are defined as PWM channels. As long as these channels are not started with function
pwm_set, they can be used as normal GPIOs for other purposes.
PWM0_CHANNEL_GPIOS with a duty cycle value of 0 can be used as normal GPIOs for other purposes. GPIOs in
PWM0_CHANNEL_GPIOS that are used for other purposes, e.g., I2C or SPI, are no longer available as PWM channels.
To define other GPIOs as PWM channels, just overwrite the definition of
PWM_CHANNEL_GPIOS in an application-specific board configuration
There are two timer implementations:
By default, the hardware timer implementation is used.
When the SDK version of the RIOT port (
USE_SDK=1) is used, the software timer implementation is activated by using module
The software timer uses SDK's software timers to implement the timer channels. Although these SDK timers usually have a precision of a few microseconds, they can deviate up to 500 microseconds. So if you need a timer with high accuracy, you'll need to use the hardware timer with only one timer channel.
esp_sw_timeris used, the SDK version is automatically compiled (
If SPIFFS module is enabled (
USEMODULE += esp_spiffs), the implemented MTD system drive
mtd0 for the on-board SPI flash memory is used together with modules
vfs to realize a persistent file system.
For this purpose, the flash memory is formatted as SPIFFS starting at the address
0x80000 (512 kByte) on first boot. All sectors up to the last 5 sectors of the flash memory are then used for the file system. With a fixed sector size of 4096 bytes, the top address of the SPIFF is
flash_size - 5 * 4096, e.g.,
0xfb000 for a flash memory of 1 MByte. The size of the SPIFF then results from:
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
The ESP8266 port of RIOT also supports
RTC is not yet implemented.
The ESP8266 port of RIOT has been tested with several common external devices that can be connected to ESP8266 boards and are preconfigured accordingly.
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 ESP8266 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:
mrf24j40 driver module uses the following preconfigured interface parameters for ESP8266 boards:
|MRF24J40_PARAM_SPI||SPI_DEV(0)||fixed, see section SPI Interfaces|
|MRF24J40_PARAM_CS||GPIO16||can be overridden|
|MRF24J40_PARAM_INT||GPIO0||can be overridden|
|MRF24J40_PARAM_RESET||GPIO2||can be overridden|
The GPIOs in this configuration can be overridden by application-specific board configurations.
To use ENC28J60 Ethernet modules as network device, the
enc28j60 driver module has to be added to the makefile of the application:
enc28j60 driver module uses the following preconfigured interface parameters for ESP8266 boards:
|ENC28J60_PARAM_SPI||SPI_DEV(0)||fixed, see section SPI Interfaces|
|ENC28J60_PARAM_CS||GPIO4||can be overridden|
|ENC28J60_PARAM_INT||GPIO9||can be overridden|
|ENC28J60_PARAM_RESET||GPIO10||can be overridden|
The GPIOs in this configuration can be overridden by application-specific board configurations.
ESP8266 port of RIOT is preconfigured for RIOT applications that use the SPI SD-Card driver. To use SPI SD-Card driver, the
sdcard_spi module has to be added to a makefile:
sdcard_spi driver module uses the following preconfigured interface parameters for ESP8266 boards:
|SDCARD_SPI_PARAM_SPI||SPI0_DEV||fix, see section SPI Interfaces|
|SDCARD_SPI_PARAM_CS||SPI0_CS0_GPIO||can be overridden|
The GPIO used as CS signal can be overridden by application-specific board configurations.
The board-specific configuration files
periph_conf.h as 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.
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
Pleae note:** To make such application-specific board configurations dependent on the ESP8266 MCU or a particular ESP8266 board, you should always enclose these definitions in the following constructs:
With make command variable
USE_SDK=1 the Espressif SDK is used. This is necessary, for example, if you want to use the built-in WLAN module. The SDK internally uses its own tasks (SDK tasks) and its own scheduling mechanism to realize event-driven SDK functions such as WiFi functions and software timers, and to keep the system alive. For this purpose, the SDK regularly executes SDK tasks with pending events in an endless loop using the ROM function
Interrupt service routines do not process interrupts directly but use the
ets_post ROM function to send an event to one of these SDK tasks, which then processes the interrupts asynchronously. A context switch is not possible in the interrupt service routines.
In the RIOT port, the task management of the SDK is replaced by the task management of the RIOT. To handle SDK tasks with pending events so that the SDK functions work and the system keeps alive, the ROM functions
ets_post are overwritten. The
ets_run function performs all SDK tasks with pending events exactly once. It is executed at the end of the
ets_post function and thus usually at the end of an SDK interrupt service routine or before the system goes into the lowest power mode.
USE_SDK=0, the default) if you don't need the built-in WiFi module.
When QEMU mode is enabled (
QEMU=1), instead of loading the image to the target hardware, a binary image
$ELFFILE.bin is created in the target directory. This binary image file can be used together with QEMU to debug the code in GDB.
The binary image can be compiled with debugging information (
ENABLE_GDB=1 or module
esp_gdb) or optimized without debugging information (
ENABLE_GDB=0). 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 ESP8266 machine implementation as following.
Once the compilation has been finished, QEMU for Xtensa with ESP8266 machine implementation should be available in
/path/to/esp/qemu/bin and you can start it with
/path/to/the/target/image.elf.bin is the path to the binary image as generated by the
make command as
$ELFFILE.bin. After that you can start GDB in another terminal window using command:
If you have compiled your binary image with debugging information, you can load the ELF file in gdb with:
To start debugging, you have to connect to QEMU with command:
|ESP8266 SDK interface|
|Function declarations and mappings for compatibility with ESP8266 SDK. |
|ESP8266 compile configurations|
|Compile-time configuration macros for ESP8266 modules. |
|Common helper macros. |
|CPU common functions. |
|ESP8266 exception handling. |
|Low-level GPIO driver implementation for ESP8266. |
|Implementation of the kernels irq interface. |
|CPU specific definitions and functions for peripheral handling. |
|Implementation of required system calls. |
|Implementation of the kernel's architecture dependent thread interface. |
|Implementation of some tools. |
|Default configurations required by the SDK. |
|Xtensa ASM code specific configuration options. |