ESP-IDF 编程指导(中文版)¶
本文档是为乐鑫 IoT 开发框架(ESP-IDF)而设计的文档。ESP-IDF 是 ESP32 芯片官方的开发框架。
提示
该中文文档非乐鑫官方文档,而是由个人翻译的,以方便广大初学者。
文档源码位于 https://github.com/tidyjiang8/esp-idf-zh,欢迎大家 Star、参与翻译。
个人的能力、精力都非常有限,如果读者在阅读时发现任何翻译有误的地方,请到 这里 指出,或直接提交PR。
![]() |
![]() |
![]() |
Get Started | API Reference | H/W Reference |
![]() |
![]() |
![]() |
API Guides | Contribute | Resources |
快速入门¶
开发 ESP32 应用程序需要准备:
- 安装有 Windows、Linux 或者 Mac 操作系统的 PC
- 用于编译 ESP32 应用程序 的 工具链
- ESP-IDF —— 包含 ESP32 的 API 和用于操作 工具链 的脚本
- 编写 C 语言程序的文本编辑器,例如 Eclipse
- ESP32 开发板

为 ESP32 开发应用程序
开发环境的准备工作包括以下三部分:
- 设置 工具链
- 从 GitHub 上面获取 ESP-IDF
- 安装和配置 Eclipse
如果你喜欢用其它的编辑器,则可以跳过最后一步。
环境设置好后,你就可以开始开发应用程序了。整个过程可以概括为如下四步:
- 配置 工程 并编写代码
- 编译 工程 并链接成一个 应用程序
- 烧写 应用程序 到 ESP32 上面
- 监视/调试 应用程序
请继续阅读下面的指令,它将带你完成这些步骤。
指导¶
如果你有下面所列举的某块 ESP32 开发板,请点击对应的链接,它会教你如何让你的板子跑起来。
ESP32-DevKitC Getting Started Guide¶
This user guide shows how to get started with ESP32-DevKitC development board.
What You Need¶
- 1 × ESP32-DevKitC board
- 1 × USB A / mini USB B cable
- 1 × PC loaded with Windows, Linux or Mac O/S
Overview¶
ESP32-DevKitC is a small-sized ESP32-based development board produced by Espressif. Most of the I/O pins are broken out to the pin headers on both sides for easy interfacing. Developers can connect these pins to peripherals as needed. Standard headers also make development easy and convenient when using a breadboard.
Functional Description¶
The following list and figure below describe key components, interfaces and controls of ESP32-DevKitC board.
- ESP-WROOM-32
- Standard ESP-WROOM-32 module soldered to the ESP32-DevKitC board.
- EN
- Reset button: pressing this button resets the system.
- Boot
- Download button: holding down the Boot button and pressing the EN button initiates the firmware download mode. Then user can download firmware through the serial port.
- USB
- USB interface. It functions as the power supply for the board and the communication interface between PC and ESP-WROOM-32.
- I/O
- Most of the pins on the ESP-WROOM-32 are broken out to the pin headers on the board. Users can program ESP32 to enable multiple functions such as PWM,ADC, DAC, I2C, I2S, SPI, etc.

ESP32-DevKitC board layout
ESP-WROVER-KIT Getting Started Guide¶
This user guide shows how to get started with ESP-WROVER-KIT development board.
What You Need¶
- 1 × ESP-WROVER-KIT board
- 1 × USB A / mini USB B cable
- 1 × PC loaded with Windows, Linux or Mac O/S
The Board¶
This section describes functionality of ESP-WROVER-KIT board and configuration options. If you like to start using it now, go directly to section Start Application Development
Overview¶
The ESP-WROVER-KIT is a development board produced by Espressif built around ESP32. This board is compatible with ESP32 modules, including the ESP-WROOM-32 and ESP32-WROVER. The ESP-WROVER-KIT features support for an LCD and MicroSD card. The I/O pins have been broken out from the ESP32 module for easy extension. The board carries an advanced multi-protocol USB bridge (the FTDI FT2232HL), enabling developers to use JTAG directly to debug the ESP32 through the USB interface. The development board makes secondary development easy and cost-effective.
注解
ESP-WROVER-KIT integrates the ESP-WROOM-32 module by default.
Functionality Overview¶
Block diagram below presents main components of ESP-WROVER-KIT and interconnections between components.

ESP-WROVER-KIT block diagram
Functional Description¶
The following list and figures below describe key components, interfaces and controls of ESP-WROVER-KIT board.
- 32.768 kHz
- An external precision 32.768 kHz crystal oscillator provides the chip with a clock of low-power consumption during the Deep-sleep mode.
- ESP32 Module
ESP-WROVER-KIT is compatible with both ESP-WROOM-32 and ESP32-WROVER. The ESP32-WROVER module features all the functions of ESP-WROOM-32 and integrates an external 32-MBit PSRAM for flexible extended storage and data processing capabilities.
注解
GPIO16 and GPIO17 are used as the CS and clock signal for PSRAM. To ensure reliable performance, the two GPIOs are not broken out.
- CTS/RTS
- Serial port flow control signals: the pins are not connected to the circuitry by default. To enable them, respective pins of JP14 must be shorted with jumpers.
- UART
- Serial port: the serial TX/RX signals on FT2232HL and ESP32 are broken out to the two sides of JP11. By default, the two signals are connected with jumpers. To use the ESP32 module serial interface only, the jumpers may be removed and the module can be connected to another external serial device.
- SPI
- SPI interface: the SPI interface connects to an external flash (PSRAM). To interface another SPI device, an extra CS signal is needed. If an ESP32-WROVER is being used, please note that the electrical level on the flash and SRAM is 1.8V.
- JTAG
- JTAG interface: the JTAG signals on FT2232HL and ESP32 are broken out to the two sides of JP8. By default, the two signals are disconnected. To enable JTAG, shorting jumpers are required on the signals.
- FT2232
FT2232 chip is a multi-protocol USB-to-serial bridge. The FT2232 chip features USB-to-UART and USB-to-JTAG functionalities. Users can control and program the FT2232 chip through the USB interface to establish communication with ESP32.
The embedded FT2232 chip is one of the distinguishing features of the ESPWROVER-KIT. It enhances users’ convenience in terms of application development and debugging. In addition, uses do not need to buy a JTAG debugger separately, which reduces the development cost. The schematics is provided in section Related Documents.
- EN
- Reset button: pressing this button resets the system.
- Boot
- Download button: holding down the Boot button and pressing the EN button initiates the firmware download mode. Then user can download firmware through the serial port.
- USB
- USB interface. It functions as the power supply for the board and the communication interface between PC and ESP32 module.
- Power Select
- Power supply selection interface: the ESP-WROVER-KIT can be powered through the USB interface or the 5V Input interface. The user can select the power supply with a jumper. More details can be found in section Setup Options, jumper header JP7.
- Power Key
- Power on/off button: toggling to the right powers the board on; toggling to the left powers the board off.
- 5V Input
- The 5V power supply interface is used as a backup power supply in case of full-load operation.
- LDO
- NCP1117(1A). 5V-to-3.3V LDO. (There is an alternative pin-compatible LDO — LM317DCY, with an output current of up to 1.5A). NCP1117 can provide a maximum current of 1A. The LDO solutions are available with both fixed output voltage and variable output voltage. For details please refer to ESP-WROVER-KIT schematic.
- Camera
- Camera interface: a standard OV7670 camera module is supported.
- RGB
- Red, green and blue (RGB) light emitting diodes (LEDs), which may be controlled by pulse width modulation (PWM).
- I/O
- All the pins on the ESP32 module are led out to the pin headers on the ESPWROVER-KIT. Users can program ESP32 to enable multiple functions such as PWM, ADC, DAC, I2C, I2S, SPI, etc.
- Micro SD Card
- Micro SD card slot for data storage: when ESP32 enters the download mode, GPIO2 cannot be held high. However, a pull-up resistor is required on GPIO2 to enable the Micro SD Card. By default, GPIO2 and the pull-up resistor R153 are disconnected. To enable the SD Card, use jumpers on JP1 as shown in section Setup Options.
- LCD
- ESP-WROVER-KIT supports mounting and interfacing a 3.2” SPI (standard 4-wire Serial Peripheral Interface) LCD, as shown on figure ESP-WROVER-KIT board layout - back.

ESP-WROVER-KIT board layout - front

ESP-WROVER-KIT board layout - back
Setup Options¶
There are five jumper headers available to set up the board functionality. Typical options to select from are listed in table below.
Header | Jumper Setting | Description of Functionality |
JP1 | ![]() |
Enable pull up for the Micro SD Card |
JP1 | ![]() |
Assert GPIO2 low during each download (by jumping it to GPIO0) |
JP7 | ![]() |
Power ESP-WROVER-KIT board from an external power supply |
JP7 | ![]() |
Power ESP-WROVER-KIT board from an USB port |
JP8 | ![]() |
Enable JTAG functionality |
JP11 | ![]() |
Enable UART communication |
JP14 | ![]() |
Enable RTS/CTS flow control for serial communication |
Start Application Development¶
Before powering up the ESP-WROVER-KIT, please make sure that the board has been received in good condition with no obvious signs of damage.
Initial Setup¶
Select the source of power supply for the board by setting jumper JP7. The options are either USB port or an external power supply. For this application selection of USB port is sufficient. Enable UART communication by installing jumpers on JP11. Both selections are shown in table below.
Power up from USB port | Enable UART communication |
![]() |
![]() |
Do not install any other jumpers.
如果你有其它的开发板,请查看下面的内容。
设置工具链¶
你可以完全遵循标准安装过程或者自定义你的环境,这完全依赖于你个人的经验和喜好。下面的指令用于标准安装。如果要在你自己的系统上进行设置,请移步 工具链的自定义设置。
工具链的标准设置¶
用 ESP32 进行开发最快的方法是安装预编译的工具链。请根据你的操作系选择点击对应的链接,并按照该链接中的指令进行安装。
Windows 平台工具链的标准设置¶
引言¶
Windows 没有内置的 “make” 环境,因此如果要安装工具链,你需要一个 GNU-兼容 环境。我们这里使用 MSYS2 来提供该环境。你可能不需要一直使用这个环境(你可以使用 Eclipse 或其它前段工具),但是它在你的屏幕后面隐藏着。
工具链的设置¶
快速设置的方法是从 dl.espressif.com 下载集成在一起的工具链 & MSYS zip 压缩文件:
https://dl.espressif.com/dl/esp32_win32_msys2_environment_and_toolchain-20170330.zip
将 zip 压缩文件解压到 C:\
(或其它路径,但是这里假设解压缩到 C:\
),它会使用预先准备的环境创建一个 msys32
目录。
检出¶
运行 C:\msys32\mingw32.exe
可以打开 MSYS2 的终端窗口。该窗口的环境是一个 bash shell。

MSYS2 终端窗口
后续步骤将会使用这个窗口来为 ESP32 设置开发环境。
后续步骤¶
要继续设置开发环境,请参考 获取 ESP-IDF 一节。
相关文档¶
Setting up the environment gives you some more control over the process, and also provides the information for advanced users to customize the install. The pre-built environment, addressed to less experienced users, has been prepared by following these steps.
To quickly setup the toolchain in standard way, using prebuild environment, proceed to section Windows 平台工具链的标准设置.
This process involves installing MSYS2, then installing the MSYS2 and Python packages which ESP-IDF uses, and finally downloading and installing the Xtensa toolchain.
Navigate to the MSYS2 installer page and download the
msys2-i686-xxxxxxx.exe
installer executable (we only support a 32-bit MSYS environment, it works on both 32-bit and 64-bit Windows.) At time of writing, the latest installer ismsys2-i686-20161025.exe
.Run through the installer steps. Uncheck the “Run MSYS2 32-bit now” checkbox at the end.
Once the installer exits, open Start Menu and find “MSYS2 MinGW 32-bit” to run the terminal.
(Why launch this different terminal? MSYS2 has the concept of different kinds of environments. The default “MSYS” environment is Cygwin-like and uses a translation layer for all Windows API calls. We need the “MinGW” environment in order to have a native Python which supports COM ports.)
The ESP-IDF repository on github contains a script in the tools directory titled
windows_install_prerequisites.sh
. If you haven’t got a local copy of the ESP-IDF yet, that’s OK - you can just download that one file in Raw format from here: tools/windows/windows_install_prerequisites.sh. Save it somewhere on your computer.Type the path to the shell script into the MSYS2 terminal window. You can type it as a normal Windows path, but use forward-slashes instead of back-slashes. ie:
C:/Users/myuser/Downloads/windows_install_prerequisites.sh
. You can read the script beforehand to check what it does.The
windows_install_prerequisites.sh
script will download and install packages for ESP-IDF support, and the ESP32 toolchain.During the initial update step, MSYS may update itself into a state where it can no longer operate. You may see errors like the following:
*** fatal error - cygheap base mismatch detected - 0x612E5408/0x612E4408. This problem is probably due to using incompatible versions of the cygwin DLL.
If you see errors like this, close the terminal window entirely (terminating the processes running there) and then re-open a new terminal. Re-run
windows_install_prerequisites.sh
(tip: use the up arrow key to see the last run command). The update process will resume after this step.
There are some (unofficial) MSYS2 mirrors inside China, which substantially improves download speeds inside China.
To add these mirrors, edit the following two MSYS2 mirrorlist files before running the setup script. The mirrorlist files can be found in the /etc/pacman.d
directory (i.e. c:\msys2\etc\pacman.d
).
Add these lines at the top of mirrorlist.mingw32
:
Server = http://mirrors.ustc.edu.cn/msys2/mingw/i686/
Server = http://mirror.bit.edu.cn/msys2/REPOS/MINGW/i686
Add these lines at the top of mirrorlist.msys
:
Server = http://mirrors.ustc.edu.cn/msys2/msys/$arch
Server = http://mirror.bit.edu.cn/msys2/REPOS/MSYS2/$arch
You can enable an HTTP proxy for MSYS and PIP downloads by setting the http_proxy
variable in the terminal before running the setup script:
export http_proxy='http://http.proxy.server:PORT'
Or with credentials:
export http_proxy='http://user:password@http.proxy.server:PORT'
Add this line to /etc/profile
in the MSYS directory in order to permanently enable the proxy when using MSYS.
If you already have an MSYS2 install or want to do things differently, you can download just the toolchain here:
https://dl.espressif.com/dl/xtensa-esp32-elf-win32-1.22.0-61-gab8375a-5.2.0.zip
注解
If you followed instructions Configure Toolchain & Environment from Scratch, you already have the toolchain and you won’t need this download.
重要
Just having this toolchain is not enough to use ESP-IDF on Windows. You will need GNU make, bash, and sed at minimum. The above environments provide all this, plus a host compiler (required for menuconfig support).
要继续设置开发环境,请参考 获取 ESP-IDF 一节。
Linux 平台工具链的标准设置¶
安装前提¶
要编译 ESP-IDF,你需要先安装如下的软件包。
CentOS 7:
sudo yum install git wget make ncurses-devel flex bison gperf python pyserial
Ubuntu and Debian:
sudo apt-get install git wget make libncurses-dev flex bison gperf python python-serial
Arch:
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial
工具链的设置¶
Linux 版的 ESP32 工具链可以从 Espressif 的网站下载:
for 64-bit Linux:
https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-61-gab8375a-5.2.0.tar.gz
for 32-bit Linux:
https://dl.espressif.com/dl/xtensa-esp32-elf-linux32-1.22.0-61-gab8375a-5.2.0.tar.gz
下载完成后,将它解压到 ~/esp
目录
mkdir -p ~/esp
cd ~/esp
tar -xzf ~/Downloads/xtensa-esp32-elf-linux64-1.22.0-61-gab8375a-5.2.0.tar.gz
工具链将会被解压到 ~/esp/xtensa-esp32-elf/
目录。
要使用工具链,你还需要在 ~/.bash_profile
文件中更新环境变量 PATH
。要使 xtensa-esp32-elf
在所有的终端会话中有效,需要将下面这一行代码添加到你的 ~/.bash_profile
文件中
export PATH=$PATH:$HOME/esp/xtensa-esp32-elf/bin
可选地,你也可以给上面的命令创建一个别名。这样的好处是,你只在需要使用它的时候才获取工具链。你只需要将下面这行代码添加到 ~/.bash_profile
文件中即可
alias get_esp32="export PATH=$PATH:$HOME/esp/xtensa-esp32-elf/bin"
然后,当你需要使用工具链时,在命令行输入 get_esp32
,然后工具链会自动添加到你的 ``PATH``中。
在 Arch Linux 中运行预编译的 gdb(xtensa-esp32-elf-gdb) 需要 ncurses 5,但是 Arch 使用的是 ncurses 6。
在 AUR 中有可用于本地和 lib32 配置的后向兼容库:
- https://aur.archlinux.org/packages/ncurses5-compat-libs/
- https://aur.archlinux.org/packages/lib32-ncurses5-compat-libs/
可选地,你也可以使用 crosstool-NG 编译一个链接 ncurses 6 的 gdb。
后续步骤¶
要继续设置开发环境,请参考 获取 ESP-IDF 一节。
修改文档¶
下列指令是可选的,用于从 Espressif 网站下载二进制工具链。如果需呀快速设置工具链,而不是自己编译,请回到 Linux 平台工具链的标准设置 一节。
要编译 ESP-IDF,你需要先安装如下的软件包。
Ubuntu and Debian:
sudo apt-get install git wget make libncurses-dev flex bison gperf python python-serial
Arch:
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial
安装依赖:
CentOS 7:
sudo yum install gawk gperf grep gettext ncurses-devel python python-devel automake bison flex texinfo help2man libtool
Ubuntu pre-16.04:
sudo apt-get install gawk gperf grep gettext libncurses-dev python python-dev automake bison flex texinfo help2man libtool
Ubuntu 16.04:
sudo apt-get install gawk gperf grep gettext python python-dev automake bison flex texinfo help2man libtool libtool-bin
Debian:
TODO
Arch:
TODO
下载 crosstool-NG
并编译
cd ~/esp
git clone -b xtensa-1.22.x https://github.com/espressif/crosstool-NG.git
cd crosstool-NG
./bootstrap && ./configure --enable-local && make install
编译工具链
./ct-ng xtensa-esp32-elf
./ct-ng build
chmod -R u+w builds/xtensa-esp32-elf
工具链将会被编译到 ~/esp/crosstool-NG/builds/xtensa-esp32-elf
。请参考 标准设置指令 将工具链添加到你的 ``PATH``中。
要继续设置开发环境,请参考 获取 ESP-IDF 一节。
为 Mac OS 设置标准工具链¶
安装前提¶
install pip:
sudo easy_install pip
install pyserial:
sudo pip install pyserial
工具链的设置¶
macOS 版的 ESP32 工具链可以从 Espressif 的网站下载:
https://dl.espressif.com/dl/xtensa-esp32-elf-osx-1.22.0-80-g6c4433a-5.2.0.tar.gz
下载完成后,将它解压到 ~/esp
目录
mkdir -p ~/esp
cd ~/esp
tar -xzf ~/Downloads/xtensa-esp32-elf-osx-1.22.0-61-gab8375a-5.2.0.tar.gz
工具链将会被解压到 ~/esp/xtensa-esp32-elf/
目录。
要使用工具链,你还需要在 ~/.profile
文件中更新环境变量 PATH
。要使 xtensa-esp32-elf
在所有的终端会话中有效,需要将下面这一行代码添加到你的 ~/.profile
文件中
export PATH=$PATH:$HOME/esp/xtensa-esp32-elf/bin
可选地,你也可以给上面的命令创建一个别名。这样的好处是,你只在需要使用它的时候才获取工具链。你只需要将下面这行代码添加到 ~/.profile
文件中即可
alias get_esp32="export PATH=$PATH:$HOME/esp/xtensa-esp32-elf/bin"
然后,当你需要使用工具链时,在命令行输入 get_esp32
,然后工具链会自动添加到你的 ``PATH``中。
后续步骤¶
要继续设置开发环境,请参考 获取 ESP-IDF 一节。
相关文档¶
install pip:
sudo easy_install pip
install pyserial:
sudo pip install pyserial
Install dependencies:
Install either MacPorts or homebrew package manager. MacPorts needs a full XCode installation, while homebrew only needs XCode command line tools.
with MacPorts:
sudo port install gsed gawk binutils gperf grep gettext wget libtool autoconf automake
with homebrew:
brew install gnu-sed gawk binutils gperftools gettext wget help2man libtool autoconf automake
Create a case-sensitive filesystem image:
hdiutil create ~/esp/crosstool.dmg -volname "ctng" -size 10g -fs "Case-sensitive HFS+"
Mount it:
hdiutil mount ~/esp/crosstool.dmg
Create a symlink to your work directory:
cd ~/esp
ln -s /Volumes/ctng crosstool-NG
Download crosstool-NG
and build it:
cd ~/esp
git clone -b xtensa-1.22.x https://github.com/espressif/crosstool-NG.git
cd crosstool-NG
./bootstrap && ./configure --enable-local && make install
Build the toolchain:
./ct-ng xtensa-esp32-elf
./ct-ng build
chmod -R u+w builds/xtensa-esp32-elf
Toolchain will be built in ~/esp/crosstool-NG/builds/xtensa-esp32-elf
. Follow instructions for standard setup to add the toolchain to your PATH
.
要继续设置开发环境,请参考 获取 ESP-IDF 一节。
![]() |
![]() |
![]() |
Windows | Linux | Mac OS |
注解
我们默认使用 ~/esp
目录来安装预编译的工具链、ESP-IDF 和示例程序。你也可以使用其它目录,但是需要注意调整对应的命令。
设置完工具链后,你可以进入 获取 ESP-IDF 一节。
获取 ESP-IDF¶
工具链(包括用于编译和构建应用程序的程序)安装完后,你还需要 ESP32 相关的 API/库。乐鑫已经将它们放到 ESP-IDF 仓库 中了。 要获取这些 API/库,请打开一个控制台终端,进入某个你希望存放 ESP-IDF 的目录,然后克隆代码
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
ESP-IDF 将会被下载到 ~/esp/esp-idf
。
注解
注意这里还有个 --recursive
选项。如果你克隆 ESP-IDF 时没有带这个选项,你还需要运行额外的命令来获取子模块
cd ~/esp/esp-idf
git submodule update --init
注解
在 Windows 平台克隆子模块时,git clone
命令可能会打印一些 ': not a valid identifier...
消息。这是一个 已知问题 ,但实际上 git clone 已经成功了,没有任何问题。
设置 ESP-IDF 路径¶
工具链程序使用环境变量 IDF_PATH
来访问 ESP-IDF。这个变量应该设置在你的 PC 中,否则工程将不会编译。你可以在每次 PC 重启时手工设置。你也可以通过在 user profile 中定义 IDF_PATH
变量来永久性设置。要永久性设置,请按照 将 IDF_PATH 添加到 User Profile 一节中 Windows 或者 Linux and MacOS 中所指定的指令进行操作。
Linux and MacOS in section 将 IDF_PATH 添加到 User Profile.
开始一个工程¶
到了这里,你已经完成为 ESP32 编写应用程序的所有准备工作了。为了快速开始,我们这里以 IDF 的 examples 目录下的 get-started/hello_world 工程为例进行说明。
将 get-started/hello_world 拷贝到 ~/esp
目录:
cd ~/esp
cp -r $IDF_PATH/examples/get-started/hello_world .
你可以在 ESP-IDF 的 examples 目录下面发现一系列的示例工程。你可以按照上面的方法将使用这些例子作为你自己的工程,并在此基础之上进行开发。
重要
esp-idf 构建系统不支持在路径中存在空格。
连接¶
现在已经差不多了。在继续后续操作前,请现将 ESP32 的板子连接到 PC,然后检查 PC 所识别到的板子的串口号,看看它是否能正常通信。如果你不知道如何操作,请查看 与 ESP32 建立串口连接 中的相关指令。请注意一下端口号,因为我们在下一步中将会用到。
配置¶
在终端窗口中,输入 cd ~/esp/hello_world
进入 hello_world
所在目录,然后启动刚工程配置工具 menuconfig
:
cd ~/esp/hello_world
make menuconfig
如果之前的步骤都正确,则会显示下面的菜单:

工程配置 - 主窗口
在菜单中,进入 Serial flasher config
> Default serial port
来配置串口(工程将会加载到该串口上)。输入回车来确认选择,选择 < Save >
来保存配置,选择 < Exit >
来退出应用程序。
下面是一些使用 menuconfig
的小技巧:
- 使用 up & down 组合键在菜单中上下移动
- 使用 Enter 键进入一个子菜单,Escape 键退出子菜单或退出整个菜单
- 输入
?
查看帮助信息,Enter 键退出帮助屏幕 - 使用空格键或
Y
和N
键来使能(Yes) 和禁止 (No) 带有复选框 “[*]
” 的配置项 - 当光标在某个配置项上面高亮时,输入
?
可以直接查看该项的帮助信息 - 输入
/
可以来搜索某个配置项
注解
如果你是 Arch Linux 用户,需要进入 SDK tool configuration
将 Python 2 interpreter
从 python
修改为 python2
。
编译和烧写¶
现在你可以编译和烧写应用程序了,输入
make flash
上面的命令会将应用程序、所有的 ESP-IDF 组件、通用的 bootloader、分区表编译成应用程序二进制文件,并将这些应用程序二进制文件烧写到 ESP32 的板子上面。
esptool.py v2.0-beta2
Flashing binaries to serial port /dev/ttyUSB0 (app at offset 0x10000)...
esptool.py v2.0-beta2
Connecting........___
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Changed.
Attaching SPI flash...
Configuring flash size...
Auto-detected Flash size: 4MB
Flash params set to 0x0220
Compressed 11616 bytes to 6695...
Wrote 11616 bytes (6695 compressed) at 0x00001000 in 0.1 seconds (effective 920.5 kbit/s)...
Hash of data verified.
Compressed 408096 bytes to 171625...
Wrote 408096 bytes (171625 compressed) at 0x00010000 in 3.9 seconds (effective 847.3 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 82...
Wrote 3072 bytes (82 compressed) at 0x00008000 in 0.0 seconds (effective 8297.4 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting...
如果没有任何问题,在编译过程结束后,你将能看到类似上面的将程序加载到板子上面的消息。最后,板子将会复位,应用程序 “hello_world” 开始启动。
如果你偏向于使用 Eclipse IDE 而不是运行 make
,请参考 Eclipse guide。
监视器¶
如果要看 “hello_world” 程序是否真的在运行,输入命令 make monitor
。这个命令会启动 IDF Monitor 程序
$ make monitor
MONITOR
--- idf_monitor on /dev/ttyUSB0 115200 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
ets Jun 8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
ets Jun 8 2016 00:22:57
...
板子启动后,你就能看到 “Hello world!” 程序所打印的消息:
...
Hello world!
Restarting in 10 seconds...
I (211) cpu_start: Starting scheduler on APP CPU.
Restarting in 9 seconds...
Restarting in 8 seconds...
Restarting in 7 seconds...
要退出监视器,请使用快捷键 Ctrl+]
。如果要在同一个命令中执行 make flash
和 make monitor
,可以直接输入 make flash monitor
。关于监视器的更多使用细节请参考 IDF Monitor。
相关文档¶
将 IDF_PATH 添加到 User Profile¶
要使环境变量 IDF_PATH
在系统重启后依然有效,需要将它添加到用户 profile,具体方法请参考下面的指令。
Windows¶
用户 profile 脚本位于 C:/msys32/etc/profile.d/
目录,它会在你每次打开一个新的 MSYS2 窗口时被执行。
在
C:/msys32/etc/profile.d/
目录创建一个新的脚本文件,将将其命名为export_idf_path.sh
。指定 ESP-IDF 目录所在路径。这与你的系统配置相关,比如你的路径可能是
C:\msys32\home\Krzysztof\esp\esp-idf
。向脚本文件中添加
export
命令,例如export IDF_PATH="C:/msys32/home/Krzysztof/esp/esp-idf"
记得在原始 Windows 路径中将反斜线替换为斜线。
保存脚本文件。
关闭 MSYS2 窗口后重新打开。检查
IDF_PATH
是否被设置了,输入printenv IDF_PATH
之前在脚本文件中输入的路劲会被打印出来。
如果你不希望将 IDF_PATH
永久设置到 user profile 中,你需要在每次重新打开 MSYS2 窗口时手工输入下面的命令
export IDF_PATH="C:/msys32/home/Krzysztof/esp/esp-idf"
如果你是从 设置 ESP-IDF 路径 一节中进入本页的,可以直接点击 开始一个工程 跳转回去。
Linux 和 MacOS¶
直接将下面一行代码添加到 ~/.bash
文件就能设置 IDF_PATH
export IDF_PATH=~/esp/esp-idf
注销并重新登录后,修改将生效。
如果你不希望永久设置 IDF_PATH
,你需要在每次重新打开终端窗口后手工输入上面的代码。
运行下面的命令可以检查 IDF_PATH
是否设置正确
printenv IDF_PATH
之前在 ~/.bash
文件中输入(或者手工输入)的路径将会被打印出来。
如果你是从 设置 ESP-IDF 路径 一节中进入本页的,可以直接点击 开始一个工程 跳转回去。
与 ESP32 建立串口连接¶
本节用于说明如何在 ESP32 和 PC 之间建立串口连接。
将 ESP32 连接到 PC¶
使用 USB 线将 ESP32 板子和 PC 连接在一起。如果你的设备驱动没有自动安装,请先确认你 ESP32 板子(或者外部转换器 dongle)上面的 USB 转串口芯片的型号,然后在互联网上搜索对应的驱动并将其安装好。
下面的链接包含乐鑫生产的 ESP32 开发板的驱动程序:
- ESP32 Core Board - CP210x USB to UART Bridge VCP Drivers
- ESP32 WROVER KIT and ESP32 Demo Board - FTDI Virtual COM Port Drivers
在 Windows 上查看端口¶
在 Windows 设备管理器中查看系统所识别到的 COM 端口。断开 ESP32 并重新连接,看看哪个端口从列表中消失了然后又显示出来了。
下图显示了 ESP32 DevKitC 和 ESP32 WROVER KIT 的串口

USB to UART bridge of ESP32-DevKitC in Windows Device Manager

Two USB Serial Ports of ESP-WROVER-KIT in Windows Device Manager
在 Linux 和 MacOS 上查看端口¶
要查看 ESP32 板子(或外部转换器)上面的串口的设备名,运行下面的命令两次,第一次运行前将板子/dognle断开,第二次运行前再将其插上。第二次出现的端口号就是你需要的:
Linux
ls /dev/tty*
MacOS
ls /dev/tty.*
验证串口通信¶
验证串口通信是可选的。你可以使用一个串口终端程序完成它。在这个例子中,我们使用的是 PuTTY SSH Client ,它同时支持 Linux 和 Windows。你也可以使用其它串口工具,并设置如下的参数。
运行终端,设置端口号,波特率 115200,数据位 8,停止位 1,奇偶 N。下面分别是在 Windows 和 Linux 下面配置这些传输参数(简单的描述就是 115200-8-1-N)的例子。请一定选择你上面说识别出来的端口号。

在 Windows 设置 PuTTY 的串口通信

在 Linux 设置 PuTTY 的串口通信
然后在终端中打开串口,并查看是否有 ESP32 的消息打印出来。消息的内容是跟你加载到 ESP32 中的程序有关的,例如:
ets Jun 8 2016 00:22:57
rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
ets Jun 8 2016 00:22:57
rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0x00
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0008,len:8
load:0x3fff0010,len:3464
load:0x40078000,len:7828
load:0x40080000,len:252
entry 0x40080034
I (44) boot: ESP-IDF v2.0-rc1-401-gf9fba35 2nd stage bootloader
I (45) boot: compile time 18:48:10
...
如果你看到人类可识别的打印消息,表示串口连接工作正常,你可以继续安装并将应用程序下载到 ESP32 中。
注解
验证串口通信后,请先关闭串口终端。在下一步中,我们将会使用另一个应用程序进行下载。当串口打开时,这个应用程序就无法串口。
如果你是从 get-started-connect`跳转到此处的,点击链接 :ref:`get-started-configure 回到之前的章节。
使用 Make 进行编译和烧写¶
配置你的工程¶
make menuconfig
烧写你的工程¶
当 make all
完成后,它会打印一行命令,提示使用 esptool.py 来烧写芯片。不过,你也可以直接运行如下命令来烧写
make flash
该命令将会烧写整个工程(app、bootloader 和分区表)到芯片中。用于烧写程序的串行端口可以使用 make menuconfig 进行配置。
你不需要在运行 make flash
前运行 make all
,因为 make flash
会自动重新编译它所需要的任何文件。
仅编译 & 烧写 APP¶
完成第一次烧写后,你可以只编译和烧写应用程序,而不需要 bootloader 和分区表:
make app
- 仅编译应用程序make app-flash
- 仅烧写应用程序
make app-flash
会自动重新编译它所需要的任何文件。
如果 bootloader 和分区表没有改动,则不需要重新烧写。
分区表¶
工程编译完成后,”build” 目录下将会产生一个名字类似于 “my_app.bin” 的二进制文件,这是可以被 ESP32 bootloader 加载的二进制镜像。
一片 ESP32 flash 上面可以包含多个 app 和多种数据(校正数据、文件系统、参数存储器等)。因此,一个分区表被烧写到 flash 的地址 0x8000 处。
分区表的每个入口都有一个名字(label)、类型(app、数据或其它一些类型)、子类型和分区表被加载时在 flash 中的偏移。
使用分区表最简单的方法是运行 make menuconfig 并选择一个预定义的分区表:
- “Single factory app, no OTA”
- “Factory app, two OTA definitions”
在这两个情况下,工厂 app 都会被烧写到偏移地址 0x10000 处。如果你输入 如果你输入 make partition_table 命令,它将会打印分区表的参数。
使用 Eclipse IDE 编译和烧写¶
安装 Eclipse IDE¶
Eclipse 提供了一个可用于编写、编译和调试 ESP-IDF 工程的图形化集成开发环境。
- 请先在你的平台上按照好 esp-idf。
- 我们建议先使用命令行编译一个工程,感受一下整个过程是如何工作的。此外,你也需要使用命令行通过(
make menuconfig
)来配置你的 esp-idf 工程,因为当前并不支持在 Eclipse 里面进行配置。 - 从 eclipse.org 下载适合你的平台的安装器(Installer)。
- 运行 Eclipse 安装器,选择 “Eclipse for C/C++ Development” (在其它某些地方也将它叫做 CDT)。
Windows 用户¶
在 Windows 上使用 Eclipse 来编译 ESP-IDF 的配置步骤略有不同,请参考 Windows Eclipse IDE 指南.
设置 Eclipse¶
当你的 Eclipse 安装完成后,你需要完成这些步骤:
导入新工程 Project¶
- Eclipse 会借助 ESP-IDF 中的 Makefile。这意味着,你需要先创建一个 ESP-IDF 工程。你可以使用 github 上面的 idf-template 工程,也可以使用在 esp-idf examples 子目录下的工程。
- Eclipse 启动后,依次选择 File -> Import…
- 在弹出的对话框中,选择 “C/C++” -> “Existing Code as Makefile Project”,然后点击 Next。
- 在下一页中,将 “Existing Code Location” 设置为你的 IDF 工程所在路径。这里不要把路径设置为 ESP-IDF 的根目录了(随后会设置)。你所指定的目录中应当包含一个名为 “Makefile” 的文件,即工程 Makefile。
- 在同一页中,在 “Toolchain for Indexer Settings” 下面选择 “Cross GCC”,然后点击 Finish。
工程属性¶
- 工程浏览器(Project Explorer)中将会出现新工程。右击工程,并在弹出的菜单中选择属性(Properties)。
- 在 “C/C++ Build” 下面点击 “Environment” 属性页。点击 “Add…” ,并输入名字(name)``BATCH_BUILD`` 和值(value)``1``。
- 再次点击 “Add…”,输入名字(name)
IDF_PATH
。值(value)应当填写为 ESP-IDF 的完整安装路径。 - 编辑环境变量 PATH。保持当前值不变,将路径追加到 Xtensa 工具链(
something/xtensa-esp32-elf/bin
) 后面。 - On macOS, add a
PYTHONPATH
environment variable and set it to/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages
. This is so that the system Python, which has pyserial installed as part of the setup steps, overrides any built-in Eclipse Python.
点击 “C/C++ General” -> “Preprocessor Include Paths” 属性页:
- 点击 “Providers” 标签
- 在 providers 列表中,点击 “CDT Cross GCC Built-in Compiler Settings”。在 “Command to get compiler specs” 下面,用
xtensa-esp32-elf-gcc
将该行开始处的文本${COMMAND}
替换到。即完整的 “Command to get compiler specs” 应当是xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"
。 - 在 providers 列表中,点击 “CDT GCC Build Output Parser”,在编译器命令行模式(Compiler command pattern)的开始处输入
xtensa-esp32-elf-
。即编译器目录模式的完整路径是xtensa-esp32-elf-(g?cc)|([gc]\+\+)|(clang)
。
在 Eclipse 中编译¶
你的工程在第一次编译之前,Eclipse 可能会显示许多关于未定义值的错误和警告,这是因为某些源文件是由 esp-idf 编译过程中自动生成的。当你编译完工程后,这些错误和警告就会消失。
- 在 Eclipse 中点击 OK 按钮关闭属性对话框。
- 在 Eclipse 外面,打开一个命令行提示符,进入工程所在目录,运行命令
make menuconfig
来配置你的工程的 esp-idf 设置。目前,这一步必须在 Eclipse 外面运行。 - 如果你编译之前没有运行配置步骤,esp-idf 会在命令行提示你进行配置,但是 Eclipse 不能处理这样的消息,因此编译过程将会挂起或者失败。
- 回到 Eclipse,选择 Project -> Build 来编译你的工程。
TIP: 如果你的工程已在 Eclipse 外面编译过,你可能需要执行 Project -> Clean before choosing Project -> Build 操作,这样 Eclipse 就能看到所有源文件的编译器参数。它使用这些参数来判断头文件的包含路径。
从 Eclipse 烧写¶
你可以将 “make flash” 目标集成到你的 Eclipse 工程中,然后通过 Eclipse UI 调用 esptool.py 来完成烧写操作:
- 在工程浏览器(Project Explorer)中右键你的工程(一定要确保你选择的是一个工程,而不是工程中的某个目录,否则 Eclipse 不能找到正确的 Makefile 文件)。
- 从弹出的菜单中选择 Make Targets -> Create 。
- 在目标名(target name)中输入 “flash”,保持其它选项默认不变。
- 现在,你可以使用 Project -> Make Target -> Build (Shift+F9) 来编译预定义的自定义 flash 目标,它会编译和烧写工程。
注意,你需要使用 “make menuconfig” 来设置串口和与烧写相关的其它配置项。”make menuconfig” 任然需要在命令行终端中执行,详细相信请参考你的平台所对应的文档。
如果有需要,你可以按照相同的步骤添加 bootloader
和 partition_table
目标。
相关文档¶
在 Windows 上面配置 Eclipse 需要一些不同的步骤,下面将展示完整的配置步骤。
(对于 OS X 和 Linux 上面的指令,请参考 Eclipse IDE page)
请按照 安装 Eclipse IDE 中的步骤安装 Eclipse。
当你的 Eclipse 安装完成后,你需要完成这些步骤:
- Eclipse 会借助 ESP-IDF 中的 Makefile。这意味着,你需要先创建一个 ESP-IDF 工程。你可以使用 github 上面的 idf-template 工程,也可以使用在 esp-idf examples 子目录下的工程。
- Eclipse 启动后,依次选择 File -> Import…
- 在弹出的对话框中,选择 “C/C++” -> “Existing Code as Makefile Project”,然后点击 Next。
- 在下一页中,将 “Existing Code Location” 设置为你的 IDF 工程所在路径。这里不要把路径设置为 ESP-IDF 的根目录了(随后会设置)。你所指定的目录中应当包含一个名为 “Makefile” 的文件,即工程 Makefile。
- 在同一页中,在 “Toolchain for Indexer Settings” 下面取消复选框 “Show only available toolchains that support this platform”。
- 在出现的扩展列表中,选择 “Cygwin GCC”,然后点击 Finish。
*Note: 你可能会在 UI 上面看到警告“Cygwin GCC Toolchain could not be found”。没关系,我们将会重新配置 Eclipse,让其能够找打工具链。
工程浏览器(Project Explorer)中将会出现新工程。右击工程,并在弹出的菜单中选择属性(Properties)。
点击 “C/C++ Build” 属性也(顶层):
- 取消勾选 “Use default build command”,并输入自定义编译命令:
python ${IDF_PATH}/tools/windows/eclipse_make.py
。
- 取消勾选 “Use default build command”,并输入自定义编译命令:
在 “C/C++ Build” 下面点击 “Environment” 属性页:
- 点击 “Add…”,输入名字(name)``BATCH_BUILD`` 和值(value)
1
。 - 再次点击 “Add…”,输入名字(name)
IDF_PATH
。值(value)应当填写为 ESP-IDF 的完整安装路径。IDF_PATH 路径应当用斜线而不要用反斜线,即使用 C:/Users/MyUser/Development/esp-idf。 - 编辑环境变量 PATH。删除已存在的值,并用
C:\msys32\usr\bin;C:\msys32\mingw32\bin;C:\msys32\opt\xtensa-esp32-elf\bin
替代(如果你将 msys32 安装到其它目录了,则需要修改对应的路径)。
- 点击 “Add…”,输入名字(name)``BATCH_BUILD`` 和值(value)
点击 “C/C++ General” -> “Preprocessor Include Paths, Macros, etc.” 属性页:
点击 “Providers” 标签
- 在 providers 列表中,点击 “CDT GCC Built-in Compiler Settings Cygwin”。在 “Command to get compiler specs” 下面,用
xtensa-esp32-elf-gcc
将该行开始处的文本${COMMAND}
替换到。即完整的 “Command to get compiler specs” 应当是xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"
。 - 在 providers 列表中,点击 “CDT GCC Build Output Parser”,在编译器命令行模式(Compiler command pattern)的开始处输入
xtensa-esp32-elf-
。即编译器目录模式的完整路径是xtensa-esp32-elf-(g?cc)|([gc]\+\+)|(clang)
。
- 在 providers 列表中,点击 “CDT GCC Built-in Compiler Settings Cygwin”。在 “Command to get compiler specs” 下面,用
请按照 在 Eclipse 中编译 中的步骤进行编译。
仅争对 Windows 专家和好奇心比较重的小伙伴
- Explanations of the technical reasons for some of these steps. You don’t need to know this to use esp-idf with Eclipse on Windows,
- but it may be helpful background knowledge if you plan to do dig into the Eclipse support:
- The xtensa-esp32-elf-gcc cross-compiler is not a Cygwin toolchain, even though we tell Eclipse that it is one.
This is because msys2 uses Cygwin and supports Cygwin paths (of the type /c/blah
instead of c:/blah
or c:\\blah
).
In particular, xtensa-esp32-elf-gcc reports to the Eclipse “built-in compiler settings” function that its built-in include directories
are all under /usr/
, which is a Unix/Cygwin-style path that Eclipse otherwise can’t resolve. By telling Eclipse the compiler is Cygwin,
it resolves these paths internally using thecygpath
utility.
- The same problem occurs when parsing make output from esp-idf. Eclipse parses this output to find header directories,
- but it can’t resolve include directories of the form
/c/blah
without usingcygpath
. There is a heuristic that
- Eclipse Build Output Parser uses to determine whether it should call
cygpath
, but for currently unknown reasons the- esp-idf configuration doesn’t trigger it. For this reason, the
eclipse_make.py
wrapper script is used to callmake
and then usecygpath
to process the output for Eclipse.
IDF Monitor¶
idf_monitor 是一个用 Python 编写的工具程序。当你在 IDF 中调用 make monitor
目标时,该程序会被执行。
idf_monitor 的主要功能是进行串口通信,将串行数据转发到目标设备的串行端口或者或者获取端口中传递出来的数据。此外,它还有一些其它的与 IDF 相关的功能。
与 idf_monitor 交互¶
Ctrl-]
将退出 monitor。Ctrl-T Ctrl-H
将显示一个带有键盘快捷键的帮助菜单。- 除
Ctrl-]
和Ctrl-T
之外的其它键都会通过串行端口发送出去。
对地址自动解码¶
在任何时候,只要 esp-idf 打印出类似于 0x4_______
形式的十六进制代码时,idf_monitor 都会使用 addr2line 来查看源代码的位置和函数名。
当 esp-idf 的应用程序 crash 或者 panic 时,将会产生一个像下面这样的寄存器 dump 和 backtrace
Guru Meditation Error of type StoreProhibited occurred on core 0. Exception was unhandled.
Register dump:
PC : 0x400f360d PS : 0x00060330 A0 : 0x800dbf56 A1 : 0x3ffb7e00
A2 : 0x3ffb136c A3 : 0x00000005 A4 : 0x00000000 A5 : 0x00000000
A6 : 0x00000000 A7 : 0x00000080 A8 : 0x00000000 A9 : 0x3ffb7dd0
A10 : 0x00000003 A11 : 0x00060f23 A12 : 0x00060f20 A13 : 0x3ffba6d0
A14 : 0x00000047 A15 : 0x0000000f SAR : 0x00000019 EXCCAUSE: 0x0000001d
EXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000
Backtrace: 0x400f360d:0x3ffb7e00 0x400dbf56:0x3ffb7e20 0x400dbf5e:0x3ffb7e40 0x400dbf82:0x3ffb7e60 0x400d071d:0x3ffb7e90
idf_monitor 将会增加 dump
Guru Meditation Error of type StoreProhibited occurred on core 0. Exception was unhandled.
Register dump:
PC : 0x400f360d PS : 0x00060330 A0 : 0x800dbf56 A1 : 0x3ffb7e00
0x400f360d: do_something_to_crash at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:57
(inlined by) inner_dont_crash at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:52
A2 : 0x3ffb136c A3 : 0x00000005 A4 : 0x00000000 A5 : 0x00000000
A6 : 0x00000000 A7 : 0x00000080 A8 : 0x00000000 A9 : 0x3ffb7dd0
A10 : 0x00000003 A11 : 0x00060f23 A12 : 0x00060f20 A13 : 0x3ffba6d0
A14 : 0x00000047 A15 : 0x0000000f SAR : 0x00000019 EXCCAUSE: 0x0000001d
EXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000
Backtrace: 0x400f360d:0x3ffb7e00 0x400dbf56:0x3ffb7e20 0x400dbf5e:0x3ffb7e40 0x400dbf82:0x3ffb7e60 0x400d071d:0x3ffb7e90
0x400f360d: do_something_to_crash at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:57
(inlined by) inner_dont_crash at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:52
0x400dbf56: still_dont_crash at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:47
0x400dbf5e: dont_crash at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:42
0x400dbf82: app_main at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:33
0x400d071d: main_task at /home/gus/esp/32/idf/components/esp32/./cpu_start.c:254
对于上面到结果,idf_monitor 其实在后台运行了下面的命令来对每个地址进行解码的
xtensa-esp32-elf-addr2line -pfia -e build/PROJECT.elf ADDRESS
为 GDBStub 加载 GDB¶
默认情况下,如果 esp-idf 应用程序崩溃(crash)了,panic handler 会打印像上面展示的寄存器和栈 dump 消息,然后复位。
可选地,panic handler 可以被配置为去运行一个串行 “gdb stub”。“gdb stub” 可以与 gdb 调试程序通信,从而对内存进行读取,对变量和栈帧进行检查等等。这种功能虽然不如 JTAG 那样强大,但是不需要额外的硬件即可完成。
要使能 gdbstub,请运行 make menuconfig
并进入 Component config
-> ESP32-specific
-> Panic handler behaviour
,然后将其设为 Invoke GDBStub
。
如果该选项被使能且 idf_monitor 能看到 gdb stub,则它会暂停监视串口并使用正确的参数运行 GDB。当 GDB 退出后,板子会通过 RST 串行线复位(如果连接了该线)。
在这北湖,idf_monitor 运行了如下目录
xtensa-esp32-elf-gdb -ex "set serial baud BAUD" -ex "target remote PORT" -ex interrupt build/PROJECT.elf
快速编译和烧写¶
键盘快捷键 Ctrl-T Ctrl-F
会暂停 idf_monitor 并运行 make flash
目标,然后恢复 idf_monitor。任何有改动的源文件都会在重新烧写前被重新编译。
键盘快捷键 Ctrl-T Ctrl-A
会暂停 idf-monitor 鳖你个运行 make app-flash
目标,然后恢复 idf_monitor。.这与 make flash
很相似,但是只会编译和重新烧写 main app。
快速复位¶
键盘快捷键 Ctrl-T Ctrl-R
会通过 RTS 线对开发板进行复位(如果连接了该线)。
API 参考手册¶
Wi-Fi API¶
Wi-Fi¶
应用程序示例¶
示例代码 esp-idf-template 展示了如何将 ESP32 模块连接到 AP。
API 参考手册¶
类型定义¶
-
typedef void (*
wifi_promiscuous_cb_t
)(void *buf, wifi_promiscuous_pkt_type_t type)¶ The RX callback function in the promiscuous mode. Each time a packet is received, the callback function will be called.
- Parameters
buf
: Data received. Type of data in buffer (wifi_promiscuous_pkt_t or wifi_pkt_rx_ctrl_t) indicated by ‘type’ parameter.type
: promiscuous packet type.
-
typedef void (*
esp_vendor_ie_cb_t
)(void *ctx, wifi_vendor_ie_type_t type, const uint8_t sa[6], const uint8_t *vnd_ie, int rssi)¶ Define function pointer for vendor specific element callback.
- Parameters
ctx
: reservedtype
: information element typesa
: source addressvnd_ie
: pointer to a vendor specific elementrssi
: received signal strength indication
函数¶
-
esp_err_t
esp_wifi_init
(wifi_init_config_t *config)¶ Init WiFi Alloc resource for WiFi driver, such as WiFi control structure, RX/TX buffer, WiFi NVS structure etc, this WiFi also start WiFi task.
- Attention
- 1. This API must be called before all other WiFi API can be called
- Attention
- 2. Always use WIFI_INIT_CONFIG_DEFAULT macro to init the config to default values, this can guarantee all the fields got correct value when more fields are added into wifi_init_config_t in future release. If you want to set your owner initial values, overwrite the default values which are set by WIFI_INIT_CONFIG_DEFAULT, please be notified that the field ‘magic’ of wifi_init_config_t should always be WIFI_INIT_CONFIG_MAGIC!
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NO_MEM: out of memory
- others: refer to error code esp_err.h
- Parameters
config
: provide WiFi init configuration
-
esp_err_t
esp_wifi_deinit
(void)¶ Deinit WiFi Free all resource allocated in esp_wifi_init and stop WiFi task.
- Attention
- 1. This API should be called if you want to remove WiFi driver from the system
- Return
- ESP_OK: succeed
-
esp_err_t
esp_wifi_set_mode
(wifi_mode_t mode)¶ Set the WiFi operating mode.
Set the WiFi operating mode as station, soft-AP or station+soft-AP, The default mode is soft-AP mode.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- others: refer to error code in esp_err.h
- Parameters
mode
: WiFi operating mode
-
esp_err_t
esp_wifi_get_mode
(wifi_mode_t *mode)¶ Get current operating mode of WiFi.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- Parameters
mode
: store current WiFi mode
-
esp_err_t
esp_wifi_start
(void)¶ Start WiFi according to current configuration If mode is WIFI_MODE_STA, it create station control block and start station If mode is WIFI_MODE_AP, it create soft-AP control block and start soft-AP If mode is WIFI_MODE_APSTA, it create soft-AP and station control block and start soft-AP and station.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- ESP_ERR_WIFI_NO_MEM: out of memory
- ESP_ERR_WIFI_CONN: WiFi internal error, station or soft-AP control block wrong
- ESP_ERR_WIFI_FAIL: other WiFi internal errors
-
esp_err_t
esp_wifi_stop
(void)¶ Stop WiFi If mode is WIFI_MODE_STA, it stop station and free station control block If mode is WIFI_MODE_AP, it stop soft-AP and free soft-AP control block If mode is WIFI_MODE_APSTA, it stop station/soft-AP and free station/soft-AP control block.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
-
esp_err_t
esp_wifi_connect
(void)¶ Connect the ESP32 WiFi station to the AP.
- Attention
- 1. This API only impact WIFI_MODE_STA or WIFI_MODE_APSTA mode
- Attention
- 2. If the ESP32 is connected to an AP, call esp_wifi_disconnect to disconnect.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start
- ESP_ERR_WIFI_CONN: WiFi internal error, station or soft-AP control block wrong
- ESP_ERR_WIFI_SSID: SSID of AP which station connects is invalid
-
esp_err_t
esp_wifi_disconnect
(void)¶ Disconnect the ESP32 WiFi station from the AP.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi was not initialized by eps_wifi_init
- ESP_ERR_WIFI_NOT_STARTED: WiFi was not started by esp_wifi_start
- ESP_ERR_WIFI_FAIL: other WiFi internal errors
-
esp_err_t
esp_wifi_clear_fast_connect
(void)¶ Currently this API is just an stub API.
- Return
- ESP_OK: succeed
- others: fail
-
esp_err_t
esp_wifi_deauth_sta
(uint16_t aid)¶ deauthenticate all stations or associated id equals to aid
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_NOT_STARTED: WiFi was not started by esp_wifi_start
- ESP_ERR_WIFI_ARG: invalid argument
- ESP_ERR_WIFI_MODE: WiFi mode is wrong
- Parameters
aid
: when aid is 0, deauthenticate all stations, otherwise deauthenticate station whose associated id is aid
-
esp_err_t
esp_wifi_scan_start
(wifi_scan_config_t *config, bool block)¶ Scan all available APs.
- Attention
- If this API is called, the found APs are stored in WiFi driver dynamic allocated memory and the will be freed in esp_wifi_get_ap_list, so generally, call esp_wifi_get_ap_list to cause the memory to be freed once the scan is done
- Attention
- The values of maximum active scan time and passive scan time per channel are limited to 1500 milliseconds. Values above 1500ms may cause station to disconnect from AP and are not recommended.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_NOT_STARTED: WiFi was not started by esp_wifi_start
- ESP_ERR_WIFI_TIMEOUT: blocking scan is timeout
- others: refer to error code in esp_err.h
- Parameters
config
: configuration of scanningblock
: if block is true, this API will block the caller until the scan is done, otherwise it will return immediately
-
esp_err_t
esp_wifi_scan_stop
(void)¶ Stop the scan in process.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_NOT_STARTED: WiFi is not started by esp_wifi_start
-
esp_err_t
esp_wifi_scan_get_ap_num
(uint16_t *number)¶ Get number of APs found in last scan.
- Attention
- This API can only be called when the scan is completed, otherwise it may get wrong value.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_NOT_STARTED: WiFi is not started by esp_wifi_start
- ESP_ERR_WIFI_ARG: invalid argument
- Parameters
number
: store number of APIs found in last scan
-
esp_err_t
esp_wifi_scan_get_ap_records
(uint16_t *number, wifi_ap_record_t *ap_records)¶ Get AP list found in last scan.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_NOT_STARTED: WiFi is not started by esp_wifi_start
- ESP_ERR_WIFI_ARG: invalid argument
- ESP_ERR_WIFI_NO_MEM: out of memory
- Parameters
number
: As input param, it stores max AP number ap_records can hold. As output param, it receives the actual AP number this API returns.ap_records
: wifi_ap_record_t array to hold the found APs
-
esp_err_t
esp_wifi_sta_get_ap_info
(wifi_ap_record_t *ap_info)¶ Get information of AP which the ESP32 station is associated with.
- Return
- ESP_OK: succeed
- others: fail
- Parameters
ap_info
: the wifi_ap_record_t to hold AP information
-
esp_err_t
esp_wifi_set_ps
(wifi_ps_type_t type)¶ Set current power save type.
- Attention
- Default power save type is WIFI_PS_NONE.
- Return
- ESP_ERR_WIFI_NOT_SUPPORT: not supported yet
- Parameters
type
: power save type
-
esp_err_t
esp_wifi_get_ps
(wifi_ps_type_t *type)¶ Get current power save type.
- Attention
- Default power save type is WIFI_PS_NONE.
- Return
- ESP_ERR_WIFI_NOT_SUPPORT: not supported yet
- Parameters
type
: store current power save type
-
esp_err_t
esp_wifi_set_protocol
(wifi_interface_t ifx, uint8_t protocol_bitmap)¶ Set protocol type of specified interface The default protocol is (WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)
- Attention
- Currently we only support 802.11b or 802.11bg or 802.11bgn mode
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_IF: invalid interface
- others: refer to error codes in esp_err.h
- Parameters
ifx
: interfacesprotocol_bitmap
: WiFi protocol bitmap
-
esp_err_t
esp_wifi_get_protocol
(wifi_interface_t ifx, uint8_t *protocol_bitmap)¶ Get the current protocol bitmap of the specified interface.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_IF: invalid interface
- ESP_ERR_WIFI_ARG: invalid argument
- others: refer to error codes in esp_err.h
- Parameters
ifx
: interfaceprotocol_bitmap
: store current WiFi protocol bitmap of interface ifx
-
esp_err_t
esp_wifi_set_bandwidth
(wifi_interface_t ifx, wifi_bandwidth_t bw)¶ Set the bandwidth of ESP32 specified interface.
- Attention
- 1. API return false if try to configure an interface that is not enabled
- Attention
- 2. WIFI_BW_HT40 is supported only when the interface support 11N
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_IF: invalid interface
- ESP_ERR_WIFI_ARG: invalid argument
- others: refer to error codes in esp_err.h
- Parameters
ifx
: interface to be configuredbw
: bandwidth
-
esp_err_t
esp_wifi_get_bandwidth
(wifi_interface_t ifx, wifi_bandwidth_t *bw)¶ Get the bandwidth of ESP32 specified interface.
- Attention
- 1. API return false if try to get a interface that is not enable
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_IF: invalid interface
- ESP_ERR_WIFI_ARG: invalid argument
- Parameters
ifx
: interface to be configuredbw
: store bandwidth of interface ifx
-
esp_err_t
esp_wifi_set_channel
(uint8_t primary, wifi_second_chan_t second)¶ Set primary/secondary channel of ESP32.
- Attention
- 1. This is a special API for sniffer
- Attention
- 2. This API should be called after esp_wifi_start() or esp_wifi_set_promiscuous()
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_IF: invalid interface
- ESP_ERR_WIFI_ARG: invalid argument
- Parameters
primary
: for HT20, primary is the channel number, for HT40, primary is the primary channelsecond
: for HT20, second is ignored, for HT40, second is the second channel
-
esp_err_t
esp_wifi_get_channel
(uint8_t *primary, wifi_second_chan_t *second)¶ Get the primary/secondary channel of ESP32.
- Attention
- 1. API return false if try to get a interface that is not enable
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- Parameters
primary
: store current primary channelsecond
: store current second channel
-
esp_err_t
esp_wifi_set_country
(wifi_country_t country)¶ Set country code The default value is WIFI_COUNTRY_CN.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- others: refer to error code in esp_err.h
- Parameters
country
: country type
-
esp_err_t
esp_wifi_get_country
(wifi_country_t *country)¶ Get country code.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- Parameters
country
: store current country
-
esp_err_t
esp_wifi_set_mac
(wifi_interface_t ifx, uint8_t mac[6])¶ Set MAC address of the ESP32 WiFi station or the soft-AP interface.
- Attention
- 1. This API can only be called when the interface is disabled
- Attention
- 2. ESP32 soft-AP and station have different MAC addresses, do not set them to be the same.
- Attention
- 3. The bit 0 of the first byte of ESP32 MAC address can not be 1. For example, the MAC address can set to be “1a:XX:XX:XX:XX:XX”, but can not be “15:XX:XX:XX:XX:XX”.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- ESP_ERR_WIFI_IF: invalid interface
- ESP_ERR_WIFI_MAC: invalid mac address
- ESP_ERR_WIFI_MODE: WiFi mode is wrong
- others: refer to error codes in esp_err.h
- Parameters
ifx
: interfacemac
: the MAC address
-
esp_err_t
esp_wifi_get_mac
(wifi_interface_t ifx, uint8_t mac[6])¶ Get mac of specified interface.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- ESP_ERR_WIFI_IF: invalid interface
- Parameters
ifx
: interfacemac
: store mac of the interface ifx
-
esp_err_t
esp_wifi_set_promiscuous_rx_cb
(wifi_promiscuous_cb_t cb)¶ Register the RX callback function in the promiscuous mode.
Each time a packet is received, the registered callback function will be called.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- Parameters
cb
: callback
-
esp_err_t
esp_wifi_set_promiscuous
(bool en)¶ Enable the promiscuous mode.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- Parameters
en
: false - disable, true - enable
-
esp_err_t
esp_wifi_get_promiscuous
(bool *en)¶ Get the promiscuous mode.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- Parameters
en
: store the current status of promiscuous mode
-
esp_err_t
esp_wifi_set_config
(wifi_interface_t ifx, wifi_config_t *conf)¶ Set the configuration of the ESP32 STA or AP.
- Attention
- 1. This API can be called only when specified interface is enabled, otherwise, API fail
- Attention
- 2. For station configuration, bssid_set needs to be 0; and it needs to be 1 only when users need to check the MAC address of the AP.
- Attention
- 3. ESP32 is limited to only one channel, so when in the soft-AP+station mode, the soft-AP will adjust its channel automatically to be the same as the channel of the ESP32 station.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- ESP_ERR_WIFI_IF: invalid interface
- ESP_ERR_WIFI_MODE: invalid mode
- ESP_ERR_WIFI_PASSWORD: invalid password
- ESP_ERR_WIFI_NVS: WiFi internal NVS error
- others: refer to the erro code in esp_err.h
- Parameters
ifx
: interfaceconf
: station or soft-AP configuration
-
esp_err_t
esp_wifi_get_config
(wifi_interface_t ifx, wifi_config_t *conf)¶ Get configuration of specified interface.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- ESP_ERR_WIFI_IF: invalid interface
- Parameters
ifx
: interfaceconf
: station or soft-AP configuration
-
esp_err_t
esp_wifi_ap_get_sta_list
(wifi_sta_list_t *sta)¶ Get STAs associated with soft-AP.
- Attention
- SSC only API
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- ESP_ERR_WIFI_MODE: WiFi mode is wrong
- ESP_ERR_WIFI_CONN: WiFi internal error, the station/soft-AP control block is invalid
- Parameters
sta
: station list
-
esp_err_t
esp_wifi_set_storage
(wifi_storage_t storage)¶ Set the WiFi API configuration storage type.
- Attention
- 1. The default value is WIFI_STORAGE_FLASH
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- Parameters
storage
: : storage type
-
esp_err_t
esp_wifi_set_auto_connect
(bool en)¶ Set auto connect The default value is true.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_MODE: WiFi internal error, the station/soft-AP control block is invalid
- others: refer to error code in esp_err.h
- Parameters
en
: : true - enable auto connect / false - disable auto connect
-
esp_err_t
esp_wifi_get_auto_connect
(bool *en)¶ Get the auto connect flag.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- Parameters
en
: store current auto connect configuration
-
esp_err_t
esp_wifi_set_vendor_ie
(bool enable, wifi_vendor_ie_type_t type, wifi_vendor_ie_id_t idx, uint8_t *vnd_ie)¶ Set vendor specific element.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- ESP_ERR_WIFI_ARG: invalid argument
- ESP_ERR_WIFI_NO_MEM: out of memory
- Parameters
enable
: enable or nottype
: information element typeidx
: information element indexvnd_ie
: pointer to a vendor specific element
-
esp_err_t
esp_wifi_set_vendor_ie_cb
(esp_vendor_ie_cb_t cb, void *ctx)¶ Set vendor specific element callback.
- Return
- ESP_OK: succeed
- ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
- Parameters
cb
: callback functionctx
: reserved
智能配置¶
API 参考手册¶
类型定义¶
-
typedef void (*
sc_callback_t
)(smartconfig_status_t status, void *pdata)¶ The callback of SmartConfig, executed when smart-config status changed.
- Parameters
status
: Status of SmartConfig:- SC_STATUS_GETTING_SSID_PSWD : pdata is a pointer of smartconfig_type_t, means config type.
- SC_STATUS_LINK : pdata is a pointer of struct station_config.
- SC_STATUS_LINK_OVER : pdata is a pointer of phone’s IP address(4 bytes) if pdata unequal NULL.
- otherwise : parameter void *pdata is NULL.
pdata
: According to the different status have different values.
函数¶
-
const char *
esp_smartconfig_get_version
(void)¶ Get the version of SmartConfig.
- Return
- SmartConfig version const char.
-
esp_err_t
esp_smartconfig_start
(sc_callback_t cb, ...)¶ Start SmartConfig, config ESP device to connect AP. You need to broadcast information by phone APP. Device sniffer special packets from the air that containing SSID and password of target AP.
- Attention
- 1. This API can be called in station or softAP-station mode.
- Attention
- 2. Can not call esp_smartconfig_start twice before it finish, please call esp_smartconfig_stop first.
- Return
- ESP_OK: succeed
- others: fail
- Parameters
cb
: SmartConfig callback function....
: log 1: UART output logs; 0: UART only outputs the result.
-
esp_err_t
esp_smartconfig_stop
(void)¶ Stop SmartConfig, free the buffer taken by esp_smartconfig_start.
- Attention
- Whether connect to AP succeed or not, this API should be called to free memory taken by smartconfig_start.
- Return
- ESP_OK: succeed
- others: fail
-
esp_err_t
esp_esptouch_set_timeout
(uint8_t time_s)¶ Set timeout of SmartConfig process.
- Attention
- Timing starts from SC_STATUS_FIND_CHANNEL status. SmartConfig will restart if timeout.
- Return
- ESP_OK: succeed
- others: fail
- Parameters
time_s
: range 15s~255s, offset:45s.
-
esp_err_t
esp_smartconfig_set_type
(smartconfig_type_t type)¶ Set protocol type of SmartConfig.
- Attention
- If users need to set the SmartConfig type, please set it before calling esp_smartconfig_start.
- Return
- ESP_OK: succeed
- others: fail
- Parameters
type
: Choose from the smartconfig_type_t.
-
esp_err_t
esp_smartconfig_fast_mode
(bool enable)¶ Set mode of SmartConfig. default normal mode.
- Attention
- 1. Please call it before API esp_smartconfig_start.
- Attention
- 2. Fast mode have corresponding APP(phone).
- Attention
- 3. Two mode is compatible.
- Return
- ESP_OK: succeed
- others: fail
- Parameters
enable
: false-disable(default); true-enable;
关于本节 API 的示例代码请参考 ESP-IDF 示例中的 wifi 目录。
蓝牙 API¶
控制器 && VHCI¶
应用程序示例¶
请检查 ESP-IDF 示例中的 bluetooth 文件夹,它包含如下示例:
这是一个带有虚拟 HCI 接口的 BLE 广播 demo。BLE 广播时发送 Reset/ADV_PARAM/ADV_DATA/ADV_ENABLE HCI 命令。
API 参考手册¶
头文件¶
类型定义¶
-
typedef struct esp_vhci_host_callback
esp_vhci_host_callback_t
¶ esp_vhci_host_callback used for vhci call host function to notify what host need to do
枚举¶
结构体¶
-
struct
esp_bt_controller_config_t
¶ Controller config options, depend on config mask. Config mask indicate which functions enabled, this means some options or parameters of some functions enabled by config mask.
-
struct
esp_vhci_host_callback
¶ esp_vhci_host_callback used for vhci call host function to notify what host need to do
函数¶
-
esp_err_t
esp_bt_controller_init
(esp_bt_controller_config_t *cfg)¶ Initialize BT controller to allocate task and other resource.
- Return
- ESP_OK - success, other - failed
- Parameters
cfg
: Initial configuration of BT controller. This function should be called only once, before any other BT functions are called.
-
void
esp_bt_controller_deinit
(void)¶ De-initialize BT controller to free resource and delete task.
This function should be called only once, after any other BT functions are called. This function is not whole completed, esp_bt_controller_init cannot called after this function.
-
esp_err_t
esp_bt_controller_enable
(esp_bt_mode_t mode)¶ Enable BT controller.
- Return
- ESP_OK - success, other - failed
- Parameters
mode
: : the mode(BLE/BT/BTDM) to enable. Now only support BTDM.
-
esp_err_t
esp_bt_controller_disable
(esp_bt_mode_t mode)¶ Disable BT controller.
- Return
- ESP_OK - success, other - failed
- Parameters
mode
: : the mode(BLE/BT/BTDM) to disable. Now only support BTDM.
-
esp_bt_controller_status_t
esp_bt_controller_get_status
(void)¶ Get BT controller is initialised/de-initialised/enabled/disabled.
- Return
- status value
-
bool
esp_vhci_host_check_send_available
(void)¶ esp_vhci_host_check_send_available used for check actively if the host can send packet to controller or not.
- Return
- true for ready to send, false means cannot send packet
-
void
esp_vhci_host_send_packet
(uint8_t *data, uint16_t len)¶ esp_vhci_host_send_packet host send packet to controller
- Parameters
data
: the packet point ,len
: the packet length
-
void
esp_vhci_host_register_callback
(const esp_vhci_host_callback_t *callback)¶ esp_vhci_host_register_callback register the vhci referece callback, the call back struct defined by vhci_host_callback structure.
- Parameters
callback
: esp_vhci_host_callback type variable
BT 通用说明¶
BT GENERIC DEFINES¶
应用程序示例¶
API 参考手册¶
-
ESP_BT_OCTET16_LEN
¶
-
ESP_BT_OCTET8_LEN
¶
-
ESP_DEFAULT_GATT_IF
¶ Default GATT interface id.
-
ESP_BLE_CONN_PARAM_UNDEF
¶ Default BLE connection param, if the value doesn’t be overwritten.
-
ESP_BLE_IS_VALID_PARAM
(x, min, max)¶ Check the param is valid or not.
-
ESP_UUID_LEN_16
¶
-
ESP_UUID_LEN_32
¶
-
ESP_UUID_LEN_128
¶
-
ESP_BD_ADDR_LEN
¶ Bluetooth address length.
-
ESP_APP_ID_MIN
¶ Minimum of the application id.
-
ESP_APP_ID_MAX
¶ Maximum of the application id.
-
ESP_BD_ADDR_STR
¶
-
ESP_BD_ADDR_HEX
(addr)¶
-
typedef uint8_t
esp_bt_octet16_t
[ESP_BT_OCTET16_LEN]¶
-
typedef uint8_t
esp_bt_octet8_t
[ESP_BT_OCTET8_LEN]¶
-
typedef uint8_t
esp_bd_addr_t
[ESP_BD_ADDR_LEN]¶ Bluetooth device address.
-
enum
esp_bt_status_t
¶ Status Return Value.
Values:
-
ESP_BT_STATUS_SUCCESS
= 0¶
-
ESP_BT_STATUS_FAILURE
= 1¶
-
ESP_BT_STATUS_PENDING
= 2¶
-
ESP_BT_STATUS_BUSY
= 3¶
-
ESP_BT_STATUS_NO_RESOURCES
= 4¶
-
ESP_BT_STATUS_WRONG_MODE
= 5¶
-
-
enum
esp_bt_dev_type_t
¶ Bluetooth device type.
Values:
-
ESP_BT_DEVICE_TYPE_BREDR
= 0x01¶
-
ESP_BT_DEVICE_TYPE_BLE
= 0x02¶
-
ESP_BT_DEVICE_TYPE_DUMO
= 0x03¶
-
-
enum
esp_bd_addr_type_t
¶ Own BD address source of the device.
Values:
-
BD_ADDR_PUBLIC
¶ Public Address.
-
BD_ADDR_PROVIDED_RND
¶ Provided random address.
-
BD_ADDR_GEN_STATIC_RND
¶ Provided static random address.
-
BD_ADDR_GEN_RSLV
¶ Generated resolvable private random address.
-
BD_ADDR_GEN_NON_RSLV
¶ Generated non-resolvable private random address.
-
BD_ADDR_PROVIDED_RECON
¶ Provided Reconnection address.
-
BT MAIN API¶
应用程序示例¶
API 参考手册¶
-
enum
esp_bluedroid_status_t
¶ Bluetooth stack status type, to indicate whether the bluetooth stack is ready.
Values:
-
ESP_BLUEDROID_STATUS_UNINITIALIZED
= 0¶ Bluetooth not initialized
-
ESP_BLUEDROID_STATUS_INITIALIZED
¶ Bluetooth initialized but not enabled
-
ESP_BLUEDROID_STATUS_ENABLED
¶ Bluetooth initialized and enabled
-
-
esp_bluedroid_status_t
esp_bluedroid_get_status
(void)¶ Get bluetooth stack status.
- Return
- Bluetooth stack status
-
esp_err_t
esp_bluedroid_enable
(void)¶ Enable bluetooth, must after esp_bluedroid_init()
- Return
- ESP_OK : Succeed
- Other : Failed
-
esp_err_t
esp_bluedroid_disable
(void)¶ Disable bluetooth, must prior to esp_bluedroid_deinit()
- Return
- ESP_OK : Succeed
- Other : Failed
-
esp_err_t
esp_bluedroid_init
(void)¶ Init and alloc the resource for bluetooth, must be prior to every bluetooth stuff.
- Return
- ESP_OK : Succeed
- Other : Failed
-
esp_err_t
esp_bluedroid_deinit
(void)¶ Deinit and free the resource for bluetooth, must be after every bluetooth stuff.
- Return
- ESP_OK : Succeed
- Other : Failed
BT 设备 API¶
应用程序示例¶
API 参考手册¶
-
const uint8_t *
esp_bt_dev_get_address
(void)¶ Get bluetooth device address. Must use after “esp_bluedroid_enable”.
- Return
- bluetooth device address (six bytes), or NULL if bluetooth stack is not enabled
-
esp_err_t
esp_bt_dev_set_device_name
(const char *name)¶ Set bluetooth device name. This function should be called after esp_bluedroid_enable() completes successfully.
- Return
- ESP_OK : Succeed
- ESP_ERR_INVALID_ARG : if name is NULL pointer or empty, or string length out of limit
- ESP_INVALID_STATE : if bluetooth stack is not yet enabled
- ESP_FAIL : others
- Parameters
name
: : device name to be set
低功耗蓝牙¶
GAP API¶
应用程序示例¶
请检查 ESP-IDF 示例中的 bluetooth 文件夹,它包含如下示例:
bluetooth/gatt_server, bluetooth/gatt_client
这两个 demos 使用不同的 GAP API,例如广播、扫描、设置设备名等。
API 参考手册¶
-
ESP_BLE_ADV_FLAG_LIMIT_DISC
¶ BLE_ADV_DATA_FLAG data flag bit definition used for advertising data flag
-
ESP_BLE_ADV_FLAG_GEN_DISC
¶
-
ESP_BLE_ADV_FLAG_BREDR_NOT_SPT
¶
-
ESP_BLE_ADV_FLAG_DMT_CONTROLLER_SPT
¶
-
ESP_BLE_ADV_FLAG_DMT_HOST_SPT
¶
-
ESP_BLE_ADV_FLAG_NON_LIMIT_DISC
¶
-
ESP_LE_KEY_NONE
¶
-
ESP_LE_KEY_PENC
¶ encryption key, encryption information of peer device
-
ESP_LE_KEY_PID
¶ identity key of the peer device
-
ESP_LE_KEY_PCSRK
¶ peer SRK
-
ESP_LE_KEY_PLK
¶ Link key
-
ESP_LE_KEY_LLK
¶
-
ESP_LE_KEY_LENC
¶ master role security information:div
-
ESP_LE_KEY_LID
¶ master device ID key
-
ESP_LE_KEY_LCSRK
¶ local CSRK has been deliver to peer
-
ESP_LE_AUTH_NO_BOND
¶ 0
-
ESP_LE_AUTH_BOND
¶ 1 << 0
-
ESP_LE_AUTH_REQ_MITM
¶ 1 << 2
-
ESP_LE_AUTH_REQ_SC_ONLY
¶ 1 << 3
-
ESP_LE_AUTH_REQ_SC_BOND
¶ 1001
-
ESP_LE_AUTH_REQ_SC_MITM
¶ 1100
-
ESP_LE_AUTH_REQ_SC_MITM_BOND
¶ 1101
-
ESP_IO_CAP_OUT
¶ DisplayOnly
-
ESP_IO_CAP_IO
¶ DisplayYesNo
-
ESP_IO_CAP_IN
¶ KeyboardOnly
-
ESP_IO_CAP_NONE
¶ NoInputNoOutput
-
ESP_IO_CAP_KBDISP
¶ Keyboard display
-
ESP_BLE_ADV_DATA_LEN_MAX
¶ Advertising data maximum length.
-
ESP_BLE_SCAN_RSP_DATA_LEN_MAX
¶ Scan response data maximum length.
-
typedef uint8_t
esp_ble_key_type_t
¶
-
typedef uint8_t
esp_ble_auth_req_t
¶ combination of the above bit pattern
-
typedef uint8_t
esp_ble_io_cap_t
¶ combination of the io capability
-
typedef void (*
esp_gap_ble_cb_t
)(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)¶ GAP callback function type.
- Parameters
event
: : Event typeparam
: : Point to callback parameter, currently is union type
-
enum
esp_gap_ble_cb_event_t
¶ GAP BLE callback event type.
Values:
-
ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT
= 0¶ When advertising data set complete, the event comes
-
ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT
¶ When scan response data set complete, the event comes
-
ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT
¶ When scan parameters set complete, the event comes
-
ESP_GAP_BLE_SCAN_RESULT_EVT
¶ When one scan result ready, the event comes each time
-
ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT
¶ When raw advertising data set complete, the event comes
-
ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT
¶ When raw advertising data set complete, the event comes
-
ESP_GAP_BLE_ADV_START_COMPLETE_EVT
¶ When start advertising complete, the event comes
-
ESP_GAP_BLE_SCAN_START_COMPLETE_EVT
¶ When start scan complete, the event comes
-
ESP_GAP_BLE_AUTH_CMPL_EVT
¶
-
ESP_GAP_BLE_KEY_EVT
¶
-
ESP_GAP_BLE_SEC_REQ_EVT
¶
-
ESP_GAP_BLE_PASSKEY_NOTIF_EVT
¶
-
ESP_GAP_BLE_PASSKEY_REQ_EVT
¶
-
ESP_GAP_BLE_OOB_REQ_EVT
¶
-
ESP_GAP_BLE_LOCAL_IR_EVT
¶
-
ESP_GAP_BLE_LOCAL_ER_EVT
¶
-
ESP_GAP_BLE_NC_REQ_EVT
¶
-
ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT
¶ When stop adv complete, the event comes
-
ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT
¶ When stop scan complete, the event comes
-
-
enum
esp_ble_adv_data_type
¶ The type of advertising data(not adv_type)
Values:
-
ESP_BLE_AD_TYPE_FLAG
= 0x01¶
-
ESP_BLE_AD_TYPE_16SRV_PART
= 0x02¶
-
ESP_BLE_AD_TYPE_16SRV_CMPL
= 0x03¶
-
ESP_BLE_AD_TYPE_32SRV_PART
= 0x04¶
-
ESP_BLE_AD_TYPE_32SRV_CMPL
= 0x05¶
-
ESP_BLE_AD_TYPE_128SRV_PART
= 0x06¶
-
ESP_BLE_AD_TYPE_128SRV_CMPL
= 0x07¶
-
ESP_BLE_AD_TYPE_NAME_SHORT
= 0x08¶
-
ESP_BLE_AD_TYPE_NAME_CMPL
= 0x09¶
-
ESP_BLE_AD_TYPE_TX_PWR
= 0x0A¶
-
ESP_BLE_AD_TYPE_DEV_CLASS
= 0x0D¶
-
ESP_BLE_AD_TYPE_SM_TK
= 0x10¶
-
ESP_BLE_AD_TYPE_SM_OOB_FLAG
= 0x11¶
-
ESP_BLE_AD_TYPE_INT_RANGE
= 0x12¶
-
ESP_BLE_AD_TYPE_SOL_SRV_UUID
= 0x14¶
-
ESP_BLE_AD_TYPE_128SOL_SRV_UUID
= 0x15¶
-
ESP_BLE_AD_TYPE_SERVICE_DATA
= 0x16¶
-
ESP_BLE_AD_TYPE_PUBLIC_TARGET
= 0x17¶
-
ESP_BLE_AD_TYPE_RANDOM_TARGET
= 0x18¶
-
ESP_BLE_AD_TYPE_APPEARANCE
= 0x19¶
-
ESP_BLE_AD_TYPE_ADV_INT
= 0x1A¶
-
ESP_BLE_AD_TYPE_32SOL_SRV_UUID
= 0x1B¶
-
ESP_BLE_AD_TYPE_32SERVICE_DATA
= 0x1C¶
-
ESP_BLE_AD_TYPE_128SERVICE_DATA
= 0x1D¶
-
ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE
= 0xFF¶
-
-
enum
esp_ble_adv_type_t
¶ Advertising mode.
Values:
-
ADV_TYPE_IND
= 0x00¶
-
ADV_TYPE_DIRECT_IND_HIGH
= 0x01¶
-
ADV_TYPE_SCAN_IND
= 0x02¶
-
ADV_TYPE_NONCONN_IND
= 0x03¶
-
ADV_TYPE_DIRECT_IND_LOW
= 0x04¶
-
-
enum
esp_ble_adv_channel_t
¶ Advertising channel mask.
Values:
-
ADV_CHNL_37
= 0x01¶
-
ADV_CHNL_38
= 0x02¶
-
ADV_CHNL_39
= 0x04¶
-
ADV_CHNL_ALL
= 0x07¶
-
-
enum
esp_ble_adv_filter_t
¶ Values:
-
ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY
= 0x00¶ Allow both scan and connection requests from anyone.
-
ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY
¶ Allow both scan req from White List devices only and connection req from anyone.
-
ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST
¶ Allow both scan req from anyone and connection req from White List devices only.
-
ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST
¶ Allow scan and connection requests from White List devices only.
-
-
enum
esp_ble_sec_act_t
¶ Values:
-
ESP_BLE_SEC_NONE
¶
-
ESP_BLE_SEC_ENCRYPT
¶
-
ESP_BLE_SEC_ENCRYPT_NO_MITM
¶
-
ESP_BLE_SEC_ENCRYPT_MITM
¶
-
-
enum
esp_ble_sm_param_t
¶ Values:
-
ESP_BLE_SM_PASSKEY
¶
-
ESP_BLE_SM_AUTHEN_REQ_MODE
¶
-
ESP_BLE_SM_IOCAP_MODE
¶
-
ESP_BLE_SM_SET_INIT_KEY
¶
-
ESP_BLE_SM_SET_RSP_KEK
¶
-
ESP_BLE_SM_MAX_KEY_SIZE
¶
-
-
enum
esp_ble_own_addr_src_t
¶ Own BD address source of the device.
Values:
-
ESP_PUBLIC_ADDR
¶ Public Address.
-
ESP_PROVIDED_RND_ADDR
¶ Provided random address.
-
ESP_GEN_STATIC_RND_ADDR
¶ Provided static random address.
-
ESP_GEN_RSLV_ADDR
¶ Generated resolvable private random address.
-
ESP_GEN_NON_RSLV_ADDR
¶ Generated non-resolvable private random address.
-
ESP_PROVIDED_RECON_ADDR
¶ Provided Reconnection address.
-
-
enum
esp_ble_scan_type_t
¶ Ble scan type.
Values:
-
BLE_SCAN_TYPE_PASSIVE
= 0x0¶ Passive scan
-
BLE_SCAN_TYPE_ACTIVE
= 0x1¶ Active scan
-
-
enum
esp_ble_scan_filter_t
¶ Ble scan filter type.
Values:
-
BLE_SCAN_FILTER_ALLOW_ALL
= 0x0¶ Accept all :
- advertisement packets except directed advertising packets not addressed to this device (default).
-
BLE_SCAN_FILTER_ALLOW_ONLY_WLST
= 0x1¶ Accept only :
- advertisement packets from devices where the advertiser’s address is in the White list.
- Directed advertising packets which are not addressed for this device shall be ignored.
-
BLE_SCAN_FILTER_ALLOW_UND_RPA_DIR
= 0x2¶ Accept all :
- undirected advertisement packets, and
- directed advertising packets where the initiator address is a resolvable private address, and
- directed advertising packets addressed to this device.
-
BLE_SCAN_FILTER_ALLOW_WLIST_PRA_DIR
= 0x3¶ Accept all :
- advertisement packets from devices where the advertiser’s address is in the White list, and
- directed advertising packets where the initiator address is a resolvable private address, and
- directed advertising packets addressed to this device.
-
-
enum
esp_gap_search_evt_t
¶ Sub Event of ESP_GAP_BLE_SCAN_RESULT_EVT.
Values:
-
ESP_GAP_SEARCH_INQ_RES_EVT
= 0¶ Inquiry result for a peer device.
-
ESP_GAP_SEARCH_INQ_CMPL_EVT
= 1¶ Inquiry complete.
-
ESP_GAP_SEARCH_DISC_RES_EVT
= 2¶ Discovery result for a peer device.
-
ESP_GAP_SEARCH_DISC_BLE_RES_EVT
= 3¶ Discovery result for BLE GATT based service on a peer device.
-
ESP_GAP_SEARCH_DISC_CMPL_EVT
= 4¶ Discovery complete.
-
ESP_GAP_SEARCH_DI_DISC_CMPL_EVT
= 5¶ Discovery complete.
-
ESP_GAP_SEARCH_SEARCH_CANCEL_CMPL_EVT
= 6¶ Search cancelled
-
-
enum
esp_ble_evt_type_t
¶ Ble scan result event type, to indicate the result is scan response or advertising data or other.
Values:
-
ESP_BLE_EVT_CONN_ADV
= 0x00¶ Connectable undirected advertising (ADV_IND)
-
ESP_BLE_EVT_CONN_DIR_ADV
= 0x01¶ Connectable directed advertising (ADV_DIRECT_IND)
-
ESP_BLE_EVT_DISC_ADV
= 0x02¶ Scannable undirected advertising (ADV_SCAN_IND)
-
ESP_BLE_EVT_NON_CONN_ADV
= 0x03¶ Non connectable undirected advertising (ADV_NONCONN_IND)
-
ESP_BLE_EVT_SCAN_RSP
= 0x04¶ Scan Response (SCAN_RSP)
-
-
struct
esp_ble_adv_params_t
¶ Advertising parameters.
Public Members
-
uint16_t
adv_int_min
¶ Minimum advertising interval for undirected and low duty cycle directed advertising. Range: 0x0020 to 0x4000 Default: N = 0x0800 (1.28 second) Time = N * 0.625 msec Time Range: 20 ms to 10.24 sec
-
uint16_t
adv_int_max
¶ Maximum advertising interval for undirected and low duty cycle directed advertising. Range: 0x0020 to 0x4000 Default: N = 0x0800 (1.28 second) Time = N * 0.625 msec Time Range: 20 ms to 10.24 sec Advertising max interval
-
esp_ble_adv_type_t
adv_type
¶ Advertising type
-
esp_ble_addr_type_t
own_addr_type
¶ Owner bluetooth device address type
-
esp_bd_addr_t
peer_addr
¶ Peer device bluetooth device address
-
esp_ble_addr_type_t
peer_addr_type
¶ Peer device bluetooth device address type
-
esp_ble_adv_channel_t
channel_map
¶ Advertising channel map
-
esp_ble_adv_filter_t
adv_filter_policy
¶ Advertising filter policy
-
uint16_t
-
struct
esp_ble_adv_data_t
¶ Advertising data content, according to “Supplement to the Bluetooth Core Specification”.
Public Members
-
bool
set_scan_rsp
¶ Set this advertising data as scan response or not
-
bool
include_name
¶ Advertising data include device name or not
-
bool
include_txpower
¶ Advertising data include TX power
-
int
min_interval
¶ Advertising data show advertising min interval
-
int
max_interval
¶ Advertising data show advertising max interval
-
int
appearance
¶ External appearance of device
-
uint16_t
manufacturer_len
¶ Manufacturer data length
-
uint8_t *
p_manufacturer_data
¶ Manufacturer data point
-
uint16_t
service_data_len
¶ Service data length
-
uint8_t *
p_service_data
¶ Service data point
-
uint16_t
service_uuid_len
¶ Service uuid length
-
uint8_t *
p_service_uuid
¶ Service uuid array point
-
uint8_t
flag
¶ Advertising flag of discovery mode, see BLE_ADV_DATA_FLAG detail
-
bool
-
struct
esp_ble_scan_params_t
¶ Ble scan parameters.
Public Members
-
esp_ble_scan_type_t
scan_type
¶ Scan type
-
esp_ble_addr_type_t
own_addr_type
¶ Owner address type
-
esp_ble_scan_filter_t
scan_filter_policy
¶ Scan filter policy
-
uint16_t
scan_interval
¶ Scan interval. This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE scan. Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms) Time = N * 0.625 msec Time Range: 2.5 msec to 10.24 seconds
-
uint16_t
scan_window
¶ Scan window. The duration of the LE scan. LE_Scan_Window shall be less than or equal to LE_Scan_Interval Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms) Time = N * 0.625 msec Time Range: 2.5 msec to 10240 msec
-
esp_ble_scan_type_t
-
struct
esp_ble_conn_update_params_t
¶ Connection update parameters.
Public Members
-
esp_bd_addr_t
bda
¶ Bluetooth device address
-
uint16_t
min_int
¶ Min connection interval
-
uint16_t
max_int
¶ Max connection interval
-
uint16_t
latency
¶ Slave latency for the connection in number of connection events. Range: 0x0000 to 0x01F3
-
uint16_t
timeout
¶ Supervision timeout for the LE Link. Range: 0x000A to 0x0C80. Mandatory Range: 0x000A to 0x0C80 Time = N * 10 msec Time Range: 100 msec to 32 seconds
-
esp_bd_addr_t
-
struct
esp_ble_penc_keys_t
¶ BLE encryption keys.
Public Members
-
esp_bt_octet16_t
ltk
¶ The long term key
-
esp_bt_octet8_t
rand
¶ The random number
-
uint16_t
ediv
¶ The ediv value
-
uint8_t
sec_level
¶ The security level of the security link
-
uint8_t
key_size
¶ The key size(7~16) of the security link
-
esp_bt_octet16_t
-
struct
esp_ble_pcsrk_keys_t
¶ BLE CSRK keys.
Public Members
-
uint32_t
counter
¶ The counter
-
esp_bt_octet16_t
csrk
¶ The csrk key
-
uint8_t
sec_level
¶ The security level
-
uint32_t
-
struct
esp_ble_pid_keys_t
¶ BLE pid keys.
Public Members
-
esp_bt_octet16_t
irk
¶ The irk value
-
esp_bd_addr_type_t
addr_type
¶ The address type
-
esp_bd_addr_t
static_addr
¶ The static address
-
esp_bt_octet16_t
-
struct
esp_ble_lenc_keys_t
¶ BLE Encryption reproduction keys.
Public Members
-
esp_bt_octet16_t
ltk
¶ The long term key
-
uint16_t
div
¶ The div value
-
uint8_t
key_size
¶ The key size of the security link
-
uint8_t
sec_level
¶ The security level of the security link
-
esp_bt_octet16_t
-
struct
esp_ble_lcsrk_keys
¶ BLE SRK keys.
Public Members
-
uint32_t
counter
¶ The counter value
-
uint16_t
div
¶ The div value
-
uint8_t
sec_level
¶ The security level of the security link
-
esp_bt_octet16_t
csrk
¶ The csrk key value
-
uint32_t
-
struct
esp_ble_sec_key_notif_t
¶ Structure associated with ESP_KEY_NOTIF_EVT.
Public Members
-
esp_bd_addr_t
bd_addr
¶ peer address
-
uint32_t
passkey
¶ the numeric value for comparison. If just_works, do not show this number to UI
-
esp_bd_addr_t
-
struct
esp_ble_sec_req_t
¶ Structure of the security request.
Public Members
-
esp_bd_addr_t
bd_addr
¶ peer address
-
esp_bd_addr_t
警告
doxygenstruct: Cannot find class “esp_ble_key_value_t” in doxygen xml output for project “esp32-idf” from directory: xml/
-
struct
esp_ble_key_t
¶ union type of the security key value
Public Members
-
esp_bd_addr_t
bd_addr
¶ peer address
-
esp_ble_key_type_t
key_type
¶ key type of the security link
-
esp_ble_key_value_t
p_key_value
¶ the pointer to the key value
-
esp_bd_addr_t
-
struct
esp_ble_local_id_keys_t
¶ structure type of the ble local id keys value
Public Members
-
esp_bt_octet16_t
ir
¶ the 16 bits of the ir value
-
esp_bt_octet16_t
irk
¶ the 16 bits of the ir key value
-
esp_bt_octet16_t
dhk
¶ the 16 bits of the dh key value
-
esp_bt_octet16_t
-
struct
esp_ble_auth_cmpl_t
¶ Structure associated with ESP_AUTH_CMPL_EVT.
Public Members
-
esp_bd_addr_t
bd_addr
¶ BD address peer device.
-
bool
key_present
¶ Valid link key value in key element
-
esp_link_key
key
¶ Link key associated with peer device.
-
uint8_t
key_type
¶ The type of Link Key
-
bool
success
¶ TRUE of authentication succeeded, FALSE if failed.
-
uint8_t
fail_reason
¶ The HCI reason/error code for when success=FALSE
-
esp_bd_addr_type_t
addr_type
¶ Peer device address type
-
esp_bt_dev_type_t
dev_type
¶ Device type
-
esp_bd_addr_t
警告
doxygenstruct: Cannot find class “esp_ble_sec_t” in doxygen xml output for project “esp32-idf” from directory: xml/
警告
doxygenstruct: Cannot find class “esp_ble_gap_cb_param_t” in doxygen xml output for project “esp32-idf” from directory: xml/
-
struct
esp_ble_gap_cb_param_t::
ble_adv_data_cmpl_evt_param
¶ ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT.
Public Members
-
esp_bt_status_t
status
¶ Indicate the set advertising data operation success status
-
esp_bt_status_t
-
struct
esp_ble_gap_cb_param_t::
ble_scan_rsp_data_cmpl_evt_param
¶ ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT.
Public Members
-
esp_bt_status_t
status
¶ Indicate the set scan response data operation success status
-
esp_bt_status_t
-
struct
esp_ble_gap_cb_param_t::
ble_scan_param_cmpl_evt_param
¶ ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT.
Public Members
-
esp_bt_status_t
status
¶ Indicate the set scan param operation success status
-
esp_bt_status_t
-
struct
esp_ble_gap_cb_param_t::
ble_scan_result_evt_param
¶ ESP_GAP_BLE_SCAN_RESULT_EVT.
Public Members
-
esp_gap_search_evt_t
search_evt
¶ Search event type
-
esp_bd_addr_t
bda
¶ Bluetooth device address which has been searched
-
esp_bt_dev_type_t
dev_type
¶ Device type
-
esp_ble_addr_type_t
ble_addr_type
¶ Ble device address type
-
esp_ble_evt_type_t
ble_evt_type
¶ Ble scan result event type
-
int
rssi
¶ Searched device’s RSSI
-
uint8_t
ble_adv
[ESP_BLE_ADV_DATA_LEN_MAX+ESP_BLE_SCAN_RSP_DATA_LEN_MAX]¶ Received EIR
-
int
flag
¶ Advertising data flag bit
-
int
num_resps
¶ Scan result number
-
uint8_t
adv_data_len
¶ Adv data length
-
uint8_t
scan_rsp_len
¶ Scan response length
-
esp_gap_search_evt_t
-
struct
esp_ble_gap_cb_param_t::
ble_adv_data_raw_cmpl_evt_param
¶ ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT.
Public Members
-
esp_bt_status_t
status
¶ Indicate the set raw advertising data operation success status
-
esp_bt_status_t
-
struct
esp_ble_gap_cb_param_t::
ble_scan_rsp_data_raw_cmpl_evt_param
¶ ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT.
Public Members
-
esp_bt_status_t
status
¶ Indicate the set raw advertising data operation success status
-
esp_bt_status_t
-
struct
esp_ble_gap_cb_param_t::
ble_adv_start_cmpl_evt_param
¶ ESP_GAP_BLE_ADV_START_COMPLETE_EVT.
Public Members
-
esp_bt_status_t
status
¶ Indicate advertising start operation success status
-
esp_bt_status_t
-
struct
esp_ble_gap_cb_param_t::
ble_scan_start_cmpl_evt_param
¶ ESP_GAP_BLE_SCAN_START_COMPLETE_EVT.
Public Members
-
esp_bt_status_t
status
¶ Indicate scan start operation success status
-
esp_bt_status_t
-
esp_err_t
esp_ble_gap_register_callback
(esp_gap_ble_cb_t callback)¶ This function is called to occur gap event, such as scan result.
- Return
- ESP_OK : success
- other : failed
- Parameters
callback
: callback function
-
esp_err_t
esp_ble_gap_config_adv_data
(esp_ble_adv_data_t *adv_data)¶ This function is called to override the BTA default ADV parameters.
- Return
- ESP_OK : success
- other : failed
- Parameters
adv_data
: Pointer to User defined ADV data structure. This memory space can not be freed until callback of config_adv_data is received.
-
esp_err_t
esp_ble_gap_set_scan_params
(esp_ble_scan_params_t *scan_params)¶ This function is called to set scan parameters.
- Return
- ESP_OK : success
- other : failed
- Parameters
scan_params
: Pointer to User defined scan_params data structure. This memory space can not be freed until callback of set_scan_params
-
esp_err_t
esp_ble_gap_start_scanning
(uint32_t duration)¶ This procedure keep the device scanning the peer device which advertising on the air.
- Return
- ESP_OK : success
- other : failed
- Parameters
duration
: Keeping the scanning time, the unit is second.
-
esp_err_t
esp_ble_gap_stop_scanning
(void)¶ This function call to stop the device scanning the peer device which advertising on the air.
- Return
- ESP_OK : success
- other : failed
- ESP_OK : success
-
esp_err_t
esp_ble_gap_start_advertising
(esp_ble_adv_params_t *adv_params)¶ This function is called to start advertising.
- Return
- ESP_OK : success
- other : failed
- Parameters
adv_params
: pointer to User defined adv_params data structure.
-
esp_err_t
esp_ble_gap_stop_advertising
(void)¶ This function is called to stop advertising.
- Return
- ESP_OK : success
- other : failed
-
esp_err_t
esp_ble_gap_update_conn_params
(esp_ble_conn_update_params_t *params)¶ Update connection parameters, can only be used when connection is up.
- Return
- ESP_OK : success
- other : failed
- Parameters
params
: - connection update parameters
-
esp_err_t
esp_ble_gap_set_pkt_data_len
(esp_bd_addr_t remote_device, uint16_t tx_data_length)¶ This function is to set maximum LE data packet size.
- Return
- ESP_OK : success
- other : failed
-
esp_err_t
esp_ble_gap_set_rand_addr
(esp_bd_addr_t rand_addr)¶ This function set the random address for the application.
- Return
- ESP_OK : success
- other : failed
- Parameters
rand_addr
: the random address which should be setting
-
esp_err_t
esp_ble_gap_config_local_privacy
(bool privacy_enable)¶ Enable/disable privacy on the local device.
- Return
- ESP_OK : success
- other : failed
- Parameters
privacy_enable
: - enable/disable privacy on remote device.
-
esp_err_t
esp_ble_gap_set_device_name
(const char *name)¶ Set device name to the local device.
- Return
- ESP_OK : success
- other : failed
- Parameters
name
: - device name.
-
uint8_t *
esp_ble_resolve_adv_data
(uint8_t *adv_data, uint8_t type, uint8_t *length)¶ This function is called to get ADV data for a specific type.
- Return
- - ESP_OK : success
- other : failed
- Parameters
adv_data
: - pointer of ADV data which to be resolvedtype
: - finding ADV data typelength
: - return the length of ADV data not including type
-
esp_err_t
esp_ble_gap_config_adv_data_raw
(uint8_t *raw_data, uint32_t raw_data_len)¶ This function is called to set raw advertising data. User need to fill ADV data by self.
- Return
- ESP_OK : success
- other : failed
- Parameters
raw_data
: : raw advertising dataraw_data_len
: : raw advertising data length , less than 31 bytes
-
esp_err_t
esp_ble_gap_config_scan_rsp_data_raw
(uint8_t *raw_data, uint32_t raw_data_len)¶ This function is called to set raw scan response data. User need to fill scan response data by self.
- Return
- ESP_OK : success
- other : failed
- Parameters
raw_data
: : raw scan response dataraw_data_len
: : raw scan response data length , less than 31 bytes
-
esp_err_t
esp_ble_gap_set_security_param
(esp_ble_sm_param_t param_type, void *value, uint8_t len)¶ Set a GAP security parameter value. Overrides the default value.
- Return
- - ESP_OK : success
- other : failed
- Parameters
param_type
: :L the type of the param which to be setvalue
: : the param valuelen
: : the length of the param value
-
esp_err_t
esp_ble_gap_security_rsp
(esp_bd_addr_t bd_addr, bool accept)¶ Grant security request access.
- Return
- - ESP_OK : success
- other : failed
- Parameters
bd_addr
: : BD address of the peeraccept
: : accept the security request or not
-
esp_err_t
esp_ble_set_encryption
(esp_bd_addr_t bd_addr, esp_ble_sec_act_t sec_act)¶ Set a gap parameter value. Use this function to change the default GAP parameter values.
- Return
- - ESP_OK : success
- other : failed
- Parameters
bd_addr
: : the address of the peer device need to encryptionsec_act
: : This is the security action to indicate what kind of BLE security level is required for the BLE link if the BLE is supported
-
esp_err_t
esp_ble_passkey_reply
(esp_bd_addr_t bd_addr, bool accept, uint32_t passkey)¶ Reply the key value to the peer device in the lagecy connection stage.
- Return
- - ESP_OK : success
- other : failed
- Parameters
bd_addr
: : BD address of the peeraccept
: : passkey entry sucessful or declined.passkey
: : passkey value, must be a 6 digit number, can be lead by 0.
-
esp_err_t
esp_ble_confirm_reply
(esp_bd_addr_t bd_addr, bool accept)¶ Reply the comfirm value to the peer device in the lagecy connection stage.
- Return
- - ESP_OK : success
- other : failed
- Parameters
bd_addr
: : BD address of the peer deviceaccept
: : numbers to compare are the same or different.
GATT DEFINES¶
应用程序示例¶
API 参考手册¶
-
ESP_GATT_UUID_IMMEDIATE_ALERT_SVC
¶ All “ESP_GATT_UUID_xxx” is attribute types
-
ESP_GATT_UUID_LINK_LOSS_SVC
¶
-
ESP_GATT_UUID_TX_POWER_SVC
¶
-
ESP_GATT_UUID_CURRENT_TIME_SVC
¶
-
ESP_GATT_UUID_REF_TIME_UPDATE_SVC
¶
-
ESP_GATT_UUID_NEXT_DST_CHANGE_SVC
¶
-
ESP_GATT_UUID_GLUCOSE_SVC
¶
-
ESP_GATT_UUID_HEALTH_THERMOM_SVC
¶
-
ESP_GATT_UUID_DEVICE_INFO_SVC
¶
-
ESP_GATT_UUID_HEART_RATE_SVC
¶
-
ESP_GATT_UUID_PHONE_ALERT_STATUS_SVC
¶
-
ESP_GATT_UUID_BATTERY_SERVICE_SVC
¶
-
ESP_GATT_UUID_BLOOD_PRESSURE_SVC
¶
-
ESP_GATT_UUID_ALERT_NTF_SVC
¶
-
ESP_GATT_UUID_HID_SVC
¶
-
ESP_GATT_UUID_SCAN_PARAMETERS_SVC
¶
-
ESP_GATT_UUID_RUNNING_SPEED_CADENCE_SVC
¶
-
ESP_GATT_UUID_CYCLING_SPEED_CADENCE_SVC
¶
-
ESP_GATT_UUID_CYCLING_POWER_SVC
¶
-
ESP_GATT_UUID_LOCATION_AND_NAVIGATION_SVC
¶
-
ESP_GATT_UUID_USER_DATA_SVC
¶
-
ESP_GATT_UUID_WEIGHT_SCALE_SVC
¶
-
ESP_GATT_UUID_PRI_SERVICE
¶
-
ESP_GATT_UUID_SEC_SERVICE
¶
-
ESP_GATT_UUID_INCLUDE_SERVICE
¶
-
ESP_GATT_UUID_CHAR_DECLARE
¶
-
ESP_GATT_UUID_CHAR_EXT_PROP
¶
-
ESP_GATT_UUID_CHAR_DESCRIPTION
¶
-
ESP_GATT_UUID_CHAR_CLIENT_CONFIG
¶
-
ESP_GATT_UUID_CHAR_SRVR_CONFIG
¶
-
ESP_GATT_UUID_CHAR_PRESENT_FORMAT
¶
-
ESP_GATT_UUID_CHAR_AGG_FORMAT
¶
-
ESP_GATT_UUID_CHAR_VALID_RANGE
¶
-
ESP_GATT_UUID_EXT_RPT_REF_DESCR
¶
-
ESP_GATT_UUID_RPT_REF_DESCR
¶
-
ESP_GATT_UUID_GAP_DEVICE_NAME
¶
-
ESP_GATT_UUID_GAP_ICON
¶
-
ESP_GATT_UUID_GAP_PREF_CONN_PARAM
¶
-
ESP_GATT_UUID_GAP_CENTRAL_ADDR_RESOL
¶
-
ESP_GATT_UUID_GATT_SRV_CHGD
¶
-
ESP_GATT_UUID_ALERT_LEVEL
¶
-
ESP_GATT_UUID_TX_POWER_LEVEL
¶
-
ESP_GATT_UUID_CURRENT_TIME
¶
-
ESP_GATT_UUID_LOCAL_TIME_INFO
¶
-
ESP_GATT_UUID_REF_TIME_INFO
¶
-
ESP_GATT_UUID_NW_STATUS
¶
-
ESP_GATT_UUID_NW_TRIGGER
¶
-
ESP_GATT_UUID_ALERT_STATUS
¶
-
ESP_GATT_UUID_RINGER_CP
¶
-
ESP_GATT_UUID_RINGER_SETTING
¶
-
ESP_GATT_UUID_GM_MEASUREMENT
¶
-
ESP_GATT_UUID_GM_CONTEXT
¶
-
ESP_GATT_UUID_GM_CONTROL_POINT
¶
-
ESP_GATT_UUID_GM_FEATURE
¶
-
ESP_GATT_UUID_SYSTEM_ID
¶
-
ESP_GATT_UUID_MODEL_NUMBER_STR
¶
-
ESP_GATT_UUID_SERIAL_NUMBER_STR
¶
-
ESP_GATT_UUID_FW_VERSION_STR
¶
-
ESP_GATT_UUID_HW_VERSION_STR
¶
-
ESP_GATT_UUID_SW_VERSION_STR
¶
-
ESP_GATT_UUID_MANU_NAME
¶
-
ESP_GATT_UUID_IEEE_DATA
¶
-
ESP_GATT_UUID_PNP_ID
¶
-
ESP_GATT_UUID_HID_INFORMATION
¶
-
ESP_GATT_UUID_HID_REPORT_MAP
¶
-
ESP_GATT_UUID_HID_CONTROL_POINT
¶
-
ESP_GATT_UUID_HID_REPORT
¶
-
ESP_GATT_UUID_HID_PROTO_MODE
¶
-
ESP_GATT_UUID_HID_BT_KB_INPUT
¶
-
ESP_GATT_UUID_HID_BT_KB_OUTPUT
¶
-
ESP_GATT_UUID_HID_BT_MOUSE_INPUT
¶
-
ESP_GATT_HEART_RATE_MEAS
¶ Heart Rate Measurement.
-
ESP_GATT_BODY_SENSOR_LOCATION
¶ Body Sensor Location.
-
ESP_GATT_HEART_RATE_CNTL_POINT
¶ Heart Rate Control Point.
-
ESP_GATT_UUID_BATTERY_LEVEL
¶
-
ESP_GATT_UUID_SC_CONTROL_POINT
¶
-
ESP_GATT_UUID_SENSOR_LOCATION
¶
-
ESP_GATT_UUID_RSC_MEASUREMENT
¶
-
ESP_GATT_UUID_RSC_FEATURE
¶
-
ESP_GATT_UUID_CSC_MEASUREMENT
¶
-
ESP_GATT_UUID_CSC_FEATURE
¶
-
ESP_GATT_UUID_SCAN_INT_WINDOW
¶
-
ESP_GATT_UUID_SCAN_REFRESH
¶
-
ESP_GATT_ILLEGAL_UUID
¶ GATT INVALID UUID.
-
ESP_GATT_ILLEGAL_HANDLE
¶ GATT INVALID HANDLE.
-
ESP_GATT_ATTR_HANDLE_MAX
¶ GATT attribute max handle.
-
ESP_GATT_MAX_ATTR_LEN
¶ GATT maximum attribute length.
-
ESP_GATT_RSP_BY_APP
¶
-
ESP_GATT_AUTO_RSP
¶
-
ESP_GATT_IF_NONE
¶ If callback report gattc_if/gatts_if as this macro, means this event is not correspond to any app
-
typedef uint8_t
esp_gatt_if_t
¶ Gatt interface type, different application on GATT client use different gatt_if
-
enum
esp_gatt_prep_write_type
¶ Attribute write data type from the client.
Values:
-
ESP_GATT_PREP_WRITE_CANCEL
= 0x00¶ Prepare write cancel
-
ESP_GATT_PREP_WRITE_EXEC
= 0x01¶ Prepare write execute
-
-
enum
esp_gatt_status_t
¶ GATT success code and error codes.
Values:
-
ESP_GATT_OK
= 0x0¶
-
ESP_GATT_INVALID_HANDLE
= 0x01¶
-
ESP_GATT_READ_NOT_PERMIT
= 0x02¶
-
ESP_GATT_WRITE_NOT_PERMIT
= 0x03¶
-
ESP_GATT_INVALID_PDU
= 0x04¶
-
ESP_GATT_INSUF_AUTHENTICATION
= 0x05¶
-
ESP_GATT_REQ_NOT_SUPPORTED
= 0x06¶
-
ESP_GATT_INVALID_OFFSET
= 0x07¶
-
ESP_GATT_INSUF_AUTHORIZATION
= 0x08¶
-
ESP_GATT_PREPARE_Q_FULL
= 0x09¶
-
ESP_GATT_NOT_FOUND
= 0x0a¶
-
ESP_GATT_NOT_LONG
= 0x0b¶
-
ESP_GATT_INSUF_KEY_SIZE
= 0x0c¶
-
ESP_GATT_INVALID_ATTR_LEN
= 0x0d¶
-
ESP_GATT_ERR_UNLIKELY
= 0x0e¶
-
ESP_GATT_INSUF_ENCRYPTION
= 0x0f¶
-
ESP_GATT_UNSUPPORT_GRP_TYPE
= 0x10¶
-
ESP_GATT_INSUF_RESOURCE
= 0x11¶
-
ESP_GATT_NO_RESOURCES
= 0x80¶
-
ESP_GATT_INTERNAL_ERROR
= 0x81¶
-
ESP_GATT_WRONG_STATE
= 0x82¶
-
ESP_GATT_DB_FULL
= 0x83¶
-
ESP_GATT_BUSY
= 0x84¶
-
ESP_GATT_ERROR
= 0x85¶
-
ESP_GATT_CMD_STARTED
= 0x86¶
-
ESP_GATT_ILLEGAL_PARAMETER
= 0x87¶
-
ESP_GATT_PENDING
= 0x88¶
-
ESP_GATT_AUTH_FAIL
= 0x89¶
-
ESP_GATT_MORE
= 0x8a¶
-
ESP_GATT_INVALID_CFG
= 0x8b¶
-
ESP_GATT_SERVICE_STARTED
= 0x8c¶
-
ESP_GATT_ENCRYPED_MITM
= ESP_GATT_OK¶
-
ESP_GATT_ENCRYPED_NO_MITM
= 0x8d¶
-
ESP_GATT_NOT_ENCRYPTED
= 0x8e¶
-
ESP_GATT_CONGESTED
= 0x8f¶
-
ESP_GATT_DUP_REG
= 0x90¶
-
ESP_GATT_ALREADY_OPEN
= 0x91¶
-
ESP_GATT_CANCEL
= 0x92¶
-
ESP_GATT_CCC_CFG_ERR
= 0xfd¶
-
ESP_GATT_PRC_IN_PROGRESS
= 0xfe¶
-
ESP_GATT_OUT_OF_RANGE
= 0xff¶
-
-
enum
esp_gatt_conn_reason_t
¶ Gatt Connection reason enum.
Values:
-
ESP_GATT_CONN_UNKNOWN
= 0¶ Gatt connection unknown
-
ESP_GATT_CONN_L2C_FAILURE
= 1¶ General L2cap failure
-
ESP_GATT_CONN_TIMEOUT
= 0x08¶ Connection timeout
-
ESP_GATT_CONN_TERMINATE_PEER_USER
= 0x13¶ Connection terminate by peer user
-
ESP_GATT_CONN_TERMINATE_LOCAL_HOST
= 0x16¶ Connectionterminated by local host
-
ESP_GATT_CONN_FAIL_ESTABLISH
= 0x3e¶ Connection fail to establish
-
ESP_GATT_CONN_LMP_TIMEOUT
= 0x22¶ Connection fail for LMP response tout
-
ESP_GATT_CONN_CONN_CANCEL
= 0x0100¶ L2CAP connection cancelled
-
ESP_GATT_CONN_NONE
= 0x0101¶ No connection to cancel
-
-
enum
esp_gatt_auth_req_t
¶ Gatt authentication request type.
Values:
-
ESP_GATT_AUTH_REQ_NONE
= 0¶
-
ESP_GATT_AUTH_REQ_NO_MITM
= 1¶
-
ESP_GATT_AUTH_REQ_MITM
= 2¶
-
ESP_GATT_AUTH_REQ_SIGNED_NO_MITM
= 3¶
-
ESP_GATT_AUTH_REQ_SIGNED_MITM
= 4¶
-
-
enum
esp_gatt_perm_t
¶ Attribute permissions.
Values:
-
ESP_GATT_PERM_READ
= (1 << 0)¶
-
ESP_GATT_PERM_READ_ENCRYPTED
= (1 << 1)¶
-
ESP_GATT_PERM_READ_ENC_MITM
= (1 << 2)¶
-
ESP_GATT_PERM_WRITE
= (1 << 4)¶
-
ESP_GATT_PERM_WRITE_ENCRYPTED
= (1 << 5)¶
-
ESP_GATT_PERM_WRITE_ENC_MITM
= (1 << 6)¶
-
ESP_GATT_PERM_WRITE_SIGNED
= (1 << 7)¶
-
ESP_GATT_PERM_WRITE_SIGNED_MITM
= (1 << 8)¶
-
-
enum
esp_gatt_char_prop_t
¶ Values:
-
ESP_GATT_CHAR_PROP_BIT_BROADCAST
= (1 << 0)¶
-
ESP_GATT_CHAR_PROP_BIT_READ
= (1 << 1)¶
-
ESP_GATT_CHAR_PROP_BIT_WRITE_NR
= (1 << 2)¶
-
ESP_GATT_CHAR_PROP_BIT_WRITE
= (1 << 3)¶
-
ESP_GATT_CHAR_PROP_BIT_NOTIFY
= (1 << 4)¶
-
ESP_GATT_CHAR_PROP_BIT_INDICATE
= (1 << 5)¶
-
ESP_GATT_CHAR_PROP_BIT_AUTH
= (1 << 6)¶
-
ESP_GATT_CHAR_PROP_BIT_EXT_PROP
= (1 << 7)¶
-
-
struct
esp_attr_desc_t
¶ Attribute description (used to create database)
-
struct
esp_attr_control_t
¶ attribute auto respose flag
Public Members
-
uint8_t
auto_rsp
¶ need the app response to the client if need_rsp set to 1
-
uint8_t
-
struct
esp_gatts_attr_db_t
¶ attribute type added to the gatt server database
Public Members
-
esp_attr_control_t
attr_control
¶ The attribue control type
-
esp_attr_desc_t
att_desc
¶ The attribue type
-
esp_attr_control_t
-
struct
esp_attr_value_t
¶ set the attribute value type
-
struct
esp_gatts_incl_svc_desc_t
¶ Gatt include service entry element.
-
struct
esp_gatts_incl128_svc_desc_t
¶ Gatt include 128 bit service entry element.
-
struct
esp_gatt_value_t
¶ Gatt attribute value.
警告
doxygenstruct: Cannot find class “esp_gatt_rsp_t” in doxygen xml output for project “esp32-idf” from directory: xml/
GATT SERVER API¶
应用程序示例¶
请检查 ESP-IDF 示例中的 bluetooth 文件夹,它包含如下示例:
这是一个 GATT 服务器 demo。使用 GATT API 创建一个发送广播 GATT 服务器。这个 GATT 服务器可以被连接,服务可以被发现。
API 参考手册¶
-
ESP_GATT_PREP_WRITE_CANCEL
¶ Prepare write flag to indicate cancel prepare write
-
ESP_GATT_PREP_WRITE_EXEC
¶ Prepare write flag to indicate execute prepare write
-
typedef void (*
esp_gatts_cb_t
)(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)¶ GATT Server callback function type.
- Parameters
event
: : Event typegatts_if
: : GATT server access interface, normally different gatts_if correspond to different profileparam
: : Point to callback parameter, currently is union type
-
enum
esp_gatts_cb_event_t
¶ GATT Server callback function events.
Values:
-
ESP_GATTS_REG_EVT
= 0¶ When register application id, the event comes
-
ESP_GATTS_READ_EVT
= 1¶ When gatt client request read operation, the event comes
-
ESP_GATTS_WRITE_EVT
= 2¶ When gatt client request write operation, the event comes
-
ESP_GATTS_EXEC_WRITE_EVT
= 3¶ When gatt client request execute write, the event comes
-
ESP_GATTS_MTU_EVT
= 4¶ When set mtu complete, the event comes
-
ESP_GATTS_CONF_EVT
= 5¶ When receive confirm, the event comes
-
ESP_GATTS_UNREG_EVT
= 6¶ When unregister application id, the event comes
-
ESP_GATTS_CREATE_EVT
= 7¶ When create service complete, the event comes
-
ESP_GATTS_ADD_INCL_SRVC_EVT
= 8¶ When add included service complete, the event comes
-
ESP_GATTS_ADD_CHAR_EVT
= 9¶ When add characteristic complete, the event comes
-
ESP_GATTS_ADD_CHAR_DESCR_EVT
= 10¶ When add descriptor complete, the event comes
-
ESP_GATTS_DELETE_EVT
= 11¶ When delete service complete, the event comes
-
ESP_GATTS_START_EVT
= 12¶ When start service complete, the event comes
-
ESP_GATTS_STOP_EVT
= 13¶ When stop service complete, the event comes
-
ESP_GATTS_CONNECT_EVT
= 14¶ When gatt client connect, the event comes
-
ESP_GATTS_DISCONNECT_EVT
= 15¶ When gatt client disconnect, the event comes
-
ESP_GATTS_OPEN_EVT
= 16¶ When connect to peer, the event comes
-
ESP_GATTS_CANCEL_OPEN_EVT
= 17¶ When disconnect from peer, the event comes
-
ESP_GATTS_CLOSE_EVT
= 18¶ When gatt server close, the event comes
-
ESP_GATTS_LISTEN_EVT
= 19¶ When gatt listen to be connected the event comes
-
ESP_GATTS_CONGEST_EVT
= 20¶ When congest happen, the event comes
-
ESP_GATTS_RESPONSE_EVT
= 21¶ When gatt send response complete, the event comes
-
ESP_GATTS_CREAT_ATTR_TAB_EVT
= 22¶
-
ESP_GATTS_SET_ATTR_VAL_EVT
= 23¶
-
警告
doxygenstruct: Cannot find class “esp_ble_gatts_cb_param_t” in doxygen xml output for project “esp32-idf” from directory: xml/
-
struct
esp_ble_gatts_cb_param_t::
gatts_reg_evt_param
¶ ESP_GATTS_REG_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
app_id
¶ Application id which input in register API
-
esp_gatt_status_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_read_evt_param
¶ ESP_GATTS_READ_EVT.
Public Members
-
uint16_t
conn_id
¶ Connection id
-
uint32_t
trans_id
¶ Transfer id
-
esp_bd_addr_t
bda
¶ The bluetooth device address which been read
-
uint16_t
handle
¶ The attribute handle
-
uint16_t
offset
¶ Offset of the value, if the value is too long
-
bool
is_long
¶ The value is too long or not
-
bool
need_rsp
¶ The read operation need to do response
-
uint16_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_write_evt_param
¶ ESP_GATTS_WRITE_EVT.
Public Members
-
uint16_t
conn_id
¶ Connection id
-
uint32_t
trans_id
¶ Transfer id
-
esp_bd_addr_t
bda
¶ The bluetooth device address which been written
-
uint16_t
handle
¶ The attribute handle
-
uint16_t
offset
¶ Offset of the value, if the value is too long
-
bool
need_rsp
¶ The write operation need to do response
-
bool
is_prep
¶ This write operation is prepare write
-
uint16_t
len
¶ The write attribute value length
-
uint8_t *
value
¶ The write attribute value
-
uint16_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_exec_write_evt_param
¶ ESP_GATTS_EXEC_WRITE_EVT.
Public Members
-
uint16_t
conn_id
¶ Connection id
-
uint32_t
trans_id
¶ Transfer id
-
esp_bd_addr_t
bda
¶ The bluetooth device address which been written
-
uint8_t
exec_write_flag
¶ Execute write flag
-
uint16_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_mtu_evt_param
¶ ESP_GATTS_MTU_EVT.
-
struct
esp_ble_gatts_cb_param_t::
gatts_conf_evt_param
¶ ESP_GATTS_CONF_EVT.
-
struct
esp_ble_gatts_cb_param_t::
gatts_create_evt_param
¶ ESP_GATTS_UNREG_EVT.
ESP_GATTS_CREATE_EVT
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
service_handle
¶ Service attribute handle
-
esp_gatt_srvc_id_t
service_id
¶ Service id, include service uuid and other information
-
esp_gatt_status_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_add_incl_srvc_evt_param
¶ ESP_GATTS_ADD_INCL_SRVC_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
attr_handle
¶ Included service attribute handle
-
uint16_t
service_handle
¶ Service attribute handle
-
esp_gatt_status_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_add_char_evt_param
¶ ESP_GATTS_ADD_CHAR_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
attr_handle
¶ Characteristic attribute handle
-
uint16_t
service_handle
¶ Service attribute handle
-
esp_bt_uuid_t
char_uuid
¶ Characteristic uuid
-
esp_gatt_status_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_add_char_descr_evt_param
¶ ESP_GATTS_ADD_CHAR_DESCR_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
attr_handle
¶ Descriptor attribute handle
-
uint16_t
service_handle
¶ Service attribute handle
-
esp_bt_uuid_t
char_uuid
¶ Characteristic uuid
-
esp_gatt_status_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_delete_evt_param
¶ ESP_GATTS_DELETE_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
service_handle
¶ Service attribute handle
-
esp_gatt_status_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_start_evt_param
¶ ESP_GATTS_START_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
service_handle
¶ Service attribute handle
-
esp_gatt_status_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_stop_evt_param
¶ ESP_GATTS_STOP_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
service_handle
¶ Service attribute handle
-
esp_gatt_status_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_connect_evt_param
¶ ESP_GATTS_CONNECT_EVT.
Public Members
-
uint16_t
conn_id
¶ Connection id
-
esp_bd_addr_t
remote_bda
¶ Remote bluetooth device address
-
bool
is_connected
¶ Indicate it is connected or not
-
uint16_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_disconnect_evt_param
¶ ESP_GATTS_DISCONNECT_EVT.
Public Members
-
uint16_t
conn_id
¶ Connection id
-
esp_bd_addr_t
remote_bda
¶ Remote bluetooth device address
-
bool
is_connected
¶ Indicate it is connected or not
-
uint16_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_congest_evt_param
¶ ESP_GATTS_OPEN_EVT.
ESP_GATTS_CANCEL_OPEN_EVT ESP_GATTS_CLOSE_EVT ESP_GATTS_LISTEN_EVT ESP_GATTS_CONGEST_EVT
-
struct
esp_ble_gatts_cb_param_t::
gatts_rsp_evt_param
¶ ESP_GATTS_RESPONSE_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
handle
¶ Attribute handle which send response
-
esp_gatt_status_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_add_attr_tab_evt_param
¶ ESP_GATTS_CREAT_ATTR_TAB_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
esp_bt_uuid_t
svc_uuid
¶ Service uuid type
-
uint16_t
num_handle
¶ The number of the attribute handle to be added to the gatts database
-
uint16_t *
handles
¶ The number to the handles
-
esp_gatt_status_t
-
struct
esp_ble_gatts_cb_param_t::
gatts_set_attr_val_evt_param
¶ ESP_GATTS_SET_ATTR_VAL_EVT.
Public Members
-
uint16_t
srvc_handle
¶ The service handle
-
uint16_t
attr_handle
¶ The attribute handle
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
-
esp_err_t
esp_ble_gatts_register_callback
(esp_gatts_cb_t callback)¶ This function is called to register application callbacks with BTA GATTS module.
- Return
- ESP_OK : success
- other : failed
-
esp_err_t
esp_ble_gatts_app_register
(uint16_t app_id)¶ This function is called to register application identifier.
- Return
- ESP_OK : success
- other : failed
-
esp_err_t
esp_ble_gatts_app_unregister
(esp_gatt_if_t gatts_if)¶ unregister with GATT Server.
- Return
- ESP_OK : success
- other : failed
- Parameters
gatts_if
: GATT server access interface
-
esp_err_t
esp_ble_gatts_create_service
(esp_gatt_if_t gatts_if, esp_gatt_srvc_id_t *service_id, uint16_t num_handle)¶ Create a service. When service creation is done, a callback event BTA_GATTS_CREATE_SRVC_EVT is called to report status and service ID to the profile. The service ID obtained in the callback function needs to be used when adding included service and characteristics/descriptors into the service.
- Return
- ESP_OK : success
- other : failed
- Parameters
gatts_if
: GATT server access interfaceservice_id
: service ID.num_handle
: number of handle requested for this service.
-
esp_err_t
esp_ble_gatts_create_attr_tab
(const esp_gatts_attr_db_t *gatts_attr_db, esp_gatt_if_t gatts_if, uint8_t max_nb_attr, uint8_t srvc_inst_id)¶ Create a service attribute tab.
- Return
- ESP_OK : success
- other : failed
- Parameters
gatts_attr_db
: the pointer to the service attr tabgatts_if
: GATT server access interfacemax_nb_attr
: the number of attribute to be added to the service database.srvc_inst_id
: the instance id of the service
-
esp_err_t
esp_ble_gatts_add_included_service
(uint16_t service_handle, uint16_t included_service_handle)¶ This function is called to add an included service. After included service is included, a callback event BTA_GATTS_ADD_INCL_SRVC_EVT is reported the included service ID.
- Return
- ESP_OK : success
- other : failed
- Parameters
service_handle
: service handle to which this included service is to be added.included_service_handle
: the service ID to be included.
-
esp_err_t
esp_ble_gatts_add_char
(uint16_t service_handle, esp_bt_uuid_t *char_uuid, esp_gatt_perm_t perm, esp_gatt_char_prop_t property, esp_attr_value_t *char_val, esp_attr_control_t *control)¶ This function is called to add a characteristic into a service.
- Return
- ESP_OK : success
- other : failed
- Parameters
service_handle
: service handle to which this included service is to be added.char_uuid
: : Characteristic UUID.perm
: : Characteristic value declaration attribute permission.property
: : Characteristic Propertieschar_val
: : Characteristic valuecontrol
: : attribute response control byte
-
esp_err_t
esp_ble_gatts_add_char_descr
(uint16_t service_handle, esp_bt_uuid_t *descr_uuid, esp_gatt_perm_t perm, esp_attr_value_t *char_descr_val, esp_attr_control_t *control)¶ This function is called to add characteristic descriptor. When it’s done, a callback event BTA_GATTS_ADD_DESCR_EVT is called to report the status and an ID number for this descriptor.
- Return
- ESP_OK : success
- other : failed
- Parameters
service_handle
: service handle to which this characteristic descriptor is to be added.perm
: descriptor access permission.descr_uuid
: descriptor UUID.char_descr_val
: : Characteristic descriptor valuecontrol
: : attribute response control byte
-
esp_err_t
esp_ble_gatts_delete_service
(uint16_t service_handle)¶ This function is called to delete a service. When this is done, a callback event BTA_GATTS_DELETE_EVT is report with the status.
- Return
- ESP_OK : success
- other : failed
- Parameters
service_handle
: service_handle to be deleted.
-
esp_err_t
esp_ble_gatts_start_service
(uint16_t service_handle)¶ This function is called to start a service.
- Return
- ESP_OK : success
- other : failed
- Parameters
service_handle
: the service handle to be started.
-
esp_err_t
esp_ble_gatts_stop_service
(uint16_t service_handle)¶ This function is called to stop a service.
- Return
- ESP_OK : success
- other : failed
- Parameters
service_handle
: - service to be topped.
-
esp_err_t
esp_ble_gatts_send_indicate
(esp_gatt_if_t gatts_if, uint16_t conn_id, uint16_t attr_handle, uint16_t value_len, uint8_t *value, bool need_confirm)¶ Send indicate or notify to GATT client. Set param need_confirm as false will send notification, otherwise indication.
- Return
- ESP_OK : success
- other : failed
- Parameters
gatts_if
: GATT server access interfaceconn_id
: - connection id to indicate.attr_handle
: - attribute handle to indicate.value_len
: - indicate value length.value
: value to indicate.need_confirm
: - Whether a confirmation is required. false sends a GATT notification, true sends a GATT indication.
-
esp_err_t
esp_ble_gatts_send_response
(esp_gatt_if_t gatts_if, uint16_t conn_id, uint32_t trans_id, esp_gatt_status_t status, esp_gatt_rsp_t *rsp)¶ This function is called to send a response to a request.
- Return
- ESP_OK : success
- other : failed
- Parameters
gatts_if
: GATT server access interfaceconn_id
: - connection identifier.trans_id
: - transfer idstatus
: - response statusrsp
: - response data.
-
esp_err_t
esp_ble_gatts_set_attr_value
(uint16_t attr_handle, uint16_t length, const uint8_t *value)¶ This function is called to set the attribute value by the application.
- Return
- ESP_OK : success
- other : failed
- Parameters
attr_handle
: the attribute handle which to be setlength
: the value lengthvalue
: the pointer to the attribute value
-
esp_err_t
esp_ble_gatts_get_attr_value
(uint16_t attr_handle, uint16_t *length, const uint8_t **value)¶ Retrieve attribute value.
- Return
- ESP_OK : success
- other : failed
- Parameters
attr_handle
: Attribute handle.length
: pointer to the attribute value lengthvalue
: Pointer to attribute value payload, the value cannot be modified by user
-
esp_err_t
esp_ble_gatts_open
(esp_gatt_if_t gatts_if, esp_bd_addr_t remote_bda, bool is_direct)¶ Open a direct open connection or add a background auto connection.
- Return
- ESP_OK : success
- other : failed
- Parameters
gatts_if
: GATT server access interfaceremote_bda
: remote device bluetooth device address.is_direct
: direct connection or background auto connection
-
esp_err_t
esp_ble_gatts_close
(esp_gatt_if_t gatts_if, uint16_t conn_id)¶ Close a connection a remote device.
- Return
- ESP_OK : success
- other : failed
- Parameters
gatts_if
: GATT server access interfaceconn_id
: connection ID to be closed.
GATT CLIENT API¶
应用程序示例¶
请检查 ESP-IDF 示例中的 bluetooth 文件夹,它包含如下示例:
这是一个 GATT 客户端 demo。这个 demo 可以扫描设备、连接到 GATT 服务端以及发下服务。
API 参考手册¶
-
ESP_GATT_DEF_BLE_MTU_SIZE
¶ Maximum Transmission Unit used in GATT.
-
ESP_GATT_MAX_MTU_SIZE
¶ Maximum Transmission Unit allowed in GATT.
-
typedef void (*
esp_gattc_cb_t
)(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)¶ GATT Client callback function type.
- Parameters
event
: : Event typegatts_if
: : GATT client access interface, normally different gattc_if correspond to different profileparam
: : Point to callback parameter, currently is union type
-
enum
esp_gattc_cb_event_t
¶ GATT Client callback function events.
Values:
-
ESP_GATTC_REG_EVT
= 0¶ When GATT client is registered, the event comes
-
ESP_GATTC_UNREG_EVT
= 1¶ When GATT client is unregistered, the event comes
-
ESP_GATTC_OPEN_EVT
= 2¶ When GATT connection is set up, the event comes
-
ESP_GATTC_READ_CHAR_EVT
= 3¶ When GATT characteristic is read, the event comes
-
ESP_GATTC_WRITE_CHAR_EVT
= 4¶ When GATT characteristic write operation completes, the event comes
-
ESP_GATTC_CLOSE_EVT
= 5¶ When GATT connection is closed, the event comes
-
ESP_GATTC_SEARCH_CMPL_EVT
= 6¶ When GATT service discovery is completed, the event comes
-
ESP_GATTC_SEARCH_RES_EVT
= 7¶ When GATT service discovery result is got, the event comes
-
ESP_GATTC_READ_DESCR_EVT
= 8¶ When GATT characteristic descriptor read completes, the event comes
-
ESP_GATTC_WRITE_DESCR_EVT
= 9¶ When GATT characteristic descriptor write completes, the event comes
-
ESP_GATTC_NOTIFY_EVT
= 10¶ When GATT notification or indication arrives, the event comes
-
ESP_GATTC_PREP_WRITE_EVT
= 11¶ When GATT prepare-write operation completes, the event comes
-
ESP_GATTC_EXEC_EVT
= 12¶ When write execution completes, the event comes
-
ESP_GATTC_ACL_EVT
= 13¶ When ACL connection is up, the event comes
-
ESP_GATTC_CANCEL_OPEN_EVT
= 14¶ When GATT client ongoing connection is cancelled, the event comes
-
ESP_GATTC_SRVC_CHG_EVT
= 15¶ When “service changed” occurs, the event comes
-
ESP_GATTC_ENC_CMPL_CB_EVT
= 17¶ When encryption procedure completes, the event comes
-
ESP_GATTC_CFG_MTU_EVT
= 18¶ When configuration of MTU completes, the event comes
-
ESP_GATTC_ADV_DATA_EVT
= 19¶ When advertising of data, the event comes
-
ESP_GATTC_MULT_ADV_ENB_EVT
= 20¶ When multi-advertising is enabled, the event comes
-
ESP_GATTC_MULT_ADV_UPD_EVT
= 21¶ When multi-advertising parameters are updated, the event comes
-
ESP_GATTC_MULT_ADV_DATA_EVT
= 22¶ When multi-advertising data arrives, the event comes
-
ESP_GATTC_MULT_ADV_DIS_EVT
= 23¶ When multi-advertising is disabled, the event comes
-
ESP_GATTC_CONGEST_EVT
= 24¶ When GATT connection congestion comes, the event comes
-
ESP_GATTC_BTH_SCAN_ENB_EVT
= 25¶ When batch scan is enabled, the event comes
-
ESP_GATTC_BTH_SCAN_CFG_EVT
= 26¶ When batch scan storage is configured, the event comes
-
ESP_GATTC_BTH_SCAN_RD_EVT
= 27¶ When Batch scan read event is reported, the event comes
-
ESP_GATTC_BTH_SCAN_THR_EVT
= 28¶ When Batch scan threshold is set, the event comes
-
ESP_GATTC_BTH_SCAN_PARAM_EVT
= 29¶ When Batch scan parameters are set, the event comes
-
ESP_GATTC_BTH_SCAN_DIS_EVT
= 30¶ When Batch scan is disabled, the event comes
-
ESP_GATTC_SCAN_FLT_CFG_EVT
= 31¶ When Scan filter configuration completes, the event comes
-
ESP_GATTC_SCAN_FLT_PARAM_EVT
= 32¶ When Scan filter parameters are set, the event comes
-
ESP_GATTC_SCAN_FLT_STATUS_EVT
= 33¶ When Scan filter status is reported, the event comes
-
ESP_GATTC_ADV_VSC_EVT
= 34¶ When advertising vendor spec content event is reported, the event comes
-
ESP_GATTC_GET_CHAR_EVT
= 35¶ When characteristic is got from GATT server, the event comes
-
ESP_GATTC_GET_DESCR_EVT
= 36¶ When characteristic descriptor is got from GATT server, the event comes
-
ESP_GATTC_GET_INCL_SRVC_EVT
= 37¶ When included service is got from GATT server, the event comes
-
ESP_GATTC_REG_FOR_NOTIFY_EVT
= 38¶ When register for notification of a service completes, the event comes
-
ESP_GATTC_UNREG_FOR_NOTIFY_EVT
= 39¶ When unregister for notification of a service completes, the event comes
-
警告
doxygenstruct: Cannot find class “esp_ble_gattc_cb_param_t” in doxygen xml output for project “esp32-idf” from directory: xml/
-
struct
esp_ble_gattc_cb_param_t::
gattc_reg_evt_param
¶ ESP_GATTC_REG_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
app_id
¶ Application id which input in register API
-
esp_gatt_status_t
-
struct
esp_ble_gattc_cb_param_t::
gattc_open_evt_param
¶ ESP_GATTC_OPEN_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
conn_id
¶ Connection id
-
esp_bd_addr_t
remote_bda
¶ Remote bluetooth device address
-
uint16_t
mtu
¶ MTU size
-
esp_gatt_status_t
-
struct
esp_ble_gattc_cb_param_t::
gattc_close_evt_param
¶ ESP_GATTC_CLOSE_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
conn_id
¶ Connection id
-
esp_bd_addr_t
remote_bda
¶ Remote bluetooth device address
-
esp_gatt_conn_reason_t
reason
¶ The reason of gatt connection close
-
esp_gatt_status_t
-
struct
esp_ble_gattc_cb_param_t::
gattc_cfg_mtu_evt_param
¶ ESP_GATTC_CFG_MTU_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
conn_id
¶ Connection id
-
uint16_t
mtu
¶ MTU size
-
esp_gatt_status_t
-
struct
esp_ble_gattc_cb_param_t::
gattc_search_cmpl_evt_param
¶ ESP_GATTC_SEARCH_CMPL_EVT.
-
struct
esp_ble_gattc_cb_param_t::
gattc_search_res_evt_param
¶ ESP_GATTC_SEARCH_RES_EVT.
-
struct
esp_ble_gattc_cb_param_t::
gattc_read_char_evt_param
¶ ESP_GATTC_READ_CHAR_EVT, ESP_GATTC_READ_DESCR_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
conn_id
¶ Connection id
-
esp_gatt_srvc_id_t
srvc_id
¶ Service id, include service uuid and other information
-
esp_gatt_id_t
char_id
¶ Characteristic id, include characteristic uuid and other information
-
esp_gatt_id_t
descr_id
¶ Descriptor id, include descriptor uuid and other information
-
uint8_t *
value
¶ Characteristic value
-
uint16_t
value_type
¶ Characteristic value type
-
uint16_t
value_len
¶ Characteristic value length
-
esp_gatt_status_t
-
struct
esp_ble_gattc_cb_param_t::
gattc_write_evt_param
¶ ESP_GATTC_WRITE_CHAR_EVT, ESP_GATTC_PREP_WRITE_EVT, ESP_GATTC_WRITE_DESCR_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
conn_id
¶ Connection id
-
esp_gatt_srvc_id_t
srvc_id
¶ Service id, include service uuid and other information
-
esp_gatt_id_t
char_id
¶ Characteristic id, include characteristic uuid and other information
-
esp_gatt_id_t
descr_id
¶ Descriptor id, include descriptor uuid and other information
-
esp_gatt_status_t
-
struct
esp_ble_gattc_cb_param_t::
gattc_exec_cmpl_evt_param
¶ ESP_GATTC_EXEC_EVT.
-
struct
esp_ble_gattc_cb_param_t::
gattc_notify_evt_param
¶ ESP_GATTC_NOTIFY_EVT.
Public Members
-
uint16_t
conn_id
¶ Connection id
-
esp_bd_addr_t
remote_bda
¶ Remote bluetooth device address
-
esp_gatt_srvc_id_t
srvc_id
¶ Service id, include service uuid and other information
-
esp_gatt_id_t
char_id
¶ Characteristic id, include characteristic uuid and other information
-
esp_gatt_id_t
descr_id
¶ Descriptor id, include descriptor uuid and other information
-
uint16_t
value_len
¶ Notify attribute value
-
uint8_t *
value
¶ Notify attribute value
-
bool
is_notify
¶ True means notify, false means indicate
-
uint16_t
-
struct
esp_ble_gattc_cb_param_t::
gattc_srvc_chg_evt_param
¶ ESP_GATTC_SRVC_CHG_EVT.
Public Members
-
esp_bd_addr_t
remote_bda
¶ Remote bluetooth device address
-
esp_bd_addr_t
-
struct
esp_ble_gattc_cb_param_t::
gattc_congest_evt_param
¶ ESP_GATTC_CONGEST_EVT.
-
struct
esp_ble_gattc_cb_param_t::
gattc_get_char_evt_param
¶ ESP_GATTC_GET_CHAR_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
conn_id
¶ Connection id
-
esp_gatt_srvc_id_t
srvc_id
¶ Service id, include service uuid and other information
-
esp_gatt_id_t
char_id
¶ Characteristic id, include characteristic uuid and other information
-
esp_gatt_char_prop_t
char_prop
¶ Characteristic property
-
esp_gatt_status_t
-
struct
esp_ble_gattc_cb_param_t::
gattc_get_descr_evt_param
¶ ESP_GATTC_GET_DESCR_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
conn_id
¶ Connection id
-
esp_gatt_srvc_id_t
srvc_id
¶ Service id, include service uuid and other information
-
esp_gatt_id_t
char_id
¶ Characteristic id, include characteristic uuid and other information
-
esp_gatt_id_t
descr_id
¶ Descriptor id, include descriptor uuid and other information
-
esp_gatt_status_t
-
struct
esp_ble_gattc_cb_param_t::
gattc_get_incl_srvc_evt_param
¶ ESP_GATTC_GET_INCL_SRVC_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
uint16_t
conn_id
¶ Connection id
-
esp_gatt_srvc_id_t
srvc_id
¶ Service id, include service uuid and other information
-
esp_gatt_srvc_id_t
incl_srvc_id
¶ Included service id, include service uuid and other information
-
esp_gatt_status_t
-
struct
esp_ble_gattc_cb_param_t::
gattc_reg_for_notify_evt_param
¶ ESP_GATTC_REG_FOR_NOTIFY_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
esp_gatt_srvc_id_t
srvc_id
¶ Service id, include service uuid and other information
-
esp_gatt_id_t
char_id
¶ Characteristic id, include characteristic uuid and other information
-
esp_gatt_status_t
-
struct
esp_ble_gattc_cb_param_t::
gattc_unreg_for_notify_evt_param
¶ ESP_GATTC_UNREG_FOR_NOTIFY_EVT.
Public Members
-
esp_gatt_status_t
status
¶ Operation status
-
esp_gatt_srvc_id_t
srvc_id
¶ Service id, include service uuid and other information
-
esp_gatt_id_t
char_id
¶ Characteristic id, include characteristic uuid and other information
-
esp_gatt_status_t
-
esp_err_t
esp_ble_gattc_register_callback
(esp_gattc_cb_t callback)¶ This function is called to register application callbacks with GATTC module.
- Return
- ESP_OK: success
- other: failed
- Parameters
callback
: : pointer to the application callback function.
-
esp_err_t
esp_ble_gattc_app_register
(uint16_t app_id)¶ This function is called to register application callbacks with GATTC module.
- Return
- ESP_OK: success
- other: failed
- Parameters
app_id
: : Application Identify (UUID), for different application
-
esp_err_t
esp_ble_gattc_app_unregister
(esp_gatt_if_t gattc_if)¶ This function is called to unregister an application from GATTC module.
- Return
- ESP_OK: success
- other: failed
- Parameters
gattc_if
: Gatt client access interface.
-
esp_err_t
esp_ble_gattc_open
(esp_gatt_if_t gattc_if, esp_bd_addr_t remote_bda, bool is_direct)¶ Open a direct connection or add a background auto connection.
- Return
- ESP_OK: success
- other: failed
- Parameters
gattc_if
: Gatt client access interface.remote_bda
: remote device bluetooth device address.is_direct
: direct connection or background auto connection
-
esp_err_t
esp_ble_gattc_close
(esp_gatt_if_t gattc_if, uint16_t conn_id)¶ Close a connection to a GATT server.
- Return
- ESP_OK: success
- other: failed
- Parameters
gattc_if
: Gatt client access interface.conn_id
: connection ID to be closed.
-
esp_err_t
esp_ble_gattc_config_mtu
(esp_gatt_if_t gattc_if, uint16_t conn_id, uint16_t mtu)¶ Configure the MTU size in the GATT channel. This can be done only once per connection.
- Return
- ESP_OK: success
- other: failed
- Parameters
gattc_if
: Gatt client access interface.conn_id
: connection ID.mtu
: desired MTU size to use.
-
esp_err_t
esp_ble_gattc_search_service
(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_bt_uuid_t *filter_uuid)¶ This function is called to request a GATT service discovery on a GATT server. This function report service search result by a callback event, and followed by a service search complete event.
- Return
- ESP_OK: success
- other: failed
- Parameters
gattc_if
: Gatt client access interface.conn_id
: connection ID.filter_uuid
: a UUID of the service application is interested in. If Null, discover for all services.
-
esp_err_t
esp_ble_gattc_get_characteristic
(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_gatt_srvc_id_t *srvc_id, esp_gatt_id_t *start_char_id)¶ This function is called to find the first characteristic of the service on the given server.
- Return
- ESP_OK: success
- other: failed
- Parameters
gattc_if
: Gatt client access interface.conn_id
: connection ID which identify the server.srvc_id
: service IDstart_char_id
: the start characteristic ID
-
esp_err_t
esp_ble_gattc_get_descriptor
(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_gatt_srvc_id_t *srvc_id, esp_gatt_id_t *char_id, esp_gatt_id_t *start_descr_id)¶ This function is called to find the descriptor of the service on the given server.
- Return
- ESP_OK: success
- other: failed
- Parameters
gattc_if
: Gatt client access interface.conn_id
: connection ID which identify the server.srvc_id
: the service ID of which the characteristic is belonged to.char_id
: Characteristic ID, if NULL find the first available characteristic.start_descr_id
: the start descriptor id
-
esp_err_t
esp_ble_gattc_get_included_service
(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_gatt_srvc_id_t *srvc_id, esp_gatt_srvc_id_t *start_incl_srvc_id)¶ This function is called to find the first characteristic of the service on the given server.
- Return
- ESP_OK: success
- other: failed
- Parameters
gattc_if
: Gatt client access interface.conn_id
: connection ID which identify the server.srvc_id
: the service ID of which the characteristic is belonged to.start_incl_srvc_id
: the start include service id
-
esp_err_t
esp_ble_gattc_read_char
(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_gatt_srvc_id_t *srvc_id, esp_gatt_id_t *char_id, esp_gatt_auth_req_t auth_req)¶ This function is called to read a service’s characteristics of the given characteristic ID.
- Return
- ESP_OK: success
- other: failed
- Parameters
gattc_if
: Gatt client access interface.conn_id
: : connection ID.srvc_id
: : service ID.char_id
: : characteristic ID to read.auth_req
: : authenticate request type
-
esp_err_t
esp_ble_gattc_read_char_descr
(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_gatt_srvc_id_t *srvc_id, esp_gatt_id_t *char_id, esp_gatt_id_t *descr_id, esp_gatt_auth_req_t auth_req)¶ This function is called to read a characteristics descriptor.
- Return
- ESP_OK: success
- other: failed
- Parameters
gattc_if
: Gatt client access interface.conn_id
: : connection ID.srvc_id
: : service ID.char_id
: : characteristic ID to read.descr_id
: : characteristic descriptor ID to read.auth_req
: : authenticate request type
-
esp_err_t
esp_ble_gattc_write_char
(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_gatt_srvc_id_t *srvc_id, esp_gatt_id_t *char_id, uint16_t value_len, uint8_t *value, esp_gatt_write_type_t write_type, esp_gatt_auth_req_t auth_req)¶ This function is called to write characteristic value.
- Return
- ESP_OK: success
- other: failed
- Parameters
gattc_if
: Gatt client access interface.conn_id
: : connection ID.srvc_id
: : service ID.char_id
: : characteristic ID to write.value_len
: length of the value to be written.value
: : the value to be written.write_type
: : the type of attribute write operation.auth_req
: : authentication request.
-
esp_err_t
esp_ble_gattc_write_char_descr
(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_gatt_srvc_id_t *srvc_id, esp_gatt_id_t *char_id, esp_gatt_id_t *descr_id, uint16_t value_len, uint8_t *value, esp_gatt_write_type_t write_type, esp_gatt_auth_req_t auth_req)¶ This function is called to write characteristic descriptor value.
- Return
- ESP_OK: success
- other: failed
- Parameters
gattc_if
: Gatt client access interface.conn_id
: : connection IDsrvc_id
: : service ID.char_id
: : characteristic ID.descr_id
: : characteristic descriptor ID to write.value_len
: length of the value to be written.value
: : the value to be written.write_type
: : the type of attribute write operation.auth_req
: : authentication request.
-
esp_err_t
esp_ble_gattc_prepare_write
(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_gatt_srvc_id_t *srvc_id, esp_gatt_id_t *char_id, uint16_t offset, uint16_t value_len, uint8_t *value, esp_gatt_auth_req_t auth_req)¶ This function is called to prepare write a characteristic value.
- Return
- ESP_OK: success
- other: failed
- Parameters
gattc_if
: Gatt client access interface.conn_id
: : connection ID.srvc_id
: : service ID.char_id
: : GATT characteristic ID of the service.offset
: : offset of the write value.value_len
: length of the value to be written.value
: : the value to be written.auth_req
: : authentication request.
-
esp_err_t
esp_ble_gattc_execute_write
(esp_gatt_if_t gattc_if, uint16_t conn_id, bool is_execute)¶ This function is called to execute write a prepare write sequence.
- Return
- ESP_OK: success
- other: failed
- Parameters
gattc_if
: Gatt client access interface.conn_id
: : connection ID.is_execute
: : execute or cancel.
-
esp_gatt_status_t
esp_ble_gattc_register_for_notify
(esp_gatt_if_t gattc_if, esp_bd_addr_t server_bda, esp_gatt_srvc_id_t *srvc_id, esp_gatt_id_t *char_id)¶ This function is called to register for notification of a service.
- Return
- ESP_OK: registration succeeds
- other: failed
- Parameters
gattc_if
: Gatt client access interface.server_bda
: : target GATT server.srvc_id
: : pointer to GATT service ID.char_id
: : pointer to GATT characteristic ID.
-
esp_gatt_status_t
esp_ble_gattc_unregister_for_notify
(esp_gatt_if_t gattc_if, esp_bd_addr_t server_bda, esp_gatt_srvc_id_t *srvc_id, esp_gatt_id_t *char_id)¶ This function is called to de-register for notification of a service.
- Return
- ESP_OK: unregister succeeds
- other: failed
- Parameters
gattc_if
: Gatt client access interface.server_bda
: : target GATT server.srvc_id
: : pointer to GATT service ID.char_id
: : pointer to GATT characteristic ID.
BLUFI API¶
Over概述view¶
BLUFI 是一个基于 GATT 的属性,用于配置 ESP32 WIFI 与 AP 的连接/断开连接,或者设置 softap 等。在使用时应当关注如下两点:
- 从 profile 发送的事件。你需要根据事件的指示完成某些工作。
- 安全引用。你可以自己写安全函数,例如对称加密/解密、校验和等函数。你甚至可以定义 “Key Exchange/Negotiation” 过程。
应用程序示例¶
请检查 ESP-IDF 示例中的 bluetooth 文件夹,它包含如下示例:
这是一个 BLUFI demo。该 demo 可以设置 ESP32 的 wifi 为 softap/station/softap&station 模式,并且可以配置 wifi 连接。
API 参考手册¶
-
typedef void (*
esp_blufi_event_cb_t
)(esp_blufi_cb_event_t event, esp_blufi_cb_param_t *param)¶ BLUFI event callback function type.
- Parameters
event
: : Event typeparam
: : Point to callback parameter, currently is union type
-
typedef void (*
esp_blufi_negotiate_data_handler_t
)(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free)¶ BLUFI negotiate data handler.
- Parameters
data
: : data from phonelen
: : length of data from phoneoutput_data
: : data want to send to phoneoutput_len
: : length of data want to send to phone
-
typedef int (*
esp_blufi_encrypt_func_t
)(uint8_t iv8, uint8_t *crypt_data, int cyprt_len)¶ BLUFI encrypt the data after negotiate a share key.
- Return
- Nonnegative number is encrypted length, if error, return negative number;
- Parameters
iv8
: : initial vector(8bit), normally, blufi core will input packet sequence numbercrypt_data
: : plain text and encrypted data, the encrypt function must support autochthonous encryptcrypt_len
: : length of plain text
-
typedef int (*
esp_blufi_decrypt_func_t
)(uint8_t iv8, uint8_t *crypt_data, int crypt_len)¶ BLUFI decrypt the data after negotiate a share key.
- Return
- Nonnegative number is decrypted length, if error, return negative number;
- Parameters
iv8
: : initial vector(8bit), normally, blufi core will input packet sequence numbercrypt_data
: : encrypted data and plain text, the encrypt function must support autochthonous decryptcrypt_len
: : length of encrypted text
-
typedef uint16_t (*
esp_blufi_checksum_func_t
)(uint8_t iv8, uint8_t *data, int len)¶ BLUFI checksum.
- Parameters
iv8
: : initial vector(8bit), normally, blufi core will input packet sequence numberdata
: : data need to checksumlen
: : length of data
-
enum
esp_blufi_cb_event_t
¶ Values:
-
ESP_BLUFI_EVENT_INIT_FINISH
= 0¶
-
ESP_BLUFI_EVENT_DEINIT_FINISH
¶
-
ESP_BLUFI_EVENT_SET_WIFI_OPMODE
¶
-
ESP_BLUFI_EVENT_BLE_CONNECT
¶
-
ESP_BLUFI_EVENT_BLE_DISCONNECT
¶
-
ESP_BLUFI_EVENT_REQ_CONNECT_TO_AP
¶
-
ESP_BLUFI_EVENT_REQ_DISCONNECT_FROM_AP
¶
-
ESP_BLUFI_EVENT_GET_WIFI_STATUS
¶
-
ESP_BLUFI_EVENT_DEAUTHENTICATE_STA
¶
-
ESP_BLUFI_EVENT_RECV_STA_BSSID
¶
-
ESP_BLUFI_EVENT_RECV_STA_SSID
¶
-
ESP_BLUFI_EVENT_RECV_STA_PASSWD
¶
-
ESP_BLUFI_EVENT_RECV_SOFTAP_SSID
¶
-
ESP_BLUFI_EVENT_RECV_SOFTAP_PASSWD
¶
-
ESP_BLUFI_EVENT_RECV_SOFTAP_MAX_CONN_NUM
¶
-
ESP_BLUFI_EVENT_RECV_SOFTAP_AUTH_MODE
¶
-
ESP_BLUFI_EVENT_RECV_SOFTAP_CHANNEL
¶
-
ESP_BLUFI_EVENT_RECV_USERNAME
¶
-
ESP_BLUFI_EVENT_RECV_CA_CERT
¶
-
ESP_BLUFI_EVENT_RECV_CLIENT_CERT
¶
-
ESP_BLUFI_EVENT_RECV_SERVER_CERT
¶
-
ESP_BLUFI_EVENT_RECV_CLIENT_PRIV_KEY
¶
-
ESP_BLUFI_EVENT_RECV_SERVER_PRIV_KEY
¶
-
-
enum
esp_blufi_sta_conn_state_t
¶ BLUFI config status.
Values:
-
ESP_BLUFI_STA_CONN_SUCCESS
= 0x00¶
-
ESP_BLUFI_STA_CONN_FAIL
= 0x01¶
-
-
struct
esp_blufi_extra_info_t
¶ BLUFI extra information structure.
Public Members
-
uint8_t
sta_bssid
[6]¶ BSSID of station interface
-
bool
sta_bssid_set
¶ is BSSID of station interface set
-
uint8_t *
sta_ssid
¶ SSID of station interface
-
int
sta_ssid_len
¶ length of SSID of station interface
-
uint8_t *
sta_passwd
¶ password of station interface
-
int
sta_passwd_len
¶ length of password of station interface
-
uint8_t *
softap_ssid
¶ SSID of softap interface
-
int
softap_ssid_len
¶ length of SSID of softap interface
-
uint8_t *
softap_passwd
¶ password of station interface
-
int
softap_passwd_len
¶ length of password of station interface
-
uint8_t
softap_authmode
¶ authentication mode of softap interface
-
bool
softap_authmode_set
¶ is authentication mode of softap interface set
-
uint8_t
softap_max_conn_num
¶ max connection number of softap interface
-
bool
softap_max_conn_num_set
¶ is max connection number of softap interface set
-
uint8_t
softap_channel
¶ channel of softap interface
-
bool
softap_channel_set
¶ is channel of softap interface set
-
uint8_t
警告
doxygenstruct: Cannot find class “esp_blufi_cb_param_t” in doxygen xml output for project “esp32-idf” from directory: xml/
-
struct
esp_blufi_cb_param_t::
blufi_init_finish_evt_param
¶ ESP_BLUFI_EVENT_INIT_FINISH.
Public Members
-
esp_blufi_init_state_t
state
¶ Initial status
-
esp_blufi_init_state_t
-
struct
esp_blufi_cb_param_t::
blufi_deinit_finish_evt_param
¶ ESP_BLUFI_EVENT_DEINIT_FINISH.
Public Members
-
esp_blufi_deinit_state_t
state
¶ De-initial status
-
esp_blufi_deinit_state_t
-
struct
esp_blufi_cb_param_t::
blufi_set_wifi_mode_evt_param
¶ ESP_BLUFI_EVENT_SET_WIFI_MODE.
Public Members
-
wifi_mode_t
op_mode
¶ Wifi operation mode
-
wifi_mode_t
-
struct
esp_blufi_cb_param_t::
blufi_connect_evt_param
¶ ESP_BLUFI_EVENT_CONNECT.
Public Members
-
esp_bd_addr_t
remote_bda
¶ Blufi Remote bluetooth device address
-
esp_bd_addr_t
-
struct
esp_blufi_cb_param_t::
blufi_disconnect_evt_param
¶ ESP_BLUFI_EVENT_DISCONNECT.
Public Members
-
esp_bd_addr_t
remote_bda
¶ Blufi Remote bluetooth device address
-
esp_bd_addr_t
-
struct
esp_blufi_cb_param_t::
blufi_recv_sta_bssid_evt_param
¶ ESP_BLUFI_EVENT_RECV_STA_BSSID.
Public Members
-
uint8_t
bssid
[6]¶ BSSID
-
uint8_t
-
struct
esp_blufi_cb_param_t::
blufi_recv_sta_ssid_evt_param
¶ ESP_BLUFI_EVENT_RECV_STA_SSID.
-
struct
esp_blufi_cb_param_t::
blufi_recv_sta_passwd_evt_param
¶ ESP_BLUFI_EVENT_RECV_STA_PASSWD.
-
struct
esp_blufi_cb_param_t::
blufi_recv_softap_ssid_evt_param
¶ ESP_BLUFI_EVENT_RECV_SOFTAP_SSID.
-
struct
esp_blufi_cb_param_t::
blufi_recv_softap_passwd_evt_param
¶ ESP_BLUFI_EVENT_RECV_SOFTAP_PASSWD.
-
struct
esp_blufi_cb_param_t::
blufi_recv_softap_max_conn_num_evt_param
¶ ESP_BLUFI_EVENT_RECV_SOFTAP_MAX_CONN_NUM.
Public Members
-
int
max_conn_num
¶ SSID
-
int
-
struct
esp_blufi_cb_param_t::
blufi_recv_softap_auth_mode_evt_param
¶ ESP_BLUFI_EVENT_RECV_SOFTAP_AUTH_MODE.
Public Members
-
wifi_auth_mode_t
auth_mode
¶ Authentication mode
-
wifi_auth_mode_t
-
struct
esp_blufi_cb_param_t::
blufi_recv_softap_channel_evt_param
¶ ESP_BLUFI_EVENT_RECV_SOFTAP_CHANNEL.
Public Members
-
uint8_t
channel
¶ Authentication mode
-
uint8_t
-
struct
esp_blufi_cb_param_t::
blufi_recv_username_evt_param
¶ ESP_BLUFI_EVENT_RECV_USERNAME.
-
struct
esp_blufi_cb_param_t::
blufi_recv_ca_evt_param
¶ ESP_BLUFI_EVENT_RECV_CA_CERT.
-
struct
esp_blufi_cb_param_t::
blufi_recv_client_cert_evt_param
¶ ESP_BLUFI_EVENT_RECV_CLIENT_CERT
-
struct
esp_blufi_cb_param_t::
blufi_recv_server_cert_evt_param
¶ ESP_BLUFI_EVENT_RECV_SERVER_CERT
-
struct
esp_blufi_cb_param_t::
blufi_recv_client_pkey_evt_param
¶ ESP_BLUFI_EVENT_RECV_CLIENT_PRIV_KEY
-
struct
esp_blufi_cb_param_t::
blufi_recv_server_pkey_evt_param
¶ ESP_BLUFI_EVENT_RECV_SERVER_PRIV_KEY
-
struct
esp_blufi_callbacks_t
¶ BLUFI callback functions type.
Public Members
-
esp_blufi_event_cb_t
event_cb
¶ BLUFI event callback
-
esp_blufi_negotiate_data_handler_t
negotiate_data_handler
¶ BLUFI negotiate data function for negotiate share key
-
esp_blufi_encrypt_func_t
encrypt_func
¶ BLUFI encrypt data function with share key generated by negotiate_data_handler
-
esp_blufi_decrypt_func_t
decrypt_func
¶ BLUFI decrypt data function with share key generated by negotiate_data_handler
-
esp_blufi_checksum_func_t
checksum_func
¶ BLUFI check sum function (FCS)
-
esp_blufi_event_cb_t
-
esp_err_t
esp_blufi_register_callbacks
(esp_blufi_callbacks_t *callbacks)¶ This function is called to receive blufi callback event.
- Return
- ESP_OK - success, other - failed
- Parameters
callbacks
: callback functions
-
esp_err_t
esp_blufi_profile_init
(void)¶ This function is called to initialize blufi_profile.
- Return
- ESP_OK - success, other - failed
-
esp_err_t
esp_blufi_profile_deinit
(void)¶ This function is called to de-initialize blufi_profile.
- Return
- ESP_OK - success, other - failed
-
esp_err_t
esp_blufi_send_wifi_conn_report
(wifi_mode_t opmode, esp_blufi_sta_conn_state_t sta_conn_state, uint8_t softap_conn_num, esp_blufi_extra_info_t *extra_info)¶ This function is called to send wifi connection report.
- Return
- ESP_OK - success, other - failed
- Parameters
opmode
: : wifi opmodesta_conn_state
: : station is already in connection or notsoftap_conn_num
: : softap connection numberextra_info
: : extra information, such as sta_ssid, softap_ssid and etc.
-
uint16_t
esp_blufi_get_version
(void)¶ Get BLUFI profile version.
- Return
- Most 8bit significant is Great version, Least 8bit is Sub version
经典蓝牙¶
经典蓝牙 GAP API¶
应用程序示例¶
API 参考手册¶
-
esp_err_t
esp_bt_gap_set_scan_mode
(esp_bt_scan_mode_t mode)¶ Set discoverability and connectability mode for legacy bluetooth. This function should be called after esp_bluedroid_enable() completes successfully.
- Return
- ESP_OK : Succeed
- ESP_ERR_INVALID_ARG: if argument invalid
- ESP_INVALID_STATE: if bluetooth stack is not yet enabled
- ESP_FAIL: others
- Parameters
mode
: : one of the enums of bt_scan_mode_t
Bluetooth A2DP API¶
应用程序示例¶
请检查 ESP-IDF 示例中的 bluetooth 文件夹,它包含如下示例:
这是一个 A2DP sink 客户端 demo。该 demo 可以被 A2DP 设备发现和连接,从远程设备接收音频数据。
API 参考手册¶
-
ESP_A2D_MCT_SBC
¶ Media codec types supported by A2DP.
SBC
-
ESP_A2D_MCT_M12
¶ MPEG-1, 2 Audio
-
ESP_A2D_MCT_M24
¶ MPEG-2, 4 AAC
-
ESP_A2D_MCT_ATRAC
¶ ATRAC family
-
ESP_A2D_MCT_NON_A2DP
¶
-
ESP_A2D_CIE_LEN_SBC
¶
-
ESP_A2D_CIE_LEN_M12
¶
-
ESP_A2D_CIE_LEN_M24
¶
-
ESP_A2D_CIE_LEN_ATRAC
¶
-
typedef uint8_t
esp_a2d_mct_t
¶
-
typedef void (*
esp_a2d_cb_t
)(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)¶ A2DP profile callback function type.
- Parameters
event
: : Event typeparam
: : Pointer to callback parameter
-
typedef void (*
esp_a2d_data_cb_t
)(const uint8_t *buf, uint32_t len)¶ A2DP profile data callback function.
- Parameters
buf
: : data received from A2DP source device and is PCM format decoder from SBC decoder; buf references to a static memory block and can be overwritten by upcoming datalen
: : size(in bytes) in buf
-
enum
esp_a2d_connection_state_t
¶ Bluetooth A2DP connection states.
Values:
-
ESP_A2D_CONNECTION_STATE_DISCONNECTED
= 0¶ connection released
-
ESP_A2D_CONNECTION_STATE_CONNECTING
¶ connecting remote device
-
ESP_A2D_CONNECTION_STATE_CONNECTED
¶ connection established
-
ESP_A2D_CONNECTION_STATE_DISCONNECTING
¶ disconnecting remote device
-
-
enum
esp_a2d_disc_rsn_t
¶ Bluetooth A2DP disconnection reason.
Values:
-
ESP_A2D_DISC_RSN_NORMAL
= 0¶ Finished disconnection that is initiated by local or remote device
-
ESP_A2D_DISC_RSN_ABNORMAL
¶ Abnormal disconnection caused by signal loss
-
警告
doxygenstruct: Cannot find class “esp_a2d_cb_param_t” in doxygen xml output for project “esp32-idf” from directory: xml/
-
struct
esp_a2d_cb_param_t::
a2d_conn_stat_param
¶ ESP_A2D_CONNECTION_STATE_EVT.
Public Members
-
esp_a2d_connection_state_t
state
¶ one of values from esp_a2d_connection_state_t
-
esp_bd_addr_t
remote_bda
¶ remote bluetooth device address
-
esp_a2d_disc_rsn_t
disc_rsn
¶ reason of disconnection for “DISCONNECTED”
-
esp_a2d_connection_state_t
-
struct
esp_a2d_cb_param_t::
a2d_audio_stat_param
¶ ESP_A2D_AUDIO_STATE_EVT.
Public Members
-
esp_a2d_audio_state_t
state
¶ one of the values from esp_a2d_audio_state_t
-
esp_bd_addr_t
remote_bda
¶ remote bluetooth device address
-
esp_a2d_audio_state_t
-
struct
esp_a2d_cb_param_t::
a2d_audio_cfg_param
¶ ESP_A2D_AUDIO_CFG_EVT.
Public Members
-
esp_bd_addr_t
remote_bda
¶ remote bluetooth device address
-
esp_a2d_mcc_t
mcc
¶ A2DP media codec capability information
-
esp_bd_addr_t
-
esp_err_t
esp_a2d_register_callback
(esp_a2d_cb_t callback)¶ Register application callback function to A2DP module. This function should be called only after esp_bluedroid_enable() completes successfully.
- Return
- ESP_OK: success
- ESP_INVALID_STATE: if bluetooth stack is not yet enabled
- ESP_FAIL: if callback is a NULL function pointer
- Parameters
callback
: A2DP sink event callback function
-
esp_err_t
esp_a2d_register_data_callback
(esp_a2d_data_cb_t callback)¶ Register A2DP sink data output function; For now the output is PCM data stream decoded from SBC format. This function should be called only after esp_bluedroid_enable() completes successfully.
- Return
- ESP_OK: success
- ESP_INVALID_STATE: if bluetooth stack is not yet enabled
- ESP_FAIL: if callback is a NULL function pointer
- Parameters
callback
: A2DP data callback function
-
esp_err_t
esp_a2d_sink_init
(void)¶ Initialize the bluetooth A2DP sink module. This function should be called after esp_bluedroid_enable() completes successfully.
- Return
- ESP_OK: if the initialization request is sent successfully
- ESP_INVALID_STATE: if bluetooth stack is not yet enabled
- ESP_FAIL: others
-
esp_err_t
esp_a2d_sink_deinit
(void)¶ De-initialize for A2DP sink module. This function should be called only after esp_bluedroid_enable() completes successfully.
- Return
- ESP_OK: success
- ESP_INVALID_STATE: if bluetooth stack is not yet enabled
- ESP_FAIL: others
-
esp_err_t
esp_a2d_sink_connect
(esp_bd_addr_t remote_bda)¶ Connect the remote bluetooth device bluetooth, must after esp_a2d_sink_init()
- Return
- ESP_OK: connect request is sent to lower layer
- ESP_INVALID_STATE: if bluetooth stack is not yet enabled
- ESP_FAIL: others
- Parameters
remote_bda
: remote bluetooth device address
-
esp_err_t
esp_a2d_sink_disconnect
(esp_bd_addr_t remote_bda)¶ Disconnect the remote bluetooth device.
- Return
- ESP_OK: disconnect request is sent to lower layer
- ESP_INVALID_STATE: if bluetooth stack is not yet enabled
- ESP_FAIL: others
- Parameters
remote_bda
: remote bluetooth device address
BT AVRCP API¶
应用程序示例¶
API 参考手册¶
-
typedef void (*
esp_avrc_ct_cb_t
)(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param)¶ AVRCP controller callback function type.
- Parameters
event
: : Event typeparam
: : Pointer to callback parameter union
-
enum
esp_avrc_features_t
¶ AVRC feature bit mask.
Values:
-
ESP_AVRC_FEAT_RCTG
= 0x0001¶ remote control target
-
ESP_AVRC_FEAT_RCCT
= 0x0002¶ remote control controller
-
ESP_AVRC_FEAT_VENDOR
= 0x0008¶ remote control vendor dependent commands
-
ESP_AVRC_FEAT_BROWSE
= 0x0010¶ use browsing channel
-
ESP_AVRC_FEAT_META_DATA
= 0x0040¶ remote control metadata transfer command/response
-
ESP_AVRC_FEAT_ADV_CTRL
= 0x0200¶ remote control advanced control commmand/response
-
-
enum
esp_avrc_pt_cmd_t
¶ AVRC passthrough command code.
Values:
-
ESP_AVRC_PT_CMD_PLAY
= 0x44¶ play
-
ESP_AVRC_PT_CMD_STOP
= 0x45¶ stop
-
ESP_AVRC_PT_CMD_PAUSE
= 0x46¶ pause
-
ESP_AVRC_PT_CMD_FORWARD
= 0x4B¶ forward
-
ESP_AVRC_PT_CMD_BACKWARD
= 0x4C¶ backward
-
警告
doxygenstruct: Cannot find class “esp_avrc_ct_cb_param_t” in doxygen xml output for project “esp32-idf” from directory: xml/
-
struct
esp_avrc_ct_cb_param_t::
avrc_ct_conn_stat_param
¶ ESP_AVRC_CT_CONNECTION_STATE_EVT.
Public Members
-
bool
connected
¶ whether AVRC connection is set up
-
uint32_t
feat_mask
¶ AVRC feature mask of remote device
-
esp_bd_addr_t
remote_bda
¶ remote bluetooth device address
-
bool
-
struct
esp_avrc_ct_cb_param_t::
avrc_ct_psth_rsp_param
¶ ESP_AVRC_CT_PASSTHROUGH_RSP_EVT.
-
esp_err_t
esp_avrc_ct_register_callback
(esp_avrc_ct_cb_t callback)¶ Register application callbacks to AVRCP module; for now only AVRCP Controller role is supported. This function should be called after esp_bluedroid_enable() completes successfully.
- Return
- ESP_OK: success
- ESP_INVALID_STATE: if bluetooth stack is not yet enabled
- ESP_FAIL: others
- Parameters
callback
: AVRCP controller callback function
-
esp_err_t
esp_avrc_ct_init
(void)¶ Initialize the bluetooth AVRCP controller module, This function should be called after esp_bluedroid_enable() completes successfully.
- Return
- ESP_OK: success
- ESP_INVALID_STATE: if bluetooth stack is not yet enabled
- ESP_FAIL: others
-
esp_err_t
esp_avrc_ct_deinit
(void)¶ De-initialize AVRCP controller module. This function should be called after after esp_bluedroid_enable() completes successfully.
- Return
- ESP_OK: success
- ESP_INVALID_STATE: if bluetooth stack is not yet enabled
- ESP_FAIL: others
-
esp_err_t
esp_avrc_ct_send_passthrough_cmd
(uint8_t tl, uint8_t key_code, uint8_t key_state)¶ Send passthrough command to AVRCP target, This function should be called after ESP_AVRC_CT_CONNECTION_STATE_EVT is received and AVRCP connection is established.
- Return
- ESP_OK: success
- ESP_INVALID_STATE: if bluetooth stack is not yet enabled
- ESP_FAIL: others
- Parameters
tl
: : transaction label, 0 to 15, consecutive commands should use different values.key_code
: : passthrough command code, e.g. ESP_AVRC_PT_CMD_PLAY, ESP_AVRC_PT_CMD_STOP, etc.key_state
: : passthrough command key state, ESP_AVRC_PT_CMD_STATE_PRESSED or ESP_AVRC_PT_CMD_STATE_PRESSED
关于本节 API 的示例代码请参考 ESP-IDF 示例中的 bluetooth 目录。
以太网 API¶
以太网¶
应用程序示例¶
以太网示例 ethernet/ethernet.
API 参考手册¶
PHY 接口¶
PHY 模块通过配置所给 PHY 的结构体 eth_config_t 进行配置。
头部包含一个默认的配置结构体。这些默认配置中的某些成员在被用于一个特殊的 PHY 硬件配置之前需要被覆盖或重置。查看以太网的示例代码可以了解这是如何完成的。
类型定义¶
-
typedef bool (*
eth_phy_check_link_func
)(void)¶
-
typedef void (*
eth_phy_check_init_func
)(void)¶
-
typedef eth_speed_mode_t (*
eth_phy_get_speed_mode_func
)(void)¶
-
typedef eth_duplex_mode_t (*
eth_phy_get_duplex_mode_func
)(void)¶
-
typedef void (*
eth_phy_func
)(void)¶
-
typedef esp_err_t (*
eth_tcpip_input_func
)(void *buffer, uint16_t len, void *eb)¶
-
typedef void (*
eth_gpio_config_func
)(void)¶
-
typedef bool (*
eth_phy_get_partner_pause_enable_func
)(void)¶
枚举¶
结构体¶
-
struct
eth_config_t
¶ ethernet configuration
Public Members
-
eth_phy_base_t
phy_addr
¶ phy base addr (0~31)
-
eth_mode_t
mac_mode
¶ mac mode only support RMII now
-
eth_tcpip_input_func
tcpip_input
¶ tcpip input func
-
eth_phy_func
phy_init
¶ phy init func
-
eth_phy_check_link_func
phy_check_link
¶ phy check link func
-
eth_phy_check_init_func
phy_check_init
¶ phy check init func
-
eth_phy_get_speed_mode_func
phy_get_speed_mode
¶ phy check init func
-
eth_phy_get_duplex_mode_func
phy_get_duplex_mode
¶ phy check init func
-
eth_gpio_config_func
gpio_config
¶ gpio config func
-
bool
flow_ctrl_enable
¶ flag of flow ctrl enable
-
eth_phy_get_partner_pause_enable_func
phy_get_partner_pause_enable
¶ get partner pause enable
-
eth_phy_power_enable_func
phy_power_enable
¶ enable or disable phy power
-
eth_phy_base_t
函数¶
-
esp_err_t
esp_eth_init
(eth_config_t *config)¶ Init ethernet mac.
- Note
- config can not be NULL,and phy chip must be suitable to phy init func.
- Return
- ESP_OK
- ESP_FAIL
- Parameters
config
: mac init data.
-
esp_err_t
esp_eth_tx
(uint8_t *buf, uint16_t size)¶ Send packet from tcp/ip to mac.
- Note
- buf can not be NULL,size must be less than 1580
- Return
- ESP_OK
- ESP_FAIL
- Parameters
buf
: start address of packet data.size
: size (byte) of packet data.
-
esp_err_t
esp_eth_enable
(void)¶ Enable ethernet interface.
- Note
- Shout be called after esp_eth_init
- Return
- ESP_OK
- ESP_FAIL
-
esp_err_t
esp_eth_disable
(void)¶ Disable ethernet interface.
- Note
- Shout be called after esp_eth_init
- Return
- ESP_OK
- ESP_FAIL
-
void
esp_eth_get_mac
(uint8_t mac[6])¶ Get mac addr.
- Note
- mac addr must be a valid unicast address
- Parameters
mac
: start address of mac address.
-
void
esp_eth_smi_write
(uint32_t reg_num, uint16_t value)¶ Read phy reg with smi interface.
- Note
- phy base addr must be right.
- Parameters
reg_num
: phy reg num.value
: value which write to phy reg.
-
uint16_t
esp_eth_smi_read
(uint32_t reg_num)¶ Read phy reg with smi interface.
- Note
- phy base addr must be right.
- Return
- value what read from phy reg
- Parameters
reg_num
: phy reg num.
-
esp_err_t
esp_eth_smi_wait_value
(uint32_t reg_num, uint16_t value, uint16_t value_mask, int timeout_ms)¶ Continuously read a PHY register over SMI interface, wait until the register has the desired value.
- Note
- PHY base address must be right.
- Return
- ESP_OK if desired value matches, ESP_ERR_TIMEOUT if timed out.
- Parameters
reg_num
: PHY register numbervalue
: Value to wait for (masked with value_mask)value_mask
: Mask of bits to match in the register.timeout_ms
: Timeout to wait for this value (milliseconds). 0 means never timeout.
-
static esp_err_t
esp_eth_smi_wait_set
(uint32_t reg_num, uint16_t value_mask, int timeout_ms)¶ Continuously read a PHY register over SMI interface, wait until the register has all bits in a mask set.
- Note
- PHY base address must be right.
- Return
- ESP_OK if desired value matches, ESP_ERR_TIMEOUT if timed out.
- Parameters
reg_num
: PHY register numbervalue_mask
: Value mask to wait for (all bits in this mask must be set)timeout_ms
: Timeout to wait for this value (milliseconds). 0 means never timeout.
-
void
esp_eth_free_rx_buf
(void *buf)¶ Free emac rx buf.
- Note
- buf can not be null,and it is tcpip input buf.
- Parameters
buf
: start address of recevie packet data.
PHY 配置常量¶
警告
doxygenvariable: Cannot find variable “phy_tlk110_default_ethernet_config” in doxygen xml output for project “esp32-idf” from directory: xml/
警告
doxygenvariable: Cannot find variable “phy_lan8720_default_ethernet_config” in doxygen xml output for project “esp32-idf” from directory: xml/
关于本节 API 的示例代码请参考 ESP-IDF 示例中的 ethernet 目录。
外设 API¶
Analog to Digital Converter¶
概述¶
ESP32 integrates two 12-bit SAR (“Successive Approximation Register”) ADCs (Analog to Digital Converters) and supports measurements on 18 channels (analog enabled pins). Some of these pins can be used to build a programmable gain amplifier which is used for the measurement of small analog signals.
The ADC driver API currently only supports ADC1 (9 channels, attached to GPIOs 32-39).
Taking an ADC reading involves configuring the ADC with the desired precision and attentuation settings, and then calling adc1_get_voltage() to read the channel.
It is also possible to read the internal hall effect sensor via ADC1.
应用程序示例¶
Reading voltage on ADC1 channel 0 (GPIO 36):
#include <driver/adc.h>
...
adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(ADC1_CHANNEL_0,ADC_ATTEN_0db);
int val = adc1_get_voltage(ADC1_CHANNEL_0);
Reading the internal hall effect sensor:
#include <driver/adc.h>
...
adc1_config_width(ADC_WIDTH_12Bit);
int val = hall_sensor_read();
The value read in both these examples is 12 bits wide (range 0-4095).
API 参考手册¶
头文件¶
- components/driver/include/driver/adc.h
枚举¶
- enum
adc1_channel_t
¶Values:
ADC1_CHANNEL_0
= 0¶ADC1 channel 0 is GPIO36
ADC1_CHANNEL_1
¶ADC1 channel 1 is GPIO37
ADC1_CHANNEL_2
¶ADC1 channel 2 is GPIO38
ADC1_CHANNEL_3
¶ADC1 channel 3 is GPIO39
ADC1_CHANNEL_4
¶ADC1 channel 4 is GPIO32
ADC1_CHANNEL_5
¶ADC1 channel 5 is GPIO33
ADC1_CHANNEL_6
¶ADC1 channel 6 is GPIO34
ADC1_CHANNEL_7
¶ADC1 channel 7 is GPIO35
ADC1_CHANNEL_MAX
¶
- enum
adc_atten_t
¶Values:
ADC_ATTEN_0db
= 0¶The input voltage of ADC will be reduced to about 1/1
ADC_ATTEN_2_5db
= 1¶The input voltage of ADC will be reduced to about 1/1.34
ADC_ATTEN_6db
= 2¶The input voltage of ADC will be reduced to about 1/2
ADC_ATTEN_11db
= 3¶The input voltage of ADC will be reduced to about 1/3.6
函数¶
- esp_err_t
adc1_config_width
(adc_bits_width_t width_bit)¶Configure ADC1 capture width.
The configuration is for all channels of ADC1
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
width_bit
: Bit capture width for ADC1
- esp_err_t
adc1_config_channel_atten
(adc1_channel_t channel, adc_atten_t atten)¶Configure the ADC1 channel, including setting attenuation.
The default ADC full-scale voltage is 1.1V. To read higher voltages (up to the pin maximum voltage, usually 3.3V) requires setting >0dB signal attenuation for that ADC channel.
- Note
- This function also configures the input GPIO pin mux to connect it to the ADC1 channel. It must be called before calling adc1_get_voltage() for this channel.
When VDD_A is 3.3V:
- 0dB attenuaton (ADC_ATTEN_0db) gives full-scale voltage 1.1V
- 2.5dB attenuation (ADC_ATTEN_2_5db) gives full-scale voltage 1.5V
- 6dB attenuation (ADC_ATTEN_6db) gives full-scale voltage 2.2V
- 11dB attenuation (ADC_ATTEN_11db) gives full-scale voltage 3.9V (see note below)
- Note
- The full-scale voltage is the voltage corresponding to a maximum reading (depending on ADC1 configured bit width, this value is: 4095 for 12-bits, 2047 for 11-bits, 1023 for 10-bits, 511 for 9 bits.)
- Note
- At 11dB attenuation the maximum voltage is limited by VDD_A, not the full scale voltage.
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
channel
: ADC1 channel to configureatten
: Attenuation level
- int
adc1_get_voltage
(adc1_channel_t channel)¶Take an ADC1 reading on a single channel.
- Note
- Call adc1_config_width() before the first time this function is called.
- Note
- For a given channel, adc1_config_channel_atten(channel) must be called before the first time this function is called.
- Return
- -1: Parameter error
- Other: ADC1 channel reading.
- Parameters
channel
: ADC1 channel to read
- int
hall_sensor_read
()¶Read Hall Sensor.
- Note
- The Hall Sensor uses channels 0 and 3 of ADC1. Do not configure these channels for use as ADC channels.
- Note
- The ADC1 module must be enabled by calling adc1_config_width() before calling hall_sensor_read(). ADC1 should be configured for 12 bit readings, as the hall sensor readings are low values and do not cover the full range of the ADC.
- Return
- The hall sensor reading.
Digital To Analog Converter¶
概述¶
ESP32 has two 8-bit DAC (digital to analog converter) channels, connected to GPIO25 (Channel 1) and GPIO26 (Channel 2).
The DAC driver allows these channels to be set to arbitrary voltages.
The DAC channels can also be driven with DMA-style written sample data, via the I2S driver when using the “built-in DAC mode”.
For other analog output options, see the Sigma-delta Modulation module and the LED Control module. Both these modules produce high frequency PWM output, which can be hardware low-pass filtered in order to generate a lower frequency analog output.
应用程序示例¶
Setting DAC channel 1 (GPIO 25) voltage to approx 0.78 of VDD_A voltage (VDD * 200 / 255). For VDD_A 3.3V, this is 2.59V:
#include <driver/dac.h>
...
dac_out_voltage(DAC_CHANNEL_1, 200);
API 参考手册¶
头文件¶
- components/driver/include/driver/dac.h
枚举¶
函数¶
- esp_err_t
dac_out_voltage
(dac_channel_t channel, uint8_t dac_value)¶Set DAC output voltage.
DAC output is 8-bit. Maximum (255) corresponds to VDD.
- Note
- When this function is called, function for the DAC channel’s GPIO pin is reconfigured for RTC DAC function.
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
channel
: DAC channeldac_value
: DAC output value
GPIO & RTC GPIO¶
概述¶
The ESP32 chip features 40 physical GPIO pads. Some GPIO pads cannot be used or do not have the corresponding pin on the chip package(refer to technical reference manual). Each pad can be used as a general purpose I/O or can be connected to an internal peripheral signal.
- Note that GPIO6-11 are usually used for SPI flash.
- GPIO34-39 can only be set as input mode and do not have software pullup or pulldown functions.
There is also separate “RTC GPIO” support, which functions when GPIOs are routed to the “RTC” low-power and analog subsystem. These pin functions can be used when in deep sleep, when the Ultra Low Power co-processor is running, or when analog functions such as ADC/DAC/etc are in use.
应用程序示例¶
GPIO output and input interrupt example: peripherals/gpio.
API 参考手册¶
宏¶
-
GPIO_SEL_0
¶ Pin 0 selected
-
GPIO_SEL_1
¶ Pin 1 selected
-
GPIO_SEL_2
¶ Pin 2 selected
-
GPIO_SEL_3
¶ Pin 3 selected
-
GPIO_SEL_4
¶ Pin 4 selected
-
GPIO_SEL_5
¶ Pin 5 selected
-
GPIO_SEL_6
¶ Pin 6 selected
-
GPIO_SEL_7
¶ Pin 7 selected
-
GPIO_SEL_8
¶ Pin 8 selected
-
GPIO_SEL_9
¶ Pin 9 selected
-
GPIO_SEL_10
¶ Pin 10 selected
-
GPIO_SEL_11
¶ Pin 11 selected
-
GPIO_SEL_12
¶ Pin 12 selected
-
GPIO_SEL_13
¶ Pin 13 selected
-
GPIO_SEL_14
¶ Pin 14 selected
-
GPIO_SEL_15
¶ Pin 15 selected
-
GPIO_SEL_16
¶ Pin 16 selected
-
GPIO_SEL_17
¶ Pin 17 selected
-
GPIO_SEL_18
¶ Pin 18 selected
-
GPIO_SEL_19
¶ Pin 19 selected
-
GPIO_SEL_21
¶ Pin 21 selected
-
GPIO_SEL_22
¶ Pin 22 selected
-
GPIO_SEL_23
¶ Pin 23 selected
-
GPIO_SEL_25
¶ Pin 25 selected
-
GPIO_SEL_26
¶ Pin 26 selected
-
GPIO_SEL_27
¶ Pin 27 selected
-
GPIO_SEL_32
¶ Pin 32 selected
-
GPIO_SEL_33
¶ Pin 33 selected
-
GPIO_SEL_34
¶ Pin 34 selected
-
GPIO_SEL_35
¶ Pin 35 selected
-
GPIO_SEL_36
¶ Pin 36 selected
-
GPIO_SEL_37
¶ Pin 37 selected
-
GPIO_SEL_38
¶ Pin 38 selected
-
GPIO_SEL_39
¶ Pin 39 selected
-
GPIO_PIN_REG_0
¶
-
GPIO_PIN_REG_1
¶
-
GPIO_PIN_REG_2
¶
-
GPIO_PIN_REG_3
¶
-
GPIO_PIN_REG_4
¶
-
GPIO_PIN_REG_5
¶
-
GPIO_PIN_REG_6
¶
-
GPIO_PIN_REG_7
¶
-
GPIO_PIN_REG_8
¶
-
GPIO_PIN_REG_9
¶
-
GPIO_PIN_REG_10
¶
-
GPIO_PIN_REG_11
¶
-
GPIO_PIN_REG_12
¶
-
GPIO_PIN_REG_13
¶
-
GPIO_PIN_REG_14
¶
-
GPIO_PIN_REG_15
¶
-
GPIO_PIN_REG_16
¶
-
GPIO_PIN_REG_17
¶
-
GPIO_PIN_REG_18
¶
-
GPIO_PIN_REG_19
¶
-
GPIO_PIN_REG_20
¶
-
GPIO_PIN_REG_21
¶
-
GPIO_PIN_REG_22
¶
-
GPIO_PIN_REG_23
¶
-
GPIO_PIN_REG_25
¶
-
GPIO_PIN_REG_26
¶
-
GPIO_PIN_REG_27
¶
-
GPIO_PIN_REG_32
¶
-
GPIO_PIN_REG_33
¶
-
GPIO_PIN_REG_34
¶
-
GPIO_PIN_REG_35
¶
-
GPIO_PIN_REG_36
¶
-
GPIO_PIN_REG_37
¶
-
GPIO_PIN_REG_38
¶
-
GPIO_PIN_REG_39
¶
-
GPIO_APP_CPU_INTR_ENA
¶
-
GPIO_APP_CPU_NMI_INTR_ENA
¶
-
GPIO_PRO_CPU_INTR_ENA
¶
-
GPIO_PRO_CPU_NMI_INTR_ENA
¶
-
GPIO_SDIO_EXT_INTR_ENA
¶
-
GPIO_MODE_DEF_INPUT
¶
-
GPIO_MODE_DEF_OUTPUT
¶
-
GPIO_MODE_DEF_OD
¶
-
GPIO_PIN_COUNT
¶
-
GPIO_IS_VALID_GPIO
(gpio_num)¶
-
GPIO_IS_VALID_OUTPUT_GPIO
(gpio_num)¶
枚举¶
-
enum
gpio_num_t
¶ Values:
-
GPIO_NUM_0
= 0¶ GPIO0, input and output
-
GPIO_NUM_1
= 1¶ GPIO1, input and output
-
GPIO_NUM_2
= 2¶ GPIO2, input and output
-
GPIO_NUM_3
= 3¶ GPIO3, input and output
-
GPIO_NUM_4
= 4¶ GPIO4, input and output
-
GPIO_NUM_5
= 5¶ GPIO5, input and output
-
GPIO_NUM_6
= 6¶ GPIO6, input and output
-
GPIO_NUM_7
= 7¶ GPIO7, input and output
-
GPIO_NUM_8
= 8¶ GPIO8, input and output
-
GPIO_NUM_9
= 9¶ GPIO9, input and output
-
GPIO_NUM_10
= 10¶ GPIO10, input and output
-
GPIO_NUM_11
= 11¶ GPIO11, input and output
-
GPIO_NUM_12
= 12¶ GPIO12, input and output
-
GPIO_NUM_13
= 13¶ GPIO13, input and output
-
GPIO_NUM_14
= 14¶ GPIO14, input and output
-
GPIO_NUM_15
= 15¶ GPIO15, input and output
-
GPIO_NUM_16
= 16¶ GPIO16, input and output
-
GPIO_NUM_17
= 17¶ GPIO17, input and output
-
GPIO_NUM_18
= 18¶ GPIO18, input and output
-
GPIO_NUM_19
= 19¶ GPIO19, input and output
-
GPIO_NUM_21
= 21¶ GPIO21, input and output
-
GPIO_NUM_22
= 22¶ GPIO22, input and output
-
GPIO_NUM_23
= 23¶ GPIO23, input and output
-
GPIO_NUM_25
= 25¶ GPIO25, input and output
-
GPIO_NUM_26
= 26¶ GPIO26, input and output
-
GPIO_NUM_27
= 27¶ GPIO27, input and output
-
GPIO_NUM_32
= 32¶ GPIO32, input and output
-
GPIO_NUM_33
= 33¶ GPIO32, input and output
-
GPIO_NUM_34
= 34¶ GPIO34, input mode only
-
GPIO_NUM_35
= 35¶ GPIO35, input mode only
-
GPIO_NUM_36
= 36¶ GPIO36, input mode only
-
GPIO_NUM_37
= 37¶ GPIO37, input mode only
-
GPIO_NUM_38
= 38¶ GPIO38, input mode only
-
GPIO_NUM_39
= 39¶ GPIO39, input mode only
-
GPIO_NUM_MAX
= 40¶
-
-
enum
gpio_int_type_t
¶ Values:
-
GPIO_INTR_DISABLE
= 0¶ Disable GPIO interrupt
-
GPIO_INTR_POSEDGE
= 1¶ GPIO interrupt type : rising edge
-
GPIO_INTR_NEGEDGE
= 2¶ GPIO interrupt type : falling edge
-
GPIO_INTR_ANYEDGE
= 3¶ GPIO interrupt type : both rising and falling edge
-
GPIO_INTR_LOW_LEVEL
= 4¶ GPIO interrupt type : input low level trigger
-
GPIO_INTR_HIGH_LEVEL
= 5¶ GPIO interrupt type : input high level trigger
-
GPIO_INTR_MAX
¶
-
-
enum
gpio_mode_t
¶ Values:
-
GPIO_MODE_INPUT
= GPIO_MODE_DEF_INPUT¶ GPIO mode : input only
-
GPIO_MODE_OUTPUT
= GPIO_MODE_DEF_OUTPUT¶ GPIO mode : output only mode
-
GPIO_MODE_OUTPUT_OD
= ((GPIO_MODE_DEF_OUTPUT)|(GPIO_MODE_DEF_OD))¶ GPIO mode : output only with open-drain mode
-
GPIO_MODE_INPUT_OUTPUT_OD
= ((GPIO_MODE_DEF_INPUT)|(GPIO_MODE_DEF_OUTPUT)|(GPIO_MODE_DEF_OD))¶ GPIO mode : output and input with open-drain mode
-
GPIO_MODE_INPUT_OUTPUT
= ((GPIO_MODE_DEF_INPUT)|(GPIO_MODE_DEF_OUTPUT))¶ GPIO mode : output and input mode
-
-
enum
gpio_pullup_t
¶ Values:
-
GPIO_PULLUP_DISABLE
= 0x0¶ Disable GPIO pull-up resistor
-
GPIO_PULLUP_ENABLE
= 0x1¶ Enable GPIO pull-up resistor
-
结构体¶
-
struct
gpio_config_t
¶ Configuration parameters of GPIO pad for gpio_config function.
Public Members
-
uint64_t
pin_bit_mask
¶ GPIO pin: set with bit mask, each bit maps to a GPIO
-
gpio_mode_t
mode
¶ GPIO mode: set input/output mode
-
gpio_pullup_t
pull_up_en
¶ GPIO pull-up
-
gpio_pulldown_t
pull_down_en
¶ GPIO pull-down
-
gpio_int_type_t
intr_type
¶ GPIO interrupt type
-
uint64_t
函数¶
-
esp_err_t
gpio_config
(const gpio_config_t *pGPIOConfig)¶ GPIO common configuration.
Configure GPIO’s Mode,pull-up,PullDown,IntrType
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
pGPIOConfig
: Pointer to GPIO configure struct
-
esp_err_t
gpio_set_intr_type
(gpio_num_t gpio_num, gpio_int_type_t intr_type)¶ GPIO set interrupt trigger type.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
gpio_num
: GPIO number. If you want to set the trigger type of e.g. of GPIO16, gpio_num should be GPIO_NUM_16 (16);intr_type
: Interrupt type, select from gpio_int_type_t
-
esp_err_t
gpio_intr_enable
(gpio_num_t gpio_num)¶ Enable GPIO module interrupt signal.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
gpio_num
: GPIO number. If you want to enable an interrupt on e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
-
esp_err_t
gpio_intr_disable
(gpio_num_t gpio_num)¶ Disable GPIO module interrupt signal.
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
gpio_num
: GPIO number. If you want to disable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
-
esp_err_t
gpio_set_level
(gpio_num_t gpio_num, uint32_t level)¶ GPIO set output level.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG GPIO number error
- Parameters
gpio_num
: GPIO number. If you want to set the output level of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);level
: Output level. 0: low ; 1: high
-
int
gpio_get_level
(gpio_num_t gpio_num)¶ GPIO get input level.
- Return
- 0 the GPIO input level is 0
- 1 the GPIO input level is 1
- Parameters
gpio_num
: GPIO number. If you want to get the logic level of e.g. pin GPIO16, gpio_num should be GPIO_NUM_16 (16);
-
esp_err_t
gpio_set_direction
(gpio_num_t gpio_num, gpio_mode_t mode)¶ GPIO set direction.
Configure GPIO direction,such as output_only,input_only,output_and_input
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG GPIO error
- Parameters
gpio_num
: Configure GPIO pins number, it should be GPIO number. If you want to set direction of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);mode
: GPIO direction
-
esp_err_t
gpio_set_pull_mode
(gpio_num_t gpio_num, gpio_pull_mode_t pull)¶ Configure GPIO pull-up/pull-down resistors.
Only pins that support both input & output have integrated pull-up and pull-down resistors. Input-only GPIOs 34-39 do not.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG : Parameter error
- Parameters
gpio_num
: GPIO number. If you want to set pull up or down mode for e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);pull
: GPIO pull up/down mode.
-
esp_err_t
gpio_wakeup_enable
(gpio_num_t gpio_num, gpio_int_type_t intr_type)¶ Enable GPIO wake-up function.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
gpio_num
: GPIO number.intr_type
: GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL or GPIO_INTR_HIGH_LEVEL can be used.
-
esp_err_t
gpio_wakeup_disable
(gpio_num_t gpio_num)¶ Disable GPIO wake-up function.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
gpio_num
: GPIO number
-
esp_err_t
gpio_isr_register
(void (*fn)(void *), void *arg, int intr_alloc_flags, gpio_isr_handle_t *handle, )¶ Register GPIO interrupt handler, the handler is an ISR. The handler will be attached to the same CPU core that this function is running on.
This ISR function is called whenever any GPIO interrupt occurs. See the alternative gpio_install_isr_service() and gpio_isr_handler_add() API in order to have the driver support per-GPIO ISRs.
To disable or remove the ISR, pass the returned handle to the interrupt allocation functions.
- Parameters
fn
: Interrupt handler function.intr_alloc_flags
: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.arg
: Parameter for handler functionhandle
: Pointer to return handle. If non-NULL, a handle for the interrupt will be returned here.
- Return
- ESP_OK Success ;
- ESP_ERR_INVALID_ARG GPIO error
-
esp_err_t
gpio_pullup_en
(gpio_num_t gpio_num)¶ Enable pull-up on GPIO.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
gpio_num
: GPIO number
-
esp_err_t
gpio_pullup_dis
(gpio_num_t gpio_num)¶ Disable pull-up on GPIO.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
gpio_num
: GPIO number
-
esp_err_t
gpio_pulldown_en
(gpio_num_t gpio_num)¶ Enable pull-down on GPIO.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
gpio_num
: GPIO number
-
esp_err_t
gpio_pulldown_dis
(gpio_num_t gpio_num)¶ Disable pull-down on GPIO.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
gpio_num
: GPIO number
-
esp_err_t
gpio_install_isr_service
(int intr_alloc_flags)¶ Install the driver’s GPIO ISR handler service, which allows per-pin GPIO interrupt handlers.
This function is incompatible with gpio_isr_register() - if that function is used, a single global ISR is registered for all GPIO interrupts. If this function is used, the ISR service provides a global GPIO ISR and individual pin handlers are registered via the gpio_isr_register() function.
- Return
- ESP_OK Success
- ESP_FAIL Operation fail
- ESP_ERR_NO_MEM No memory to install this service
- Parameters
intr_alloc_flags
: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
-
void
gpio_uninstall_isr_service
()¶ Uninstall the driver’s GPIO ISR service, freeing related resources.
-
esp_err_t
gpio_isr_handler_add
(gpio_num_t gpio_num, gpio_isr_t isr_handler, void *args)¶ Add ISR handler for the corresponding GPIO pin.
Call this function after using gpio_install_isr_service() to install the driver’s GPIO ISR handler service.
The pin ISR handlers no longer need to be declared with IRAM_ATTR, unless you pass the ESP_INTR_FLAG_IRAM flag when allocating the ISR in gpio_install_isr_service().
This ISR handler will be called from an ISR. So there is a stack size limit (configurable as “ISR stack size” in menuconfig). This limit is smaller compared to a global GPIO interrupt handler due to the additional level of indirection.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_STATE Wrong state, the ISR service has not been initialized.
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
gpio_num
: GPIO numberisr_handler
: ISR handler function for the corresponding GPIO number.args
: parameter for ISR handler.
-
esp_err_t
gpio_isr_handler_remove
(gpio_num_t gpio_num)¶ Remove ISR handler for the corresponding GPIO pin.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_STATE Wrong state, the ISR service has not been initialized.
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
gpio_num
: GPIO number
-
static bool
rtc_gpio_is_valid_gpio
(gpio_num_t gpio_num)¶ Determine if the specified GPIO is a valid RTC GPIO.
- Return
- true if GPIO is valid for RTC GPIO use. talse otherwise.
- Parameters
gpio_num
: GPIO number
-
esp_err_t
rtc_gpio_init
(gpio_num_t gpio_num)¶ Init a GPIO as RTC GPIO.
This function must be called when initializing a pad for an analog function.
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG GPIO is not an RTC IO
- Parameters
gpio_num
: GPIO number (e.g. GPIO_NUM_12)
-
esp_err_t
rtc_gpio_deinit
(gpio_num_t gpio_num)¶ Init a GPIO as digital GPIO.
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG GPIO is not an RTC IO
- Parameters
gpio_num
: GPIO number (e.g. GPIO_NUM_12)
-
uint32_t
rtc_gpio_get_level
(gpio_num_t gpio_num)¶ Get the RTC IO input level.
- Return
- 1 High level
- 0 Low level
- ESP_ERR_INVALID_ARG GPIO is not an RTC IO
- Parameters
gpio_num
: GPIO number (e.g. GPIO_NUM_12)
-
esp_err_t
rtc_gpio_set_level
(gpio_num_t gpio_num, uint32_t level)¶ Set the RTC IO output level.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG GPIO is not an RTC IO
- Parameters
gpio_num
: GPIO number (e.g. GPIO_NUM_12)level
: output level
-
esp_err_t
rtc_gpio_set_direction
(gpio_num_t gpio_num, rtc_gpio_mode_t mode)¶ RTC GPIO set direction.
Configure RTC GPIO direction, such as output only, input only, output and input.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG GPIO is not an RTC IO
- Parameters
gpio_num
: GPIO number (e.g. GPIO_NUM_12)mode
: GPIO direction
-
esp_err_t
rtc_gpio_pullup_en
(gpio_num_t gpio_num)¶ RTC GPIO pullup enable.
This function only works for RTC IOs. In general, call gpio_pullup_en, which will work both for normal GPIOs and RTC IOs.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG GPIO is not an RTC IO
- Parameters
gpio_num
: GPIO number (e.g. GPIO_NUM_12)
-
esp_err_t
rtc_gpio_pulldown_en
(gpio_num_t gpio_num)¶ RTC GPIO pulldown enable.
This function only works for RTC IOs. In general, call gpio_pulldown_en, which will work both for normal GPIOs and RTC IOs.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG GPIO is not an RTC IO
- Parameters
gpio_num
: GPIO number (e.g. GPIO_NUM_12)
-
esp_err_t
rtc_gpio_pullup_dis
(gpio_num_t gpio_num)¶ RTC GPIO pullup disable.
This function only works for RTC IOs. In general, call gpio_pullup_dis, which will work both for normal GPIOs and RTC IOs.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG GPIO is not an RTC IO
- Parameters
gpio_num
: GPIO number (e.g. GPIO_NUM_12)
-
esp_err_t
rtc_gpio_pulldown_dis
(gpio_num_t gpio_num)¶ RTC GPIO pulldown disable.
This function only works for RTC IOs. In general, call gpio_pulldown_dis, which will work both for normal GPIOs and RTC IOs.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG GPIO is not an RTC IO
- Parameters
gpio_num
: GPIO number (e.g. GPIO_NUM_12)
警告
doxygenfunction: Cannot find function “rtc_gpio_unhold_all” in doxygen xml output for project “esp32-idf” from directory: xml/
I2C¶
概述¶
ESP32 has two I2C controllers which can be set as master mode or slave mode.
应用程序示例¶
I2C master and slave example: peripherals/i2c.
API 参考手册¶
枚举¶
-
enum
i2c_mode_t
¶ Values:
-
I2C_MODE_SLAVE
= 0¶ I2C slave mode
-
I2C_MODE_MASTER
¶ I2C master mode
-
I2C_MODE_MAX
¶
-
-
enum
i2c_trans_mode_t
¶ Values:
-
I2C_DATA_MODE_MSB_FIRST
= 0¶ I2C data msb first
-
I2C_DATA_MODE_LSB_FIRST
= 1¶ I2C data lsb first
-
I2C_DATA_MODE_MAX
¶
-
结构体¶
-
struct
i2c_config_t
¶ I2C initialization parameters.
Public Members
-
i2c_mode_t
mode
¶ I2C mode
-
gpio_num_t
sda_io_num
¶ GPIO number for I2C sda signal
-
gpio_pullup_t
sda_pullup_en
¶ Internal GPIO pull mode for I2C sda signal
-
gpio_num_t
scl_io_num
¶ GPIO number for I2C scl signal
-
gpio_pullup_t
scl_pullup_en
¶ Internal GPIO pull mode for I2C scl signal
-
uint32_t
clk_speed
¶ I2C clock frequency for master mode, (no higher than 1MHz for now)
-
uint8_t
addr_10bit_en
¶ I2C 10bit address mode enable for slave mode
-
uint16_t
slave_addr
¶ I2C address for slave mode
-
i2c_mode_t
函数¶
-
esp_err_t
i2c_driver_install
(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_buf_len, size_t slv_tx_buf_len, int intr_alloc_flags)¶ I2C driver install.
- Note
- Only slave mode will use this value, driver will ignore this value in master mode.
- Note
- Only slave mode will use this value, driver will ignore this value in master mode.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_FAIL Driver install error
- Parameters
i2c_num
: I2C port numbermode
: I2C mode( master or slave )slv_rx_buf_len
: receiving buffer size for slave mode
- Parameters
slv_tx_buf_len
: sending buffer size for slave mode
- Parameters
intr_alloc_flags
: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
-
esp_err_t
i2c_driver_delete
(i2c_port_t i2c_num)¶ I2C driver delete.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port number
-
esp_err_t
i2c_param_config
(i2c_port_t i2c_num, const i2c_config_t *i2c_conf)¶ I2C parameter initialization.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port numberi2c_conf
: pointer to I2C parameter settings
-
esp_err_t
i2c_reset_tx_fifo
(i2c_port_t i2c_num)¶ reset I2C tx hardware fifo
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port number
-
esp_err_t
i2c_reset_rx_fifo
(i2c_port_t i2c_num)¶ reset I2C rx fifo
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port number
-
esp_err_t
i2c_isr_register
(i2c_port_t i2c_num, void (*fn)(void *), void *arg, int intr_alloc_flags, intr_handle_t *handle, )¶ I2C isr handler register.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port numberfn
: isr handler functionarg
: parameter for isr handler functionintr_alloc_flags
: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.handle
: handle return from esp_intr_alloc.
-
esp_err_t
i2c_isr_free
(intr_handle_t handle)¶ to delete and free I2C isr.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
handle
: handle of isr.
-
esp_err_t
i2c_set_pin
(i2c_port_t i2c_num, gpio_num_t sda_io_num, gpio_num_t scl_io_num, gpio_pullup_t sda_pullup_en, gpio_pullup_t scl_pullup_en, i2c_mode_t mode)¶ Configure GPIO signal for I2C sck and sda.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port numbersda_io_num
: GPIO number for I2C sda signalscl_io_num
: GPIO number for I2C scl signalsda_pullup_en
: Whether to enable the internal pullup for sda pinscl_pullup_en
: Whether to enable the internal pullup for scl pinmode
: I2C mode
-
esp_err_t
i2c_master_start
(i2c_cmd_handle_t cmd_handle)¶ Queue command for I2C master to generate a start signal.
- Note
- Only call this function in I2C master mode Call i2c_master_cmd_begin() to send all queued commands
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
cmd_handle
: I2C cmd link
-
esp_err_t
i2c_master_write_byte
(i2c_cmd_handle_t cmd_handle, uint8_t data, bool ack_en)¶ Queue command for I2C master to write one byte to I2C bus.
- Note
- Only call this function in I2C master mode Call i2c_master_cmd_begin() to send all queued commands
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
cmd_handle
: I2C cmd linkdata
: I2C one byte command to write to busack_en
: enable ack check for master
-
esp_err_t
i2c_master_write
(i2c_cmd_handle_t cmd_handle, uint8_t *data, size_t data_len, bool ack_en)¶ Queue command for I2C master to write buffer to I2C bus.
- Note
- Only call this function in I2C master mode Call i2c_master_cmd_begin() to send all queued commands
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
cmd_handle
: I2C cmd linkdata
: data to senddata_len
: data lengthack_en
: enable ack check for master
-
esp_err_t
i2c_master_read_byte
(i2c_cmd_handle_t cmd_handle, uint8_t *data, int ack)¶ Queue command for I2C master to read one byte from I2C bus.
- Note
- Only call this function in I2C master mode Call i2c_master_cmd_begin() to send all queued commands
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
cmd_handle
: I2C cmd linkdata
: pointer accept the data byteack
: ack value for read command
-
esp_err_t
i2c_master_read
(i2c_cmd_handle_t cmd_handle, uint8_t *data, size_t data_len, int ack)¶ Queue command for I2C master to read data from I2C bus.
- Note
- Only call this function in I2C master mode Call i2c_master_cmd_begin() to send all queued commands
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
cmd_handle
: I2C cmd linkdata
: data buffer to accept the data from busdata_len
: read data lengthack
: ack value for read command
-
esp_err_t
i2c_master_stop
(i2c_cmd_handle_t cmd_handle)¶ Queue command for I2C master to generate a stop signal.
- Note
- Only call this function in I2C master mode Call i2c_master_cmd_begin() to send all queued commands
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
cmd_handle
: I2C cmd link
-
esp_err_t
i2c_master_cmd_begin
(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, portBASE_TYPE ticks_to_wait)¶ I2C master send queued commands. This function will trigger sending all queued commands. The task will be blocked until all the commands have been sent out. The I2C APIs are not thread-safe, if you want to use one I2C port in different tasks, you need to take care of the multi-thread issue.
- Note
- Only call this function in I2C master mode
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_FAIL Sending command error, slave doesn’t ACK the transfer.
- ESP_ERR_INVALID_STATE I2C driver not installed or not in master mode.
- ESP_ERR_TIMEOUT Operation timeout because the bus is busy.
- Parameters
i2c_num
: I2C port numbercmd_handle
: I2C command handlerticks_to_wait
: maximum wait ticks.
-
int
i2c_slave_write_buffer
(i2c_port_t i2c_num, uint8_t *data, int size, portBASE_TYPE ticks_to_wait)¶ I2C slave write data to internal ringbuffer, when tx fifo empty, isr will fill the hardware fifo from the internal ringbuffer.
- Note
- Only call this function in I2C slave mode
- Return
- ESP_FAIL(-1) Parameter error
- Others(>=0) The number of data bytes that pushed to the I2C slave buffer.
- Parameters
i2c_num
: I2C port numberdata
: data pointer to write into internal buffersize
: data sizeticks_to_wait
: Maximum waiting ticks
警告
doxygenfunction: Cannot find function “i2c_slave_read” in doxygen xml output for project “esp32-idf” from directory: xml/
-
esp_err_t
i2c_set_period
(i2c_port_t i2c_num, int high_period, int low_period)¶ set I2C master clock period
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port numberhigh_period
: clock cycle number during SCL is high level, high_period is a 14 bit valuelow_period
: clock cycle number during SCL is low level, low_period is a 14 bit value
-
esp_err_t
i2c_get_period
(i2c_port_t i2c_num, int *high_period, int *low_period)¶ get I2C master clock period
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port numberhigh_period
: pointer to get clock cycle number during SCL is high level, will get a 14 bit valuelow_period
: pointer to get clock cycle number during SCL is low level, will get a 14 bit value
-
esp_err_t
i2c_set_start_timing
(i2c_port_t i2c_num, int setup_time, int hold_time)¶ set I2C master start signal timing
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port numbersetup_time
: clock number between the falling-edge of SDA and rising-edge of SCL for start mark, it’s a 10-bit value.hold_time
: clock num between the falling-edge of SDA and falling-edge of SCL for start mark, it’s a 10-bit value.
-
esp_err_t
i2c_get_start_timing
(i2c_port_t i2c_num, int *setup_time, int *hold_time)¶ get I2C master start signal timing
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port numbersetup_time
: pointer to get setup timehold_time
: pointer to get hold time
-
esp_err_t
i2c_set_stop_timing
(i2c_port_t i2c_num, int setup_time, int hold_time)¶ set I2C master stop signal timing
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port numbersetup_time
: clock num between the rising-edge of SCL and the rising-edge of SDA, it’s a 10-bit value.hold_time
: clock number after the STOP bit’s rising-edge, it’s a 14-bit value.
-
esp_err_t
i2c_get_stop_timing
(i2c_port_t i2c_num, int *setup_time, int *hold_time)¶ get I2C master stop signal timing
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port numbersetup_time
: pointer to get setup time.hold_time
: pointer to get hold time.
-
esp_err_t
i2c_set_data_timing
(i2c_port_t i2c_num, int sample_time, int hold_time)¶ set I2C data signal timing
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port numbersample_time
: clock number I2C used to sample data on SDA after the rising-edge of SCL, it’s a 10-bit valuehold_time
: clock number I2C used to hold the data after the falling-edge of SCL, it’s a 10-bit value
-
esp_err_t
i2c_get_data_timing
(i2c_port_t i2c_num, int *sample_time, int *hold_time)¶ get I2C data signal timing
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port numbersample_time
: pointer to get sample timehold_time
: pointer to get hold time
-
esp_err_t
i2c_set_data_mode
(i2c_port_t i2c_num, i2c_trans_mode_t tx_trans_mode, i2c_trans_mode_t rx_trans_mode)¶ set I2C data transfer mode
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port numbertx_trans_mode
: I2C sending data moderx_trans_mode
: I2C receving data mode
-
esp_err_t
i2c_get_data_mode
(i2c_port_t i2c_num, i2c_trans_mode_t *tx_trans_mode, i2c_trans_mode_t *rx_trans_mode)¶ get I2C data transfer mode
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
i2c_num
: I2C port numbertx_trans_mode
: pointer to get I2C sending data moderx_trans_mode
: pointer to get I2C receiving data mode
-
i2c_cmd_handle_t
i2c_cmd_link_create
()¶ Create and init I2C command link.
- Note
- Before we build I2C command link, we need to call i2c_cmd_link_create() to create a command link. After we finish sending the commands, we need to call i2c_cmd_link_delete() to release and return the resources.
- Return
- i2c command link handler
-
void
i2c_cmd_link_delete
(i2c_cmd_handle_t cmd_handle)¶ Free I2C command link.
- Note
- Before we build I2C command link, we need to call i2c_cmd_link_create() to create a command link. After we finish sending the commands, we need to call i2c_cmd_link_delete() to release and return the resources.
- Parameters
cmd_handle
: I2C command handle
I2S¶
概述¶
ESP32 contains two I2S peripherals. These peripherals can be configured to input and output sample data via the I2S driver.
The I2S peripheral supports DMA meaning it can stream sample data without requiring each sample to be read or written by the CPU.
I2S output can also be routed directly to the Digital/Analog Converter output channels (GPIO 25 & GPIO 26) to produce analog output directly, rather than via an external I2S codec.
应用程序示例¶
A full I2S example is available in esp-idf: peripherals/i2s.
Short example of I2S configuration:
#include "driver/i2s.h"
#include "freertos/queue.h"
static const int i2s_num = 0; // i2s port number
static const i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
.sample_rate = 44100,
.bits_per_sample = 16,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // high interrupt priority
.dma_buf_count = 8,
.dma_buf_len = 64
};
static const i2s_pin_config_t pin_config = {
.bck_io_num = 26,
.ws_io_num = 25,
.data_out_num = 22,
.data_in_num = I2S_PIN_NO_CHANGE
};
...
i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver
i2s_set_pin(i2s_num, &pin_config);
i2s_set_sample_rates(i2s_num, 22050); //set sample rates
i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
Short example configuring I2S to use internal DAC for analog output:
#include "driver/i2s.h"
#include "freertos/queue.h"
static const int i2s_num = 0; // i2s port number
static const i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
.sample_rate = 44100,
.bits_per_sample = 8, /* must be 8 for built-in DAC */
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // high interrupt priority
.dma_buf_count = 8,
.dma_buf_len = 64
};
...
i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver
i2s_set_pin(i2s_num, NULL); //for internal DAC
i2s_set_sample_rates(i2s_num, 22050); //set sample rates
i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
API 参考手册¶
头文件¶
- components/driver/include/driver/i2s.h
Data 结构体¶
- struct
i2s_config_t
¶I2S configuration parameters for i2s_param_config function.
Public Members
- i2s_mode_t
mode
¶I2S work mode
- int
sample_rate
¶I2S sample rate
- i2s_bits_per_sample_t
bits_per_sample
¶I2S bits per sample
- i2s_channel_fmt_t
channel_format
¶I2S channel format
- i2s_comm_format_t
communication_format
¶I2S communication format
- int
intr_alloc_flags
¶Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info
- int
dma_buf_count
¶I2S DMA Buffer Count
- int
dma_buf_len
¶I2S DMA Buffer Length
- struct
i2s_event_t
¶Event structure used in I2S event queue.
- struct
i2s_pin_config_t
¶I2S pin number for i2s_set_pin.
宏¶
I2S_PIN_NO_CHANGE
¶Use in i2s_pin_config_t for pins which should not be changed
枚举¶
- enum
i2s_bits_per_sample_t
¶I2S bit width per sample.
Values:
I2S_BITS_PER_SAMPLE_8BIT
= 8¶I2S bits per sample: 8-bits
I2S_BITS_PER_SAMPLE_16BIT
= 16¶I2S bits per sample: 16-bits
I2S_BITS_PER_SAMPLE_24BIT
= 24¶I2S bits per sample: 24-bits
I2S_BITS_PER_SAMPLE_32BIT
= 32¶I2S bits per sample: 32-bits
- enum
i2s_comm_format_t
¶I2S communication standard format.
Values:
I2S_COMM_FORMAT_I2S
= 0x01¶I2S communication format I2S
I2S_COMM_FORMAT_I2S_MSB
= 0x02¶I2S format MSB
I2S_COMM_FORMAT_I2S_LSB
= 0x04¶I2S format LSB
I2S_COMM_FORMAT_PCM
= 0x08¶I2S communication format PCM
I2S_COMM_FORMAT_PCM_SHORT
= 0x10¶PCM Short
I2S_COMM_FORMAT_PCM_LONG
= 0x20¶PCM Long
- enum
i2s_channel_fmt_t
¶I2S channel format type.
Values:
I2S_CHANNEL_FMT_RIGHT_LEFT
= 0x00¶
I2S_CHANNEL_FMT_ALL_RIGHT
¶
I2S_CHANNEL_FMT_ALL_LEFT
¶
I2S_CHANNEL_FMT_ONLY_RIGHT
¶
I2S_CHANNEL_FMT_ONLY_LEFT
¶
- enum
pdm_sample_rate_ratio_t
¶PDM sample rate ratio, measured in Hz.
Values:
PDM_SAMPLE_RATE_RATIO_64
¶
PDM_SAMPLE_RATE_RATIO_128
¶
- enum
pdm_pcm_conv_t
¶PDM PCM convter enable/disable.
Values:
PDM_PCM_CONV_ENABLE
¶
PDM_PCM_CONV_DISABLE
¶
- enum
i2s_port_t
¶I2S Peripheral, 0 & 1.
Values:
I2S_NUM_0
= 0x0¶I2S 0
I2S_NUM_1
= 0x1¶I2S 1
I2S_NUM_MAX
¶
函数¶
- esp_err_t
i2s_set_pin
(i2s_port_t i2s_num, const i2s_pin_config_t *pin)¶Set I2S pin number.
Inside the pin configuration structure, set I2S_PIN_NO_CHANGE for any pin where the current configuration should not be changed.
- Note
- The I2S peripheral output signals can be connected to multiple GPIO pads. However, the I2S peripheral input signal can only be connected to one GPIO pad.
- Parameters
i2s_num
: I2S_NUM_0 or I2S_NUM_1pin
: I2S Pin structure, or NULL to set 2-channel 8-bit internal DAC pin configuration (GPIO25 & GPIO26)
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- esp_err_t
i2s_driver_install
(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue)¶Install and start I2S driver.
This function must be called before any I2S driver read/write operations.
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1i2s_config
: I2S configurations - see i2s_config_t structqueue_size
: I2S event queue size/depth.i2s_queue
: I2S event queue handle, if set NULL, driver will not use an event queue.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- esp_err_t
i2s_driver_uninstall
(i2s_port_t i2s_num)¶Uninstall I2S driver.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1
- int
i2s_write_bytes
(i2s_port_t i2s_num, const char *src, size_t size, TickType_t ticks_to_wait)¶Write data to I2S DMA transmit buffer.
Format of the data in source buffer is determined by the I2S configuration (see i2s_config_t).
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1src
: Source address to write fromsize
: Size of data in bytesticks_to_wait
: TX buffer wait timeout in RTOS ticks. If this many ticks pass without space becoming available in the DMA transmit buffer, then the function will return (note that if the data is written to the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout.
- Return
- Number of bytes written, or ESP_FAIL (-1) for parameter error. If a timeout occurred, bytes written will be less than total size.
- int
i2s_read_bytes
(i2s_port_t i2s_num, char *dest, size_t size, TickType_t ticks_to_wait)¶Read data from I2S DMA receive buffer.
Format of the data in source buffer is determined by the I2S configuration (see i2s_config_t).
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1dest
: Destination address to read intosize
: Size of data in bytesticks_to_wait
: RX buffer wait timeout in RTOS ticks. If this many ticks pass without bytes becoming available in the DMA receive buffer, then the function will return (note that if data is read from the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout.
- Return
- Number of bytes read, or ESP_FAIL (-1) for parameter error. If a timeout occurred, bytes read will be less than total size.
- int
i2s_push_sample
(i2s_port_t i2s_num, const char *sample, TickType_t ticks_to_wait)¶Push (write) a single sample to the I2S DMA TX buffer.
Size of the sample is determined by the channel_format (mono or stereo)) & bits_per_sample configuration (see i2s_config_t).
- Return
- Number of bytes successfully pushed to DMA buffer, or ESP_FAIL (-1) for parameter error. Will be either zero or the size of configured sample buffer.
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1sample
: Pointer to buffer containing sample to write. Size of buffer (in bytes) = (number of channels) * bits_per_sample / 8.ticks_to_wait
: Push timeout in RTOS ticks. If space is not available in the DMA TX buffer within this period, no data is written and function returns 0.
- int
i2s_pop_sample
(i2s_port_t i2s_num, char *sample, TickType_t ticks_to_wait)¶Pop (read) a single sample from the I2S DMA RX buffer.
Size of the sample is determined by the channel_format (mono or stereo)) & bits_per_sample configuration (see i2s_config_t).
- Return
- Number of bytes successfully read from DMA buffer, or ESP_FAIL (-1) for parameter error. Byte count will be either zero or the size of the configured sample buffer.
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1sample
: Buffer sample data will be read into. Size of buffer (in bytes) = (number of channels) * bits_per_sample / 8.ticks_to_wait
: Pop timeout in RTOS ticks. If a sample is not available in the DMA buffer within this period, no data is read and function returns zero.
- esp_err_t
i2s_set_sample_rates
(i2s_port_t i2s_num, uint32_t rate)¶Set sample rate used for I2S RX and TX.
The bit clock rate is determined by the sample rate and i2s_config_t configuration parameters (number of channels, bits_per_sample).
bit_clock = rate * (number of channels) * bits_per_sample
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1rate
: I2S sample rate (ex: 8000, 44100…)
- esp_err_t
i2s_start
(i2s_port_t i2s_num)¶Start I2S driver.
It is not necessary to call this function after i2s_driver_install() (it is started automatically), however it is necessary to call it after i2s_stop().
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1
- esp_err_t
i2s_stop
(i2s_port_t i2s_num)¶Stop I2S driver.
Disables I2S TX/RX, until i2s_start() is called.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1
- esp_err_t
i2s_zero_dma_buffer
(i2s_port_t i2s_num)¶Zero the contents of the TX DMA buffer.
Pushes zero-byte samples into the TX DMA buffer, until it is full.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
i2s_num
: I2S_NUM_0, I2S_NUM_1
LED Control¶
概述¶
The LED control module is primarily designed to control the intensity of LEDs, although it can be used to generate PWM signals for other purposes as well. It has 16 channels which can generate independent waveforms that can be used to drive e.g. RGB LED devices. For maximum flexibility, the high-speed as well as the low-speed channels can be driven from one of four high-speed/low-speed timers. The PWM controller also has the ability to automatically increase or decrease the duty cycle gradually, allowing for fades without any processor interference.
应用程序示例¶
LEDC change duty cycle and fading control example: peripherals/ledc.
API 参考手册¶
枚举¶
-
enum
ledc_mode_t
¶ Values:
-
LEDC_HIGH_SPEED_MODE
= 0¶ LEDC high speed speed_mode
-
LEDC_LOW_SPEED_MODE
¶ LEDC low speed speed_mode
-
LEDC_SPEED_MODE_MAX
¶ LEDC speed limit
-
-
enum
ledc_intr_type_t
¶ Values:
-
LEDC_INTR_DISABLE
= 0¶ Disable LEDC interrupt
-
LEDC_INTR_FADE_END
¶ Enable LEDC interrupt
-
-
enum
ledc_duty_direction_t
¶ Values:
-
LEDC_DUTY_DIR_DECREASE
= 0¶ LEDC duty decrease direction
-
LEDC_DUTY_DIR_INCREASE
= 1¶ LEDC duty increase direction
-
-
enum
ledc_clk_src_t
¶ Values:
-
LEDC_REF_TICK
= 0¶ LEDC timer clock divided from reference tick(1Mhz)
-
LEDC_APB_CLK
¶ LEDC timer clock divided from APB clock(80Mhz)
-
-
enum
ledc_timer_t
¶ Values:
-
LEDC_TIMER_0
= 0¶ LEDC source timer TIMER0
-
LEDC_TIMER_1
¶ LEDC source timer TIMER1
-
LEDC_TIMER_2
¶ LEDC source timer TIMER2
-
LEDC_TIMER_3
¶ LEDC source timer TIMER3
-
-
enum
ledc_channel_t
¶ Values:
-
LEDC_CHANNEL_0
= 0¶ LEDC channel 0
-
LEDC_CHANNEL_1
¶ LEDC channel 1
-
LEDC_CHANNEL_2
¶ LEDC channel 2
-
LEDC_CHANNEL_3
¶ LEDC channel 3
-
LEDC_CHANNEL_4
¶ LEDC channel 4
-
LEDC_CHANNEL_5
¶ LEDC channel 5
-
LEDC_CHANNEL_6
¶ LEDC channel 6
-
LEDC_CHANNEL_7
¶ LEDC channel 7
-
LEDC_CHANNEL_MAX
¶
-
-
enum
ledc_timer_bit_t
¶ Values:
-
LEDC_TIMER_10_BIT
= 10¶ LEDC PWM depth 10Bit
-
LEDC_TIMER_11_BIT
= 11¶ LEDC PWM depth 11Bit
-
LEDC_TIMER_12_BIT
= 12¶ LEDC PWM depth 12Bit
-
LEDC_TIMER_13_BIT
= 13¶ LEDC PWM depth 13Bit
-
LEDC_TIMER_14_BIT
= 14¶ LEDC PWM depth 14Bit
-
LEDC_TIMER_15_BIT
= 15¶ LEDC PWM depth 15Bit
-
结构体¶
-
struct
ledc_channel_config_t
¶ Configuration parameters of LEDC channel for ledc_channel_config function.
Public Members
-
int
gpio_num
¶ the LEDC output gpio_num, if you want to use gpio16, gpio_num = 16
-
ledc_mode_t
speed_mode
¶ LEDC speed speed_mode, high-speed mode or low-speed mode
-
ledc_channel_t
channel
¶ LEDC channel(0 - 7)
-
ledc_intr_type_t
intr_type
¶ configure interrupt, Fade interrupt enable or Fade interrupt disable
-
ledc_timer_t
timer_sel
¶ Select the timer source of channel (0 - 3)
-
uint32_t
duty
¶ LEDC channel duty, the duty range is [0, (2**bit_num) - 1],
-
int
-
struct
ledc_timer_config_t
¶ Configuration parameters of LEDC Timer timer for ledc_timer_config function.
Public Members
-
ledc_mode_t
speed_mode
¶ LEDC speed speed_mode, high-speed mode or low-speed mode
-
ledc_timer_bit_t
bit_num
¶ LEDC channel duty depth
-
ledc_timer_t
timer_num
¶ The timer source of channel (0 - 3)
-
uint32_t
freq_hz
¶ LEDC timer frequency(Hz)
-
ledc_mode_t
函数¶
-
esp_err_t
ledc_channel_config
(const ledc_channel_config_t *ledc_conf)¶ LEDC channel configuration Configure LEDC channel with the given channel/output gpio_num/interrupt/source timer/frequency(Hz)/LEDC depth.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
ledc_conf
: Pointer of LEDC channel configure struct
-
esp_err_t
ledc_timer_config
(const ledc_timer_config_t *timer_conf)¶ LEDC timer configuration Configure LEDC timer with the given source timer/frequency(Hz)/bit_num.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_FAIL Can not find a proper pre-divider number base on the given frequency and the current bit_num.
- Parameters
timer_conf
: Pointer of LEDC timer configure struct
-
esp_err_t
ledc_update_duty
(ledc_mode_t speed_mode, ledc_channel_t channel)¶ LEDC update channel parameters Call this function to activate the LEDC updated parameters. After ledc_set_duty, ledc_set_fade, we need to call this function to update the settings.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed mode,channel
: LEDC channel(0-7), select from ledc_channel_t
-
esp_err_t
ledc_stop
(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_level)¶ LEDC stop. Disable LEDC output, and set idle level.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modechannel
: LEDC channel(0-7), select from ledc_channel_tidle_level
: Set output idle level after LEDC stops.
-
esp_err_t
ledc_set_freq
(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t freq_hz)¶ LEDC set channel frequency(Hz)
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_FAIL Can not find a proper pre-divider number base on the given frequency and the current bit_num.
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modetimer_num
: LEDC timer index(0-3), select from ledc_timer_tfreq_hz
: Set the LEDC frequency
-
uint32_t
ledc_get_freq
(ledc_mode_t speed_mode, ledc_timer_t timer_num)¶ LEDC get channel frequency(Hz)
- Return
- 0 error
- Others Current LEDC frequency
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modetimer_num
: LEDC timer index(0-3), select from ledc_timer_t
-
esp_err_t
ledc_set_duty
(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty)¶ LEDC set duty Only after calling ledc_update_duty will the duty update.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modechannel
: LEDC channel(0-7), select from ledc_channel_tduty
: Set the LEDC duty, the duty range is [0, (2**bit_num) - 1]
-
int
ledc_get_duty
(ledc_mode_t speed_mode, ledc_channel_t channel)¶ LEDC get duty.
- Return
- (-1) parameter error
- Others Current LEDC duty
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modechannel
: LEDC channel(0-7), select from ledc_channel_t
-
esp_err_t
ledc_set_fade
(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, ledc_duty_direction_t gradule_direction, uint32_t step_num, uint32_t duty_cyle_num, uint32_t duty_scale)¶ LEDC set gradient Set LEDC gradient, After the function calls the ledc_update_duty function, the function can take effect.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modechannel
: LEDC channel(0-7), select from ledc_channel_tduty
: Set the start of the gradient duty, the duty range is [0, (2**bit_num) - 1]gradule_direction
: Set the direction of the gradientstep_num
: Set the number of the gradientduty_cyle_num
: Set how many LEDC tick each time the gradient lastsduty_scale
: Set gradient change amplitude
-
esp_err_t
ledc_isr_register
(void (*fn)(void *), void *arg, int intr_alloc_flags, ledc_isr_handle_t *handle, )¶ Register LEDC interrupt handler, the handler is an ISR. The handler will be attached to the same CPU core that this function is running on.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Function pointer error.
- Parameters
fn
: Interrupt handler function.arg
: User-supplied argument passed to the handler function.intr_alloc_flags
: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.arg
: Parameter for handler functionhandle
: Pointer to return handle. If non-NULL, a handle for the interrupt will be returned here.
-
esp_err_t
ledc_timer_set
(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t div_num, uint32_t bit_num, ledc_clk_src_t clk_src)¶ Configure LEDC settings.
- Return
- (-1) Parameter error
- Other Current LEDC duty
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modetimer_sel
: Timer index(0-3), there are 4 timers in LEDC modulediv_num
: Timer clock divide number, the timer clock is divided from the selected clock sourcebit_num
: The count number of one period, counter range is 0 ~ ((2 ** bit_num) - 1)clk_src
: Select LEDC source clock.
-
esp_err_t
ledc_timer_rst
(ledc_mode_t speed_mode, uint32_t timer_sel)¶ Reset LEDC timer.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modetimer_sel
: LEDC timer index(0-3), select from ledc_timer_t
-
esp_err_t
ledc_timer_pause
(ledc_mode_t speed_mode, uint32_t timer_sel)¶ Pause LEDC timer counter.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modetimer_sel
: LEDC timer index(0-3), select from ledc_timer_t
-
esp_err_t
ledc_timer_resume
(ledc_mode_t speed_mode, uint32_t timer_sel)¶ Resume LEDC timer.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modetimer_sel
: LEDC timer index(0-3), select from ledc_timer_t
-
esp_err_t
ledc_bind_channel_timer
(ledc_mode_t speed_mode, uint32_t channel, uint32_t timer_idx)¶ Bind LEDC channel with the selected timer.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modechannel
: LEDC channel index(0-7), select from ledc_channel_ttimer_idx
: LEDC timer index(0-3), select from ledc_timer_t
-
esp_err_t
ledc_set_fade_with_step
(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int scale, int cycle_num)¶ Set LEDC fade function. Should call ledc_fade_func_install() before calling this function. Call ledc_fade_start() after this to start fading.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- ESP_ERR_INVALID_STATE Fade function not installed.
- ESP_FAIL Fade function init error
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed mode,channel
: LEDC channel index(0-7), select from ledc_channel_ttarget_duty
: Target duty of fading.( 0 - (2 ** bit_num - 1)))scale
: Controls the increase or decrease step scale.cycle_num
: increase or decrease the duty every cycle_num cycles
-
esp_err_t
ledc_set_fade_with_time
(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int max_fade_time_ms)¶ Set LEDC fade function, with a limited time. Should call ledc_fade_func_install() before calling this function. Call ledc_fade_start() after this to start fading.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- ESP_ERR_INVALID_STATE Fade function not installed.
- ESP_FAIL Fade function init error
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed mode,channel
: LEDC channel index(0-7), select from ledc_channel_ttarget_duty
: Target duty of fading.( 0 - (2 ** bit_num - 1)))max_fade_time_ms
: The maximum time of the fading ( ms ).
-
esp_err_t
ledc_fade_func_install
(int intr_alloc_flags)¶ Install ledc fade function. This function will occupy interrupt of LEDC module.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_STATE Fade function already installed.
- Parameters
intr_alloc_flags
: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
-
void
ledc_fade_func_uninstall
()¶ Uninstall LEDC fade function.
-
esp_err_t
ledc_fade_start
(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t wait_done)¶ Start LEDC fading.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_STATE Fade function not installed.
- ESP_ERR_INVALID_ARG Parameter error.
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modechannel
: LEDC channel numberwait_done
: Whether to block until fading done.
Pulse Counter¶
概述¶
The PCNT (Pulse Counter) module is designed to count the number of rising and/or falling edges of an input signal. Each pulse counter unit has a 16-bit signed counter register and two channels that can be configured to either increment or decrement the counter. Each channel has a signal input that accepts signal edges to be detected, as well as a control input that can be used to enable or disable the signal input. The inputs have optional filters that can be used to discard unwanted glitches in the signal.
应用程序示例¶
Pulse counter with control signal and event interrupt example: peripherals/pcnt.
API 参考手册¶
宏¶
类型定义¶
枚举¶
-
enum
pcnt_ctrl_mode_t
¶ Values:
-
PCNT_MODE_KEEP
= 0¶ Control mode: won’t change counter mode
-
PCNT_MODE_REVERSE
= 1¶ Control mode: invert counter mode(increase -> decrease, decrease -> increase);
-
PCNT_MODE_DISABLE
= 2¶ Control mode: Inhibit counter(counter value will not change in this condition)
-
PCNT_MODE_MAX
¶
-
-
enum
pcnt_count_mode_t
¶ Values:
-
PCNT_COUNT_DIS
= 0¶ Counter mode: Inhibit counter(counter value will not change in this condition)
-
PCNT_COUNT_INC
= 1¶ Counter mode: Increase counter value
-
PCNT_COUNT_DEC
= 2¶ Counter mode: Decrease counter value
-
PCNT_COUNT_MAX
¶
-
-
enum
pcnt_unit_t
¶ Values:
-
PCNT_UNIT_0
= 0¶ PCNT unit0
-
PCNT_UNIT_1
= 1¶ PCNT unit1
-
PCNT_UNIT_2
= 2¶ PCNT unit2
-
PCNT_UNIT_3
= 3¶ PCNT unit3
-
PCNT_UNIT_4
= 4¶ PCNT unit4
-
PCNT_UNIT_5
= 5¶ PCNT unit5
-
PCNT_UNIT_6
= 6¶ PCNT unit6
-
PCNT_UNIT_7
= 7¶ PCNT unit7
-
PCNT_UNIT_MAX
¶
-
-
enum
pcnt_channel_t
¶ Values:
-
PCNT_CHANNEL_0
= 0x00¶ PCNT channel0
-
PCNT_CHANNEL_1
= 0x01¶ PCNT channel1
-
PCNT_CHANNEL_MAX
¶
-
-
enum
pcnt_evt_type_t
¶ Values:
-
PCNT_EVT_L_LIM
= 0¶ PCNT watch point event: Minimum counter value
-
PCNT_EVT_H_LIM
= 1¶ PCNT watch point event: Maximum counter value
-
PCNT_EVT_THRES_0
= 2¶ PCNT watch point event: threshold0 value event
-
PCNT_EVT_THRES_1
= 3¶ PCNT watch point event: threshold1 value event
-
PCNT_EVT_ZERO
= 4¶ PCNT watch point event: counter value zero event
-
PCNT_EVT_MAX
¶
-
函数¶
-
esp_err_t
pcnt_unit_config
(const pcnt_config_t *pcnt_config)¶ Configure Pulse Counter unit.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
pcnt_config
: Pointer of Pulse Counter unit configure parameter
-
esp_err_t
pcnt_get_counter_value
(pcnt_unit_t pcnt_unit, int16_t *count)¶ Get pulse counter value.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
pcnt_unit
: Pulse Counter unit numbercount
: Pointer to accept counter value
-
esp_err_t
pcnt_counter_pause
(pcnt_unit_t pcnt_unit)¶ Pause PCNT counter of PCNT unit.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
pcnt_unit
: PCNT unit number
-
esp_err_t
pcnt_counter_resume
(pcnt_unit_t pcnt_unit)¶ Resume counting for PCNT counter.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
pcnt_unit
: PCNT unit number, select from pcnt_unit_t
-
esp_err_t
pcnt_counter_clear
(pcnt_unit_t pcnt_unit)¶ Clear and reset PCNT counter value to zero.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
pcnt_unit
: PCNT unit number, select from pcnt_unit_t
-
esp_err_t
pcnt_intr_enable
(pcnt_unit_t pcnt_unit)¶ Enable PCNT interrupt for PCNT unit.
- Note
- Each Pulse counter unit has five watch point events that share the same interrupt. Configure events with pcnt_event_enable() and pcnt_event_disable()
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
pcnt_unit
: PCNT unit number
-
esp_err_t
pcnt_intr_disable
(pcnt_unit_t pcnt_unit)¶ Disable PCNT interrupt for PCNT uint.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
pcnt_unit
: PCNT unit number
-
esp_err_t
pcnt_event_enable
(pcnt_unit_t unit, pcnt_evt_type_t evt_type)¶ Enable PCNT event of PCNT unit.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
unit
: PCNT unit numberevt_type
: Watch point event type. All enabled events share the same interrupt (one interrupt per pulse counter unit).
-
esp_err_t
pcnt_event_disable
(pcnt_unit_t unit, pcnt_evt_type_t evt_type)¶ Disable PCNT event of PCNT unit.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
unit
: PCNT unit numberevt_type
: Watch point event type. All enabled events share the same interrupt (one interrupt per pulse counter unit).
-
esp_err_t
pcnt_set_event_value
(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value)¶ Set PCNT event value of PCNT unit.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
unit
: PCNT unit numberevt_type
: Watch point event type. All enabled events share the same interrupt (one interrupt per pulse counter unit).value
: Counter value for PCNT event
-
esp_err_t
pcnt_get_event_value
(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value)¶ Get PCNT event value of PCNT unit.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
unit
: PCNT unit numberevt_type
: Watch point event type. All enabled events share the same interrupt (one interrupt per pulse counter unit).value
: Pointer to accept counter value for PCNT event
-
esp_err_t
pcnt_isr_register
(void (*fn)(void *), void *arg, int intr_alloc_flags, pcnt_isr_handle_t *handle, )¶ Register PCNT interrupt handler, the handler is an ISR. The handler will be attached to the same CPU core that this function is running on.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Function pointer error.
- Parameters
fn
: Interrupt handler function.arg
: Parameter for handler functionintr_alloc_flags
: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.handle
: Pointer to return handle. If non-NULL, a handle for the interrupt will be returned here.
-
esp_err_t
pcnt_set_pin
(pcnt_unit_t unit, pcnt_channel_t channel, int pulse_io, int ctrl_io)¶ Configure PCNT pulse signal input pin and control input pin.
- Note
- Set to PCNT_PIN_NOT_USED if unused.
- Note
- Set to PCNT_PIN_NOT_USED if unused.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
unit
: PCNT unit numberchannel
: PCNT channel numberpulse_io
: Pulse signal input GPIO
- Parameters
ctrl_io
: Control signal input GPIO
-
esp_err_t
pcnt_filter_enable
(pcnt_unit_t unit)¶ Enable PCNT input filter.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
unit
: PCNT unit number
-
esp_err_t
pcnt_filter_disable
(pcnt_unit_t unit)¶ Disable PCNT input filter.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
unit
: PCNT unit number
-
esp_err_t
pcnt_set_filter_value
(pcnt_unit_t unit, uint16_t filter_val)¶ Set PCNT filter value.
- Note
- filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
unit
: PCNT unit numberfilter_val
: PCNT signal filter value, counter in APB_CLK cycles. Any pulses lasting shorter than this will be ignored when the filter is enabled.
-
esp_err_t
pcnt_get_filter_value
(pcnt_unit_t unit, uint16_t *filter_val)¶ Get PCNT filter value.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
unit
: PCNT unit numberfilter_val
: Pointer to accept PCNT filter value.
-
esp_err_t
pcnt_set_mode
(pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode)¶ Set PCNT counter mode.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
unit
: PCNT unit numberchannel
: PCNT channel numberpos_mode
: Counter mode when detecting positive edgeneg_mode
: Counter mode when detecting negative edgehctrl_mode
: Counter mode when control signal is high levellctrl_mode
: Counter mode when control signal is low level
SDMMC Host Peripheral¶
概述¶
SDMMC peripheral supports SD and MMC memory cards and SDIO cards. SDMMC software builds on top of SDMMC driver and consists of the following parts:
- SDMMC host driver (
driver/sdmmc_host.h
) — this driver provides APIs to send commands to the slave device(s), send and receive data, and handling error conditions on the bus. - SDMMC protocol layer (
sdmmc_cmd.h
) — this component handles specifics of SD protocol such as card initialization and data transfer commands. Despite the name, only SD (SDSC/SDHC/SDXC) cards are supported at the moment. Support for MCC/eMMC cards can be added in the future.
Protocol layer works with the host via sdmmc_host_t
structure. This structure contains pointers to various functions of the host. This design makes it possible to implement an SD host using SPI interface later.
应用程序示例¶
An example which combines SDMMC driver with FATFS library is provided in examples/storage/sd_card
directory. This example initializes the card, writes and reads data from it using POSIX and C library APIs. See README.md file in the example directory for more information.
Protocol layer APIs¶
Protocol layer is given sdmmc_host_t
structure which describes the SD/MMC host driver, lists its capabilites, and provides pointers to functions of the driver. Protocol layer stores card-specific information in sdmmc_card_t
structure. When sending commands to the SD/MMC host driver, protocol layer uses sdmmc_command_t
structure to describe the command, argument, expected return value, and data to transfer, if any.
Normal usage of the protocol layer is as follows:
- Call the host driver functions to initialize the host (e.g.
sdmmc_host_init
,sdmmc_host_init_slot
). - Call
sdmmc_card_init
to initialize the card, passing it host driver information (host
) and a pointer tosdmmc_card_t
structure which will be filled in (card
). - To read and write sectors of the card, use
sdmmc_read_sectors
andsdmmc_write_sectors
, passing the pointer to card information structure (card
). - When card is not used anymore, call the host driver function to disable SDMMC host peripheral and free resources allocated by the driver (e.g.
sdmmc_host_deinit
).
Most applications need to use the protocol layer only in one task; therefore the protocol layer doesn’t implement any kind of locking on the sdmmc_card_t
structure, or when accessing SDMMC host driver. Such locking has to be implemented in the higher layer, if necessary (e.g. in the filesystem driver).
-
struct
sdmmc_host_t
¶ SD/MMC Host description
This structure defines properties of SD/MMC host and functions of SD/MMC host which can be used by upper layers.
Public Members
-
uint32_t
flags
¶ flags defining host properties
-
int
slot
¶ slot number, to be passed to host functions
-
int
max_freq_khz
¶ max frequency supported by the host
-
float
io_voltage
¶ I/O voltage used by the controller (voltage switching is not supported)
-
esp_err_t (*
init
)(void)¶ Host function to initialize the driver
-
esp_err_t (*
set_bus_width
)(int slot, size_t width)¶ host function to set bus width
-
esp_err_t (*
set_card_clk
)(int slot, uint32_t freq_khz)¶ host function to set card clock frequency
-
esp_err_t (*
do_transaction
)(int slot, sdmmc_command_t *cmdinfo)¶ host function to do a transaction
-
esp_err_t (*
deinit
)(void)¶ host function to deinitialize the driver
-
uint32_t
-
SDMMC_HOST_FLAG_1BIT
¶ host supports 1-line SD and MMC protocol
-
SDMMC_HOST_FLAG_4BIT
¶ host supports 4-line SD and MMC protocol
-
SDMMC_HOST_FLAG_8BIT
¶ host supports 8-line MMC protocol
-
SDMMC_HOST_FLAG_SPI
¶ host supports SPI protocol
-
SDMMC_FREQ_DEFAULT
¶ SD/MMC Default speed (limited by clock divider)
-
SDMMC_FREQ_HIGHSPEED
¶ SD High speed (limited by clock divider)
-
SDMMC_FREQ_PROBING
¶ SD/MMC probing speed
-
struct
sdmmc_command_t
¶ SD/MMC command information
Public Members
-
uint32_t
opcode
¶ SD or MMC command index
-
uint32_t
arg
¶ SD/MMC command argument
-
sdmmc_response_t
response
¶ response buffer
-
void *
data
¶ buffer to send or read into
-
size_t
datalen
¶ length of data buffer
-
size_t
blklen
¶ block length
-
int
flags
¶ see below
-
esp_err_t
error
¶ error returned from transfer
-
uint32_t
-
struct
sdmmc_card_t
¶ SD/MMC card information structure
Public Members
-
sdmmc_host_t
host
¶ Host with which the card is associated
-
uint32_t
ocr
¶ OCR (Operation Conditions Register) value
-
sdmmc_cid_t
cid
¶ decoded CID (Card IDentification) register value
-
sdmmc_csd_t
csd
¶ decoded CSD (Card-Specific Data) register value
-
sdmmc_scr_t
scr
¶ decoded SCR (SD card Configuration Register) value
-
uint16_t
rca
¶ RCA (Relative Card Address)
-
sdmmc_host_t
-
struct
sdmmc_csd_t
¶ Decoded values from SD card Card Specific Data register
-
struct
sdmmc_cid_t
¶ Decoded values from SD card Card IDentification register
-
struct
sdmmc_scr_t
¶ Decoded values from SD Configuration Register
-
esp_err_t
sdmmc_card_init
(const sdmmc_host_t *host, sdmmc_card_t *out_card)¶ Probe and initialize SD/MMC card using given host
- Note
- Only SD cards (SDSC and SDHC/SDXC) are supported now. Support for MMC/eMMC cards will be added later.
- Return
- ESP_OK on success
- One of the error codes from SDMMC host controller
- Parameters
host
: pointer to structure defining host controllerout_card
: pointer to structure which will receive information about the card when the function completes
-
esp_err_t
sdmmc_write_sectors
(sdmmc_card_t *card, const void *src, size_t start_sector, size_t sector_count)¶ Write given number of sectors to SD/MMC card
- Return
- ESP_OK on success
- One of the error codes from SDMMC host controller
- Parameters
card
: pointer to card information structure previously initialized using sdmmc_card_initsrc
: pointer to data buffer to read data from; data size must be equal to sector_count * card->csd.sector_sizestart_sector
: sector where to start writingsector_count
: number of sectors to write
-
esp_err_t
sdmmc_read_sectors
(sdmmc_card_t *card, void *dst, size_t start_sector, size_t sector_count)¶ Write given number of sectors to SD/MMC card
- Return
- ESP_OK on success
- One of the error codes from SDMMC host controller
- Parameters
card
: pointer to card information structure previously initialized using sdmmc_card_initdst
: pointer to data buffer to write into; buffer size must be at least sector_count * card->csd.sector_sizestart_sector
: sector where to start readingsector_count
: number of sectors to read
SDMMC host driver APIs¶
On the ESP32, SDMMC host peripheral has two slots:
- Slot 0 (
SDMMC_HOST_SLOT_0
) is an 8-bit slot. It usesHS1_*
signals in the PIN MUX. - Slot 1 (
SDMMC_HOST_SLOT_1
) is a 4-bit slot. It usesHS2_*
signals in the PIN MUX.
Card Detect and Write Protect signals can be routed to arbitrary pins using GPIO matrix. To use these pins, set gpio_cd
and gpio_wp
members of sdmmc_slot_config_t
structure when calling sdmmc_host_init_slot
.
Of all the funtions listed below, only sdmmc_host_init
, sdmmc_host_init_slot
, and sdmmc_host_deinit
will be used directly by most applications. Other functions, such as sdmmc_host_set_bus_width
, sdmmc_host_set_card_clk
, and sdmmc_host_do_transaction
will be called by the SD/MMC protocol layer via function pointers in sdmmc_host_t
structure.
-
esp_err_t
sdmmc_host_init
()¶ Initialize SDMMC host peripheral.
- Note
- This function is not thread safe
- Return
- ESP_OK on success
- ESP_ERR_INVALID_STATE if sdmmc_host_init was already called
- ESP_ERR_NO_MEM if memory can not be allocated
-
SDMMC_HOST_SLOT_0
¶ SDMMC slot 0.
-
SDMMC_HOST_SLOT_1
¶ SDMMC slot 1.
-
SDMMC_HOST_DEFAULT
¶ Default sdmmc_host_t structure initializer for SDMMC peripheral.
Uses SDMMC peripheral, with 4-bit mode enabled, and max frequency set to 20MHz
-
SDMMC_SLOT_WIDTH_DEFAULT
¶ use the default width for the slot (8 for slot 0, 4 for slot 1)
-
esp_err_t
sdmmc_host_init_slot
(int slot, const sdmmc_slot_config_t *slot_config)¶ Initialize given slot of SDMMC peripheral.
On the ESP32, SDMMC peripheral has two slots:
- Slot 0: 8-bit wide, maps to HS1_* signals in PIN MUX
- Slot 1: 4-bit wide, maps to HS2_* signals in PIN MUX
Card detect and write protect signals can be routed to arbitrary GPIOs using GPIO matrix.
- Note
- This function is not thread safe
- Return
- ESP_OK on success
- ESP_ERR_INVALID_STATE if host has not been initialized using sdmmc_host_init
- Parameters
slot
: slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)slot_config
: additional configuration for the slot
-
struct
sdmmc_slot_config_t
¶ Extra configuration for SDMMC peripheral slot
Public Members
-
gpio_num_t
gpio_cd
¶ GPIO number of card detect signal.
-
gpio_num_t
gpio_wp
¶ GPIO number of write protect signal.
-
uint8_t
width
¶ Bus width used by the slot (might be less than the max width supported)
-
gpio_num_t
-
SDMMC_SLOT_NO_CD
¶ indicates that card detect line is not used
-
SDMMC_SLOT_NO_WP
¶ indicates that write protect line is not used
-
SDMMC_SLOT_CONFIG_DEFAULT
¶ Macro defining default configuration of SDMMC host slot
-
esp_err_t
sdmmc_host_set_bus_width
(int slot, size_t width)¶ Select bus width to be used for data transfer.
SD/MMC card must be initialized prior to this command, and a command to set bus width has to be sent to the card (e.g. SD_APP_SET_BUS_WIDTH)
- Note
- This function is not thread safe
- Return
- ESP_OK on success
- ESP_ERR_INVALID_ARG if slot number or width is not valid
- Parameters
slot
: slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)width
: bus width (1, 4, or 8 for slot 0; 1 or 4 for slot 1)
-
esp_err_t
sdmmc_host_set_card_clk
(int slot, uint32_t freq_khz)¶ Set card clock frequency.
Currently only integer fractions of 40MHz clock can be used. For High Speed cards, 40MHz can be used. For Default Speed cards, 20MHz can be used.
- Note
- This function is not thread safe
- Return
- ESP_OK on success
- other error codes may be returned in the future
- Parameters
slot
: slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)freq_khz
: card clock frequency, in kHz
-
esp_err_t
sdmmc_host_do_transaction
(int slot, sdmmc_command_t *cmdinfo)¶ Send command to the card and get response.
This function returns when command is sent and response is received, or data is transferred, or timeout occurs.
- Note
- This function is not thread safe w.r.t. init/deinit functions, and bus width/clock speed configuration functions. Multiple tasks can call sdmmc_host_do_transaction as long as other sdmmc_host_* functions are not called.
- Return
- ESP_OK on success
- ESP_ERR_TIMEOUT if response or data transfer has timed out
- ESP_ERR_INVALID_CRC if response or data transfer CRC check has failed
- ESP_ERR_INVALID_RESPONSE if the card has sent an invalid response
- Parameters
slot
: slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)cmdinfo
: pointer to structure describing command and data to transfer
-
esp_err_t
sdmmc_host_deinit
()¶ Disable SDMMC host and release allocated resources.
- Note
- This function is not thread safe
- Return
- ESP_OK on success
- ESP_ERR_INVALID_STATE if sdmmc_host_init function has not been called
Sigma-delta Modulation¶
概述¶
ESP32 has a second-order sigma-delta modulation module. This driver configures the channels of the sigma-delta module.
应用程序示例¶
Sigma-delta Modulation example: peripherals/sigmadelta.
API 参考手册¶
宏¶
类型定义¶
枚举¶
-
enum
sigmadelta_channel_t
¶ Sigma-delta channel list.
Values:
-
SIGMADELTA_CHANNEL_0
= 0¶ Sigma-delta channel0
-
SIGMADELTA_CHANNEL_1
= 1¶ Sigma-delta channel1
-
SIGMADELTA_CHANNEL_2
= 2¶ Sigma-delta channel2
-
SIGMADELTA_CHANNEL_3
= 3¶ Sigma-delta channel3
-
SIGMADELTA_CHANNEL_4
= 4¶ Sigma-delta channel4
-
SIGMADELTA_CHANNEL_5
= 5¶ Sigma-delta channel5
-
SIGMADELTA_CHANNEL_6
= 6¶ Sigma-delta channel6
-
SIGMADELTA_CHANNEL_7
= 7¶ Sigma-delta channel7
-
SIGMADELTA_CHANNEL_MAX
¶
-
结构体¶
-
struct
sigmadelta_config_t
¶ Sigma-delta configure struct.
Public Members
-
sigmadelta_channel_t
channel
¶ Sigma-delta channel number
-
int8_t
sigmadelta_duty
¶ Sigma-delta duty, duty ranges from -128 to 127.
-
uint8_t
sigmadelta_prescale
¶ Sigma-delta prescale, prescale ranges from 0 to 255.
-
uint8_t
sigmadelta_gpio
¶ Sigma-delta output io number, refer to gpio.h for more details.
-
sigmadelta_channel_t
函数¶
-
esp_err_t
sigmadelta_config
(const sigmadelta_config_t *config)¶ Configure Sigma-delta channel.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
config
: Pointer of Sigma-delta channel configuration struct
-
esp_err_t
sigmadelta_set_duty
(sigmadelta_channel_t channel, int8_t duty)¶ Set Sigma-delta channel duty.
This function is used to set Sigma-delta channel duty, If you add a capacitor between the output pin and ground, the average output voltage Vdc = VDDIO / 256 * duty + VDDIO/2, VDDIO is power supply voltage.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
channel
: Sigma-delta channel numberduty
: Sigma-delta duty of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90. The waveform is more like a random one in this range.
-
esp_err_t
sigmadelta_set_prescale
(sigmadelta_channel_t channel, uint8_t prescale)¶ Set Sigma-delta channel’s clock pre-scale value. The source clock is APP_CLK, 80MHz. The clock frequency of the sigma-delta channel is APP_CLK / pre_scale.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
channel
: Sigma-delta channel numberprescale
: The divider of source clock, ranges from 0 to 255
-
esp_err_t
sigmadelta_set_pin
(sigmadelta_channel_t channel, gpio_num_t gpio_num)¶ Set Sigma-delta signal output pin.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
channel
: Sigma-delta channel numbergpio_num
: GPIO number of output pin.
SPI Master driver¶
概述¶
The ESP32 has four SPI peripheral devices, called SPI0, SPI1, HSPI and VSPI. SPI0 is entirely dedicated to the flash cache the ESP32 uses to map the SPI flash device it is connected to into memory. SPI1 is connected to the same hardware lines as SPI0 and is used to write to the flash chip. HSPI and VSPI are free to use. SPI1, HSPI and VSPI all have three chip select lines, allowing them to drive up to three SPI devices each as a master.
The spi_master driver¶
The spi_master driver allows easy communicating with SPI slave devices, even in a multithreaded environment. It fully transparently handles DMA transfers to read and write data and automatically takes care of multiplexing between different SPI slaves on the same master
Terminology¶
The spi_master driver uses the following terms:
- Host: The SPI peripheral inside the ESP32 initiating the SPI transmissions. One of SPI, HSPI or VSPI. (For now, only HSPI or VSPI are actually supported in the driver; it will support all 3 peripherals somewhere in the future.)
- Bus: The SPI bus, common to all SPI devices connected to one host. In general the bus consists of the
miso, mosi, sclk and optionally quadwp and quadhd signals. The SPI slaves are connected to these
signals in parallel.
- miso - Also known as q, this is the input of the serial stream into the ESP32
- mosi - Also known as d, this is the output of the serial stream from the ESP32
- sclk - Clock signal. Each data bit is clocked out or in on the positive or negative edge of this signal
- quadwp - Write Protect signal. Only used for 4-bit (qio/qout) transactions.
- quadhd - Hold signal. Only used for 4-bit (qio/qout) transactions.
- Device: A SPI slave. Each SPI slave has its own chip select (CS) line, which is made active when a transmission to/from the SPI slave occurs.
- Transaction: One instance of CS going active, data transfer from and/or to a device happening, and CS going inactive again. Transactions are atomic, as in they will never be interrupted by another transaction.
SPI transactions¶
A transaction on the SPI bus consists of five phases, any of which may be skipped:
- The command phase. In this phase, a command (0-16 bit) is clocked out.
- The address phase. In this phase, an address (0-64 bit) is clocked out.
- The read phase. The slave sends data to the master.
- The write phase. The master sends data to the slave.
In full duplex, the read and write phases are combined, causing the SPI host to read and write data simultaneously.
The command and address phase are optional in that not every SPI device will need to be sent a command
and/or address. Tis is reflected in the device configuration: when the command_bits
or data_bits
fields are set to zero, no command or address phase is done.
Something similar is true for the read and write phase: not every transaction needs both data to be written
as well as data to be read. When rx_buffer
is NULL (and SPI_USE_RXDATA) is not set) the read phase
is skipped. When tx_buffer
is NULL (and SPI_USE_TXDATA) is not set) the write phase is skipped.
Using the spi_master driver¶
- Initialize a SPI bus by calling
spi_bus_initialize
. Make sure to set the correct IO pins in thebus_config
struct. Take care to set signals that are not needed to -1. - Tell the driver about a SPI slave device connected to the bus by calling spi_bus_add_device.
Make sure to configure any timing requirements the device has in the
dev_config
structure. You should now have a handle for the device, to be used when sending it a transaction. - To interact with the device, fill one or more spi_transaction_t structure with any transaction
parameters you need. Either queue all transactions by calling
spi_device_queue_trans
, later quering the result usingspi_device_get_trans_result
, or handle all requests synchroneously by feeding them intospi_device_transmit
. - Optional: to unload the driver for a device, call
spi_bus_remove_device
with the device handle as an argument - Optional: to remove the driver for a bus, make sure no more drivers are attached and call
spi_bus_free
.
Transaction data¶
Normally, data to be transferred to or from a device will be read from or written to a chunk of memory
indicated by the rx_buffer
and tx_buffer
members of the transaction structure. The SPI driver
may decide to use DMA for transfers, so these buffers should be allocated in DMA-capable memory using
pvPortMallocCaps(size, MALLOC_CAP_DMA)
.
Sometimes, the amount of data is very small making it less than optimal allocating a separate buffer
for it. If the data to be transferred is 32 bits or less, it can be stored in the transaction struct
itself. For transmitted data, use the tx_data
member for this and set the SPI_USE_TXDATA
flag
on the transmission. For received data, use rx_data
and set SPI_USE_RXDATA
. In both cases, do
not touch the tx_buffer
or rx_buffer
members, because they use the same memory locations
as tx_data
and rx_data
.
应用程序示例¶
Display graphics on the ILI9341-based 320x240 LCD: peripherals/spi_master.
API 参考手册¶
宏¶
-
SPI_DEVICE_TXBIT_LSBFIRST
¶ Transmit command/address/data LSB first instead of the default MSB first.
-
SPI_DEVICE_RXBIT_LSBFIRST
¶ Receive data LSB first instead of the default MSB first.
-
SPI_DEVICE_BIT_LSBFIRST
¶ Transmit and receive LSB first.
-
SPI_DEVICE_3WIRE
¶ Use MOSI (=spid) for both sending and receiving data.
-
SPI_DEVICE_POSITIVE_CS
¶ Make CS positive during a transaction instead of negative.
-
SPI_DEVICE_HALFDUPLEX
¶ Transmit data before receiving it, instead of simultaneously.
-
SPI_DEVICE_CLK_AS_CS
¶ Output clock on CS line if CS is active.
-
SPI_TRANS_MODE_DIO
¶ Transmit/receive data in 2-bit mode.
-
SPI_TRANS_MODE_QIO
¶ Transmit/receive data in 4-bit mode.
-
SPI_TRANS_MODE_DIOQIO_ADDR
¶ Also transmit address in mode selected by SPI_MODE_DIO/SPI_MODE_QIO.
-
SPI_TRANS_USE_RXDATA
¶ Receive into rx_data member of spi_transaction_t instead into memory at rx_buffer.
-
SPI_TRANS_USE_TXDATA
¶ Transmit tx_data member of spi_transaction_t instead of data at tx_buffer. Do not set tx_buffer when using this.
枚举¶
结构体¶
-
struct
spi_transaction_t
¶ This structure describes one SPI transaction
Public Members
-
uint32_t
flags
¶ Bitwise OR of SPI_TRANS_* flags.
-
uint16_t
command
¶ Command data. Specific length was given when device was added to the bus.
-
uint64_t
address
¶ Address. Specific length was given when device was added to the bus.
-
size_t
length
¶ Total data length, in bits.
-
size_t
rxlength
¶ Total data length received, if different from length. (0 defaults this to the value of
length
)
-
void *
user
¶ User-defined variable. Can be used to store eg transaction ID.
-
const void *
tx_buffer
¶ Pointer to transmit buffer, or NULL for no MOSI phase.
-
uint8_t
tx_data
[4]¶ If SPI_USE_TXDATA is set, data set here is sent directly from this variable.
-
void *
rx_buffer
¶ Pointer to receive buffer, or NULL for no MISO phase.
-
uint8_t
rx_data
[4]¶ If SPI_USE_RXDATA is set, data is received directly to this variable.
-
uint32_t
-
struct
spi_bus_config_t
¶ This is a configuration structure for a SPI bus.
You can use this structure to specify the GPIO pins of the bus. Normally, the driver will use the GPIO matrix to route the signals. An exception is made when all signals either can be routed through the IO_MUX or are -1. In that case, the IO_MUX is used, allowing for >40MHz speeds.
Public Members
-
int
mosi_io_num
¶ GPIO pin for Master Out Slave In (=spi_d) signal, or -1 if not used.
-
int
miso_io_num
¶ GPIO pin for Master In Slave Out (=spi_q) signal, or -1 if not used.
-
int
sclk_io_num
¶ GPIO pin for Spi CLocK signal, or -1 if not used.
-
int
quadwp_io_num
¶ GPIO pin for WP (Write Protect) signal which is used as D2 in 4-bit communication modes, or -1 if not used.
-
int
quadhd_io_num
¶ GPIO pin for HD (HolD) signal which is used as D3 in 4-bit communication modes, or -1 if not used.
-
int
max_transfer_sz
¶ Maximum transfer size, in bytes. Defaults to 4094 if 0.
-
int
-
struct
spi_device_interface_config_t
¶ This is a configuration for a SPI slave device that is connected to one of the SPI buses.
Public Members
-
uint8_t
command_bits
¶ Amount of bits in command phase (0-16)
-
uint8_t
address_bits
¶ Amount of bits in address phase (0-64)
-
uint8_t
dummy_bits
¶ Amount of dummy bits to insert between address and data phase.
-
uint8_t
mode
¶ SPI mode (0-3)
-
uint8_t
duty_cycle_pos
¶ Duty cycle of positive clock, in 1/256th increments (128 = 50%/50% duty). Setting this to 0 (=not setting it) is equivalent to setting this to 128.
-
uint8_t
cs_ena_pretrans
¶ Amount of SPI bit-cycles the cs should be activated before the transmission (0-16). This only works on half-duplex transactions.
-
uint8_t
cs_ena_posttrans
¶ Amount of SPI bit-cycles the cs should stay active after the transmission (0-16)
-
int
clock_speed_hz
¶ Clock speed, in Hz.
-
int
spics_io_num
¶ CS GPIO pin for this device, or -1 if not used.
-
uint32_t
flags
¶ Bitwise OR of SPI_DEVICE_* flags.
-
int
queue_size
¶ Transaction queue size. This sets how many transactions can be ‘in the air’ (queued using spi_device_queue_trans but not yet finished using spi_device_get_trans_result) at the same time.
-
transaction_cb_t
pre_cb
¶ Callback to be called before a transmission is started. This callback is called within interrupt context.
-
transaction_cb_t
post_cb
¶ Callback to be called after a transmission has completed. This callback is called within interrupt context.
-
uint8_t
函数¶
-
esp_err_t
spi_bus_initialize
(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan)¶ Initialize a SPI bus.
- Warning
- For now, only supports HSPI and VSPI.
- Return
- ESP_ERR_INVALID_ARG if configuration is invalid
- ESP_ERR_INVALID_STATE if host already is in use
- ESP_ERR_NO_MEM if out of memory
- ESP_OK on success
- Parameters
host
: SPI peripheral that controls this busbus_config
: Pointer to a spi_bus_config_t struct specifying how the host should be initializeddma_chan
: Either channel 1 or 2, or 0 in the case when no DMA is required. Selecting a DMA channel for a SPI bus allows transfers on the bus to have sizes only limited by the amount of internal memory. Selecting no DMA channel (by passing the value 0) limits the amount of bytes transfered to a maximum of 32.
-
esp_err_t
spi_bus_free
(spi_host_device_t host)¶ Free a SPI bus.
- Warning
- In order for this to succeed, all devices have to be removed first.
- Return
- ESP_ERR_INVALID_ARG if parameter is invalid
- ESP_ERR_INVALID_STATE if not all devices on the bus are freed
- ESP_OK on success
- Parameters
host
: SPI peripheral to free
-
esp_err_t
spi_bus_add_device
(spi_host_device_t host, spi_device_interface_config_t *dev_config, spi_device_handle_t *handle)¶ Allocate a device on a SPI bus.
This initializes the internal structures for a device, plus allocates a CS pin on the indicated SPI master peripheral and routes it to the indicated GPIO. All SPI master devices have three CS pins and can thus control up to three devices.
- Note
- While in general, speeds up to 80MHz on the dedicated SPI pins and 40MHz on GPIO-matrix-routed pins are supported, full-duplex transfers routed over the GPIO matrix only support speeds up to 26MHz.
- Return
- ESP_ERR_INVALID_ARG if parameter is invalid
- ESP_ERR_NOT_FOUND if host doesn’t have any free CS slots
- ESP_ERR_NO_MEM if out of memory
- ESP_OK on success
- Parameters
host
: SPI peripheral to allocate device ondev_config
: SPI interface protocol config for the devicehandle
: Pointer to variable to hold the device handle
-
esp_err_t
spi_bus_remove_device
(spi_device_handle_t handle)¶ Remove a device from the SPI bus.
- Return
- ESP_ERR_INVALID_ARG if parameter is invalid
- ESP_ERR_INVALID_STATE if device already is freed
- ESP_OK on success
- Parameters
handle
: Device handle to free
-
esp_err_t
spi_device_queue_trans
(spi_device_handle_t handle, spi_transaction_t *trans_desc, TickType_t ticks_to_wait)¶ Queue a SPI transaction for execution.
- Return
- ESP_ERR_INVALID_ARG if parameter is invalid
- ESP_OK on success
- Parameters
handle
: Device handle obtained using spi_host_add_devtrans_desc
: Description of transaction to executeticks_to_wait
: Ticks to wait until there’s room in the queue; use portMAX_DELAY to never time out.
-
esp_err_t
spi_device_get_trans_result
(spi_device_handle_t handle, spi_transaction_t **trans_desc, TickType_t ticks_to_wait)¶ Get the result of a SPI transaction queued earlier.
This routine will wait until a transaction to the given device (queued earlier with spi_device_queue_trans) has succesfully completed. It will then return the description of the completed transaction so software can inspect the result and e.g. free the memory or re-use the buffers.
- Return
- ESP_ERR_INVALID_ARG if parameter is invalid
- ESP_OK on success
- Parameters
handle
: Device handle obtained using spi_host_add_devtrans_desc
: Pointer to variable able to contain a pointer to the description of the transaction that is executedticks_to_wait
: Ticks to wait until there’s a returned item; use portMAX_DELAY to never time out.
-
esp_err_t
spi_device_transmit
(spi_device_handle_t handle, spi_transaction_t *trans_desc)¶ Do a SPI transaction.
Essentially does the same as spi_device_queue_trans followed by spi_device_get_trans_result. Do not use this when there is still a transaction queued that hasn’t been finalized using spi_device_get_trans_result.
- Return
- ESP_ERR_INVALID_ARG if parameter is invalid
- ESP_OK on success
- Parameters
handle
: Device handle obtained using spi_host_add_devtrans_desc
: Pointer to variable able to contain a pointer to the description of the transaction that is executed
SPI Slave driver¶
概述¶
The ESP32 has four SPI peripheral devices, called SPI0, SPI1, HSPI and VSPI. SPI0 is entirely dedicated to the flash cache the ESP32 uses to map the SPI flash device it is connected to into memory. SPI1 is connected to the same hardware lines as SPI0 and is used to write to the flash chip. HSPI and VSPI are free to use, and with the spi_slave driver, these can be used as a SPI slave, driven from a connected SPI master.
The spi_slave driver¶
The spi_slave driver allows using the HSPI and/or VSPI peripheral as a full-duplex SPI slave. It can make use of DMA to send/receive transactions of arbitrary length.
Terminology¶
The spi_slave driver uses the following terms:
- Host: The SPI peripheral inside the ESP32 initiating the SPI transmissions. One of HSPI or VSPI.
- Bus: The SPI bus, common to all SPI devices connected to a master. In general the bus consists of the
miso, mosi, sclk and optionally quadwp and quadhd signals. The SPI slaves are connected to these
signals in parallel. Each SPI slave is also connected to one CS signal.
- miso - Also known as q, this is the output of the serial stream from the ESP32 to the SPI master
- mosi - Also known as d, this is the output of the serial stream from the SPI master to the ESP32
- sclk - Clock signal. Each data bit is clocked out or in on the positive or negative edge of this signal
- cs - Chip Select. An active Chip Select delineates a single transaction to/from a slave.
- Transaction: One instance of CS going active, data transfer from and to a master happening, and CS going inactive again. Transactions are atomic, as in they will never be interrupted by another transaction.
SPI transactions¶
A full-duplex SPI transaction starts with the master pulling CS low. After this happens, the master starts sending out clock pulses on the CLK line: every clock pulse causes a data bit to be shifted from the master to the slave on the MOSI line and vice versa on the MISO line. At the end of the transaction, the master makes CS high again.
Using the spi_slave driver¶
- Initialize a SPI peripheral as a slave by calling
spi_slave_initialize
. Make sure to set the correct IO pins in thebus_config
struct. Take care to set signals that are not needed to -1. A DMA channel (either 1 or 2) must be given if transactions will be larger than 32 bytes, if not the dma_chan parameter may be 0. - To set up a transaction, fill one or more spi_transaction_t structure with any transaction
parameters you need. Either queue all transactions by calling
spi_slave_queue_trans
, later quering the result usingspi_slave_get_trans_result
, or handle all requests synchroneously by feeding them intospi_slave_transmit
. The latter two functions will block until the master has initiated and finished a transaction, causing the queued data to be sent and received. - Optional: to unload the SPI slave driver, call
spi_slave_free
.
Transaction data and master/slave length mismatches¶
Normally, data to be transferred to or from a device will be read from or written to a chunk of memory
indicated by the rx_buffer
and tx_buffer
members of the transaction structure. The SPI driver
may decide to use DMA for transfers, so these buffers should be allocated in DMA-capable memory using
pvPortMallocCaps(size, MALLOC_CAP_DMA)
.
The amount of data written to the buffers is limited by the length
member of the transaction structure:
the driver will never read/write more data than indicated there. The length
cannot define the actual
length of the SPI transaction; this is determined by the master as it drives the clock and CS lines. In
case the length of the transmission is larger than the buffer length, only the start of the transmission
will be sent and received. In case the transmission length is shorter than the buffer length, only data up
to the length of the buffer will be exchanged.
Warning: Due to a design peculiarity in the ESP32, if the amount of bytes sent by the master or the length of the transmission queues in the slave driver, in bytes, is not both larger than eight and dividable by four, the SPI hardware can fail to write the last one to seven bytes to the receive buffer.
应用程序示例¶
Slave/master communication: peripherals/spi_slave.
API 参考手册¶
宏¶
-
SPI_SLAVE_TXBIT_LSBFIRST
¶ Transmit command/address/data LSB first instead of the default MSB first.
-
SPI_SLAVE_RXBIT_LSBFIRST
¶ Receive data LSB first instead of the default MSB first.
-
SPI_SLAVE_BIT_LSBFIRST
¶ Transmit and receive LSB first.
警告
doxygendefine: Cannot find define “SPI_SLAVE_POSITIVE_CS” in doxygen xml output for project “esp32-idf” from directory: xml/
枚举¶
类型定义¶
结构体¶
-
struct
spi_slave_transaction_t
¶ This structure describes one SPI transaction
-
struct
spi_slave_interface_config_t
¶ This is a configuration for a SPI host acting as a slave device.
Public Members
-
int
spics_io_num
¶ CS GPIO pin for this device.
-
uint32_t
flags
¶ Bitwise OR of SPI_SLAVE_* flags.
-
int
queue_size
¶ Transaction queue size. This sets how many transactions can be ‘in the air’ (queued using spi_slave_queue_trans but not yet finished using spi_slave_get_trans_result) at the same time.
-
uint8_t
mode
¶ SPI mode (0-3)
-
slave_transaction_cb_t
post_setup_cb
¶ Callback called after the SPI registers are loaded with new data.
-
slave_transaction_cb_t
post_trans_cb
¶ Callback called after a transaction is done.
-
int
-
struct
spi_bus_config_t
¶ This is a configuration structure for a SPI bus.
You can use this structure to specify the GPIO pins of the bus. Normally, the driver will use the GPIO matrix to route the signals. An exception is made when all signals either can be routed through the IO_MUX or are -1. In that case, the IO_MUX is used, allowing for >40MHz speeds.
Public Members
-
int
mosi_io_num
¶ GPIO pin for Master Out Slave In (=spi_d) signal, or -1 if not used.
-
int
miso_io_num
¶ GPIO pin for Master In Slave Out (=spi_q) signal, or -1 if not used.
-
int
sclk_io_num
¶ GPIO pin for Spi CLocK signal, or -1 if not used.
-
int
quadwp_io_num
¶ GPIO pin for WP (Write Protect) signal which is used as D2 in 4-bit communication modes, or -1 if not used.
-
int
quadhd_io_num
¶ GPIO pin for HD (HolD) signal which is used as D3 in 4-bit communication modes, or -1 if not used.
-
int
max_transfer_sz
¶ Maximum transfer size, in bytes. Defaults to 4094 if 0.
-
int
Be advised that the slave driver does not use the quadwp/quadhd lines and fields in spi_bus_config_t
refering to these lines
will be ignored and can thus safely be left uninitialized.
函数¶
-
esp_err_t
spi_slave_initialize
(spi_host_device_t host, const spi_bus_config_t *bus_config, const spi_slave_interface_config_t *slave_config, int dma_chan)¶ Initialize a SPI bus as a slave interface.
- Warning
- For now, only supports HSPI and VSPI.
- Return
- ESP_ERR_INVALID_ARG if configuration is invalid
- ESP_ERR_INVALID_STATE if host already is in use
- ESP_ERR_NO_MEM if out of memory
- ESP_OK on success
- Parameters
host
: SPI peripheral to use as a SPI slave interfacebus_config
: Pointer to a spi_bus_config_t struct specifying how the host should be initializedslave_config
: Pointer to a spi_slave_interface_config_t struct specifying the details for the slave interfacedma_chan
: Either 1 or 2. A SPI bus used by this driver must have a DMA channel associated with it. The SPI hardware has two DMA channels to share. This parameter indicates which one to use.
-
esp_err_t
spi_slave_free
(spi_host_device_t host)¶ Free a SPI bus claimed as a SPI slave interface.
- Return
- ESP_ERR_INVALID_ARG if parameter is invalid
- ESP_ERR_INVALID_STATE if not all devices on the bus are freed
- ESP_OK on success
- Parameters
host
: SPI peripheral to free
-
esp_err_t
spi_slave_queue_trans
(spi_host_device_t host, const spi_slave_transaction_t *trans_desc, TickType_t ticks_to_wait)¶ Queue a SPI transaction for execution.
Queues a SPI transaction to be executed by this slave device. (The transaction queue size was specified when the slave device was initialised via spi_slave_initialize.) This function may block if the queue is full (depending on the ticks_to_wait parameter). No SPI operation is directly initiated by this function, the next queued transaction will happen when the master initiates a SPI transaction by pulling down CS and sending out clock signals.
This function hands over ownership of the buffers in
trans_desc
to the SPI slave driver; the application is not to access this memory untilspi_slave_queue_trans
is called to hand ownership back to the application.- Return
- ESP_ERR_INVALID_ARG if parameter is invalid
- ESP_OK on success
- Parameters
host
: SPI peripheral that is acting as a slavetrans_desc
: Description of transaction to execute. Not const because we may want to write status back into the transaction description.ticks_to_wait
: Ticks to wait until there’s room in the queue; use portMAX_DELAY to never time out.
-
esp_err_t
spi_slave_get_trans_result
(spi_host_device_t host, spi_slave_transaction_t **trans_desc, TickType_t ticks_to_wait)¶ Get the result of a SPI transaction queued earlier.
This routine will wait until a transaction to the given device (queued earlier with spi_slave_queue_trans) has succesfully completed. It will then return the description of the completed transaction so software can inspect the result and e.g. free the memory or re-use the buffers.
It is mandatory to eventually use this function for any transaction queued by
spi_slave_queue_trans
.- Return
- ESP_ERR_INVALID_ARG if parameter is invalid
- ESP_OK on success
- Parameters
host
: SPI peripheral to that is acting as a slavetrans_desc
: Pointer to variable able to contain a pointer to the description of the transaction that is executedticks_to_wait
: Ticks to wait until there’s a returned item; use portMAX_DELAY to never time out.
-
esp_err_t
spi_slave_transmit
(spi_host_device_t host, spi_slave_transaction_t *trans_desc, TickType_t ticks_to_wait)¶ Do a SPI transaction.
Essentially does the same as spi_slave_queue_trans followed by spi_slave_get_trans_result. Do not use this when there is still a transaction queued that hasn’t been finalized using spi_slave_get_trans_result.
- Return
- ESP_ERR_INVALID_ARG if parameter is invalid
- ESP_OK on success
- Parameters
host
: SPI peripheral to that is acting as a slavetrans_desc
: Pointer to variable able to contain a pointer to the description of the transaction that is executed. Not const because we may want to write status back into the transaction description.ticks_to_wait
: Ticks to wait until there’s a returned item; use portMAX_DELAY to never time out.
RMT¶
概述¶
The RMT (Remote Control) module driver can be used to send and receive infrared remote control signals. Due to flexibility of RMT module, the driver can also be used to generate many other types of signals.
应用程序示例¶
NEC remote control TX and RX example: peripherals/rmt_nec_tx_rx.
API 参考手册¶
枚举¶
-
enum
rmt_channel_t
¶ Values:
-
RMT_CHANNEL_0
=0¶ RMT Channel0
-
RMT_CHANNEL_1
¶ RMT Channel1
-
RMT_CHANNEL_2
¶ RMT Channel2
-
RMT_CHANNEL_3
¶ RMT Channel3
-
RMT_CHANNEL_4
¶ RMT Channel4
-
RMT_CHANNEL_5
¶ RMT Channel5
-
RMT_CHANNEL_6
¶ RMT Channel6
-
RMT_CHANNEL_7
¶ RMT Channel7
-
RMT_CHANNEL_MAX
¶
-
-
enum
rmt_mem_owner_t
¶ Values:
-
RMT_MEM_OWNER_TX
= 0¶ RMT RX mode, RMT transmitter owns the memory block
-
RMT_MEM_OWNER_RX
= 1¶ RMT RX mode, RMT receiver owns the memory block
-
RMT_MEM_OWNER_MAX
¶
-
-
enum
rmt_source_clk_t
¶ Values:
-
RMT_BASECLK_REF
= 0¶ RMT source clock system reference tick, 1MHz by default(Not supported in this version)
-
RMT_BASECLK_APB
¶ RMT source clock is APB CLK, 80Mhz by default
-
RMT_BASECLK_MAX
¶
-
结构体¶
-
struct
rmt_tx_config_t
¶ Data struct of RMT TX configure parameters.
Public Members
-
bool
loop_en
¶ RMT loop output mode
-
uint32_t
carrier_freq_hz
¶ RMT carrier frequency
-
uint8_t
carrier_duty_percent
¶ RMT carrier duty (%)
-
rmt_carrier_level_t
carrier_level
¶ RMT carrier level
-
bool
carrier_en
¶ RMT carrier enable
-
rmt_idle_level_t
idle_level
¶ RMT idle level
-
bool
idle_output_en
¶ RMT idle level output enable
-
bool
-
struct
rmt_rx_config_t
¶ Data struct of RMT RX configure parameters.
-
struct
rmt_config_t
¶ Data struct of RMT configure parameters.
Public Members
-
rmt_mode_t
rmt_mode
¶ RMT mode: transmitter or receiver
-
rmt_channel_t
channel
¶ RMT channel
-
uint8_t
clk_div
¶ RMT channel counter divider
-
gpio_num_t
gpio_num
¶ RMT GPIO number
-
uint8_t
mem_block_num
¶ RMT memory block number
-
rmt_tx_config_t
tx_config
¶ RMT TX parameter
-
rmt_rx_config_t
rx_config
¶ RMT RX parameter
-
rmt_mode_t
函数¶
-
esp_err_t
rmt_set_clk_div
(rmt_channel_t channel, uint8_t div_cnt)¶ Set RMT clock divider, channel clock is divided from source clock.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)div_cnt
: RMT counter clock divider
-
esp_err_t
rmt_get_clk_div
(rmt_channel_t channel, uint8_t *div_cnt)¶ Get RMT clock divider, channel clock is divided from source clock.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)div_cnt
: pointer to accept RMT counter divider
-
esp_err_t
rmt_set_rx_idle_thresh
(rmt_channel_t channel, uint16_t thresh)¶ Set RMT RX idle threshold value.
In receive mode, when no edge is detected on the input signal for longer than idle_thres channel clock cycles, the receive process is finished.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)thresh
: RMT RX idle threshold
-
esp_err_t
rmt_get_rx_idle_thresh
(rmt_channel_t channel, uint16_t *thresh)¶ Get RMT idle threshold value.
In receive mode, when no edge is detected on the input signal for longer than idle_thres channel clock cycles, the receive process is finished.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)thresh
: pointer to accept RMT RX idle threshold value
-
esp_err_t
rmt_set_mem_block_num
(rmt_channel_t channel, uint8_t rmt_mem_num)¶ Set RMT memory block number for RMT channel.
This function is used to configure the amount of memory blocks allocated to channel n The 8 channels share a 512x32-bit RAM block which can be read and written by the processor cores over the APB bus, as well as read by the transmitters and written by the receivers. The RAM address range for channel n is start_addr_CHn to end_addr_CHn, which are defined by: Memory block start address is RMT_CHANNEL_MEM(n) (in soc/rmt_reg.h), that is, start_addr_chn = RMT base address + 0x800 + 64 ∗ 4 ∗ n, and end_addr_chn = RMT base address + 0x800 + 64 ∗ 4 ∗ n + 64 ∗ 4 ∗ RMT_MEM_SIZE_CHn mod 512 ∗ 4
- Note
- If memory block number of one channel is set to a value greater than 1, this channel will occupy the memory block of the next channel. Channel0 can use at most 8 blocks of memory, accordingly channel7 can only use one memory block.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)rmt_mem_num
: RMT RX memory block number, one block has 64 * 32 bits.
-
esp_err_t
rmt_get_mem_block_num
(rmt_channel_t channel, uint8_t *rmt_mem_num)¶ Get RMT memory block number.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)rmt_mem_num
: Pointer to accept RMT RX memory block number
-
esp_err_t
rmt_set_tx_carrier
(rmt_channel_t channel, bool carrier_en, uint16_t high_level, uint16_t low_level, rmt_carrier_level_t carrier_level)¶ Configure RMT carrier for TX signal.
Set different values for carrier_high and carrier_low to set different frequency of carrier. The unit of carrier_high/low is the source clock tick, not the divided channel counter clock.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)carrier_en
: Whether to enable output carrier.high_level
: High level duration of carrierlow_level
: Low level duration of carrier.carrier_level
: Configure the way carrier wave is modulated for channel0-7.1'b1:transmit on low output level 1'b0:transmit on high output level
-
esp_err_t
rmt_set_mem_pd
(rmt_channel_t channel, bool pd_en)¶ Set RMT memory in low power mode.
Reduce power consumed by memory. 1:memory is in low power state.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)pd_en
: RMT memory low power enable.
-
esp_err_t
rmt_get_mem_pd
(rmt_channel_t channel, bool *pd_en)¶ Get RMT memory low power mode.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)pd_en
: Pointer to accept RMT memory low power mode.
-
esp_err_t
rmt_tx_start
(rmt_channel_t channel, bool tx_idx_rst)¶ Set RMT start sending data from memory.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)tx_idx_rst
: Set true to reset memory index for TX. Otherwise, transmitter will continue sending from the last index in memory.
-
esp_err_t
rmt_tx_stop
(rmt_channel_t channel)¶ Set RMT stop sending.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)
-
esp_err_t
rmt_rx_start
(rmt_channel_t channel, bool rx_idx_rst)¶ Set RMT start receiving data.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)rx_idx_rst
: Set true to reset memory index for receiver. Otherwise, receiver will continue receiving data to the last index in memory.
-
esp_err_t
rmt_rx_stop
(rmt_channel_t channel)¶ Set RMT stop receiving data.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)
-
esp_err_t
rmt_memory_rw_rst
(rmt_channel_t channel)¶ Reset RMT TX/RX memory index.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)
-
esp_err_t
rmt_set_memory_owner
(rmt_channel_t channel, rmt_mem_owner_t owner)¶ Set RMT memory owner.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)owner
: To set when the transmitter or receiver can process the memory of channel.
-
esp_err_t
rmt_get_memory_owner
(rmt_channel_t channel, rmt_mem_owner_t *owner)¶ Get RMT memory owner.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)owner
: Pointer to get memory owner.
-
esp_err_t
rmt_set_tx_loop_mode
(rmt_channel_t channel, bool loop_en)¶ Set RMT tx loop mode.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)loop_en
: To enable RMT transmitter loop sending mode.If set true, transmitter will continue sending from the first data to the last data in channel0-7 again and again.
-
esp_err_t
rmt_get_tx_loop_mode
(rmt_channel_t channel, bool *loop_en)¶ Get RMT tx loop mode.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)loop_en
: Pointer to accept RMT transmitter loop sending mode.
-
esp_err_t
rmt_set_rx_filter
(rmt_channel_t channel, bool rx_filter_en, uint8_t thresh)¶ Set RMT RX filter.
In receive mode, channel0-7 will ignore input pulse when the pulse width is smaller than threshold. Counted in source clock, not divided counter clock.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)rx_filter_en
: To enable RMT receiver filter.thresh
: Threshold of pulse width for receiver.
-
esp_err_t
rmt_set_source_clk
(rmt_channel_t channel, rmt_source_clk_t base_clk)¶ Set RMT source clock.
RMT module has two source clock:
- APB clock which is 80Mhz
- REF tick clock, which would be 1Mhz( not supported in this version).
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)base_clk
: To choose source clock for RMT module.
-
esp_err_t
rmt_get_source_clk
(rmt_channel_t channel, rmt_source_clk_t *src_clk)¶ Get RMT source clock.
RMT module has two source clock:
- APB clock which is 80Mhz
- REF tick clock, which would be 1Mhz( not supported in this version).
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)src_clk
: Pointer to accept source clock for RMT module.
-
esp_err_t
rmt_set_idle_level
(rmt_channel_t channel, bool idle_out_en, rmt_idle_level_t level)¶ Set RMT idle output level for transmitter.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)idle_out_en
: To enable idle level output.level
: To set the output signal’s level for channel0-7 in idle state.
-
esp_err_t
rmt_get_status
(rmt_channel_t channel, uint32_t *status)¶ Get RMT status.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0-7)status
: Pointer to accept channel status.
-
void
rmt_set_intr_enable_mask
(uint32_t mask)¶ Set mask value to RMT interrupt enable register.
- Parameters
mask
: Bit mask to set to the register
-
void
rmt_clr_intr_enable_mask
(uint32_t mask)¶ Clear mask value to RMT interrupt enable register.
- Parameters
mask
: Bit mask to clear the register
-
esp_err_t
rmt_set_rx_intr_en
(rmt_channel_t channel, bool en)¶ Set RMT RX interrupt enable.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0 - 7)en
: enable or disable RX interrupt.
-
esp_err_t
rmt_set_err_intr_en
(rmt_channel_t channel, bool en)¶ Set RMT RX error interrupt enable.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0 - 7)en
: enable or disable RX err interrupt.
-
esp_err_t
rmt_set_tx_intr_en
(rmt_channel_t channel, bool en)¶ Set RMT TX interrupt enable.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0 - 7)en
: enable or disable TX interrupt.
警告
doxygenfunction: Cannot find function “rmt_set_evt_intr_en” in doxygen xml output for project “esp32-idf” from directory: xml/
-
esp_err_t
rmt_set_pin
(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_num)¶ Set RMT pins.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0 - 7)mode
: TX or RX mode for RMTgpio_num
: GPIO number to transmit or receive the signal.
-
esp_err_t
rmt_config
(const rmt_config_t *rmt_param)¶ Configure RMT parameters.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
rmt_param
: RMT parameter structor
-
esp_err_t
rmt_isr_register
(void (*fn)(void *), void *arg, int intr_alloc_flags, rmt_isr_handle_t *handle, )¶ register RMT interrupt handler, the handler is an ISR.
The handler will be attached to the same CPU core that this function is running on.
- Note
- If you already called rmt_driver_install to use system RMT driver, please do not register ISR handler again.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Function pointer error.
- ESP_FAIL System driver installed, can not register ISR handler for RMT
- Parameters
fn
: Interrupt handler function.arg
: Parameter for handler functionintr_alloc_flags
: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.handle
: If non-zero, a handle to later clean up the ISR gets stored here.
-
esp_err_t
rmt_fill_tx_items
(rmt_channel_t channel, const rmt_item32_t *item, uint16_t item_num, uint16_t mem_offset)¶ Fill memory data of channel with given RMT items.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0 - 7)item
: Pointer of items.item_num
: RMT sending items number.mem_offset
: Index offset of memory.
-
esp_err_t
rmt_driver_install
(rmt_channel_t channel, size_t rx_buf_size, int intr_alloc_flags)¶ Initialize RMT driver.
- Return
- ESP_ERR_INVALID_STATE Driver is already installed, call rmt_driver_uninstall first.
- ESP_ERR_NO_MEM Memory allocation failure
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0 - 7)rx_buf_size
: Size of RMT RX ringbuffer. Can be 0 if the RX ringbuffer is not used.intr_alloc_flags
: Flags for the RMT driver interrupt handler. Pass 0 for default flags. See esp_intr_alloc.h for details.
-
esp_err_t
rmt_driver_uninstall
(rmt_channel_t channel)¶ Uninstall RMT driver.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0 - 7)
-
esp_err_t
rmt_write_items
(rmt_channel_t channel, const rmt_item32_t *rmt_item, int item_num, bool wait_tx_done)¶ RMT send waveform from rmt_item array.
This API allows user to send waveform with any length.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0 - 7)rmt_item
: head point of RMT items array.item_num
: RMT data item number.wait_tx_done
: If set 1, it will block the task and wait for sending done.If set 0, it will not wait and return immediately. @note This function will not copy data, instead, it will point to the original items, and send the waveform items. If wait_tx_done is set to true, this function will block and will not return until all items have been sent out. If wait_tx_done is set to false, this function will return immediately, and the driver interrupt will continue sending the items. We must make sure the item data will not be damaged when the driver is still sending items in driver interrupt.
-
esp_err_t
rmt_wait_tx_done
(rmt_channel_t channel)¶ Wait RMT TX finished.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0 - 7)
-
esp_err_t
rmt_get_ringbuf_handler
(rmt_channel_t channel, RingbufHandle_t *buf_handler)¶ Get ringbuffer from UART.
Users can get the RMT RX ringbuffer handler, and process the RX data.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
channel
: RMT channel (0 - 7)buf_handler
: Pointer to buffer handler to accept RX ringbuffer handler.
TIMER¶
概述¶
ESP32 chip contains two hardware timer groups, each containing two general-purpose hardware timers.
They are all 64-bit generic timers based on 16-bit prescalers and 64-bit auto-reload-capable up/down counters.
应用程序示例¶
64-bit hardware timer example: peripherals/timer_group.
API 参考手册¶
类型定义¶
枚举¶
-
enum
timer_group_t
¶ Selects a Timer-Group out of 2 available groups.
Values:
-
TIMER_GROUP_0
= 0¶ Hw timer group 0
-
TIMER_GROUP_1
= 1¶ Hw timer group 1
-
TIMER_GROUP_MAX
¶
-
-
enum
timer_idx_t
¶ Select a hardware timer from timer groups.
Values:
-
TIMER_0
= 0¶ Select timer0 of GROUPx
-
TIMER_1
= 1¶ Select timer1 of GROUPx
-
TIMER_MAX
¶
-
-
enum
timer_count_dir_t
¶ Decides the direction of counter.
Values:
-
TIMER_COUNT_DOWN
= 0¶ Descending Count from cnt.high|cnt.low
-
TIMER_COUNT_UP
= 1¶ Ascending Count from Zero
-
TIMER_COUNT_MAX
¶
-
-
enum
timer_start_t
¶ Decides whether timer is on or paused.
Values:
-
TIMER_PAUSE
= 0¶ Pause timer counter
-
TIMER_START
= 1¶ Start timer counter
-
-
enum
timer_alarm_t
¶ Decides whether to enable alarm mode.
Values:
-
TIMER_ALARM_DIS
= 0¶ Disable timer alarm
-
TIMER_ALARM_EN
= 1¶ Enable timer alarm
-
TIMER_ALARM_MAX
¶
-
-
enum
timer_intr_mode_t
¶ Select interrupt type if running in alarm mode.
Values:
-
TIMER_INTR_LEVEL
= 0¶ Interrupt mode: level mode
-
TIMER_INTR_MAX
¶
-
-
enum
timer_autoreload_t
¶ Select if Alarm needs to be loaded by software or automatically reload by hardware.
Values:
-
TIMER_AUTORELOAD_DIS
= 0¶ Disable auto-reload: hardware will not load counter value after an alarm event
-
TIMER_AUTORELOAD_EN
= 1¶ Enable auto-reload: hardware will load counter value after an alarm event
-
TIMER_AUTORELOAD_MAX
¶
-
结构体¶
-
struct
timer_config_t
¶ timer configure struct
Public Members
-
bool
alarm_en
¶ Timer alarm enable
-
bool
counter_en
¶ Counter enable
-
timer_intr_mode_t
intr_type
¶ Interrupt mode
-
timer_count_dir_t
counter_dir
¶ Counter direction
-
bool
auto_reload
¶ Timer auto-reload
-
uint16_t
divider
¶ Counter clock divider
-
bool
函数¶
-
esp_err_t
timer_get_counter_value
(timer_group_t group_num, timer_idx_t timer_num, uint64_t *timer_val)¶ Read the counter value of hardware timer.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]timer_val
: Pointer to accept timer counter value.
-
esp_err_t
timer_get_counter_time_sec
(timer_group_t group_num, timer_idx_t timer_num, double *time)¶ Read the counter value of hardware timer, in unit of a given scale.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]time
: Pointer, type of double*, to accept timer counter value, in seconds.
-
esp_err_t
timer_set_counter_value
(timer_group_t group_num, timer_idx_t timer_num, uint64_t load_val)¶ Set counter value to hardware timer.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]load_val
: Counter value to write to the hardware timer.
-
esp_err_t
timer_start
(timer_group_t group_num, timer_idx_t timer_num)¶ Start the counter of hardware timer.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group number, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
-
esp_err_t
timer_pause
(timer_group_t group_num, timer_idx_t timer_num)¶ Pause the counter of hardware timer.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group number, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
-
esp_err_t
timer_set_counter_mode
(timer_group_t group_num, timer_idx_t timer_num, timer_count_dir_t counter_dir)¶ Set counting mode for hardware timer.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group number, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]counter_dir
: Counting direction of timer, count-up or count-down
-
esp_err_t
timer_set_auto_reload
(timer_group_t group_num, timer_idx_t timer_num, timer_autoreload_t reload)¶ Enable or disable counter reload function when alarm event occurs.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group number, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]reload
: Counter reload mode.
-
esp_err_t
timer_set_divider
(timer_group_t group_num, timer_idx_t timer_num, uint16_t divider)¶ Set hardware timer source clock divider. Timer groups clock are divider from APB clock.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group number, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]divider
: Timer clock divider value.
-
esp_err_t
timer_set_alarm_value
(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_value)¶ Set timer alarm value.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]alarm_value
: A 64-bit value to set the alarm value.
-
esp_err_t
timer_get_alarm_value
(timer_group_t group_num, timer_idx_t timer_num, uint64_t *alarm_value)¶ Get timer alarm value.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]alarm_value
: Pointer of A 64-bit value to accept the alarm value.
-
esp_err_t
timer_set_alarm
(timer_group_t group_num, timer_idx_t timer_num, timer_alarm_t alarm_en)¶ Get timer alarm value.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]alarm_en
: To enable or disable timer alarm function.
-
esp_err_t
timer_isr_register
(timer_group_t group_num, timer_idx_t timer_num, void (*fn)(void *), void *arg, int intr_alloc_flags, timer_isr_handle_t *handle, )¶ register Timer interrupt handler, the handler is an ISR. The handler will be attached to the same CPU core that this function is running on.
- Note
- In case the this is called with the INIRAM flag, code inside the handler function can only call functions in IRAM, so it cannot call other timer APIs. Use direct register access to access timers from inside the ISR in this case.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Function pointer error.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group numbertimer_num
: Timer index of timer groupfn
: Interrupt handler function.
- Parameters
arg
: Parameter for handler functionintr_alloc_flags
: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.handle
: Pointer to return handle. If non-NULL, a handle for the interrupt will be returned here.
-
esp_err_t
timer_init
(timer_group_t group_num, timer_idx_t timer_num, const timer_config_t *config)¶ Initializes and configure the timer.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group number, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]config
: Pointer to timer initialization parameters.
-
esp_err_t
timer_get_config
(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config)¶ Get timer configure value.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group number, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]config
: Pointer of struct to accept timer parameters.
-
esp_err_t
timer_group_intr_enable
(timer_group_t group_num, uint32_t en_mask)¶ Enable timer group interrupt, by enable mask.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group number, 0 for TIMERG0 or 1 for TIMERG1en_mask
: Timer interrupt enable mask. Use TIMG_T0_INT_ENA_M to enable t0 interrupt Use TIMG_T1_INT_ENA_M to enable t1 interrupt
-
esp_err_t
timer_group_intr_disable
(timer_group_t group_num, uint32_t disable_mask)¶ Disable timer group interrupt, by disable mask.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group number, 0 for TIMERG0 or 1 for TIMERG1disable_mask
: Timer interrupt disable mask. Use TIMG_T0_INT_ENA_M to disable t0 interrupt Use TIMG_T1_INT_ENA_M to disable t1 interrupt
-
esp_err_t
timer_enable_intr
(timer_group_t group_num, timer_idx_t timer_num)¶ Enable timer interrupt.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group number, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index.
-
esp_err_t
timer_disable_intr
(timer_group_t group_num, timer_idx_t timer_num)¶ Disable timer interrupt.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
group_num
: Timer group number, 0 for TIMERG0 or 1 for TIMERG1timer_num
: Timer index.
UART¶
应用程序示例¶
Configure uart settings and install uart driver to read/write using UART0 and UART1 interfaces: peripherals/uart.
API 参考手册¶
Data 结构体¶
-
struct
uart_config_t
¶ UART configuration parameters for uart_param_config function.
Public Members
-
int
baud_rate
¶ UART baudrate
-
uart_word_length_t
data_bits
¶ UART byte size
-
uart_parity_t
parity
¶ UART parity mode
-
uart_stop_bits_t
stop_bits
¶ UART stop bits
-
uart_hw_flowcontrol_t
flow_ctrl
¶ UART HW flow control mode(cts/rts)
-
uint8_t
rx_flow_ctrl_thresh
¶ UART HW RTS threshold
-
int
-
struct
uart_intr_config_t
¶ UART interrupt configuration parameters for uart_intr_config function.
Public Members
-
uint32_t
intr_enable_mask
¶ UART interrupt enable mask, choose from UART_XXXX_INT_ENA_M under UART_INT_ENA_REG(i), connect with bit-or operator
-
uint8_t
rx_timeout_thresh
¶ UART timeout interrupt threshold(unit: time of sending one byte)
-
uint8_t
txfifo_empty_intr_thresh
¶ UART TX empty interrupt threshold.
-
uint8_t
rxfifo_full_thresh
¶ UART RX full interrupt threshold.
-
uint32_t
-
struct
uart_event_t
¶ Event structure used in UART event queue.
Public Members
-
uart_event_type_t
type
¶ UART event type
-
size_t
size
¶ UART data size for UART_DATA event
-
uart_event_type_t
宏¶
-
UART_FIFO_LEN
¶ Length of the hardware FIFO buffers
-
UART_INTR_MASK
¶ mask of all UART interrupts
-
UART_LINE_INV_MASK
¶ TBD
-
UART_BITRATE_MAX
¶ Max bit rate supported by UART
-
UART_PIN_NO_CHANGE
¶ Constant for uart_set_pin function which indicates that UART pin should not be changed
-
UART_INVERSE_DISABLE
¶ Disable UART signal inverse
-
UART_INVERSE_RXD
¶ UART RXD input inverse
-
UART_INVERSE_CTS
¶ UART CTS input inverse
-
UART_INVERSE_TXD
¶ UART TXD output inverse
-
UART_INVERSE_RTS
¶ UART RTS output inverse
枚举¶
-
enum
uart_word_length_t
¶ UART word length constants.
Values:
-
UART_DATA_5_BITS
= 0x0¶ word length: 5bits
-
UART_DATA_6_BITS
= 0x1¶ word length: 6bits
-
UART_DATA_7_BITS
= 0x2¶ word length: 7bits
-
UART_DATA_8_BITS
= 0x3¶ word length: 8bits
-
UART_DATA_BITS_MAX
= 0X4¶
-
-
enum
uart_stop_bits_t
¶ UART stop bits number.
Values:
-
UART_STOP_BITS_1
= 0x1¶ stop bit: 1bit
-
UART_STOP_BITS_1_5
= 0x2¶ stop bit: 1.5bits
-
UART_STOP_BITS_2
= 0x3¶ stop bit: 2bits
-
UART_STOP_BITS_MAX
= 0x4¶
-
-
enum
uart_port_t
¶ UART peripheral number.
Values:
-
UART_NUM_0
= 0x0¶ UART base address 0x3ff40000
-
UART_NUM_1
= 0x1¶ UART base address 0x3ff50000
-
UART_NUM_2
= 0x2¶ UART base address 0x3ff6E000
-
UART_NUM_MAX
¶
-
-
enum
uart_parity_t
¶ UART parity constants.
Values:
-
UART_PARITY_DISABLE
= 0x0¶ Disable UART parity
-
UART_PARITY_EVEN
= 0x2¶ Enable UART even parity
-
UART_PARITY_ODD
= 0x3¶ Enable UART odd parity
-
-
enum
uart_hw_flowcontrol_t
¶ UART hardware flow control modes.
Values:
-
UART_HW_FLOWCTRL_DISABLE
= 0x0¶ disable hardware flow control
-
UART_HW_FLOWCTRL_RTS
= 0x1¶ enable RX hardware flow control (rts)
-
UART_HW_FLOWCTRL_CTS
= 0x2¶ enable TX hardware flow control (cts)
-
UART_HW_FLOWCTRL_CTS_RTS
= 0x3¶ enable hardware flow control
-
UART_HW_FLOWCTRL_MAX
= 0x4¶
-
-
enum
uart_event_type_t
¶ UART event types used in the ringbuffer.
Values:
-
UART_DATA
¶ UART data event
-
UART_BREAK
¶ UART break event
-
UART_BUFFER_FULL
¶ UART RX buffer full event
-
UART_FIFO_OVF
¶ UART FIFO overflow event
-
UART_FRAME_ERR
¶ UART RX frame error event
-
UART_PARITY_ERR
¶ UART RX parity event
-
UART_DATA_BREAK
¶ UART TX data and break event
-
UART_EVENT_MAX
¶ UART event max index
-
UART_PATTERN_DET
¶ UART pattern detected
-
函数¶
-
esp_err_t
uart_set_word_length
(uart_port_t uart_num, uart_word_length_t data_bit)¶ Set UART data bits.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2data_bit
: UART data bits
-
esp_err_t
uart_get_word_length
(uart_port_t uart_num, uart_word_length_t *data_bit)¶ Get UART data bits.
- Return
- ESP_FAIL Parameter error
- ESP_OK Success, result will be put in (*data_bit)
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2data_bit
: Pointer to accept value of UART data bits.
-
esp_err_t
uart_set_stop_bits
(uart_port_t uart_num, uart_stop_bits_t stop_bits)¶ Set UART stop bits.
- Return
- ESP_OK Success
- ESP_FAIL Fail
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2stop_bits
: UART stop bits
-
esp_err_t
uart_get_stop_bits
(uart_port_t uart_num, uart_stop_bits_t *stop_bits)¶ Set UART stop bits.
- Return
- ESP_FAIL Parameter error
- ESP_OK Success, result will be put in (*stop_bit)
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2stop_bits
: Pointer to accept value of UART stop bits.
-
esp_err_t
uart_set_parity
(uart_port_t uart_num, uart_parity_t parity_mode)¶ Set UART parity.
- Return
- ESP_FAIL Parameter error
- ESP_OK Success
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2parity_mode
: the enum of uart parity configuration
-
esp_err_t
uart_get_parity
(uart_port_t uart_num, uart_parity_t *parity_mode)¶ Get UART parity mode.
- Return
- ESP_FAIL Parameter error
- ESP_OK Success, result will be put in (*parity_mode)
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2parity_mode
: Pointer to accept value of UART parity mode.
-
esp_err_t
uart_set_baudrate
(uart_port_t uart_num, uint32_t baudrate)¶ Set UART baud rate.
- Return
- ESP_FAIL Parameter error
- ESP_OK Success
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2baudrate
: UART baud rate.
-
esp_err_t
uart_get_baudrate
(uart_port_t uart_num, uint32_t *baudrate)¶ Get UART bit-rate.
- Return
- ESP_FAIL Parameter error
- ESP_OK Success, result will be put in (*baudrate)
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2baudrate
: Pointer to accept value of UART baud rate
-
esp_err_t
uart_set_line_inverse
(uart_port_t uart_num, uint32_t inverse_mask)¶ Set UART line inverse mode.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2inverse_mask
: Choose the wires that need to be inverted. Inverse_mask should be chosen from UART_INVERSE_RXD/UART_INVERSE_TXD/UART_INVERSE_RTS/UART_INVERSE_CTS, combine with OR operation.
-
esp_err_t
uart_set_hw_flow_ctrl
(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh)¶ Set hardware flow control.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2flow_ctrl
: Hardware flow control moderx_thresh
: Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN). Only when UART_HW_FLOWCTRL_RTS is set, will the rx_thresh value be set.
-
esp_err_t
uart_get_hw_flow_ctrl
(uart_port_t uart_num, uart_hw_flowcontrol_t *flow_ctrl)¶ Get hardware flow control mode.
- Return
- ESP_FAIL Parameter error
- ESP_OK Success, result will be put in (*flow_ctrl)
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2flow_ctrl
: Option for different flow control mode.
-
esp_err_t
uart_clear_intr_status
(uart_port_t uart_num, uint32_t clr_mask)¶ Clear UART interrupt status.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2clr_mask
: Bit mask of the status that to be cleared. enable_mask should be chosen from the fields of register UART_INT_CLR_REG.
-
esp_err_t
uart_enable_intr_mask
(uart_port_t uart_num, uint32_t enable_mask)¶ Set UART interrupt enable.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2enable_mask
: Bit mask of the enable bits. enable_mask should be chosen from the fields of register UART_INT_ENA_REG.
-
esp_err_t
uart_disable_intr_mask
(uart_port_t uart_num, uint32_t disable_mask)¶ Clear UART interrupt enable bits.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2disable_mask
: Bit mask of the disable bits. disable_mask should be chosen from the fields of register UART_INT_ENA_REG.
-
esp_err_t
uart_enable_rx_intr
(uart_port_t uart_num)¶ Enable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2
-
esp_err_t
uart_disable_rx_intr
(uart_port_t uart_num)¶ Disable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2
-
esp_err_t
uart_disable_tx_intr
(uart_port_t uart_num)¶ Disable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2
-
esp_err_t
uart_enable_tx_intr
(uart_port_t uart_num, int enable, int thresh)¶ Enable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2enable
: 1: enable; 0: disablethresh
: Threshold of TX interrupt, 0 ~ UART_FIFO_LEN
-
esp_err_t
uart_isr_register
(uart_port_t uart_num, void (*fn)(void *), void *arg, int intr_alloc_flags, uart_isr_handle_t *handle, )¶ register UART interrupt handler(ISR).
- Note
- UART ISR handler will be attached to the same CPU core that this function is running on.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2fn
: Interrupt handler function.arg
: parameter for handler functionintr_alloc_flags
: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.handle
: Pointer to return handle. If non-NULL, a handle for the interrupt will be returned here.
-
esp_err_t
uart_set_pin
(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num)¶ Set UART pin number.
- Note
- Internal signal can be output to multiple GPIO pads. Only one GPIO pad can connect with input signal.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2tx_io_num
: UART TX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.rx_io_num
: UART RX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.rts_io_num
: UART RTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.cts_io_num
: UART CTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
-
esp_err_t
uart_set_rts
(uart_port_t uart_num, int level)¶ UART set RTS level (before inverse) UART rx hardware flow control should not be set.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2level
: 1: RTS output low(active); 0: RTS output high(block)
-
esp_err_t
uart_set_dtr
(uart_port_t uart_num, int level)¶ UART set DTR level (before inverse)
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2level
: 1: DTR output low; 0: DTR output high
-
esp_err_t
uart_param_config
(uart_port_t uart_num, const uart_config_t *uart_config)¶ UART parameter configure.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2uart_config
: UART parameter settings
-
esp_err_t
uart_intr_config
(uart_port_t uart_num, const uart_intr_config_t *intr_conf)¶ UART interrupt configure.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2intr_conf
: UART interrupt settings
-
esp_err_t
uart_driver_install
(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t *uart_queue, int intr_alloc_flags)¶ Install UART driver.
UART ISR handler will be attached to the same CPU core that this function is running on.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2rx_buffer_size
: UART RX ring buffer size, rx_buffer_size should be greater than UART_FIFO_LEN.tx_buffer_size
: UART TX ring buffer size. If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out..queue_size
: UART event queue size/depth.uart_queue
: UART event queue handle (out param). On success, a new queue handle is written here to provide access to UART events. If set to NULL, driver will not use an event queue.intr_alloc_flags
: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. Do not set ESP_INTR_FLAG_IRAM here (the driver’s ISR handler is not located in IRAM)
-
esp_err_t
uart_driver_delete
(uart_port_t uart_num)¶ Uninstall UART driver.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2
-
esp_err_t
uart_wait_tx_done
(uart_port_t uart_num, TickType_t ticks_to_wait)¶ Wait UART TX FIFO empty.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- ESP_ERR_TIMEOUT Timeout
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2ticks_to_wait
: Timeout, count in RTOS ticks
-
int
uart_tx_chars
(uart_port_t uart_num, const char *buffer, uint32_t len)¶ Send data to the UART port from a given buffer and length.
This function will not wait for the space in TX FIFO, just fill the TX FIFO and return when the FIFO is full.
- Note
- This function should only be used when UART TX buffer is not enabled.
- Return
- (-1) Parameter error
- OTHERS(>=0) The number of data that pushed to the TX FIFO
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2buffer
: data buffer addresslen
: data length to send
-
int
uart_write_bytes
(uart_port_t uart_num, const char *src, size_t size)¶ Send data to the UART port from a given buffer and length,.
If parameter tx_buffer_size is set to zero: This function will not return until all the data have been sent out, or at least pushed into TX FIFO.
Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer, then, UART ISR will move data from ring buffer to TX FIFO gradually.
- Return
- (-1) Parameter error
- OTHERS(>=0) The number of data that pushed to the TX FIFO
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2src
: data buffer addresssize
: data length to send
-
int
uart_write_bytes_with_break
(uart_port_t uart_num, const char *src, size_t size, int brk_len)¶ Send data to the UART port from a given buffer and length,.
If parameter tx_buffer_size is set to zero: This function will not return until all the data and the break signal have been sent out. After all data send out, send a break signal.
Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer, then, UART ISR will move data from ring buffer to TX FIFO gradually. After all data send out, send a break signal.
- Return
- (-1) Parameter error
- OTHERS(>=0) The number of data that pushed to the TX FIFO
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2src
: data buffer addresssize
: data length to sendbrk_len
: break signal length (unit: time of one data bit at current_baudrate)
-
int
uart_read_bytes
(uart_port_t uart_num, uint8_t *buf, uint32_t length, TickType_t ticks_to_wait)¶ UART read bytes from UART buffer.
- Return
- (-1) Error
- Others return a char data from uart fifo.
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2buf
: pointer to the buffer.length
: data lengthticks_to_wait
: sTimeout, count in RTOS ticks
-
esp_err_t
uart_flush
(uart_port_t uart_num)¶ UART ring buffer flush.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART_NUM_0, UART_NUM_1 or UART_NUM_2
-
esp_err_t
uart_get_buffered_data_len
(uart_port_t uart_num, size_t *size)¶ UART get RX ring buffer cached data length.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART port number.size
: Pointer of size_t to accept cached data length
-
esp_err_t
uart_disable_pattern_det_intr
(uart_port_t uart_num)¶ UART disable pattern detect function. Designed for applications like ‘AT commands’. When the hardware detect a series of one same character, the interrupt will be triggered.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART port number.
-
esp_err_t
uart_enable_pattern_det_intr
(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle)¶ UART enable pattern detect function. Designed for applications like ‘AT commands’. When the hardware detect a series of one same character, the interrupt will be triggered.
- Return
- ESP_OK Success
- ESP_FAIL Parameter error
- Parameters
uart_num
: UART port number.pattern_chr
: character of the patternchr_num
: number of the character, 8bit value.chr_tout
: timeout of the interval between each pattern characters, 24bit value, unit is APB(80Mhz) clock cycle.post_idle
: idle time after the last pattern character, 24bit value, unit is APB(80Mhz) clock cycle.pre_idle
: idle time before the first pattern character, 24bit value, unit is APB(80Mhz) clock cycle.
关于本节 API 的示例代码请参考 ESP-IDF 示例中的 peripherals 目录。
系统 API¶
内存(Memory)分配¶
提示
译注:本节以及后面 深度睡眠 一节中的 Memory 都翻译为内存的,但是实际情况可能是指的存储器,其中细节请自己体会。
概述¶
ESP32 有多种 RAM。本质上,它包含 IRAM、DRAM 和可以同时用于这两者的 RAM。此外,还可以将外部 SPI flash 连接到 ESP32;可以使用 flash cache 将它的内存集成到 ESP32 的内存映射中。
为了利用这些所有的内存,esp-idf 包含了一个内存分配器。基本上,如果你想要内存具有某一属性(例如,DMA-capable、被某个特定的 PID 访问、或者执行代码的能力),你可以创建一个所需功能 OR 掩码并将它传递给 pvPortMallocCaps。例如,内部分配内存的常规 malloc 代码使用 `pvPortMallocCaps(size, MALLOC_CAP_8BIT)`
,这样就可以以字节为单位获取内存数据。
因为 malloc 也是使用的这个分配系统,所以使用 pvPortMallocCaps 分配的内存也可以通过调用标准函数 `free()`
进行释放。
本质上,这个分配器被分为两部分。FreeRTOS 目录中的分配器可以从标记的(tagged)区域分配内存:一个标记(tag)是一个整数值,空闲内存的每个区域都有一个标记。esp32 相关的代码使用一些特殊的标记来初始化这些区域,并且包含一些逻辑,这些逻辑可以根据用户所给的功能选择对应功能的标记。尽管这些 API 是公共的,但是还这些标记只能用于这两部分直接通信,而不能直接使用。
Special Uses¶
如果某个内存结构只能以 32 比特为单位进行访问(例如整数数组或指针数组),则在分配是可以使用 MALLOC_CAP_32BIT 标志。这允许分配器分发 IRAM 内存;一些在常规 malloc() 中不能做的事儿会被调用。这样有助于是哟个 ESP32 中的所有有效内存。
API 参考手册¶
宏¶
-
MALLOC_CAP_EXEC
¶ Flags to indicate the capabilities of the various memory systems.
Memory must be able to run executable code
-
MALLOC_CAP_32BIT
¶ Memory must allow for aligned 32-bit data accesses.
-
MALLOC_CAP_8BIT
¶ Memory must allow for 8/16/…-bit data accesses.
-
MALLOC_CAP_DMA
¶ Memory must be able to accessed by DMA.
-
MALLOC_CAP_PID2
¶ Memory must be mapped to PID2 memory space.
-
MALLOC_CAP_PID3
¶ Memory must be mapped to PID3 memory space.
-
MALLOC_CAP_PID4
¶ Memory must be mapped to PID4 memory space.
-
MALLOC_CAP_PID5
¶ Memory must be mapped to PID5 memory space.
-
MALLOC_CAP_PID6
¶ Memory must be mapped to PID6 memory space.
-
MALLOC_CAP_PID7
¶ Memory must be mapped to PID7 memory space.
-
MALLOC_CAP_SPISRAM
¶ Memory must be in SPI SRAM.
-
MALLOC_CAP_INVALID
¶ Memory can’t be used / list end marker.
函数¶
-
void
heap_alloc_caps_init
()¶ Initialize the capability-aware heap allocator.
For the ESP32, this is called once in the startup code.
-
void *
pvPortMallocCaps
(size_t xWantedSize, uint32_t caps)¶ Allocate a chunk of memory which has the given capabilities.
- Return
- A pointer to the memory allocated on success, NULL on failure
- Parameters
xWantedSize
: Size, in bytes, of the amount of memory to allocatecaps
: Bitwise OR of MALLOC_CAP_* flags indicating the type of memory to be returned
-
size_t
xPortGetFreeHeapSizeCaps
(uint32_t caps)¶ Get the total free size of all the regions that have the given capabilities.
This function takes all regions capable of having the given capabilities allocated in them and adds up the free space they have.
- Return
- Amount of free bytes in the regions
- Parameters
caps
: Bitwise OR of MALLOC_CAP_* flags indicating the type of memory
-
size_t
xPortGetMinimumEverFreeHeapSizeCaps
(uint32_t caps)¶ Get the total minimum free memory of all regions with the given capabilities.
This adds all the lowmarks of the regions capable of delivering the memory with the given capabilities
- Return
- Amount of free bytes in the regions
- Parameters
caps
: Bitwise OR of MALLOC_CAP_* flags indicating the type of memory
-
void
vPortDefineHeapRegionsTagged
(const HeapRegionTagged_t *const pxHeapRegions)¶ Initialize the heap allocator by feeding it the usable memory regions and their tags.
This takes an array of heapRegionTagged_t structs, the last entry of which is a dummy entry which has pucStartAddress set to NULL. It will initialize the heap allocator to serve memory from these ranges.
- Parameters
pxHeapRegions
: Array of region definitions
-
void *
pvPortMallocTagged
(size_t xWantedSize, BaseType_t tag)¶ Allocate memory from a region with a certain tag.
Like pvPortMalloc, this returns an allocated chunk of memory. This function, however, forces the allocator to allocate from a region specified by a specific tag.
- Return
- Pointer to allocated memory if succesful. NULL if unsuccesful.
- Parameters
xWantedSize
: Size needed, in bytestag
: Tag of the memory region the allocation has to be from
-
void
vPortFreeTagged
(void *pv)¶ Free memory allocated with pvPortMallocTagged.
This is basically an implementation of free().
- Parameters
pv
: Pointer to region allocated by pvPortMallocTagged
-
size_t
xPortGetMinimumEverFreeHeapSizeTagged
(BaseType_t tag)¶ Get the lowest amount of memory free for a certain tag.
This function allows the user to see what the least amount of free memory for a certain tag is.
- Return
- Minimum amount of free bytes available in the runtime of the program
- Parameters
tag
: Tag of the memory region
-
size_t
xPortGetFreeHeapSizeTagged
(BaseType_t tag)¶ Get the amount of free bytes in a certain tagged region.
Works like xPortGetFreeHeapSize but allows the user to specify a specific tag
- Return
- Remaining amount of free bytes in region
- Parameters
tag
: Tag of the memory region
中断分配¶
概述¶
ESP32 有两个核(core),每个核有 32 个中断。每个中断有一个确定的优先级,大多数(而非全部)中断被连接到中断复用矩阵中。由于中断源的数量大于中断的数量,因此在必要时可以在多个驱动程序中共享同一个中断。ESP-IDF 中提供了一个 esp_intr_alloc 抽象,它的作用就是隐藏这些实现细节。
驱动程序可以调用 esp_intr_alloc(或 esp_intr_alloc_sintrstatus)为某个外设分配一个中断。它可以通过一个传递给该函数的标志设置所分配中断的类型,指明指定的等级或者触发方法。然后中断分配代码会知道一个可用的中断,使用中断复用矩阵将它与外设挂在一起,并安装驱动程序传递给它的中断 hander 和 ISR。
该代码有两种处理方式不同的中断:共享中断和非共享中断。二者中最简单的是非共享中断:一个独立的中断会在调用 esp_intr_alloc 时被分配,且该中断仅能用于附着到它上面的外设,仅由一个 ISR 会被调用。共享中断可以被多个外设触发,当附着到它上面的某一个外设发送中断信号时,多个 ISR 都会被调用。因此,共享中断的 ISR 应当检查它们所服务的外设的中断状态,以查看是否需要执行任何动作。
非共享中断即可以由电平触发,也可以是边沿触发。共享中断仅能被电平触发(因为使用边沿触发时可能错过中断)。(它内部的逻辑是这样的:设备 A 和设备 B 共享一个中断。设备 B 发出一个中断信号。中断线为高。ISR handler 调用设备 A 的代码 -> 什么也不做。ISR handler 调用设备 B 的代码,但是在此期间,设备 A 发送了一个信号。设备 B 完成处理,清除设备 B 的中断,退出中断代码。现在,设备 A 的中断处于 pending 状态,但是由于中断线没有变为低(即使设备 B 的中断被清除了,设备 A 仍然保持为高),中断永远不会被服务)
多核问题¶
可以产生中断的外设可以被分为两类:
- 外部外设,在 ESP32 上面但是在 Xtensa 核外面。大多数 ESP32 外设都是这种类型。
- 内部外设,属于 Xtensa CPU 核自身的设备。
这两种外设的中断处理有一点点区别。
内部外设中断¶
每个 Xtensa CPU 核都有六个内部外设:
- 三个 timer 比较器(comparator)
- 一个性能监视器(monitor)
- 两个软件中断
内部中断源在 esp_intr_alloc.h 中定义为 ETS_INTERNAL_*_INTR_SOURCE
。
这些外设只能由它们所关联的核进行配置。当产生中断时,中断是通过硬连线(hard-wire)连接到它所关联的核;一个核中的中断源(例如内部 timer 比较器)不能在另一个核中产生中断。这就是为什么只能被运行在该核上面的某个任务管理。内部中断源仍然是使用 esp_intr_alloc 进行分配的,但是它们不能进行共享,且总是具有一个固定的中断等级。
外部外设中断¶
剩下的中断源来自外部设备,它们在 soc/soc.h 中定义为 ETS_*_INTR_SOURCE
。
两个 CPU 核的非内部中断槽被连接到一个中断复用器上面。中断复用器可以将任何外部中断源引导到它上面的任意中断槽。
- 分配外部中断时总是会将它分配到对它进行分配的那个核上面。
- 释放外部中断时必须发送在它所分配的同一个核上面。
- 可以从另一个核使能/禁止外部中断。
- 多个外部中断源可以通过将
ESP_INTR_FLAG_SHARED
作为标志参数传递给 esp_intr_alloc() 来共享一个中断槽。
从某个没有固定到一个具体核的任务中调用 esp_intr_alloc() 将不会有效果。在任务切换期时,这些任务可能会在两个核之间迁移。因此,它不能辨别中断被分配到哪个 CPU 上了,从而导致很难释放中断处理,且可能让调试变得更加困难。建议在创建需要分配中断的任务时,使用 xTaskCreatePinnedToCore() 函数,且指定一个参数 CoreID。在内部中断源的时候,这也是需要的。
IRAM-Safe 中断 Handler¶
使用 ESP_INTR_FLAG_IRAM
标志注册的中断 handler 将移植在 IRAM 中运行(从 DRAM 中读取它的所有数据),因此不需要在 flash
这对于那些需要保证最小执行延迟的中断来说是非常有用的,因为 falsh 的写和擦除操作可能比较慢(擦除可能哟啊花几十或几百微秒才能完成)。
如果中断 handler 的调用非常频繁,可以将它放到 IRAM 中,从而避免 flash cache 的遗漏。
更多细节请cake SPI flash API 文档。
应用程序示例¶
API 参考手册¶
宏¶
-
ESP_INTR_FLAG_LEVEL1
¶ Interrupt allocation flags.
These flags can be used to specify which interrupt qualities the code calling esp_intr_alloc* needs.Accept a Level 1 interrupt vector
-
ESP_INTR_FLAG_LEVEL2
¶ Accept a Level 2 interrupt vector.
-
ESP_INTR_FLAG_LEVEL3
¶ Accept a Level 3 interrupt vector.
-
ESP_INTR_FLAG_LEVEL4
¶ Accept a Level 4 interrupt vector.
-
ESP_INTR_FLAG_LEVEL5
¶ Accept a Level 5 interrupt vector.
-
ESP_INTR_FLAG_LEVEL6
¶ Accept a Level 6 interrupt vector.
-
ESP_INTR_FLAG_NMI
¶ Accept a Level 7 interrupt vector.
-
ESP_INTR_FLAG_LOWMED
¶ Low and medium prio interrupts. These can be handled in C.
-
ESP_INTR_FLAG_HIGH
¶ High level interrupts. Need to be handled in assembly.
-
ESP_INTR_FLAG_SHARED
¶ Interrupt can be shared between ISRs.
-
ESP_INTR_FLAG_EDGE
¶ Edge-triggered interrupt.
-
ESP_INTR_FLAG_IRAM
¶ ISR can be called if cache is disabled.
-
ESP_INTR_FLAG_INTRDISABLED
¶ Return with this interrupt disabled.
函数¶
Mark an interrupt as a shared interrupt.
This will mark a certain interrupt on the specified CPU as an interrupt that can be used to hook shared interrupt handlers to.
- Return
- ESP_ERR_INVALID_ARG if cpu or intno is invalid ESP_OK otherwise
- Parameters
intno
: The number of the interrupt (0-31)cpu
: CPU on which the interrupt should be marked as shared (0 or 1)is_in_iram
: Shared interrupt is for handlers that reside in IRAM and the int can be left enabled while the flash cache is disabled.
-
esp_err_t
esp_intr_reserve
(int intno, int cpu)¶ Reserve an interrupt to be used outside of this framewoek.
This will mark a certain interrupt on the specified CPU as reserved, not to be allocated for any reason.
- Return
- ESP_ERR_INVALID_ARG if cpu or intno is invalid ESP_OK otherwise
- Parameters
intno
: The number of the interrupt (0-31)cpu
: CPU on which the interrupt should be marked as shared (0 or 1)
-
esp_err_t
esp_intr_alloc
(int source, int flags, intr_handler_t handler, void *arg, intr_handle_t *ret_handle)¶ Allocate an interrupt with the given parameters.
This finds an interrupt that matches the restrictions as given in the flags parameter, maps the given interrupt source to it and hooks up the given interrupt handler (with optional argument) as well. If needed, it can return a handle for the interrupt as well.
The interrupt will always be allocated on the core that runs this function.
If ESP_INTR_FLAG_IRAM flag is used, and handler address is not in IRAM or RTC_FAST_MEM, then ESP_ERR_INVALID_ARG is returned.
- Return
- ESP_ERR_INVALID_ARG if the combination of arguments is invalid. ESP_ERR_NOT_FOUND No free interrupt found with the specified flags ESP_OK otherwise
- Parameters
source
: The interrupt source. One of the ETS_*_INTR_SOURCE interrupt mux sources, as defined in soc/soc.h, or one of the internal ETS_INTERNAL_*_INTR_SOURCE sources as defined in this header.flags
: An ORred mask of the ESP_INTR_FLAG_* defines. These restrict the choice of interrupts that this routine can choose from. If this value is 0, it will default to allocating a non-shared interrupt of level 1, 2 or 3. If this is ESP_INTR_FLAG_SHARED, it will allocate a shared interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return from this function with the interrupt disabled.handler
: The interrupt handler. Must be NULL when an interrupt of level >3 is requested, because these types of interrupts aren’t C-callable.arg
: Optional argument for passed to the interrupt handlerret_handle
: Pointer to an intr_handle_t to store a handle that can later be used to request details or free the interrupt. Can be NULL if no handle is required.
-
esp_err_t
esp_intr_alloc_intrstatus
(int source, int flags, uint32_t intrstatusreg, uint32_t intrstatusmask, intr_handler_t handler, void *arg, intr_handle_t *ret_handle)¶ Allocate an interrupt with the given parameters.
This essentially does the same as esp_intr_alloc, but allows specifying a register and mask combo. For shared interrupts, the handler is only called if a read from the specified register, ANDed with the mask, returns non-zero. By passing an interrupt status register address and a fitting mask, this can be used to accelerate interrupt handling in the case a shared interrupt is triggered; by checking the interrupt statuses first, the code can decide which ISRs can be skipped
- Return
- ESP_ERR_INVALID_ARG if the combination of arguments is invalid. ESP_ERR_NOT_FOUND No free interrupt found with the specified flags ESP_OK otherwise
- Parameters
source
: The interrupt source. One of the ETS_*_INTR_SOURCE interrupt mux sources, as defined in soc/soc.h, or one of the internal ETS_INTERNAL_*_INTR_SOURCE sources as defined in this header.flags
: An ORred mask of the ESP_INTR_FLAG_* defines. These restrict the choice of interrupts that this routine can choose from. If this value is 0, it will default to allocating a non-shared interrupt of level 1, 2 or 3. If this is ESP_INTR_FLAG_SHARED, it will allocate a shared interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return from this function with the interrupt disabled.intrstatusreg
: The address of an interrupt status registerintrstatusmask
: A mask. If a read of address intrstatusreg has any of the bits that are 1 in the mask set, the ISR will be called. If not, it will be skipped.handler
: The interrupt handler. Must be NULL when an interrupt of level >3 is requested, because these types of interrupts aren’t C-callable.arg
: Optional argument for passed to the interrupt handlerret_handle
: Pointer to an intr_handle_t to store a handle that can later be used to request details or free the interrupt. Can be NULL if no handle is required.
-
esp_err_t
esp_intr_free
(intr_handle_t handle)¶ Disable and free an interrupt.
Use an interrupt handle to disable the interrupt and release the resources associated with it.
- Return
- ESP_ERR_INVALID_ARG if handle is invalid, or esp_intr_free runs on another core than where the interrupt is allocated on. ESP_OK otherwise
- Parameters
handle
: The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
-
int
esp_intr_get_cpu
(intr_handle_t handle)¶ Get CPU number an interrupt is tied to.
- Return
- The core number where the interrupt is allocated
- Parameters
handle
: The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
-
int
esp_intr_get_intno
(intr_handle_t handle)¶ Get the allocated interrupt for a certain handle.
- Return
- The interrupt number
- Parameters
handle
: The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
-
esp_err_t
esp_intr_disable
(intr_handle_t handle)¶ Disable the interrupt associated with the handle.
- Note
- For local interrupts (ESP_INTERNAL_* sources), this function has to be called on the CPU the interrupt is allocated on. Other interrupts have no such restriction.
- Return
- ESP_ERR_INVALID_ARG if the combination of arguments is invalid. ESP_OK otherwise
- Parameters
handle
: The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
-
esp_err_t
esp_intr_enable
(intr_handle_t handle)¶ Ensable the interrupt associated with the handle.
- Note
- For local interrupts (ESP_INTERNAL_* sources), this function has to be called on the CPU the interrupt is allocated on. Other interrupts have no such restriction.
- Return
- ESP_ERR_INVALID_ARG if the combination of arguments is invalid. ESP_OK otherwise
- Parameters
handle
: The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
-
void
esp_intr_noniram_disable
()¶ Disable interrupts that aren’t specifically marked as running from IRAM.
-
void
esp_intr_noniram_enable
()¶ Re-enable interrupts disabled by esp_intr_noniram_disable.
看门狗¶
概述¶
Esp-idf 支持两种类型的看门狗:任务看门狗和中断看门狗。二者都可以通过使用 make menuconfig
进行配置和选择恰当的选项。
中断看门狗¶
中断看门狗可以确保 FreeRTOS 任务切换中断不会被阻塞太长时间。否则这是非常糟糕的,因为没有其它任务(包括相当重要的任务,比如 WiFi 任务和空转任务)能够获取到任何 CPU 时间。如果在中断被禁止时,程序运行到了无线循环,或者程序在中断中被挂起,则任务切换将会阻塞。
中断看门狗的默认行为是调用 panic handler。产生寄存器 dump 可以帮助程序员(使用 OpenOCD 或者 gdbstub)查看代码的问题。也可以通过配置 panic handler,让它直接对 CPU 进行复位,这更适合于实际产品环境。
中断看门狗被编译到定时器组 1 的赢硬件看门狗中。如果该看门狗由于某些原因例如 IRAM 被垃圾数据覆盖)不能执行调用 panic handler 的 NMI handler,它它将对 SoC 进行硬复位。
任务看门狗¶
任何任务都可以被任务看门狗看守。如果这个任务没有在任务看门狗所指定的超时时间(可以通过 make menuconfig
配置)内喂狗,看门狗将会打印警告消息 —— 哪些任务正在 ESP32 CPU 上面运行,哪些任务没有喂狗。
默认情况下,任务看门狗会看守空转(idle)任务。空转任务没有喂狗的原因通常是某个高优先级任务在处理循环,没有退出到低优先级任务,这可以作为有害代码(外设的 spinloop 或者陷入无线循环的任务)的指示器。
其它任务可以通过调用 esp_task_wdt_feed()
让该任务别任务看门狗看守。第一次调用这个函数时会将该任务注册到任务看门狗中;后续的调用会喂狗。如果任务不想再被看守(例如任务完成了,即将调用 vTaskDelete()
),则可以调用 esp_task_wdt_delete()
。
看门狗任务被编译到定时器组 0 的赢硬件看门狗中。如果这个看门狗由于某些原因(例如 IRAM 被垃圾数据覆盖、中断被完全禁止等)不能执行用于打印任务数据的中断 handler,它将对 SoC 进行硬复位。
JTAG 和看门狗¶
在使用 OpenOCD 进行调试时,如果 CPU 被挂起,看门狗会继续运行,最终会复位 CPU。这导致调试代码变得非常困难;这也是为什么 OpenOCD 配置会在启动时禁止所有看门狗的原因。也就是说,当 ESP32 通过 JTAG 连接到 OpenOCD 时,你不会看到由任务看门狗或中断看门狗打印的如何警告和 panic。
函数¶
-
void
esp_int_wdt_init
()¶ Initialize the interrupt watchdog. This is called in the init code if the interrupt watchdog is enabled in menuconfig.
-
void
esp_task_wdt_init
()¶ Initialize the task watchdog. This is called in the init code, if the task watchdog is enabled in menuconfig.
-
void
esp_task_wdt_feed
()¶ Feed the watchdog. After the first feeding session, the watchdog will expect the calling task to keep feeding the watchdog until task_wdt_delete() is called.
-
void
esp_task_wdt_delete
()¶ Delete the watchdog for the current task.
空中升级(OTA)¶
OTA 过程概述¶
OTA 升级机制允许常规固件在运行时基于它所接收的数据对设备进行升级(通过 WiFI 或者蓝牙)。
OTA 需要配置设备的 Partition Table,且至少需要两个 “OTA app” 分区(即 ota_0 和 ota_1)和一个 “OTA 数据分区”。
OTA 会将新的 app 固件镜像写到当前未用于启动程序的那个 OTA app 分区。当镜像校验完成后,OTA 数据分区会被更新,表示下一次启动时将使用该镜像。
OTA 数据分区¶
使用 OTA 功能的产品必须在 Partition Table 中包含一个 OTA 数据分区。
对于工厂启动设置,OTA 数据分区应当不包含数据(所有的字节被擦除为 0xFF)。在这种情况下,如果分区表中存在工厂 app,esp-idf 软件的 bootloader 会启动工厂 app。如果分区表中不存在工厂 app,则会启动第一个有效的 OTA 分区(通常是 ota_0
)。
当第一次 OTA 更新后,OTA 数据分区将会被更新,表示表示下一次启动时将使用哪个 OTA app 分区。
OTA 数据分期是两个 flash 扇区(0x2000 字节),以消除正在写时供电失败的问题。如果没有计数字段表明哪个扇区在最近被写过,则两个扇区会被独立擦除并写入匹配的数据。
See Also¶
应用程序示例¶
端到端的 OTA 固件升级流程请你参考: system/ota。
API 参考手册¶
宏¶
-
ESP_ERR_OTA_BASE
¶ Base error code for ota_ops api
-
ESP_ERR_OTA_PARTITION_CONFLICT
¶ Error if request was to write or erase the current running partition
-
ESP_ERR_OTA_SELECT_INFO_INVALID
¶ Error if OTA data partition contains invalid content
-
ESP_ERR_OTA_VALIDATE_FAILED
¶ Error if OTA app image is invalid
-
OTA_SIZE_UNKNOWN
¶ Used for esp_ota_begin() if new image size is unknown
类型定义¶
-
typedef uint32_t
esp_ota_handle_t
¶ Opaque handle for an application OTA update.
esp_ota_begin() returns a handle which is then used for subsequent calls to esp_ota_write() and esp_ota_end().
函数¶
-
esp_err_t
esp_ota_begin
(const esp_partition_t *partition, size_t image_size, esp_ota_handle_t *out_handle)¶ Commence an OTA update writing to the specified partition.
The specified partition is erased to the specified image size.
If image size is not yet known, pass OTA_SIZE_UNKNOWN which will cause the entire partition to be erased.
On success, this function allocates memory that remains in use until esp_ota_end() is called with the returned handle.
- Return
- ESP_OK: OTA operation commenced successfully.
- ESP_ERR_INVALID_ARG: partition or out_handle arguments were NULL, or partition doesn’t point to an OTA app partition.
- ESP_ERR_NO_MEM: Cannot allocate memory for OTA operation.
- ESP_ERR_OTA_PARTITION_CONFLICT: Partition holds the currently running firmware, cannot update in place.
- ESP_ERR_NOT_FOUND: Partition argument not found in partition table.
- ESP_ERR_OTA_SELECT_INFO_INVALID: The OTA data partition contains invalid data.
- ESP_ERR_INVALID_SIZE: Partition doesn’t fit in configured flash size.
- ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed.
- Parameters
partition
: Pointer to info for partition which will receive the OTA update. Required.image_size
: Size of new OTA app image. Partition will be erased in order to receive this size of image. If 0 or OTA_SIZE_UNKNOWN, the entire partition is erased.out_handle
: On success, returns a handle which should be used for subsequent esp_ota_write() and esp_ota_end() calls.
-
esp_err_t
esp_ota_write
(esp_ota_handle_t handle, const void *data, size_t size)¶ Write OTA update data to partition.
This function can be called multiple times as data is received during the OTA operation. Data is written sequentially to the partition.
- Return
- ESP_OK: Data was written to flash successfully.
- ESP_ERR_INVALID_ARG: handle is invalid.
- ESP_ERR_OTA_VALIDATE_FAILED: First byte of image contains invalid app image magic byte.
- ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed.
- ESP_ERR_OTA_SELECT_INFO_INVALID: OTA data partition has invalid contents
- Parameters
handle
: Handle obtained from esp_ota_begindata
: Data buffer to writesize
: Size of data buffer in bytes.
-
esp_err_t
esp_ota_end
(esp_ota_handle_t handle)¶ Finish OTA update and validate newly written app image.
- Note
- After calling esp_ota_end(), the handle is no longer valid and any memory associated with it is freed (regardless of result).
- Return
- ESP_OK: Newly written OTA app image is valid.
- ESP_ERR_NOT_FOUND: OTA handle was not found.
- ESP_ERR_INVALID_ARG: Handle was never written to.
- ESP_ERR_OTA_VALIDATE_FAILED: OTA image is invalid (either not a valid app image, or - if secure boot is enabled - signature failed to verify.)
- ESP_ERR_INVALID_STATE: If flash encryption is enabled, this result indicates an internal error writing the final encrypted bytes to flash.
- Parameters
handle
: Handle obtained from esp_ota_begin().
-
const esp_partition_t *
esp_ota_get_running_partition
(void)¶ Get partition info of currently running app.
This function is different to esp_ota_get_boot_partition() in that it ignores any change of selected boot partition caused by esp_ota_set_boot_partition(). Only the app whose code is currently running will have its partition information returned.
- Return
- Pointer to info for partition structure, or NULL if no partition is found or flash read operation failed. Returned pointer is valid for the lifetime of the application.
-
esp_err_t
esp_ota_set_boot_partition
(const esp_partition_t *partition)¶ Configure OTA data for a new boot partition.
- Note
- If this function returns ESP_OK, calling esp_restart() will boot the newly configured app partition.
- Return
- ESP_OK: OTA data updated, next reboot will use specified partition.
- ESP_ERR_INVALID_ARG: partition argument was NULL or didn’t point to a valid OTA partition of type “app”.
- ESP_ERR_OTA_VALIDATE_FAILED: Partition contained invalid app image. Also returned if secure boot is enabled and signature validation failed.
- ESP_ERR_NOT_FOUND: OTA data partition not found.
- ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash erase or write failed.
- Parameters
partition
: Pointer to info for partition containing app image to boot.
-
const esp_partition_t *
esp_ota_get_boot_partition
(void)¶ Get partition info of currently configured boot app.
If esp_ota_set_boot_partition() has been called, the partition which was set by that function will be returned.
If esp_ota_set_boot_partition() has not been called, the result is equivalent to esp_ota_get_running_partition().
- Return
- Pointer to info for partition structure, or NULL if no partition is found or flash read operation failed. Returned pointer is valid for the lifetime of the application.
-
const esp_partition_t *
esp_ota_get_next_update_partition
(const esp_partition_t *start_from)¶ Return the next OTA app partition which should be written with a new firmware.
Call this function to find an OTA app partition which can be passed to esp_ota_begin().
Finds next partition round-robin, starting from the current running partition.
- Return
- Pointer to info for partition which should be updated next. NULL result indicates invalid OTA data partition, or that no eligible OTA app slot partition was found.
- Parameters
start_from
: If set, treat this partition info as describing the current running partition. Can be NULL, in which case esp_ota_get_running_partition() is used to find the currently running partition. The result of this function is never the same as this argument.
深度睡眠¶
概述¶
ESP32 具有深度睡眠节电功能。在这种模式下,CPU、大多数的 RAM 和所有的由时钟 APB_CLK 驱动的数字外设都会被断电。芯片中还继续处于供电状态的部分包括:RTC 控制器、RTC 外设(包括 ULP 协处理器)、RTC 内存(低速和快速)。
从深度睡眠中唤醒可以使用几种源。这些源可以组合在一起,此时,任何一种源都可以触发唤醒。可以通过 API esp_deep_sleep_enable_X_wakeup
来使能唤醒源。下一节将描述这些 API 的细节。你可以在系统进入深度睡眠前的任何时刻配置唤醒源。
此外,应用程序可以使用 API esp_deep_sleep_pd_config
让 RTC 外设和 RTC 内存强制断电。
唤醒源被配置后,应用程序可以使用 API esp_deep_sleep_start
进入深度睡眠。从这一点看,硬件将会根据所请求的唤醒源来配置,RTC 控制器将给 CPU 和数字外设断电。
唤醒源¶
定时器¶
RTC 控制器中有一个内置的定时器,可用于在预定义的时间到达后唤醒芯片。时间的精度是微秒,但是实际的分辨率依赖于为 RTC SLOW_CLK 所选择的时钟源。关于 RTC 时钟选项的更多细节请参考 ESP32 技术参考手册的 “Reset and Clock” 一章。
这种唤醒模式不需要 RTC 外设或内存在深度睡眠器件供电。
下面的函数可以用于使能使用定时器深度睡眠唤醒。
-
esp_err_t
esp_deep_sleep_enable_timer_wakeup
(uint64_t time_in_us)¶ Enable wakeup by timer.
- Return
- ESP_OK on success
- ESP_ERR_INVALID_ARG if value is out of range (TBD)
- Parameters
time_in_us
: time before wakeup, in microseconds
触摸板¶
RTC IO 模块中包含这样一个逻辑:当发生触摸传感器中断时触发唤醒。你需要在芯片进入深度睡眠前配置触摸屏的中断。
ESP32 的修订版 0 和 1 仅在 RTC 外设没有被强制供电时支持该唤醒(即 ESP_PD_DOMAIN_RTC_PERIPH 被设置为 ESP_PD_OPTION_AUTO)。
-
esp_err_t
esp_deep_sleep_enable_touchpad_wakeup
()¶ Enable wakeup by touch sensor.
- Note
- In revisions 0 and 1 of the ESP32, touch wakeup source can not be used when RTC_PERIPH power domain is forced to be powered on (ESP_PD_OPTION_ON) or when ext0 wakeup source is used.
- Return
- ESP_OK on success
- ESP_ERR_INVALID_STATE if wakeup triggers conflict
外部唤醒(ext0)¶
RTC IO 模块中包含这样一个逻辑,当某个 RTC GPIO 被设置为预定义的逻辑值时触发唤醒。RTC IO 是 RTC 外设电源域的一部分,因此如果该唤醒源被请求的话,RTC 外设将在深度睡眠期间保持供电。
因为 RTC IO 模块在这个模式被使能,因此也可以使用内部上拉或下拉电阻。它们需要应用程序在调用 esp_deep_sleep_start
前使用先调用函数 rtc_gpio_pullup_en
或 rtc_gpio_pulldown_en
。
在 ESP32 的修订版 0 和 1 中,这个唤醒源与 ULP 和触摸唤醒源都不兼容。
警告
从深度睡眠中唤醒后,用于唤醒的 IO Pad 将被配置为 RTC IO,因此在将该 pad 用作数字 IO 前,需要使用函数 rtc_gpio_deinit(gpio_num)
对它进行重新配置。
-
esp_err_t
esp_deep_sleep_enable_ext0_wakeup
(gpio_num_t gpio_num, int level)¶ Enable wakeup using a pin.
This function uses external wakeup feature of RTC_IO peripheral. It will work only if RTC peripherals are kept on during deep sleep.
This feature can monitor any pin which is an RTC IO. Once the pin transitions into the state given by level argument, the chip will be woken up.
- Note
- This function does not modify pin configuration. The pin is configured in esp_deep_sleep_start, immediately before entering deep sleep.
- Note
- In revisions 0 and 1 of the ESP32, ext0 wakeup source can not be used together with touch or ULP wakeup sources.
- Return
- ESP_OK on success
- ESP_ERR_INVALID_ARG if the selected GPIO is not an RTC GPIO, or the mode is invalid
- ESP_ERR_INVALID_STATE if wakeup triggers conflict
- Parameters
gpio_num
: GPIO number used as wakeup source. Only GPIOs which are have RTC functionality can be used: 0,2,4,12-15,25-27,32-39.level
: input level which will trigger wakeup (0=low, 1=high)
外部唤醒(ext1)¶
RTC 控制器包含使用多个 RTC GPIO 触发唤醒的逻辑。下面其中一个逻辑功能可以用于触发唤醒:
- 当任意一个所选引脚为高电平时唤醒 (
ESP_EXT1_WAKEUP_ANY_HIGH
)- 当所有所选引脚为低电平时唤醒 (
ESP_EXT1_WAKEUP_ALL_LOW
)
这个唤醒源由 RTC 控制器实现。这种模式下的 RTC 外设和 RTC 内存可以被断电。不过,如果 RTC 外设被断电,内部上拉和下拉电阻将被禁止。为了使用内部上拉和下拉电阻,需要 RTC 外设电源域在睡眠期间保持开启,并在进入深度睡眠前使用函数 rtc_gpio_
配置上拉/下拉电阻
esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
gpio_pullup_dis(gpio_num);
gpio_pulldown_en(gpio_num);
警告
从深度睡眠中唤醒后,用于唤醒的 IO Pad 将被配置为 RTC IO,因此在将该 pad 用作数字 IO 前,需要使用函数 rtc_gpio_deinit(gpio_num)
对它进行重新配置。
下列函数可以用于使能这个唤醒模式:
-
esp_err_t
esp_deep_sleep_enable_ext1_wakeup
(uint64_t mask, esp_ext1_wakeup_mode_t mode)¶ Enable wakeup using multiple pins.
This function uses external wakeup feature of RTC controller. It will work even if RTC peripherals are shut down during deep sleep.
This feature can monitor any number of pins which are in RTC IOs. Once any of the selected pins goes into the state given by mode argument, the chip will be woken up.
- Note
- This function does not modify pin configuration. The pins are configured in esp_deep_sleep_start, immediately before entering deep sleep.
- Note
- internal pullups and pulldowns don’t work when RTC peripherals are shut down. In this case, external resistors need to be added. Alternatively, RTC peripherals (and pullups/pulldowns) may be kept enabled using esp_deep_sleep_pd_config function.
- Return
- ESP_OK on success
- ESP_ERR_INVALID_ARG if any of the selected GPIOs is not an RTC GPIO, or mode is invalid
- Parameters
mask
: bit mask of GPIO numbers which will cause wakeup. Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39.mode
: select logic function used to determine wakeup condition:- ESP_EXT1_WAKEUP_ALL_LOW: wake up when all selected GPIOs are low
- ESP_EXT1_WAKEUP_ANY_HIGH: wake up when any of the selected GPIOs is high
ULP 协处理器唤醒¶
当芯片处于深度睡眠时,ULP 协处理器能够运行,可以用于轮询传感器、监视器 ADC 或者触摸板传感器的值,并在检查到某个特殊事件时唤醒芯片。ULP 协处理器是 RTC 外设电源域的一部分,它运行存储在 RTC 低速内存中的程序。如果请求了这种唤醒模式,则 RTC 低速内存将会在深度睡眠期间保持供电状态。RTC 外设会在 ULP 协处理器开始运行程序前自动上电;一旦程序停止运行,RTC 外设会再次自动断电。
ESP32 的修订版 0 和 1 仅在 RTC 外设没有被强制供电时支持该唤醒(即 ESP_PD_DOMAIN_RTC_PERIPH 被设置为 ESP_PD_OPTION_AUTO)。
下列函数可以用于使能这个唤醒模式:
-
esp_err_t
esp_deep_sleep_enable_ulp_wakeup
()¶ Enable wakeup by ULP coprocessor.
- Note
- In revisions 0 and 1 of the ESP32, ULP wakeup source can not be used when RTC_PERIPH power domain is forced to be powered on (ESP_PD_OPTION_ON) or when ext0 wakeup source is used.
- Return
- ESP_OK on success
- ESP_ERR_INVALID_STATE if ULP co-processor is not enabled or if wakeup triggers conflict
RTC 外设和内存断电¶
默认情况下,函数 esp_deep_sleep_start
将会关掉被使能的唤醒源不需要的所有 RTC 电源域。如果向修改这个默认行为,可以使用下面的函数:
Note: 在 ESP32 的修订版 1 中,RTC 快速内存在深度睡眠期间将总是保持使能,因此深度睡眠桩(stub)可以在复位后运行。如果应用程序在深度睡眠后不需要清除复位行为,也可以对其进行修改。
如果程序中的某些值被if昂懂啊 RTC 低速内存中(例如,使用 RTC_DATA_ATTR
属性),RTC 低速内存将默认保持供电。如果有需要,也可以使用函数 esp_deep_sleep_pd_config
对其进行修改。
-
esp_err_t
esp_deep_sleep_pd_config
(esp_deep_sleep_pd_domain_t domain, esp_deep_sleep_pd_option_t option)¶ Set power down mode for an RTC power domain in deep sleep.
If not set set using this API, all power domains default to ESP_PD_OPTION_AUTO.
- Return
- ESP_OK on success
- ESP_ERR_INVALID_ARG if either of the arguments is out of range
- Parameters
domain
: power domain to configureoption
: power down option (ESP_PD_OPTION_OFF, ESP_PD_OPTION_ON, or ESP_PD_OPTION_AUTO)
-
enum
esp_deep_sleep_pd_domain_t
¶ Power domains which can be powered down in deep sleep.
Values:
-
ESP_PD_DOMAIN_RTC_PERIPH
¶ RTC IO, sensors and ULP co-processor.
-
ESP_PD_DOMAIN_RTC_SLOW_MEM
¶ RTC slow memory.
-
ESP_PD_DOMAIN_RTC_FAST_MEM
¶ RTC fast memory.
-
ESP_PD_DOMAIN_MAX
¶ Number of domains.
-
-
enum
esp_deep_sleep_pd_option_t
¶ Power down options.
Values:
-
ESP_PD_OPTION_OFF
¶ Power down the power domain in deep sleep.
-
ESP_PD_OPTION_ON
¶ Keep power domain enabled during deep sleep.
-
ESP_PD_OPTION_AUTO
¶ Keep power domain enabled in deep sleep, if it is needed by one of the wakeup options. Otherwise power it down.
-
进入深度睡眠¶
唤醒源配置后,下面函数可以用于进入深度睡眠。在没有配置唤醒源时也可以进入深度睡眠,在这种情形下,芯片将确切地处于深度睡眠模式,知道接收到外部复位。
-
void
esp_deep_sleep_start
()¶ Enter deep sleep with the configured wakeup options.
This function does not return.
检查深度睡眠唤醒原因¶
下面的函数可用于检测是何种唤醒源在深度睡眠期间被触发了。对于触摸板和 ext1 唤醒源,可以确定造成唤醒的引脚或触摸 pad。
-
esp_deep_sleep_wakeup_cause_t
esp_deep_sleep_get_wakeup_cause
()¶ Get the source which caused deep sleep wakeup.
- Return
- wakeup cause, or ESP_DEEP_SLEEP_WAKEUP_UNDEFINED if reset reason is other than deep sleep reset.
-
enum
esp_deep_sleep_wakeup_cause_t
¶ Deep sleep wakeup cause.
Values:
-
ESP_DEEP_SLEEP_WAKEUP_UNDEFINED
¶
-
ESP_DEEP_SLEEP_WAKEUP_EXT0
¶ Wakeup was not caused by deep sleep.
-
ESP_DEEP_SLEEP_WAKEUP_EXT1
¶ Wakeup caused by external signal using RTC_IO.
-
ESP_DEEP_SLEEP_WAKEUP_TIMER
¶ Wakeup caused by external signal using RTC_CNTL.
-
ESP_DEEP_SLEEP_WAKEUP_TOUCHPAD
¶ Wakeup caused by timer.
-
ESP_DEEP_SLEEP_WAKEUP_ULP
¶ Wakeup caused by touchpad.
-
-
touch_pad_t
esp_deep_sleep_get_touchpad_wakeup_status
()¶ Get the touch pad which caused wakeup.
If wakeup was caused by another source, this function will return TOUCH_PAD_MAX;
- Return
- touch pad which caused wakeup
-
uint64_t
esp_deep_sleep_get_ext1_wakeup_status
()¶ Get the bit mask of GPIOs which caused wakeup (ext1)
If wakeup was caused by another source, this function will return 0.
- Return
- bit mask, if GPIOn caused wakeup, BIT(n) will be set
应用程序示例¶
深度睡眠的基本示例程序是 protocols/sntp,它会让 ESP 模块周期性地唤醒,以从 NTP 服务器获取时间。
更多扩展示例请参考 system/deep_sleep,它描述了各种深度睡眠触发器和 ULP 协处理器编程的方法。
日志库¶
概述¶
日志库有两种方式管理日志的可见性:编译时和运行时。编译时是通过配置菜单实现的;运行时是通过函数 esp_log_level_set
实现的。
在编译时,日志的过滤是通过配置菜单的宏 CONFIG_LOG_DEFAULT_LEVEL
完成的。所有日志级别大于 CONFIG_LOG_DEFAULT_LEVEL
的语句都会被预处理器移除。
在运行时,级别在 CONFIG_LOG_DEFAULT_LEVEL
以下的日志默认都被使能。函数 esp_log_level_set
可以用于设置每个模块的日志级别。模块通过它们的标签(tags)进行标识。标签是人类可识别的以 ‘0’ 作为结尾的字符串。
如何使用日志库¶
在每个需要使用日志功能的 C 源文件中,按照类似下面的这种方式定义 TAG 变量:
static const char* TAG = "MyModule";
然后使用以下其中一个宏来产生输出,例如:
ESP_LOGW(TAG, "Baud rate error %.1f%%. Requested: %d baud, actual: %d baud", error * 100, baud_req, baud_real);
下面的几个宏可用于输出不同的日志级别:
ESP_LOGE
- 错误/errorESP_LOGW
- 警告/warningESP_LOGI
- 信息/infoESP_LOGD
- 调试/debugESP_LOGV
- 啰嗦/verbose
此外,上面的每一种宏还存在一种 _EARLY_ 变种,例如 ESP_EARLY_LOGE
。这些变种可以运行在启动代码中,在堆分配器和 syscall 被初始化之前。在编译 bootloader 时,常规的宏 ESP_LOGx
将会退化为对应的宏 ESP_EARLY_LOGx
。因此,需要明确使用 ESP_EARLY_LOGx
的地方是早起的启动代码,例如堆分配器的初始化代码。
(注意,如果我们在 ROM 中有 ets_vprintf
函数,则不需要进行这样的区分,可以直接将 _EARLY_ 版的宏切换为普通版的宏。不幸的是,ROM 中的 ets_vprintf
会被编译器内链为 ets_printf
,因此在外部不可访问)
如果想在文件或者组件内覆盖默认的可视级别,可以在文件或组件内定义一个 LOG_LOCAL_LEVEL
宏。如果是在文件内,该宏的定义需要在包含头文件 esp_log.h
之前,例如:
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#include "esp_log.h"
如果是在组件内,则需要在组件的 makefile 中定义:
CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_DEBUG
如果需要在运行时为每个模块配置日志输出,则直接调用函数 esp_log_level_set
:
esp_log_level_set("*", ESP_LOG_ERROR); // set all components to ERROR level
esp_log_level_set("wifi", ESP_LOG_WARN); // enable WARN logs from WiFi stack
esp_log_level_set("dhcpc", ESP_LOG_INFO); // enable INFO logs from DHCP client
通过 JTAG 将日志输出到主机¶
默认情况下,日志库会使用类 vprintf 函数将格式化消息输出到专用的 UART 中。通常,这会涉及到以下步骤:
- 解释格式化字符串,以获取每个参数的类型。
- 根据每个参数的类型,将其转换成字符串形式。
- 格式化字符串和转换后的参数被发送到 UART。
尽管类 vprintf 函数的实现可以被优化到一定的级别,但是在所有情形下都需要执行上面到步骤,且每个步骤(尤其是第三项)都需要花一定的时间。
So it is frequent situation when addition of extra logging to the program to diagnose some problem changes its behaviour and problem dissapears。或者在最差的情形,程序最终可能会发送错误以致完全不能工作,甚至直接挂起。克服这个问题的可用的办法是使用一个更快的 UART 波特率(或者使用另一个更快的接口)和/或将将字符串格式化过程转移到主机上。ESP IDF 有一个 应用程序跟踪(Application Tracing) 功能,它允许通过 JTAG 将任意的应用程序数据发送到主机。这个功能也可哟通过使用函数 esp_apptrace_vprintf
将日志信息传输到主机。这个函数不会对格式化字符串和参数执行完整的解释,相反,它仅仅计算传递的参数的数量,并将其与格式话字符串的地址一起发送到主机。在主机上,日志数据会被一个特俗的 Python 脚本处理并打印。
使用这个功能依赖于两个组件:
1.主机侧: 应用程序跟踪是由 JTAG 完成的,所以需要在主机上配置并运行 OpenOCD。关于如何配置的指令,请阅读 为 ESP32 设置 OpenOCD 一节。NOTE: 为了达到更高的数据速率,你需要在 OpenOCD 的配置文件中修改 JTAG 适配器的工作频率。经测试,最大的稳定速度是 26MHz,因此你需要在你的配置文件中使用 adapter_khz 26000
替换默认的 adapter_khz 200
。 JTAG 的实际的最大稳定频率依赖于主机系统的配置。
2. 目标侧:应用程序跟踪功能可以在配置菜单中通过宏 CONFIG_ESP32_APPTRACE_ENABLE
进行使能。该选项会使能该模块,并让 esp_apptrace_vprintf
对所有用户有效。
当前,通过 JTAG 打印日志消息有如下几点限制:
- 不支持对
ESP_EARLY_LOGx
宏的跟踪。 - 不支持参数(例如
double
和uint64_t
)超过 4 个字节的 printf。 - 仅支持 .rodata 段中的字符串用过格式化字符串和参数。
- printf 参数的最大数量是 256。
要使用 JTAG 输出日志,你需要执行以下步骤:
- 在目标侧,需要安装特定的类 vprintf 函数。正如之前提到的,这个函数是
esp_apptrace_vprintf
。它会通过 JTAG 向主机发送日志数据。示例代码如下:
#include "esp_app_trace.h"
...
void app_main()
{
// set log vprintf handler
esp_log_set_vprintf(esp_apptrace_vprintf);
...
// user code using ESP_LOGx starts here
// all data passed to ESP_LOGx are sent to host
...
// restore log vprintf handler
esp_log_set_vprintf(vprintf);
// flush last data to host
esp_apptrace_flush(ESP_APPTRACE_DEST_TRAX, 100000 /*tmo in us*/);
ESP_LOGI(TAG, "Tracing is finished."); // this will be printed out to UART
while (1);
}
- 按照 Developing With the ESP-IDF 一节中的方法编译应用程序镜像并将其下载到目标板中。
- 运行 OpenOCD (参考 OpenOCD setup for ESP32 一节)。
- 连接到 OpenOCD telnet 服务器。在 Linux 上,你可以在终端中使用命令
telnet <oocd_host> 4444
。如果运行 telnet 会话的主机就是你运行 OpenOCD 的同一个主机,你可以在该命令中直接使用 localhost 作为 <oocd_host>。 - 在 OpenOCD telnet 会话中运行如下命令:
esp108 apptrace start /path/to/trace/file -1 -1 0 0 1
。这个命令会等待板子复位,并以最高的速率传输跟踪数据。 - 将开发板复位。日志会自动发送到主机。
- 使用上面参数的命令
esp108 apptrace
永远不会返回(参考下面的命令选项),因此你必须手动停止,可以通过复位开发板或者在 OpenOCD 窗口(不是运行 telnet 会话的窗口)按下 CTRL+C。 - 当调试完成后(例如对于上面的示例代码,指的是当 “Tracing is finished.” 出现在 UART 后),将开发板复位,或者在 OpenOCD 窗口不是运行 telnet 会话的窗口)按下 CTRL+C。
- 如果要打印所采集的日志记录,在终端中运行如下命令:
$IDF_PATH/tools/esp_app_trace/logtrace_proc.py /path/to/trace/file /path/to/program/elf/file
。
命令的用法:
esp108 apptrace [start <outfile> [options] | [stop] | [status] | [dump <outfile>]
- 子命令:
start
. 启动跟踪 (continuous streaming).stop
. 停止跟踪status
. 获取跟踪状态dump
. Dump 尽量多的数据,不需要等待跟踪内存块切换 (post-mortem dump).
- 启动命令的语法:
start <outfile> [trace_size [stop_tmo [skip_size [poll_period [wait4halt]]]]]
命令的用法:
logtrace_proc.py [-h] [--no-errors] <trace_file> <elf_file>
必选参数:
参数 描述 trace_file 日志跟踪文件的路径 elf_file 程序 ELF 文件的路径
可选参数:
参数 描述 -h, –help 显示本帮助信息并退出 –no-errors, -n 不打印错误
应用程序示例¶
大多数 esp-idf 组件和例程都使用了日志(Log)库。日志功能的演示请参考 espressif/esp-idf 仓库的 examples 目录,建议可以参考这些示例:
API 参考手册¶
宏¶
-
LOG_COLOR_E
¶
-
LOG_COLOR_W
¶
-
LOG_COLOR_I
¶
-
LOG_COLOR_D
¶
-
LOG_COLOR_V
¶
-
LOG_RESET_COLOR
¶
-
LOG_FORMAT
(letter, format)¶
-
LOG_LOCAL_LEVEL
¶
-
ESP_EARLY_LOGE
(tag, format, ...)¶
-
ESP_EARLY_LOGW
(tag, format, ...)¶
-
ESP_EARLY_LOGI
(tag, format, ...)¶
-
ESP_EARLY_LOGD
(tag, format, ...)¶
-
ESP_EARLY_LOGV
(tag, format, ...)¶
-
ESP_LOGE
(tag, format, ...)¶
-
ESP_LOGW
(tag, format, ...)¶
-
ESP_LOGI
(tag, format, ...)¶
-
ESP_LOGD
(tag, format, ...)¶
-
ESP_LOGV
(tag, format, ...)¶
枚举¶
-
enum
esp_log_level_t
¶ Log level.
Values:
-
ESP_LOG_NONE
¶ No log output
-
ESP_LOG_ERROR
¶ Critical errors, software module can not recover on its own
-
ESP_LOG_WARN
¶ Error conditions from which recovery measures have been taken
-
ESP_LOG_INFO
¶ Information messages which describe normal flow of events
-
ESP_LOG_DEBUG
¶ Extra information which is not necessary for normal use (values, pointers, sizes, etc).
-
ESP_LOG_VERBOSE
¶ Bigger chunks of debugging information, or frequent messages which can potentially flood the output.
-
函数¶
-
void
esp_log_level_set
(const char *tag, esp_log_level_t level)¶ Set log level for given tag.
If logging for given component has already been enabled, changes previous setting.
- Parameters
tag
: Tag of the log entries to enable. Must be a non-NULL zero terminated string. Value “*” resets log level for all tags to the given value.level
: Selects log level to enable. Only logs at this and lower levels will be shown.
-
void
esp_log_set_vprintf
(vprintf_like_t func)¶ Set function used to output log entries.
By default, log output goes to UART0. This function can be used to redirect log output to some other destination, such as file or network.
- Parameters
func
: Function used for output. Must have same signature as vprintf.
-
uint32_t
esp_log_timestamp
(void)¶ Function which returns timestamp to be used in log output.
This function is used in expansion of ESP_LOGx macros. In the 2nd stage bootloader, and at early application startup stage this function uses CPU cycle counter as time source. Later when FreeRTOS scheduler start running, it switches to FreeRTOS tick count.
For now, we ignore millisecond counter overflow.
- Return
- timestamp, in milliseconds
-
void
esp_log_write
(esp_log_level_t level, const char *tag, const char *format, ...)¶ Write message into the log.
This function is not intended to be used directly. Instead, use one of ESP_LOGE, ESP_LOGW, ESP_LOGI, ESP_LOGD, ESP_LOGV macros.
This function or these macros should not be used from an interrupt.
关于本节 API 的示例代码请参考 ESP-IDF 示例中的 system 目录。
存储器 API¶
SPI Flash APIs¶
Overview¶
The spi_flash component contains APIs related to reading, writing, erasing, memory mapping data in the external SPI flash. It also has higher-level APIs which work with partitions defined in the partition table.
Note that all the functionality is limited to the “main” SPI flash chip,
the same SPI flash chip from which program runs. For spi_flash_*
functions,
this is a software limitation. The underlying ROM functions which work with SPI flash
do not have provisions for working with flash chips attached to SPI peripherals
other than SPI0.
SPI flash access APIs¶
This is the set of APIs for working with data in flash:
spi_flash_read
used to read data from flash to RAMspi_flash_write
used to write data from RAM to flashspi_flash_erase_sector
used to erase individual sectors of flashspi_flash_erase_range
used to erase range of addresses in flashspi_flash_get_chip_size
returns flash chip size, in bytes, as configured in menuconfig
Generally, try to avoid using the raw SPI flash functions in favour of partition-specific functions.
SPI Flash Size¶
The SPI flash size is configured by writing a field in the software bootloader image header, flashed at offset 0x1000.
By default, the SPI flash size is detected by esptool.py when this bootloader is
written to flash, and the header is updated with the correct
size. Alternatively, it is possible to generate a fixed flash size by disabling
detection in make menuconfig
(under Serial Flasher Config).
If it is necessary to override the configured flash size at runtime, is is
possible to set the chip_size
member of g_rom_flashchip
structure. This
size is used by spi_flash_*
functions (in both software & ROM) for bounds
checking.
Concurrency Constraints¶
Because the SPI flash is also used for firmware execution (via the instruction & data caches), these caches much be disabled while reading/writing/erasing. This means that both CPUs must be running code from IRAM and only reading data from DRAM while flash write operations occur.
Refer to the application memory layout documentation for an explanation of the differences between IRAM, DRAM and flash cache.
To avoid reading flash cache accidentally, when one CPU commences a flash write or erase operation the other CPU is put into a blocked state and all non-IRAM-safe interrupts are disabled on both CPUs, until the flash operation completes.
IRAM-Safe Interrupt Handlers¶
If you have an interrupt handler that you want to execute even when a flash
operation is in progress (for example, for low latency operations), set the
ESP_INTR_FLAG_IRAM
flag when the interrupt handler is registered.
You must ensure all data and functions accessed by these interrupt handlers are located in IRAM or DRAM. This includes any functions that the handler calls.
Use the IRAM_ATTR
attribute for functions:
#include "esp_attr.h"
void IRAM_ATTR gpio_isr_handler(void* arg)
{
// ...
}
Use the DRAM_ATTR
and DRAM_STR
attributes for constant data:
void IRAM_ATTR gpio_isr_handler(void* arg)
{
const static DRAM_ATTR uint8_t INDEX_DATA[] = { 45, 33, 12, 0 };
const static char *MSG = DRAM_STR("I am a string stored in RAM");
}
Note that knowing which data should be marked with DRAM_ATTR
can be hard,
the compiler will sometimes recognise that a variable or expression is constant
(even if it is not marked const
) and optimise it into flash, unless it is
marked with DRAM_ATTR
.
If a function or symbol is not correctly put into IRAM/DRAM and the interrupt handler reads from the flash cache during a flash operation, it will cause a crash due to Illegal Instruction exception (for code which should be in IRAM) or garbage data to be read (for constant data which should be in DRAM).
Partition table APIs¶
ESP-IDF projects use a partition table to maintain information about various regions of SPI flash memory (bootloader, various application binaries, data, filesystems). More information about partition tables can be found here.
This component provides APIs to enumerate partitions found in the partition table
and perform operations on them. These functions are declared in esp_partition.h
:
esp_partition_find
used to search partition table for entries with specific type, returns an opaque iteratoresp_partition_get
returns a structure describing the partition, for the given iteratoresp_partition_next
advances iterator to the next partition foundesp_partition_iterator_release
releases iterator returned byesp_partition_find
esp_partition_find_first
is a convenience function which returns structure describing the first partition found by esp_partition_findesp_partition_read
,esp_partition_write
,esp_partition_erase_range
are equivalent tospi_flash_read
,spi_flash_write
,spi_flash_erase_range
, but operate within partition boundaries
Most application code should use esp_partition_*
APIs instead of lower level
spi_flash_*
APIs. Partition APIs do bounds checking and calculate correct
offsets in flash based on data stored in partition table.
SPI Flash Encryption¶
It is possible to encrypt SPI flash contents, and have it transparenlty decrypted by hardware.
Refer to the Flash Encryption documentation for more details.
Memory mapping APIs¶
ESP32 features memory hardware which allows regions of flash memory to be mapped into instruction and data address spaces. This mapping works only for read operations, it is not possible to modify contents of flash memory by writing to mapped memory region. Mapping happens in 64KB pages. Memory mapping hardware can map up to 4 megabytes of flash into data address space, and up to 16 megabytes of flash into instruction address space. See the technical reference manual for more details about memory mapping hardware.
Note that some number of 64KB pages is used to map the application itself into memory, so the actual number of available 64KB pages may be less.
Reading data from flash using a memory mapped region is the only way to decrypt contents of flash when flash encryption is enabled. Decryption is performed at hardware level.
Memory mapping APIs are declared in esp_spi_flash.h
and esp_partition.h
:
spi_flash_mmap
maps a region of physical flash addresses into instruction space or data space of the CPUspi_flash_munmap
unmaps previously mapped regionesp_partition_mmap
maps part of a partition into the instruction space or data space of the CPU
Differences between spi_flash_mmap
and esp_partition_mmap
are as follows:
spi_flash_mmap
must be given a 64KB aligned physical addressesp_partition_mmap
may be given an arbitrary offset within the partition, it will adjust returned pointer to mapped memory as necessary
Note that because memory mapping happens in 64KB blocks, it may be possible to
read data outside of the partition provided to esp_partition_mmap
.
其它¶
- 分区表文档
- 空中升级(OTA)API 提供了更新存储在 flash 中的应用程序的顶层 API。
- 非易变存储器(NVS) API 提供了在 SPI flash 中存储小数据项的结构化 API。
API 参考手册¶
头文件¶
宏¶
-
ESP_ERR_FLASH_BASE
¶
-
ESP_ERR_FLASH_OP_FAIL
¶
-
ESP_ERR_FLASH_OP_TIMEOUT
¶
-
SPI_FLASH_SEC_SIZE
¶ SPI Flash sector size
-
SPI_FLASH_MMU_PAGE_SIZE
¶ Flash cache MMU mapping page size
-
ESP_PARTITION_SUBTYPE_OTA
(i)¶ Convenience macro to get esp_partition_subtype_t value for the i-th OTA partition.
-
SPI_FLASH_CACHE2PHYS_FAIL
¶
类型定义¶
-
typedef uint32_t
spi_flash_mmap_handle_t
¶ Opaque handle for memory region obtained from spi_flash_mmap.
-
typedef struct esp_partition_iterator_opaque_ *
esp_partition_iterator_t
¶ Opaque partition iterator type.
枚举¶
-
enum
spi_flash_mmap_memory_t
¶ Enumeration which specifies memory space requested in an mmap call.
Values:
-
SPI_FLASH_MMAP_DATA
¶ map to data memory (Vaddr0), allows byte-aligned access, 4 MB total
-
SPI_FLASH_MMAP_INST
¶ map to instruction memory (Vaddr1-3), allows only 4-byte-aligned access, 11 MB total
-
-
enum
esp_partition_type_t
¶ Partition type.
- Note
- Keep this enum in sync with PartitionDefinition class gen_esp32part.py
Values:
-
ESP_PARTITION_TYPE_APP
= 0x00¶ Application partition type.
-
ESP_PARTITION_TYPE_DATA
= 0x01¶ Data partition type.
-
enum
esp_partition_subtype_t
¶ Partition subtype.
- Note
- Keep this enum in sync with PartitionDefinition class gen_esp32part.py
Values:
-
ESP_PARTITION_SUBTYPE_APP_FACTORY
= 0x00¶ Factory application partition.
-
ESP_PARTITION_SUBTYPE_APP_OTA_MIN
= 0x10¶ Base for OTA partition subtypes.
-
ESP_PARTITION_SUBTYPE_APP_OTA_0
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 0¶ OTA partition 0.
-
ESP_PARTITION_SUBTYPE_APP_OTA_1
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 1¶ OTA partition 1.
-
ESP_PARTITION_SUBTYPE_APP_OTA_2
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 2¶ OTA partition 2.
-
ESP_PARTITION_SUBTYPE_APP_OTA_3
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 3¶ OTA partition 3.
-
ESP_PARTITION_SUBTYPE_APP_OTA_4
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 4¶ OTA partition 4.
-
ESP_PARTITION_SUBTYPE_APP_OTA_5
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 5¶ OTA partition 5.
-
ESP_PARTITION_SUBTYPE_APP_OTA_6
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 6¶ OTA partition 6.
-
ESP_PARTITION_SUBTYPE_APP_OTA_7
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 7¶ OTA partition 7.
-
ESP_PARTITION_SUBTYPE_APP_OTA_8
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 8¶ OTA partition 8.
-
ESP_PARTITION_SUBTYPE_APP_OTA_9
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 9¶ OTA partition 9.
-
ESP_PARTITION_SUBTYPE_APP_OTA_10
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 10¶ OTA partition 10.
-
ESP_PARTITION_SUBTYPE_APP_OTA_11
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 11¶ OTA partition 11.
-
ESP_PARTITION_SUBTYPE_APP_OTA_12
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 12¶ OTA partition 12.
-
ESP_PARTITION_SUBTYPE_APP_OTA_13
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 13¶ OTA partition 13.
-
ESP_PARTITION_SUBTYPE_APP_OTA_14
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 14¶ OTA partition 14.
-
ESP_PARTITION_SUBTYPE_APP_OTA_15
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 15¶ OTA partition 15.
-
ESP_PARTITION_SUBTYPE_APP_OTA_MAX
= ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 16¶ Max subtype of OTA partition.
-
ESP_PARTITION_SUBTYPE_APP_TEST
= 0x20¶ Test application partition.
-
ESP_PARTITION_SUBTYPE_DATA_OTA
= 0x00¶ OTA selection partition.
-
ESP_PARTITION_SUBTYPE_DATA_PHY
= 0x01¶ PHY init data partition.
-
ESP_PARTITION_SUBTYPE_DATA_NVS
= 0x02¶ NVS partition.
-
ESP_PARTITION_SUBTYPE_DATA_COREDUMP
= 0x03¶ COREDUMP partition.
-
ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD
= 0x80¶ ESPHTTPD partition.
-
ESP_PARTITION_SUBTYPE_DATA_FAT
= 0x81¶ FAT partition.
-
ESP_PARTITION_SUBTYPE_DATA_SPIFFS
= 0x82¶ SPIFFS partition.
-
ESP_PARTITION_SUBTYPE_ANY
= 0xff¶ Used to search for partitions with any subtype.
结构体¶
-
struct
esp_partition_t
¶ partition information structure
This is not the format in flash, that format is esp_partition_info_t.
However, this is the format used by this API.
函数¶
-
void
spi_flash_init
()¶ Initialize SPI flash access driver.
This function must be called exactly once, before any other spi_flash_* functions are called. Currently this function is called from startup code. There is no need to call it from application code.
-
size_t
spi_flash_get_chip_size
()¶ Get flash chip size, as set in binary image header.
- Note
- This value does not necessarily match real flash size.
- Return
- size of flash chip, in bytes
-
esp_err_t
spi_flash_erase_sector
(size_t sector)¶ Erase the Flash sector.
- Return
- esp_err_t
- Parameters
sector
: Sector number, the count starts at sector 0, 4KB per sector.
-
esp_err_t
spi_flash_erase_range
(size_t start_address, size_t size)¶ Erase a range of flash sectors.
- Return
- esp_err_t
- Parameters
start_address
: Address where erase operation has to start. Must be 4kB-alignedsize
: Size of erased range, in bytes. Must be divisible by 4kB.
-
esp_err_t
spi_flash_write
(size_t dest_addr, const void *src, size_t size)¶ Write data to Flash.
- Note
- If source address is in DROM, this function will return ESP_ERR_INVALID_ARG.
- Return
- esp_err_t
- Parameters
dest_addr
: destination address in Flash. Must be a multiple of 4 bytes.src
: pointer to the source buffer.size
: length of data, in bytes. Must be a multiple of 4 bytes.
-
esp_err_t
spi_flash_write_encrypted
(size_t dest_addr, const void *src, size_t size)¶ Write data encrypted to Flash.
- Note
- Flash encryption must be enabled for this function to work.
- Note
- Flash encryption must be enabled when calling this function. If flash encryption is disabled, the function returns ESP_ERR_INVALID_STATE. Use esp_flash_encryption_enabled() function to determine if flash encryption is enabled.
- Note
- Both dest_addr and size must be multiples of 16 bytes. For absolute best performance, both dest_addr and size arguments should be multiples of 32 bytes.
- Return
- esp_err_t
- Parameters
dest_addr
: destination address in Flash. Must be a multiple of 16 bytes.src
: pointer to the source buffer.size
: length of data, in bytes. Must be a multiple of 16 bytes.
-
esp_err_t
spi_flash_read
(size_t src_addr, void *dest, size_t size)¶ Read data from Flash.
- Return
- esp_err_t
- Parameters
src_addr
: source address of the data in Flash.dest
: pointer to the destination buffersize
: length of data
-
esp_err_t
spi_flash_read_encrypted
(size_t src, void *dest, size_t size)¶ Read data from Encrypted Flash.
If flash encryption is enabled, this function will transparently decrypt data as it is read. If flash encryption is not enabled, this function behaves the same as spi_flash_read().
See esp_flash_encryption_enabled() for a function to check if flash encryption is enabled.
- Return
- esp_err_t
- Parameters
src
: source address of the data in Flash.dest
: pointer to the destination buffersize
: length of data
-
esp_err_t
spi_flash_mmap
(size_t src_addr, size_t size, spi_flash_mmap_memory_t memory, const void **out_ptr, spi_flash_mmap_handle_t *out_handle)¶ Map region of flash memory into data or instruction address space.
This function allocates sufficient number of 64k MMU pages and configures them to map request region of flash memory into data address space or into instruction address space. It may reuse MMU pages which already provide required mapping. As with any allocator, there is possibility of fragmentation of address space if mmap/munmap are heavily used. To troubleshoot issues with page allocation, use spi_flash_mmap_dump function.
- Return
- ESP_OK on success, ESP_ERR_NO_MEM if pages can not be allocated
- Parameters
src_addr
: Physical address in flash where requested region starts. This address must be aligned to 64kB boundary (SPI_FLASH_MMU_PAGE_SIZE).size
: Size of region which has to be mapped. This size will be rounded up to a 64k boundary.memory
: Memory space where the region should be mappedout_ptr
: Output, pointer to the mapped memory regionout_handle
: Output, handle which should be used for spi_flash_munmap call
-
void
spi_flash_munmap
(spi_flash_mmap_handle_t handle)¶ Release region previously obtained using spi_flash_mmap.
- Note
- Calling this function will not necessarily unmap memory region. Region will only be unmapped when there are no other handles which reference this region. In case of partially overlapping regions it is possible that memory will be unmapped partially.
- Parameters
handle
: Handle obtained from spi_flash_mmap
-
void
spi_flash_mmap_dump
()¶ Display information about mapped regions.
This function lists handles obtained using spi_flash_mmap, along with range of pages allocated to each handle. It also lists all non-zero entries of MMU table and corresponding reference counts.
-
size_t
spi_flash_cache2phys
(const void *cached)¶ Given a memory address where flash is mapped, return the corresponding physical flash offset.
Cache address does not have have been assigned via spi_flash_mmap(), any address in flash map space can be looked up.
- Return
- SPI_FLASH_CACHE2PHYS_FAIL If cache address is outside flash cache region, or the address is not mapped.
- Otherwise, returns physical offset in flash
- Parameters
cached
: Pointer to flashed cached memory.
-
const void *
spi_flash_phys2cache
(size_t phys_offs, spi_flash_mmap_memory_t memory)¶ Given a physical offset in flash, return the address where it is mapped in the memory space.
Physical address does not have to have been assigned via spi_flash_mmap(), any address in flash can be looked up.
- Note
- Only the first matching cache address is returned. If MMU flash cache table is configured so multiple entries point to the same physical address, there may be more than one cache address corresponding to that physical address. It is also possible for a single physical address to be mapped to both the IROM and DROM regions.
- Note
- This function doesn’t impose any alignment constraints, but if memory argument is SPI_FLASH_MMAP_INST and phys_offs is not 4-byte aligned, then reading from the returned pointer will result in a crash.
- Return
- NULL if the physical address is invalid or not mapped to flash cache of the specified memory type.
- Cached memory address (in IROM or DROM space) corresponding to phys_offs.
- Parameters
phys_offs
: Physical offset in flash memory to look up.memory
: Memory type to look up a flash cache address mapping for (IROM or DROM)
-
bool
spi_flash_cache_enabled
()¶ Check at runtime if flash cache is enabled on both CPUs.
- Return
- true if both CPUs have flash cache enabled, false otherwise.
-
esp_partition_iterator_t
esp_partition_find
(esp_partition_type_t type, esp_partition_subtype_t subtype, const char *label)¶ Find partition based on one or more parameters.
- Return
- iterator which can be used to enumerate all the partitions found, or NULL if no partitions were found. Iterator obtained through this function has to be released using esp_partition_iterator_release when not used any more.
- Parameters
type
: Partition type, one of esp_partition_type_t valuessubtype
: Partition subtype, one of esp_partition_subtype_t values. To find all partitions of given type, use ESP_PARTITION_SUBTYPE_ANY.label
: (optional) Partition label. Set this value if looking for partition with a specific name. Pass NULL otherwise.
-
const esp_partition_t *
esp_partition_find_first
(esp_partition_type_t type, esp_partition_subtype_t subtype, const char *label)¶ Find first partition based on one or more parameters.
- Return
- pointer to esp_partition_t structure, or NULL if no partition is found. This pointer is valid for the lifetime of the application.
- Parameters
type
: Partition type, one of esp_partition_type_t valuessubtype
: Partition subtype, one of esp_partition_subtype_t values. To find all partitions of given type, use ESP_PARTITION_SUBTYPE_ANY.label
: (optional) Partition label. Set this value if looking for partition with a specific name. Pass NULL otherwise.
-
const esp_partition_t *
esp_partition_get
(esp_partition_iterator_t iterator)¶ Get esp_partition_t structure for given partition.
- Return
- pointer to esp_partition_t structure. This pointer is valid for the lifetime of the application.
- Parameters
iterator
: Iterator obtained using esp_partition_find. Must be non-NULL.
-
esp_partition_iterator_t
esp_partition_next
(esp_partition_iterator_t iterator)¶ Move partition iterator to the next partition found.
Any copies of the iterator will be invalid after this call.
- Return
- NULL if no partition was found, valid esp_partition_iterator_t otherwise.
- Parameters
iterator
: Iterator obtained using esp_partition_find. Must be non-NULL.
-
void
esp_partition_iterator_release
(esp_partition_iterator_t iterator)¶ Release partition iterator.
- Parameters
iterator
: Iterator obtained using esp_partition_find. Must be non-NULL.
-
esp_err_t
esp_partition_read
(const esp_partition_t *partition, size_t src_offset, void *dst, size_t size)¶ Read data from the partition.
- Return
- ESP_OK, if data was read successfully; ESP_ERR_INVALID_ARG, if src_offset exceeds partition size; ESP_ERR_INVALID_SIZE, if read would go out of bounds of the partition; or one of error codes from lower-level flash driver.
- Parameters
partition
: Pointer to partition structure obtained using esp_partition_find_first or esp_partition_get. Must be non-NULL.dst
: Pointer to the buffer where data should be stored. Pointer must be non-NULL and buffer must be at least ‘size’ bytes long.src_offset
: Address of the data to be read, relative to the beginning of the partition.size
: Size of data to be read, in bytes.
-
esp_err_t
esp_partition_write
(const esp_partition_t *partition, size_t dst_offset, const void *src, size_t size)¶ Write data to the partition.
Before writing data to flash, corresponding region of flash needs to be erased. This can be done using esp_partition_erase_range function.
Partitions marked with an encryption flag will automatically be written via the spi_flash_write_encrypted() function. If writing to an encrypted partition, all write offsets and lengths must be multiples of 16 bytes. See the spi_flash_write_encrypted() function for more details. Unencrypted partitions do not have this restriction.
- Note
- Prior to writing to flash memory, make sure it has been erased with esp_partition_erase_range call.
- Return
- ESP_OK, if data was written successfully; ESP_ERR_INVALID_ARG, if dst_offset exceeds partition size; ESP_ERR_INVALID_SIZE, if write would go out of bounds of the partition; or one of error codes from lower-level flash driver.
- Parameters
partition
: Pointer to partition structure obtained using esp_partition_find_first or esp_partition_get. Must be non-NULL.dst_offset
: Address where the data should be written, relative to the beginning of the partition.src
: Pointer to the source buffer. Pointer must be non-NULL and buffer must be at least ‘size’ bytes long.size
: Size of data to be written, in bytes.
-
esp_err_t
esp_partition_erase_range
(const esp_partition_t *partition, uint32_t start_addr, uint32_t size)¶ Erase part of the partition.
- Return
- ESP_OK, if the range was erased successfully; ESP_ERR_INVALID_ARG, if iterator or dst are NULL; ESP_ERR_INVALID_SIZE, if erase would go out of bounds of the partition; or one of error codes from lower-level flash driver.
- Parameters
partition
: Pointer to partition structure obtained using esp_partition_find_first or esp_partition_get. Must be non-NULL.start_addr
: Address where erase operation should start. Must be aligned to 4 kilobytes.size
: Size of the range which should be erased, in bytes. Must be divisible by 4 kilobytes.
-
esp_err_t
esp_partition_mmap
(const esp_partition_t *partition, uint32_t offset, uint32_t size, spi_flash_mmap_memory_t memory, const void **out_ptr, spi_flash_mmap_handle_t *out_handle)¶ Configure MMU to map partition into data memory.
Unlike spi_flash_mmap function, which requires a 64kB aligned base address, this function doesn’t impose such a requirement. If offset results in a flash address which is not aligned to 64kB boundary, address will be rounded to the lower 64kB boundary, so that mapped region includes requested range. Pointer returned via out_ptr argument will be adjusted to point to the requested offset (not necessarily to the beginning of mmap-ed region).
To release mapped memory, pass handle returned via out_handle argument to spi_flash_munmap function.
- Return
- ESP_OK, if successful
- Parameters
partition
: Pointer to partition structure obtained using esp_partition_find_first or esp_partition_get. Must be non-NULL.offset
: Offset from the beginning of partition where mapping should start.size
: Size of the area to be mapped.memory
: Memory space where the region should be mappedout_ptr
: Output, pointer to the mapped memory regionout_handle
: Output, handle which should be used for spi_flash_munmap call
-
static bool
esp_flash_encryption_enabled
(void)¶ Is flash encryption currently enabled in hardware?
Flash encryption is enabled if the FLASH_CRYPT_CNT efuse has an odd number of bits set.
- Return
- true if flash encryption is enabled.
实现细节¶
为了执行某些 flash 操作,我们需要确保两个 CPU 在 flash 操作期间都没有从 flash 运行任何代码。在单核中,这非常简单:禁止中断/调度器,然后执行 flash 操作。在双核中,所谓有点复杂。我们需要确保其它 CPU 没有从 flash 上面运行任何代码。
当 SPI flahs API 在 CPU A(可以是 PRO 或者 APP)上被调用,我们使用 API esp_ipc_call 在 CPU B 上启动函数 spi_flash_op_block_func。这个 API 会唤醒 CPU B 上的高优先级任务,告诉它取执行所给函数,即 spi_flash_op_block_func。该函数子啊 CPU B 上 When SPI flash API is called on CPU A (can be PRO or APP), we start spi_flash_op_block_func function on CPU B using esp_ipc_call API. This API wakes up high priority task on CPU B and tells it to execute given function, in this case spi_flash_op_block_func. This function disables cache on CPU B and signals that cache is disabled by setting s_flash_op_can_start flag. Then the task on CPU A disables cache as well, and proceeds to execute flash operation.
While flash operation is running, interrupts can still run on CPUs A and B. We assume that all interrupt code is placed into RAM. Once interrupt allocation API is added, we should add a flag to request interrupt to be disabled for the duration of flash operations.
Once flash operation is complete, function on CPU A sets another flag, s_flash_op_complete, to let the task on CPU B know that it can re-enable cache and release the CPU. Then the function on CPU A re-enables the cache on CPU A as well and returns control to the calling code.
Additionally, all API functions are protected with a mutex (s_flash_op_mutex).
In a single core environment (CONFIG_FREERTOS_UNICORE enabled), we simply disable both caches, no inter-CPU communication takes place.
非易失性存储器(NVS)库¶
简介¶
非易失性存储器(Non-volatile storage,NVS)库被设计用于在 flash 中存储键值对。本节介绍一些在 NVS 中所使用的概念。
Underlying storage¶
当前,NVS 通过 spi_flash_{read|write|erase}
API 使用了一部分主 flash 存储器。该库使用第一个分区 —— 其类型是 data
,子类型是 nvs
。
该库将来可能会添加其它的存储器后端,让数据可以保存在另一个 flash(I2C 或者 SPI)芯片、RTC、FRAM 等中。
注解
如果 NVS 分区被截断了(例如分区表布局文件被修改),它上面的内容必修被擦除。ESP-IDF 构建系统提供了一个 make erase_flash
目标来擦除 flash 芯片上的所有内容。
键和值¶
NVS 操作的对象是键值对。键是 ASCII 字符串,当前的最大键长度是 15 个字符。值可以是下面某一种类型:
- 整数值
uint8_t
,int8_t
,uint16_t
,int16_t
,uint32_t
,int32_t
,uint64_t
,int64_t
- 以零结尾的字符串
- 长度可变的二进制数据 (blob)
在今后也可能支持其它类型,例如 float
和 double
。
键必须是唯一的。向一个已存在的键写值时的行为如下:
- 如果新值与就指类型相同,则将值更新
- 如果新值与就指类型相同,则返回一个错误
读取值时会执行能够数据类型检查。如果读操作的数据类型与值的数据类型不匹配,则返回一个错误。
命名空间¶
为了减小不同组件间命令冲突的可能性,NVS 将每个键值对分配到一个命名空间中。命名空间的名字与键名的规则相同,即最长 15 个字符。命名空间的名字在执行 nvs_open
调用时指定。这个调用会返回一个不透明的句柄,这个句柄在随后调用函数 nvs_read_*`、nvs_write_*
和 nvs_commit
时使用。这样,句柄与命名空间相关联,键名就不会与其它组件具有相同名字的键冲突。
安全、篡改和鲁棒性¶
NVS 库没有实现篡改预防策略。任何可以在物理上访问芯片的代码都可以更改、擦除或添加新的键值对。
NVS 与 ESP32 的 flash 加密系统是兼容的,它可以以加密形式存储键值对。一些元数据,例如页状态、私立入口(individual entries)的写/擦除标志,不能被加密,因为因为它们表示为有效访问和操作 flash 存储器的比特。Flash 加密可以阻止某些形式的修改:
- 使用任意值替换键或值
- 改变值的数据类型
下列形式的修改即使在使用了 flash 加密依然可以:
- 完整地擦除页,移除该页中擦除的所有键值对
- 破坏(corrupting)页中的数据,发生这种情况将会造成页被自动擦除
- 回滚 flash 存储器的状态到某个早期快照
- 合并 flash 存储器的两个快照,回滚一些键值对到某个早起状态(即使当前的设计还不支持 — TODO)
当 flash 存储器处于非一致性状态时,库会尝试取从这些条件中恢复。特别的,你可以在任何时间、任何点将设备断电再上电,除了新键值对(即该键值对正在写时断电了),这一般不会造成数据丢失。库能够能够使用 flash 存储器中的任何随机数进行恰当地初始化。
内部¶
键值对的记录¶
NVS 按顺序存储键值对,新的键值对被添加到末尾。当任意所给键的值被更新时,新的键值对别添加到记录(log)的默认,旧的键值对被标记未已擦除。
页和条目¶
NVS 库在操作时主要使用了两种实体:页(page)和条目(entry)。页是一个存储整个记录中一部分内容的逻辑结构。逻辑页对应一个 flash 存储器的扇区。正在使用的页有一个与之绑定咋一起的 序列号(sequence number)。序列号反映了也的顺序。序列号越大表示页创建的时间越晚。每个页可以处于下列的某种状态:
- 空/未初始化(Empty/uninitialized)
- 页的 flash 存储器是空的,即所有的字节都是``0xff``。在这种状态时,页不能用于存储任何数据,也没有序列号。
- 有效(Active)
- Flash 存储器被初始化了,页的头部被写到 flash 中,且页有一个序列号。页有一些可以被写入的空的条目和数据。大多数时候,页都处于这种状态。
- 满(Full)
- Flash 存储器处于一个一致性转台,且被写满了键值对。向该页新写的键值对将失败。此时仍然可以将某些键值对标记为已擦除。
- 擦除中(Erasing)
- 未被标记未已擦除的键值对正在被移动到另一页,然后该也就可以被擦除。这是一个临时状态,即当任何 API 调用返回时页都不会处于该状态。如果遇到突然断电,移动-擦除操作将在下一次上电后继续。
- 被破坏(Corrupted)
- 页的头部包含无效的数据,对页数据的解析将会取消。之前写入该页的任何数据都不可访问。相应的 flash 扇区不会立即擦除,将会保持为 未初始化 状态,以供今后使用。这有助于进行调试。
从 flash 扇区到逻辑页的映射没有任何特殊的顺序。库将会检查每个 flash 扇区中的页序列号,然后基于这些数字将页按照形成一个链表。
+--------+ +--------+ +--------+ +--------+
| Page 1 | | Page 2 | | Page 3 | | Page 4 |
| Full +---> | Full +---> | Active | | Empty | <- states
| #11 | | #12 | | #14 | | | <- sequence numbers
+---+----+ +----+---+ +----+---+ +---+----+
| | | |
| | | |
| | | |
+---v------+ +-----v----+ +------v---+ +------v---+
| Sector 3 | | Sector 0 | | Sector 2 | | Sector 1 | <- physical sectors
+----------+ +----------+ +----------+ +----------+
页的结构¶
现在我们假设 flash 扇区的大小是 4096 字节,且 ESP32 的 flash 加密硬件是以 32 字节块为单位进行操作的。为了适应扇区大小不相同的 flash 芯片,可以在编译时(例如通过配置菜单)引入一些可配置的设置(尽管不清楚系统其它组件,例如 SPI flash 驱动和 SPI flash cache,是否可以支持其它的大小)。
页由三部分组成:头部、条目状态位映射(bitmap)和条目自身。为了与 ESP32 的 flash 加密兼容,条目的大小是 32 字节。对于整数类型,条目拥有一个键值对。对于字符串和块(blob),条目拥有部分键值对(更多的在条目的结构体描述符中)。
下列框图描述了页的结构。原括号中的数字表示每部分的大小(以字节为单位)。
+-----------+--------------+-------------+-----------+
| State (4) | Seq. no. (4) | Unused (20) | CRC32 (4) | Header (32)
+-----------+--------------+-------------+-----------+
| Entry state bitmap (32) |
+----------------------------------------------------+
| Entry 0 (32) |
+----------------------------------------------------+
| Entry 1 (32) |
+----------------------------------------------------+
/ /
/ /
+----------------------------------------------------+
| Entry 125 (32) |
+----------------------------------------------------+
页的头部和条目状态位映射通常被写到 flash 的未加密部分。如果使用了 ESP32 的 flash 加密功能,条目会被加密。
页的状态是这样定义的:向某些比特写 0 可以改变状态。因此,一般没有必要通过擦除页来改变页的状态,除非要改变的状态是 已擦除 状态。
头部中计算的 CRC32 值不包括状态值(底 4 ~ 28 字节)。未使用部分当前使用 0xff
填充。今后的库可能会在这里存储格式化版本。
下面的章节描述了条目状态位映射和条目自身的结构。
条目和条目状态位映射¶
每个条目可以处于一下三个状态之一。每个状态都由条目状态位映射中的两个比特表示。位映射中的最后四个比特(256 - 2 * 126)未被使用。
- 空 Empty (2’b11)
- 所指定的条目还没有写入任何东西。这是一个未初始化状态(所有的字节都是
0xff
)。 - 已写入 Written (2’b10)
- 一个键值对(或者跨越多个条目的键值对的一部分)已被写入到条目。
- 已擦除 Erased (2’b00)
- 该条目中的键值对被丢弃。该条目中的内容将不会被解析。
条目的结构¶
For values of primitive types (currently integers from 1 to 8 bytes long), entry holds one key-value pair. For string and blob types, entry holds part of the whole key-value pair. In case when a key-value pair spans multiple entries, all entries are stored in the same page.
+--------+----------+----------+---------+-----------+---------------+----------+
| NS (1) | Type (1) | Span (1) | Rsv (1) | CRC32 (4) | Key (16) | Data (8) |
+--------+----------+----------+---------+-----------+---------------+----------+
+--------------------------------+
+-> Fixed length: | Data (8) |
| +--------------------------------+
Data format ---+
| +----------+---------+-----------+
+-> Variable length: | Size (2) | Rsv (2) | CRC32 (4) |
+----------+---------+-----------+
Individual fields in entry structure have the following meanings:
- NS
- Namespace index for this entry. See section on namespaces implementation for explanation of this value.
- Type
- One byte indicating data type of value. See
ItemType
enumeration innvs_types.h
for possible values. - Span
- Number of entries used by this key-value pair. For integer types, this is equal to 1. For strings and blobs this depends on value length.
- Rsv
- Unused field, should be
0xff
. - CRC32
- Checksum calculated over all the bytes in this entry, except for the CRC32 field itself.
- Key
- Zero-terminated ASCII string containing key name. Maximum string length is 15 bytes, excluding zero terminator.
- Data
- For integer types, this field contains the value itself. If the value itself is shorter than 8 bytes it is padded to the right, with unused bytes filled with
0xff
. For string and blob values, these 8 bytes hold additional data about the value, described next: - Size
- (Only for strings and blobs.) Size, in bytes, of actual data. For strings, this includes zero terminator.
- CRC32
- (Only for strings and blobs.) Checksum calculated over all bytes of data.
Variable length values (strings and blobs) are written into subsequent entries, 32 bytes per entry. Span field of the first entry indicates how many entries are used.
命名空间¶
As mentioned above, each key-value pair belongs to one of the namespaces. Namespaces identifiers (strings) are stored as keys of key-value pairs in namespace with index 0. Values corresponding to these keys are indexes of these namespaces.
+-------------------------------------------+
| NS=0 Type=uint8_t Key="wifi" Value=1 | Entry describing namespace "wifi"
+-------------------------------------------+
| NS=1 Type=uint32_t Key="channel" Value=6 | Key "channel" in namespace "wifi"
+-------------------------------------------+
| NS=0 Type=uint8_t Key="pwm" Value=2 | Entry describing namespace "pwm"
+-------------------------------------------+
| NS=2 Type=uint16_t Key="channel" Value=20 | Key "channel" in namespace "pwm"
+-------------------------------------------+
Item 哈希链表¶
To reduce the number of reads performed from flash memory, each member of Page class maintains a list of pairs: (item index; item hash). This list makes searches much quicker. Instead of iterating over all entries, reading them from flash one at a time, Page::findItem
first performs search for item hash in the hash list. This gives the item index within the page, if such an item exists. Due to a hash collision it is possible that a different item will be found. This is handled by falling back to iteration over items in flash.
Each node in hash list contains a 24-bit hash and 8-bit item index. Hash is calculated based on item namespace and key name. CRC32 is used for calculation, result is truncated to 24 bits. To reduce overhead of storing 32-bit entries in a linked list, list is implemented as a doubly-linked list of arrays. Each array holds 29 entries, for the total size of 128 bytes, together with linked list pointers and 32-bit count field. Minimal amount of extra RAM useage per page is therefore 128 bytes, maximum is 640 bytes.
应用程序示例¶
下面这两个示例是在 ESP-IDF 示例的 storage 目录提供的:
演示了如何使用 NVS 读写一个整数值。
该值记录了 ESP32 模块重启的次数。由于它是写到 NVS 中的,因此重启后该值还保留着。
示例还演示了如何检查读/写操作是否成功,或者某个值在 NVS 中是否被初始化了。 提供的诊断消息可用于帮助跟踪程序流、采集问题。
演示了如何使用 NVS 读/写一个整数值和一块数据(二进制大对象,blob),让它们在 ESP32 模块重启后依然保存着。
- 值 - 跟踪 ESP32 模块软件/硬件重启的次数.
- 块(blob) - 包含一个记录模块运行时间的表格。程序会将表格由 NVS 读取到动态分配的 RAM。每次手工触发软件复位时,新的运行时间被添加到表格中,并被写回 NVS。触发是通过下拉 GPIO0 完成的。
示例还演示了如何检查读/写操作是否成功。
API 参考手册¶
宏¶
-
ESP_ERR_NVS_BASE
¶ Starting number of error codes
-
ESP_ERR_NVS_NOT_INITIALIZED
¶ The storage driver is not initialized
-
ESP_ERR_NVS_NOT_FOUND
¶ Id namespace doesn’t exist yet and mode is NVS_READONLY
-
ESP_ERR_NVS_TYPE_MISMATCH
¶ The type of set or get operation doesn’t match the type of value stored in NVS
-
ESP_ERR_NVS_READ_ONLY
¶ Storage handle was opened as read only
-
ESP_ERR_NVS_NOT_ENOUGH_SPACE
¶ There is not enough space in the underlying storage to save the value
-
ESP_ERR_NVS_INVALID_NAME
¶ Namespace name doesn’t satisfy constraints
-
ESP_ERR_NVS_INVALID_HANDLE
¶ Handle has been closed or is NULL
-
ESP_ERR_NVS_REMOVE_FAILED
¶ The value wasn’t updated because flash write operation has failed. The value was written however, and update will be finished after re-initialization of nvs, provided that flash operation doesn’t fail again.
-
ESP_ERR_NVS_KEY_TOO_LONG
¶ Key name is too long
-
ESP_ERR_NVS_PAGE_FULL
¶ Internal error; never returned by nvs_ API functions
-
ESP_ERR_NVS_INVALID_STATE
¶ NVS is in an inconsistent state due to a previous error. Call nvs_flash_init and nvs_open again, then retry.
-
ESP_ERR_NVS_INVALID_LENGTH
¶ String or blob length is not sufficient to store data
-
ESP_ERR_NVS_NO_FREE_PAGES
¶ NVS partition doesn’t contain any empty pages. This may happen if NVS partition was truncated. Erase the whole partition and call nvs_flash_init again.
枚举¶
函数¶
-
esp_err_t
nvs_flash_init
(void)¶ Initialize NVS flash storage with layout given in the partition table.
- Return
- ESP_OK if storage was successfully initialized.
- ESP_ERR_NVS_NO_FREE_PAGES if the NVS storage contains no empty pages (which may happen if NVS partition was truncated)
- one of the error codes from the underlying flash storage driver
-
esp_err_t
nvs_open
(const char *name, nvs_open_mode open_mode, nvs_handle *out_handle)¶ Open non-volatile storage with a given namespace.
Multiple internal ESP-IDF and third party application modules can store their key-value pairs in the NVS module. In order to reduce possible conflicts on key names, each module can use its own namespace.
- Return
- ESP_OK if storage handle was opened successfully
- ESP_ERR_NVS_NOT_INITIALIZED if the storage driver is not initialized
- ESP_ERR_NVS_NOT_FOUND id namespace doesn’t exist yet and mode is NVS_READONLY
- ESP_ERR_NVS_INVALID_NAME if namespace name doesn’t satisfy constraints
- other error codes from the underlying storage driver
- Parameters
name
: Namespace name. Maximal length is determined by the underlying implementation, but is guaranteed to be at least 16 characters. Shouldn’t be empty.open_mode
: NVS_READWRITE or NVS_READONLY. If NVS_READONLY, will open a handle for reading only. All write requests will be rejected for this handle.out_handle
: If successful (return code is zero), handle will be returned in this argument.
-
esp_err_t
nvs_set_i8
(nvs_handle handle, const char *key, int8_t value)¶ set value for given key
This family of functions set value for the key, given its name. Note that actual storage will not be updated until nvs_commit function is called.
- Return
- ESP_OK if value was set successfully
- ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
- ESP_ERR_NVS_READ_ONLY if storage handle was opened as read only
- ESP_ERR_NVS_INVALID_NAME if key name doesn’t satisfy constraints
- ESP_ERR_NVS_NOT_ENOUGH_SPACE if there is not enough space in the underlying storage to save the value
- ESP_ERR_NVS_REMOVE_FAILED if the value wasn’t updated because flash write operation has failed. The value was written however, and update will be finished after re-initialization of nvs, provided that flash operation doesn’t fail again.
- Parameters
handle
: Handle obtained from nvs_open function. Handles that were opened read only cannot be used.key
: Key name. Maximal length is determined by the underlying implementation, but is guaranteed to be at least 16 characters. Shouldn’t be empty.value
: The value to set.
-
esp_err_t
nvs_set_u8
(nvs_handle handle, const char *key, uint8_t value)¶
-
esp_err_t
nvs_set_i16
(nvs_handle handle, const char *key, int16_t value)¶
-
esp_err_t
nvs_set_u16
(nvs_handle handle, const char *key, uint16_t value)¶
-
esp_err_t
nvs_set_i32
(nvs_handle handle, const char *key, int32_t value)¶
-
esp_err_t
nvs_set_u32
(nvs_handle handle, const char *key, uint32_t value)¶
-
esp_err_t
nvs_set_i64
(nvs_handle handle, const char *key, int64_t value)¶
-
esp_err_t
nvs_set_u64
(nvs_handle handle, const char *key, uint64_t value)¶
-
esp_err_t
nvs_set_str
(nvs_handle handle, const char *key, const char *value)¶
-
esp_err_t
nvs_set_blob
(nvs_handle handle, const char *key, const void *value, size_t length)¶ set variable length binary value for given key
This family of functions set value for the key, given its name. Note that actual storage will not be updated until nvs_commit function is called.
- Return
- ESP_OK if value was set successfully
- ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
- ESP_ERR_NVS_READ_ONLY if storage handle was opened as read only
- ESP_ERR_NVS_INVALID_NAME if key name doesn’t satisfy constraints
- ESP_ERR_NVS_NOT_ENOUGH_SPACE if there is not enough space in the underlying storage to save the value
- ESP_ERR_NVS_REMOVE_FAILED if the value wasn’t updated because flash write operation has failed. The value was written however, and update will be finished after re-initialization of nvs, provided that flash operation doesn’t fail again.
- Parameters
handle
: Handle obtained from nvs_open function. Handles that were opened read only cannot be used.key
: Key name. Maximal length is determined by the underlying implementation, but is guaranteed to be at least 16 characters. Shouldn’t be empty.value
: The value to set.length
: length of binary value to set, in bytes.
-
esp_err_t
nvs_get_i8
(nvs_handle handle, const char *key, int8_t *out_value)¶ get value for given key
These functions retrieve value for the key, given its name. If key does not exist, or the requested variable type doesn’t match the type which was used when setting a value, an error is returned.
In case of any error, out_value is not modified.
All functions expect out_value to be a pointer to an already allocated variable of the given type.
// Example of using nvs_get_i32: int32_t max_buffer_size = 4096; // default value esp_err_t err = nvs_get_i32(my_handle, "max_buffer_size", &max_buffer_size); assert(err == ESP_OK || err == ESP_ERR_NVS_NOT_FOUND); // if ESP_ERR_NVS_NOT_FOUND was returned, max_buffer_size will still // have its default value.
- Return
- ESP_OK if the value was retrieved successfully
- ESP_ERR_NVS_NOT_FOUND if the requested key doesn’t exist
- ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
- ESP_ERR_NVS_INVALID_NAME if key name doesn’t satisfy constraints
- ESP_ERR_NVS_INVALID_LENGTH if length is not sufficient to store data
- Parameters
handle
: Handle obtained from nvs_open function.key
: Key name. Maximal length is determined by the underlying implementation, but is guaranteed to be at least 16 characters. Shouldn’t be empty.out_value
: Pointer to the output value. May be NULL for nvs_get_str and nvs_get_blob, in this case required length will be returned in length argument.
-
esp_err_t
nvs_get_u8
(nvs_handle handle, const char *key, uint8_t *out_value)¶
-
esp_err_t
nvs_get_i16
(nvs_handle handle, const char *key, int16_t *out_value)¶
-
esp_err_t
nvs_get_u16
(nvs_handle handle, const char *key, uint16_t *out_value)¶
-
esp_err_t
nvs_get_i32
(nvs_handle handle, const char *key, int32_t *out_value)¶
-
esp_err_t
nvs_get_u32
(nvs_handle handle, const char *key, uint32_t *out_value)¶
-
esp_err_t
nvs_get_i64
(nvs_handle handle, const char *key, int64_t *out_value)¶
-
esp_err_t
nvs_get_u64
(nvs_handle handle, const char *key, uint64_t *out_value)¶
-
esp_err_t
nvs_get_str
(nvs_handle handle, const char *key, char *out_value, size_t *length)¶ get value for given key
These functions retrieve value for the key, given its name. If key does not exist, or the requested variable type doesn’t match the type which was used when setting a value, an error is returned.
In case of any error, out_value is not modified.
All functions expect out_value to be a pointer to an already allocated variable of the given type.
nvs_get_str and nvs_get_blob functions support WinAPI-style length queries. To get the size necessary to store the value, call nvs_get_str or nvs_get_blob with zero out_value and non-zero pointer to length. Variable pointed to by length argument will be set to the required length. For nvs_get_str, this length includes the zero terminator. When calling nvs_get_str and nvs_get_blob with non-zero out_value, length has to be non-zero and has to point to the length available in out_value. It is suggested that nvs_get/set_str is used for zero-terminated C strings, and nvs_get/set_blob used for arbitrary data structures.
// Example (without error checking) of using nvs_get_str to get a string into dynamic array: size_t required_size; nvs_get_str(my_handle, "server_name", NULL, &required_size); char* server_name = malloc(required_size); nvs_get_str(my_handle, "server_name", server_name, &required_size); // Example (without error checking) of using nvs_get_blob to get a binary data into a static array: uint8_t mac_addr[6]; size_t size = sizeof(mac_addr); nvs_get_blob(my_handle, "dst_mac_addr", mac_addr, &size);
- Return
- ESP_OK if the value was retrieved successfully
- ESP_ERR_NVS_NOT_FOUND if the requested key doesn’t exist
- ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
- ESP_ERR_NVS_INVALID_NAME if key name doesn’t satisfy constraints
- ESP_ERR_NVS_INVALID_LENGTH if length is not sufficient to store data
- Parameters
handle
: Handle obtained from nvs_open function.key
: Key name. Maximal length is determined by the underlying implementation, but is guaranteed to be at least 16 characters. Shouldn’t be empty.out_value
: Pointer to the output value. May be NULL for nvs_get_str and nvs_get_blob, in this case required length will be returned in length argument.length
: A non-zero pointer to the variable holding the length of out_value. In case out_value a zero, will be set to the length required to hold the value. In case out_value is not zero, will be set to the actual length of the value written. For nvs_get_str this includes zero terminator.
-
esp_err_t
nvs_get_blob
(nvs_handle handle, const char *key, void *out_value, size_t *length)¶
-
esp_err_t
nvs_erase_key
(nvs_handle handle, const char *key)¶ Erase key-value pair with given key name.
Note that actual storage may not be updated until nvs_commit function is called.
- Return
- ESP_OK if erase operation was successful
- ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
- ESP_ERR_NVS_READ_ONLY if handle was opened as read only
- ESP_ERR_NVS_NOT_FOUND if the requested key doesn’t exist
- other error codes from the underlying storage driver
- Parameters
handle
: Storage handle obtained with nvs_open. Handles that were opened read only cannot be used.key
: Key name. Maximal length is determined by the underlying implementation, but is guaranteed to be at least 16 characters. Shouldn’t be empty.
-
esp_err_t
nvs_erase_all
(nvs_handle handle)¶ Erase all key-value pairs in a namespace.
Note that actual storage may not be updated until nvs_commit function is called.
- Return
- ESP_OK if erase operation was successful
- ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
- ESP_ERR_NVS_READ_ONLY if handle was opened as read only
- other error codes from the underlying storage driver
- Parameters
handle
: Storage handle obtained with nvs_open. Handles that were opened read only cannot be used.
-
esp_err_t
nvs_commit
(nvs_handle handle)¶ Write any pending changes to non-volatile storage.
After setting any values, nvs_commit() must be called to ensure changes are written to non-volatile storage. Individual implementations may write to storage at other times, but this is not guaranteed.
- Return
- ESP_OK if the changes have been written successfully
- ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
- other error codes from the underlying storage driver
- Parameters
handle
: Storage handle obtained with nvs_open. Handles that were opened read only cannot be used.
-
void
nvs_close
(nvs_handle handle)¶ Close the storage handle and free any allocated resources.
This function should be called for each handle opened with nvs_open once the handle is not in use any more. Closing the handle may not automatically write the changes to nonvolatile storage. This has to be done explicitly using nvs_commit function. Once this function is called on a handle, the handle should no longer be used.
- Parameters
handle
: Storage handle to close
虚拟文件系统(VFS)组件¶
概述¶
虚拟文件系统(VFS)组件为驱动程序提供了统一的接口,可以执行类似文件对象的操作。这既可以是一个真实文件系统(FAT、SPIFFS 等),也可以是暴露了类似文件接口的设备驱动程序。
该组件允许 C 库函数(例如 fopen、fprintf)与文件系统驱动程序一起工作。在顶层,每个文件系统驱动程序都关联了某些路径前缀。当某个 C 库函数需要打开文件时,VFS 组件会查找与文件的路径相关的文件系统驱动,然后将调用转给那个驱动。
例如,你可以通过前缀 /fat
注册一个 FAT 文件系统,然后调用 fopen("/fat/file.txt", "w")
。VFS 组件将会调用 FAT 驱动 open
函数,并将参数 /file.txt
(以及一些 mode 标志)传递给它。随后对返回的 FILE*
文件流进行调用的 C 库函数也会被转给 FAT 驱动。
FS 注册¶
要注册一个 FS 驱动,应用程序需要定义一个 esp_vfs_t 结构体的实例,并初始化它里面的函数指针
esp_vfs_t myfs = {
.fd_offset = 0,
.flags = ESP_VFS_FLAG_DEFAULT,
.write = &myfs_write,
.open = &myfs_open,
.fstat = &myfs_fstat,
.close = &myfs_close,
.read = &myfs_read,
};
ESP_ERROR_CHECK(esp_vfs_register("/data", &myfs, NULL));
你可以使用的 API 依赖于 FS 驱动程序申明 API 的方式,例如 read
, write
, 等, 或 read_p
, ``write_p``等。
情形 1: API 函数定义时没有额外的上下文指针 (FS driver is a singleton):
size_t myfs_write(int fd, const void * data, size_t size);
// In definition of esp_vfs_t:
.flags = ESP_VFS_FLAG_DEFAULT,
.write = &myfs_write,
// ... other members initialized
// 当注册 FS 时,上下文指针(第三个参数)是 NULL:
ESP_ERROR_CHECK(esp_vfs_register("/data", &myfs, NULL));
情形 2: API 函数定义时有额外的上下文指针 (FS 驱动支持多个实例):
size_t myfs_write(myfs_t* fs, int fd, const void * data, size_t size);
// In definition of esp_vfs_t:
.flags = ESP_VFS_FLAG_CONTEXT_PTR,
.write_p = &myfs_write,
// ... other members initialized
// 当注册 FS 时,FS 上下文指针传递给了第三个参数
// (hypothetical myfs_mount function is used for illustrative purposes)
myfs_t* myfs_inst1 = myfs_mount(partition1->offset, partition1->size);
ESP_ERROR_CHECK(esp_vfs_register("/data1", &myfs, myfs_inst1));
// 可以注册另外的实例
myfs_t* myfs_inst2 = myfs_mount(partition2->offset, partition2->size);
ESP_ERROR_CHECK(esp_vfs_register("/data2", &myfs, myfs_inst2));
路径¶
每个注册的 FS 都有一个相关的前缀。这个前缀可以被看成是一个该分区的“挂载点”。
在已有的挂载点上注册另一个挂载点是不被支持的,其结果是未定义的。例如,下面是正确、支持的:
- FS 1 on /data/fs1
- FS 2 on /data/fs2
下面这种方法 不会正确工作:
- FS 1 on /data
- FS 2 on /data/fs2
打开文件时,FS 驱动只会收到文件的相对路径,例如:
myfs
注册时的路径前缀是/data
- 应用程序调用
fopen("/data/config.json", ...)
- 然后 VFS 组件将调用
myfs_open("/config.json", ...)
myfs
驱动将打开文件/config.json
VFS 不会限制文件路径的总长度,但是会限制文件路径前缀的长度,即最多为 ESP_VFS_PATH_MAX
个字符。另外,FS 驱动可能自己会对文件名长度有限制。
文件描述符¶
建议在文件系统驱动中使用一个小的正整数作为文件描述符。VFS 组件假设用 CONFIG_MAX_FD_BITS
比特(默认值 12)就足够表示文件描述符。
如果文件系统配置了一个文件描述符偏移选项(一个常数值),该值应当被传递到结构体 esp_vfs_t
中的 fd_offset
字段。在处理指定的文件系统的 FS 时,VFS 组件会移除这个偏移量,使其处于小的正整数的范围。
尽管由 VFS 返回给 newlib 库的文件描述符通常对应用程序不可见,但是理解下面的这些细节有助于调试。由 VFS 组件返回的文件描述符由两部分组成:FS 驱动 ID 和实际的文件描述符。由于 newlib 用 16 比特的整数来存储文件描述符,VFS 组件在存储这两部分时也受到 16 比特的限制。
较低的 CONFIG_MAX_FD_BITS
比特被用于存储基于零(zero-based)的文件描述符。如果 FS 驱动有一个非零 fd_offset
字段, 则这个 fd_offset
会减去一个在文件系统的 open
调用时获取到的 FD,然后其结果存储到 FD 的低比特。高比特用于保存该 FS 在已注册的文件系统构成的内部表格中的索引。
当 VFS 组件从 newlib 接收到一个带有文件描述符的调用时,该文件描述符会被转换成文件系统相关的文件描述符。首先,FD 的高比特用于标识文件系统。然后,FS 的 fd_offset
字段与 fd 较低的 CONFIG_MAX_FD_BITS
比特相加,然后将其相加结果传递给文件系统的驱动。
FD as seen by newlib FD as seen by FS driver
+-----+
+-------+---------------+ | | +------------------------+
| FS id | Zero—based FD | +---------------> sum +----> |
+---+---+------+--------+ | | | +------------------------+
| | | +--^--+
| +--------------+ |
| |
| +-------------+ |
| | Table of | |
| | registered | |
| | filesystems | |
| +-------------+ +-------------+ |
+-------> entry +----> esp_vfs_t | |
index +-------------+ | structure | |
| | | | |
| | | + fd_offset +---+
+-------------+ | |
+-------------+
标准 IO 流 (stdin, stdout, stderr)¶
如果菜单配置选项 “UART for console output” 没有设置为 “None”,则 stdin
、stdout
和 stderr
会被配置成从 UART 中读写。UART0 或 UART1 均可以用作标准 IO。默认情况下使用的是 UART0,波特率是 115200,TX 引脚是 GPIO1,RX 引脚是 GPIO3。这些参数可以在配置菜单中修改。
向 stdout
或 stderr
中写时会发送字符到 UART 的传输 FIFO。从 stdin
中读会从 UART 的接收 FIFO 中取数据。
注意,向 stdout
或 stderr
中写时会阻塞,直到所有的字符都被放到 FIFO 中;从 stdin
中读是非阻塞的。从 UART 中读的函数会获取到 FIFO 中的所有存在的字符。例如,fscanf("%d\n", &var);
可能不会产生预期的结果。这个限制是临时的,且会在将 fcntl
添加到 VFS 接口后移除。
标准流和 FreeRTOS 任务¶
stdin
、stdout
和 stderr
的 FILE
对象在所有的 FreeRTOS 任务中是共享的,但是执行这些对象的指针是存储在每个任务的 struct _reent
中的。下面的代码
fprintf(stderr, "42\n");
实际上会被(由预处理器)转换成:
fprintf(__getreent()->_stderr, “42n”);
其中,函数 __getreent()
返回一个指向 struct _reent
(newlib/include/sys/reent.h#L370-L417>) 的指针。这个结构体分配在每个任务的 TCB 上。当任务被初始化时,struct _reent` 的成员 stdin
、stdout
和 stderr
的值被设置为 _GLOBAL_REENT``(FreeRTOS 启动前的一个结构体) 的 ``_stdin
、_stdout
和 _stderr
。
这样设计的结果:
- 通过执行
stdin = fopen("/dev/uart/1", "r")
可以为任何所给任务设置stdin````stdout
和stderr
。 - 使用
fclose
可以默认的stdin
、stdout
或stderr
将关闭FILE
流对象 — 这会影响其它所有任务。 - 如果要为新任务改变默认的
stdin
、stdout
或stderr
流,则在创建任务前修改_GLOBAL_REENT->_stdin
(_stdout
,_stderr
)。
应用程序示例¶
API 参考手册¶
宏¶
-
ESP_VFS_PATH_MAX
¶ Maximum length of path prefix (not including zero terminator)
-
ESP_VFS_FLAG_CONTEXT_PTR
¶ Flag which indicates that FS needs extra context pointer in syscalls.
结构体¶
-
struct
esp_vfs_t
¶ VFS definition structure.
This structure should be filled with pointers to corresponding FS driver functions.
If the FS implementation has an option to use certain offset for all file descriptors, this value should be passed into fd_offset field. Otherwise VFS component will translate all FDs to start at zero offset.
Some FS implementations expect some state (e.g. pointer to some structure) to be passed in as a first argument. For these implementations, populate the members of this structure which have _p suffix, set flags member to ESP_VFS_FLAG_CONTEXT_PTR and provide the context pointer to esp_vfs_register function. If the implementation doesn’t use this extra argument, populate the members without _p suffix and set flags member to ESP_VFS_FLAG_DEFAULT.
If the FS driver doesn’t provide some of the functions, set corresponding members to NULL.
函数¶
-
esp_err_t
esp_vfs_register
(const char *base_path, const esp_vfs_t *vfs, void *ctx)¶ Register a virtual filesystem for given path prefix.
- Return
- ESP_OK if successful, ESP_ERR_NO_MEM if too many VFSes are registered.
- Parameters
base_path
: file path prefix associated with the filesystem. Must be a zero-terminated C string, up to ESP_VFS_PATH_MAX characters long, and at least 2 characters long. Name must start with a “/” and must not end with “/”. For example, “/data” or “/dev/spi” are valid. These VFSes would then be called to handle file paths such as “/data/myfile.txt” or “/dev/spi/0”.vfs
: Pointer to esp_vfs_t, a structure which maps syscalls to the filesystem driver functions. VFS component doesn’t assume ownership of this pointer.ctx
: If vfs->flags has ESP_VFS_FLAG_CONTEXT_PTR set, a pointer which should be passed to VFS functions. Otherwise, NULL.
-
esp_err_t
esp_vfs_unregister
(const char *base_path)¶ Unregister a virtual filesystem for given path prefix
- Return
- ESP_OK if successful, ESP_ERR_INVALID_STATE if VFS for given prefix hasn’t been registered
- Parameters
base_path
: file prefix previously used in esp_vfs_register call
-
ssize_t
esp_vfs_write
(struct _reent *r, int fd, const void *data, size_t size)¶ These functions are to be used in newlib syscall table. They will be called by newlib when it needs to use any of the syscalls.
-
off_t
esp_vfs_lseek
(struct _reent *r, int fd, off_t size, int mode)¶
-
ssize_t
esp_vfs_read
(struct _reent *r, int fd, void *dst, size_t size)¶
-
int
esp_vfs_open
(struct _reent *r, const char *path, int flags, int mode)¶
-
int
esp_vfs_close
(struct _reent *r, int fd)¶
-
int
esp_vfs_fstat
(struct _reent *r, int fd, struct stat *st)¶
-
int
esp_vfs_stat
(struct _reent *r, const char *path, struct stat *st)¶
-
int
esp_vfs_link
(struct _reent *r, const char *n1, const char *n2)¶
-
int
esp_vfs_unlink
(struct _reent *r, const char *path)¶
-
int
esp_vfs_rename
(struct _reent *r, const char *src, const char *dst)¶
-
void
esp_vfs_dev_uart_register
()¶ add /dev/uart virtual filesystem driver
This function is called from startup code to enable serial output
FAT 文件系统的支持¶
ESP-IDF 使用 FatFs 库作为 FAT 文件系统。FatFs 库位于 fatfs
组件内。尽管它可以被直接访问,它的许多功能都可以通过 VFS 访问,即使用标准 C 库和 POSIX API。
此外,FatFs 已被修改,支持运行时可插拔磁盘 IO 层。这能让 FatFs 在运行时映射为物理磁盘。
FatFs with VFS¶
头文件 esp_vfs_fat.h
中定义的函数可以将 FatFs 与 VFS 连接起来。函数 esp_vfs_fat_register
分配了一个 FATFS
结构,并在 VSF 中注册了一个所给路径前缀。随后对以这个前缀作为开始的文件的操作将会被转发给 FatFs 的 API。函数 esp_vfs_fat_unregister_path
用于删除
function deletes the registration with VFS, and frees the FATFS
structure.
Most applications will use the following flow when working with esp_vfs_fat_
functions:
- Call
esp_vfs_fat_register
, specifying path prefix where the filesystem has to be mounted (e.g."/sdcard"
,"/spiflash"
), FatFs drive number, and a variable which will receive a pointer toFATFS
structure. - Call
ff_diskio_register
function to register disk IO driver for the drive number used in step 1. - Call
f_mount
function (and optionallyf_fdisk
,f_mkfs
) to mount the filesystem using the same drive number which was passed toesp_vfs_fat_register
. See FatFs documentation for more details. - Call POSIX and C standard library functions to open, read, write, erase, copy files, etc. Use paths starting with the prefix passed to
esp_vfs_register
(such as"/sdcard/hello.txt"
). - Optionally, call FatFs library functions directly. Use paths without a VFS prefix in this case (
"/hello.txt"
). - Close all open files.
- Call
f_mount
function for the same drive number, with NULLFATFS*
argument, to unmount the filesystem. - Call
ff_diskio_register
with NULLff_diskio_impl_t*
argument and the same drive number. - Call
esp_vfs_fat_unregister_path
with the path where the file system is mounted to remove FatFs from VFS, and free theFATFS
structure allocated on step 1.
Convenience functions, esp_vfs_fat_sdmmc_mount
and esp_vfs_fat_sdmmc_unmount
, which wrap these steps and also handle SD card initialization, are described in the next section.
-
esp_err_t
esp_vfs_fat_register
(const char *base_path, const char *fat_drive, size_t max_files, FATFS **out_fs)¶ Register FATFS with VFS component.
This function registers given FAT drive in VFS, at the specified base path. If only one drive is used, fat_drive argument can be an empty string. Refer to FATFS library documentation on how to specify FAT drive. This function also allocates FATFS structure which should be used for f_mount call.
- Note
- This function doesn’t mount the drive into FATFS, it just connects POSIX and C standard library IO function with FATFS. You need to mount desired drive into FATFS separately.
- Return
- ESP_OK on success
- ESP_ERR_INVALID_STATE if esp_vfs_fat_register was already called
- ESP_ERR_NO_MEM if not enough memory or too many VFSes already registered
- Parameters
base_path
: path prefix where FATFS should be registeredfat_drive
: FATFS drive specification; if only one drive is used, can be an empty stringmax_files
: maximum number of files which can be open at the same timeout_fs
: pointer to FATFS structure which can be used for FATFS f_mount call is returned via this argument.
-
esp_err_t
esp_vfs_fat_unregister_path
(const char *base_path)¶ Un-register FATFS from VFS.
- Note
- FATFS structure returned by esp_vfs_fat_register is destroyed after this call. Make sure to call f_mount function to unmount it before calling esp_vfs_fat_unregister_ctx. Difference between this function and the one above is that this one will release the correct drive, while the one above will release the last registered one
- Return
- ESP_OK on success
- ESP_ERR_INVALID_STATE if FATFS is not registered in VFS
- Parameters
base_path
: path prefix where FATFS is registered. This is the same used when esp_vfs_fat_register was called
Using FatFs with VFS and SD cards¶
esp_vfs_fat.h
header file also provides a convenience function to perform steps 1–3 and 7–9, and also handle SD card initialization: esp_vfs_fat_sdmmc_mount
. This function does only limited error handling. Developers are encouraged to look at its source code and incorporate more advanced versions into production applications. esp_vfs_fat_sdmmc_unmount
function unmounts the filesystem and releases resources acquired by esp_vfs_fat_sdmmc_mount
.
-
esp_err_t
esp_vfs_fat_sdmmc_mount
(const char *base_path, const sdmmc_host_t *host_config, const sdmmc_slot_config_t *slot_config, const esp_vfs_fat_mount_config_t *mount_config, sdmmc_card_t **out_card)¶ Convenience function to get FAT filesystem on SD card registered in VFS.
This is an all-in-one function which does the following:
- initializes SD/MMC peripheral with configuration in host_config
- initializes SD/MMC card with configuration in slot_config
- mounts FAT partition on SD/MMC card using FATFS library, with configuration in mount_config
- registers FATFS library with VFS, with prefix given by base_prefix variable
This function is intended to make example code more compact. For real world applications, developers should implement the logic of probing SD card, locating and mounting partition, and registering FATFS in VFS, with proper error checking and handling of exceptional conditions.
- Return
- ESP_OK on success
- ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount was already called
- ESP_ERR_NO_MEM if memory can not be allocated
- ESP_FAIL if partition can not be mounted
- other error codes from SDMMC host, SDMMC protocol, or FATFS drivers
- Parameters
base_path
: path where partition should be registered (e.g. “/sdcard”)host_config
: pointer to structure describing SDMMC hostslot_config
: pointer to structure with extra SDMMC slot configurationmount_config
: pointer to structure with extra parameters for mounting FATFSout_card
: if not NULL, pointer to the card information structure will be returned via this argument
-
struct
esp_vfs_fat_mount_config_t
¶ Configuration arguments for esp_vfs_fat_sdmmc_mount and esp_vfs_fat_spiflash_mount functions.
-
esp_err_t
esp_vfs_fat_sdmmc_unmount
()¶ Unmount FAT filesystem and release resources acquired using esp_vfs_fat_sdmmc_mount.
- Return
- ESP_OK on success
- ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount hasn’t been called
FatFS disk IO layer¶
FatFs has been extended with an API to register disk IO driver at runtime.
Implementation of disk IO functions for SD/MMC cards is provided. It can be registered for the given FatFs drive number using ff_diskio_register_sdmmc
function.
-
void
ff_diskio_register
(BYTE pdrv, const ff_diskio_impl_t *discio_impl)¶ Register or unregister diskio driver for given drive number.
When FATFS library calls one of disk_xxx functions for driver number pdrv, corresponding function in discio_impl for given pdrv will be called.
- Parameters
pdrv
: drive numberdiscio_impl
: pointer to ff_diskio_impl_t structure with diskio functions or NULL to unregister and free previously registered drive
-
struct
ff_diskio_impl_t
¶ Structure of pointers to disk IO driver functions.
See FatFs documentation for details about these functions
Public Members
-
DSTATUS (*
init
)(BYTE pdrv)¶ disk initialization function
-
DSTATUS (*
status
)(BYTE pdrv)¶ disk status check function
-
DRESULT (*
read
)(BYTE pdrv, BYTE *buff, DWORD sector, UINT count)¶ sector read function
-
DRESULT (*
write
)(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)¶ sector write function
-
DRESULT (*
ioctl
)(BYTE pdrv, BYTE cmd, void *buff)¶ function to get info about disk and do some misc operations
-
DSTATUS (*
-
void
ff_diskio_register_sdmmc
(BYTE pdrv, sdmmc_card_t *card)¶ Register SD/MMC diskio driver
- Parameters
pdrv
: drive numbercard
: pointer to sdmmc_card_t structure describing a card; card should be initialized before calling f_mount.
Wear Levelling APIs¶
Overview¶
Most of the flash devices and specially SPI flash devices that are used in ESP32 have sector based organization and have limited amount of erase/modification cycles per memory sector. To avoid situation when one sector reach the limit of erases when other sectors was used not often, we have made a component that avoid this situation. The wear levelling component share the amount of erases between all sectors in the memory without user interaction. The wear_levelling component contains APIs related to reading, writing, erasing, memory mapping data in the external SPI flash through the partition component. It also has higher-level APIs which work with FAT filesystem defined in the FAT filesystem.
The wear levelling component does not cache data in RAM. Write and erase functions modify flash directly, and flash contents is consistent when the function returns.
Wear Levelling access APIs¶
This is the set of APIs for working with data in flash:
wl_mount
mount wear levelling module for defined partitionwl_unmount
used to unmount levelling modulewl_erase_range
used to erase range of addresses in flashwl_write
used to write data to the partitionwl_read
used to read data from the partitionwl_size
return size of avalible memory in byteswl_sector_size
returns size of one sector
Generally, try to avoid using the raw wear levelling functions in favor of filesystem-specific functions.
Memory Size¶
The memory size calculated in the wear Levelling module based on parameters of partition. The module use few sectors of flash for internal data.
应用程序示例¶
An example which combines wear levelling driver with FATFS library is provided in examples/storage/wear_levelling
directory. This example initializes the
wear levelling driver, mounts FATFS partition, and writes and reads data from it using POSIX and C library APIs. See README.md file in the example directory for more information.
High level API 参考手册¶
函数¶
-
esp_err_t
esp_vfs_fat_spiflash_mount
(const char *base_path, const char *partition_label, const esp_vfs_fat_mount_config_t *mount_config, wl_handle_t *wl_handle)¶ Convenience function to initialize FAT filesystem in SPI flash and register it in VFS.
This is an all-in-one function which does the following:
- finds the partition with defined partition_label. Partition label should be configured in the partition table.
- initializes flash wear levelling library on top of the given partition
- mounts FAT partition using FATFS library on top of flash wear levelling library
- registers FATFS library with VFS, with prefix given by base_prefix variable
This function is intended to make example code more compact.
- Return
- ESP_OK on success
- ESP_ERR_NOT_FOUND if the partition table does not contain FATFS partition with given label
- ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount was already called
- ESP_ERR_NO_MEM if memory can not be allocated
- ESP_FAIL if partition can not be mounted
- other error codes from wear levelling library, SPI flash driver, or FATFS drivers
- Parameters
base_path
: path where FATFS partition should be mounted (e.g. “/spiflash”)partition_label
: label of the partition which should be usedmount_config
: pointer to structure with extra parameters for mounting FATFSwl_handle
: wear levelling driver handle
-
struct
esp_vfs_fat_mount_config_t
¶ Configuration arguments for esp_vfs_fat_sdmmc_mount and esp_vfs_fat_spiflash_mount functions.
-
esp_err_t
esp_vfs_fat_spiflash_unmount
(const char *base_path, wl_handle_t wl_handle)¶ Unmount FAT filesystem and release resources acquired using esp_vfs_fat_spiflash_mount.
- Return
- ESP_OK on success
- ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount hasn’t been called
- Parameters
base_path
: path where partition should be registered (e.g. “/spiflash”)wl_handle
: wear levelling driver handle returned by esp_vfs_fat_spiflash_mount
Mid level API 参考手册¶
函数¶
-
esp_err_t
wl_mount
(const esp_partition_t *partition, wl_handle_t *out_handle)¶ Mount WL for defined partition.
- Return
- ESP_OK, if the allocation was successfully;
- ESP_ERR_INVALID_ARG, if WL allocation was unsuccessful;
- ESP_ERR_NO_MEM, if there was no memory to allocate WL components;
- Parameters
partition
: that will be used for accessout_handle
: handle of the WL instance
-
esp_err_t
wl_unmount
(wl_handle_t handle)¶ Unmount WL for defined partition.
- Return
- ESP_OK, if the operation completed successfully;
- or one of error codes from lower-level flash driver.
- Parameters
handle
: WL partition handle
-
esp_err_t
wl_erase_range
(wl_handle_t handle, size_t start_addr, size_t size)¶ Erase part of the WL storage.
- Return
- ESP_OK, if the range was erased successfully;
- ESP_ERR_INVALID_ARG, if iterator or dst are NULL;
- ESP_ERR_INVALID_SIZE, if erase would go out of bounds of the partition;
- or one of error codes from lower-level flash driver.
- Parameters
handle
: WL handle that are related to the partitionstart_addr
: Address where erase operation should start. Must be aligned to the result of function wl_sector_size(…).size
: Size of the range which should be erased, in bytes. Must be divisible by result of function wl_sector_size(…)..
-
esp_err_t
wl_write
(wl_handle_t handle, size_t dest_addr, const void *src, size_t size)¶ Write data to the WL storage.
Before writing data to flash, corresponding region of flash needs to be erased. This can be done using wl_erase_range function.
- Note
- Prior to writing to WL storage, make sure it has been erased with wl_erase_range call.
- Return
- ESP_OK, if data was written successfully;
- ESP_ERR_INVALID_ARG, if dst_offset exceeds partition size;
- ESP_ERR_INVALID_SIZE, if write would go out of bounds of the partition;
- or one of error codes from lower-level flash driver.
- Parameters
handle
: WL handle that are related to the partitiondest_addr
: Address where the data should be written, relative to the beginning of the partition.src
: Pointer to the source buffer. Pointer must be non-NULL and buffer must be at least ‘size’ bytes long.size
: Size of data to be written, in bytes.
-
esp_err_t
wl_read
(wl_handle_t handle, size_t src_addr, void *dest, size_t size)¶ Read data from the WL storage.
- Return
- ESP_OK, if data was read successfully;
- ESP_ERR_INVALID_ARG, if src_offset exceeds partition size;
- ESP_ERR_INVALID_SIZE, if read would go out of bounds of the partition;
- or one of error codes from lower-level flash driver.
- Parameters
handle
: WL module instance that was initialized beforedest
: Pointer to the buffer where data should be stored. Pointer must be non-NULL and buffer must be at least ‘size’ bytes long.src_addr
: Address of the data to be read, relative to the beginning of the partition.size
: Size of data to be read, in bytes.
-
size_t
wl_size
(wl_handle_t handle)¶ Get size of the WL storage.
- Return
- usable size, in bytes
- Parameters
handle
: WL module handle that was initialized before
-
size_t
wl_sector_size
(wl_handle_t handle)¶ Get sector size of the WL instance.
- Return
- sector size, in bytes
- Parameters
handle
: WL module handle that was initialized before
关于本节 API 的示例代码请参考 ESP-IDF 示例中的 storage 目录。
协议 API¶
mDNS 服务¶
概述¶
mDNS 是一个多播 UDP 服务,它用于提供本地网络服务和发现主机。
mDNS 在大多数操作系统中都已默认安装,或者可以用于独立的软件包。在 Mac OS
上面,它默认已被安装,且被叫做 Bonjour
。苹果发布了一个 Windows
的安装器,可以在 on Apple’s support page 上面找到。在 Linux
上,mDNS 由 avahi 提供,且通常都已默认安装。
mDNS 属性¶
主机名(hostname)
: 设备将要相应的主机名。如果没设置,主机名
将会从接口中读取。例如:my-esp32
会被解析为my-esp32.local
。默认实例(default_instance)
: 设备的友好名字,例如Jhon's ESP32 Thing
。如果未被设置,默认使用主机名
。
为 STA 接口启动 mDNS 并设置 hostname
和 default_instance
的示例:
mdns_server_t * mdns = NULL; void start_mdns_service() { //initialize mDNS service on STA interface esp_err_t err = mdns_init(TCPIP_ADAPTER_IF_STA, &mdns); if (err) { printf("MDNS Init failed: %d\n", err); return; } //set hostname mdns_set_hostname(mdns, "my-esp32"); //set default instance mdns_set_instance(mdns, "Jhon's ESP32 Thing"); }
mDNS 服务¶
mDNS 可以广播你的设备所提供给的网络服务。每个服务通过一些属性定义。
服务(service)
: 所需的服务类型,使用下划线作为前缀。一些通过类型可以在 这里 找到。协议(proto)
: 服务运行所需的协议,以下划线作为前缀,例如:_tcp
或者_udp
。端口(port)
: 服务运行所需的端口。实例(instance)
: 服务的友好名字,例如Jhon's ESP32 Web Server
。如果未定义,则使用默认实例
。文本(txt)
:var=val
类型的字符串数组,用于为你的服务定义属性。
添加服务和不同属性的示例:
void add_mdns_services() { //add our services mdns_service_add(mdns, "_http", "_tcp", 80); mdns_service_add(mdns, "_arduino", "_tcp", 3232); mdns_service_add(mdns, "_myservice", "_udp", 1234); //NOTE: services must be added before their properties can be set //use custom instance for the web server mdns_service_instance_set(mdns, "_http", "_tcp", "Jhon's ESP32 Web Server"); const char * arduTxtData[4] = { "board=esp32", "tcp_check=no", "ssh_upload=no", "auth_upload=no" }; //set txt data for service (will free and replace current data) mdns_service_txt_set(mdns, "_arduino", "_tcp", 4, arduTxtData); //change service port mdns_service_port_set(mdns, "_myservice", "_udp", 4321); }
mDNS 查询¶
mDNS 提供了浏览服务和解析主机 IP/IPv6 地址的方法。
解析主机 IP 的示例:
void resolve_mdns_host(const char * hostname) { printf("mDNS Host Lookup: %s.local\n", hostname); //run search for 1000 ms if (mdns_query(mdns, hostname, NULL, 1000)) { //results were found const mdns_result_t * results = mdns_result_get(mdns, 0); //itterate through all results size_t i = 1; while(results) { //print result information printf(" %u: IP:" IPSTR ", IPv6:" IPV6STR "\n", i++ IP2STR(&results->addr), IPV62STR(results->addrv6)); //load next result. Will be NULL if this was the last one results = results->next; } //free the results from memory mdns_result_free(mdns); } else { //host was not found printf(" Host Not Found\n"); } }
解析本地服务的示例:
void find_mdns_service(const char * service, const char * proto) { printf("mDNS Service Lookup: %s.%s\n", service, proto); //run search for 1000 ms if (mdns_query(mdns, service, proto, 1000)) { //results were found const mdns_result_t * results = mdns_result_get(mdns, 0); //itterate through all results size_t i = 1; while(results) { //print result information printf(" %u: hostname:%s, instance:\"%s\", IP:" IPSTR ", IPv6:" IPV6STR ", port:%u, txt:%s\n", i++, (results->host)?results->host:"NULL", (results->instance)?results->instance:"NULL", IP2STR(&results->addr), IPV62STR(results->addrv6), results->port, (results->txt)?results->txt:"\r"); //load next result. Will be NULL if this was the last one results = results->next; } //free the results from memory mdns_result_free(mdns); } else { //service was not found printf(" Service Not Found\n"); } }
使用上面的方法的示例:
void my_app_some_method(){ //search for esp32-mdns.local resolve_mdns_host("esp32-mdns"); //search for HTTP servers find_mdns_service("_http", "_tcp"); //or file servers find_mdns_service("_smb", "_tcp"); //windows sharing find_mdns_service("_afpovertcp", "_tcp"); //apple sharing find_mdns_service("_nfs", "_tcp"); //NFS server find_mdns_service("_ftp", "_tcp"); //FTP server //or networked printer find_mdns_service("_printer", "_tcp"); find_mdns_service("_ipp", "_tcp"); }
应用程序示例¶
mDNS 的服务器/扫描示例程序: protocols/mdns.
API 参考手册¶
宏¶
类型定义¶
-
typedef struct mdns_server_s
mdns_server_t
¶
-
typedef struct mdns_result_s
mdns_result_t
¶ mDNS query result structure
枚举¶
结构体¶
-
struct
mdns_result_s
¶ mDNS query result structure
Public Members
-
const char *
host
¶ hostname
-
const char *
instance
¶ instance
-
const char *
txt
¶ txt data
-
uint16_t
priority
¶ service priority
-
uint16_t
weight
¶ service weight
-
uint16_t
port
¶ service port
-
struct ip4_addr
addr
¶ ip4 address
-
struct ip6_addr
addrv6
¶ ip6 address
-
const struct mdns_result_s *
next
¶ next result, or NULL for the last result in the list
-
const char *
函数¶
-
esp_err_t
mdns_init
(tcpip_adapter_if_t tcpip_if, mdns_server_t **server)¶ Initialize mDNS on given interface.
- Return
- ESP_OK on success
- ESP_ERR_INVALID_ARG when bad tcpip_if is given
- ESP_ERR_INVALID_STATE when the network returned error
- ESP_ERR_NO_MEM on memory error
- ESP_ERR_WIFI_NOT_INIT when WiFi is not initialized by eps_wifi_init
- Parameters
tcpip_if
: Interface that the server will listen onserver
: Server pointer to populate on success
-
void
mdns_free
(mdns_server_t *server)¶ Stop and free mDNS server.
- Parameters
server
: mDNS Server to free
-
esp_err_t
mdns_set_hostname
(mdns_server_t *server, const char *hostname)¶ Set the hostname for mDNS server.
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_ERR_NO_MEM memory error
- Parameters
server
: mDNS Serverhostname
: Hostname to set
-
esp_err_t
mdns_set_instance
(mdns_server_t *server, const char *instance)¶ Set the default instance name for mDNS server.
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_ERR_NO_MEM memory error
- Parameters
server
: mDNS Serverinstance
: Instance name to set
-
esp_err_t
mdns_service_add
(mdns_server_t *server, const char *service, const char *proto, uint16_t port)¶ Add service to mDNS server.
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_ERR_NO_MEM memory error
- Parameters
server
: mDNS Serverservice
: service type (_http, _ftp, etc)proto
: service protocol (_tcp, _udp)port
: service port
-
esp_err_t
mdns_service_remove
(mdns_server_t *server, const char *service, const char *proto)¶ Remove service from mDNS server.
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_ERR_NOT_FOUND Service not found
- ESP_FAIL unknown error
- Parameters
server
: mDNS Serverservice
: service type (_http, _ftp, etc)proto
: service protocol (_tcp, _udp)
-
esp_err_t
mdns_service_instance_set
(mdns_server_t *server, const char *service, const char *proto, const char *instance)¶ Set instance name for service.
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_ERR_NOT_FOUND Service not found
- ESP_ERR_NO_MEM memory error
- Parameters
server
: mDNS Serverservice
: service type (_http, _ftp, etc)proto
: service protocol (_tcp, _udp)instance
: instance name to set
-
esp_err_t
mdns_service_txt_set
(mdns_server_t *server, const char *service, const char *proto, uint8_t num_items, const char **txt)¶ Set TXT data for service.
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_ERR_NOT_FOUND Service not found
- ESP_ERR_NO_MEM memory error
- Parameters
server
: mDNS Serverservice
: service type (_http, _ftp, etc)proto
: service protocol (_tcp, _udp)num_items
: number of items in TXT datatxt
: string array of TXT data (eg. {“var=val”,”other=2”})
-
esp_err_t
mdns_service_port_set
(mdns_server_t *server, const char *service, const char *proto, uint16_t port)¶ Set service port.
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_ERR_NOT_FOUND Service not found
- Parameters
server
: mDNS Serverservice
: service type (_http, _ftp, etc)proto
: service protocol (_tcp, _udp)port
: service port
-
esp_err_t
mdns_service_remove_all
(mdns_server_t *server)¶ Remove and free all services from mDNS server.
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
server
: mDNS Server
-
size_t
mdns_query
(mdns_server_t *server, const char *service, const char *proto, uint32_t timeout)¶ Query mDNS for host or service.
- Return
- the number of results found
- Parameters
server
: mDNS Serverservice
: service type or host nameproto
: service protocol or NULL if searching for hosttimeout
: time to wait for answers. If 0, mdns_query_end MUST be called to end the search
-
size_t
mdns_query_end
(mdns_server_t *server)¶ Stop mDNS Query started with timeout = 0.
- Return
- the number of results found
- Parameters
server
: mDNS Server
-
size_t
mdns_result_get_count
(mdns_server_t *server)¶ get the number of results currently in memoty
- Return
- the number of results
- Parameters
server
: mDNS Server
-
const mdns_result_t *
mdns_result_get
(mdns_server_t *server, size_t num)¶ Get mDNS Search result with given index.
- Return
- the result or NULL if error
- Parameters
server
: mDNS Servernum
: the index of the result
-
esp_err_t
mdns_result_free
(mdns_server_t *server)¶ Remove and free all search results from mDNS server.
- Return
- ESP_OK success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
server
: mDNS Server
关于本节 API 的示例代码请参考 ESP-IDF 示例中的 protocols 目录。
Hardware Reference¶
ESP32 Modules and Boards¶
Espressif designed and manufactured several development modules and boards to help users evaluate functionality of ESP32 chip. Development boards, depending on intended functionality, have exposed GPIO pins headers, provide USB programming interface, JTAG interface as well as peripherals like touch pads, LCD screen, SD card slot, camera module header, etc.
For details please refer to documentation below, provided together with description of particular boards.
ESP-WROOM-32¶
The smallest module intended for installation in final products. Can be also used for evaluation after adding extra components like programming interface, boot strapping resistors and break out headers.

- Schematic (PDF)
- Datasheet (PDF)
- ESP32 Module Reference Design (ZIP) containing OrCAD schematic, PCB layout, gerbers and BOM
ESP32 Core Board V2 / ESP32 DevKitC¶
Small and convenient development board with break out pin headers and minimum additional components. Includes USB to serial programming interface, that also provides power supply for the board. Has press buttons to reset the board and put it in upload mode.

- Schematic (PDF)
- ESP32 Development Board Reference Design (ZIP) containing OrCAD schematic, PCB layout, gerbers and BOM
- ESP32-DevKitC Getting Started Guide
- CP210x USB to UART Bridge VCP Drivers
ESP32 Demo Board V2¶
One of first feature rich evaluation boards that contains several pin headers, dip switches, USB to serial programming interface, reset and boot mode press buttons, power switch, 10 touch pads and separate header to connect LCD screen.

ESP32 WROVER KIT V1 / ESP32 DevKitJ V1¶
Development board that has dual port USB to serial converter for programming and JTAG interface for debugging. Power supply is provided by USB interface or from standard 5 mm power supply jack. Power supply selection is done with a jumper and may be put on/off with a separate switch. Has SD card slot, 3.2” SPI LCD screen and dedicated header to connect a camera. Provides RGB diode for diagnostics. Also, includes 32.768 kHz XTAL for internal RTC to operate it in low power modes.

ESP32 WROVER KIT V2¶
This is an updated version of ESP32 DevKitJ V1 described above with design improvements identified when DevKitJ was in use. Both V1 and V2 versions of this board are ready to accommodate existing ESP-WROOM-32 or the new ESP32-WROVER module.

API 指导¶
关于 ESP-IDF 编程的通用说明¶
应用程序启动流程¶
本文档解释了在 ESP-IDF 应用程序的 app_main
被调用前的各个步骤。
启动过程的顶层视图如下:
- 在 ROM 中的第一阶段的 bootloader 从 flash 偏移地址 0x1000 处加载第二阶段的 bootloader 到 RAM 中。
- 第二阶段的 bootloader 从 flash 上面加载分区表和主应用程序镜像。主应用程序包含 RAM 段和通过 flash cacha 映射的只读段。
- 主应用程序镜像开始执行。此时,第二个 CPU 以及 RTOS 调度器开始启动。
下面将详细介绍这个过程。
第一阶段的 bootloader¶
SoC 复位后,PRO CPU 将会立即运行,并执行复位向量代码;此时 APP CPU 将会保持在复位状态。在启动过程中,PRO CPU 将会完成所有的初始化工作。APP CPU 由应用程序启动代码中的函数 call_start_cpu0
解除复位。复位向量表位于 ESP32 芯片的 mask ROM 中的地址 0x40000400 处,且不能被修改。
启动代码会被复位代码调用,然后通过检查寄存器 ``GPIO_STRAP_REG``(bootstrap 引脚状态)来判断启动模式。根据复位原因的不同,可能会发生如下的行为:
- 从深度睡眠中复位:如果在
RTC_CNTL_STORE6_REG
中的值非零,且在RTC_CNTL_STORE7_REG
中的 RTC 内存中的 CRC 值是有效的,则使用RTC_CNTL_STORE6_REG
作为入口点地址,并立即跳转到该地址。如果RTC_CNTL_STORE6_REG
是零,或者RTC_CNTL_STORE7_REG
包含无效的 CRC,或者通过RTC_CNTL_STORE6_REG
调用的代码立即返回了,则将这次启动作为上电复位启动。Note: 如果要在此时运行自定义的代码,可以使用所提供的深度睡眠桩机制。具体细节请参考文档 深度睡眠 。 - 对于上电复位,软件 SoC 复位,以及看门狗 SoC 复位:如果请求了 UART 或 SDIO 下载模式,则检查寄存器
GPIO_STRAP_REG
。对于这种情形,会配置 UART 或者 SDIO,并等待下载代码。否则,将这次启动作为软件 CPU 复位。 - 对于软件 CPU 复位和看门狗 CPU 复位:基于 EFUSE 的值配置 SPI,并尝试从 flash 中加载代码。这一步的更多细节将在下一段中进行描述。如果从 flash 中加载代码失败,则将基本的解释器解压缩到 RAM 中并启动它。注意,此时 RTC 看门狗依然是使能的,所以除非从解释器中接收到输入,否则看门狗将会在几百毫秒后复位 SoC,然后重复整个过程。如果解释器从 UART 接收到了输入,则它会禁止看门狗。
应用程序镜像被加载到 flash 的地址 0x10000 处。flash 的前 4 KB 扇区用于存储安全启动 IV 和应用程序镜像签名。更多细节请参考安全启动文档。
第二阶段的 bootloader¶
在 ESP-IDF 中,flash 的地址 0x1000 处存储的二进制镜像就是第二阶段的 bootloader。第二阶段的 bootloader 源代码位于 ESP-IDF 的 components/bootloader 目录下。注意,这种做法只是 ESP32 芯片的一种实现方法,你也可以直接将一个具有完整功能的应用程序镜像烧写到地址 0x1000 处,不过这超出了本文当的讨论范围。ESP-IDF 使用第二阶段的 bootloader 的好处是可以实现灵活地添加 flash 布局(使用分区表),允许实现与 flash 加密相关的各种流程、安全启动以及空中升级(OTA)。
当第一阶段的 bootloader 完成后,ESP32 会检查并加载第二阶段的 bootloader,跳转到在二进制镜像头部中找到的第二阶段 bootloader 的入口点。
第二阶段的 bootloader 会阅读位于偏移量 0x8000 处的分区表。更多信息请参考 分区表。bootloader 会找到工厂分区和 OTA 分区,然后基于 OTA info 分区中的信息判断启动哪个分区。
对于所选择的分区,第二阶段的 bootloader 会将数据段和映射到 IRAM/DRAM 中的代码段拷贝到它们对应的加载地址。对于加载地址在 IRAM/DROM 范围内的段,ESP32 会通过所提供的正确的映射来配置 flash MMU。需要注意的是,第二阶段的 bootloader 会同时为 PRO CPU 和 APP CPU 同时配置 flash MMU,但是只会使能 PRO CPU 的 flash MMU。这样做的原因是第二阶段的 bootloader 代码被加载到了由 APP CPU cache 所使用的内存范围内了。使能 APP CPU cache 的任务被移交给应用程序了。当代码被加载、flash MMU 被设置后,第二阶段的 bootloader 会跳转到由二进制镜像头部中指定的应用程序入口点。
当前不能向 bootloader 中添加由应用程序指定的钩子,因此不能自定义应用程序的分区选择逻辑。但是这可能是需要的,例如,根据某个 GPIO 的状态来加载不同的应用程序镜像。今后会将这种自定义功能添加到 ESP-IDF 中。目前为止,如果你需要自定义 bootloader,可以将 bootloader 组件拷贝懂啊应用程序目录,然后做相应的修改。对于这种情况,ESP-IDF 的编译系统会在应用程序目录编译该组件,而不会在 ESP-IDF 的组件目录中编译它。
应用程序启动¶
ESP-IDF 应用程序的入口点是 components/esp32/cpu_start.c
中的函数 call_start_cpu0
。该函数主要做了两件事儿:使能堆分配器以及让 APP CPU 跳转到它的入口点 call_start_cpu1
。在 PRO CPU 上面的代码会设置 APP CPU 的入口点,激活 APP CPU 的复位,并等待由 APP CPU 中的代码设置一个表示它已启动的全局标志。完成后,PRO CPU 会跳转到函数 start_cpu0
,APP CPU 会跳转到函数 start_cpu1
。
start_cpu0
和 start_cpu1
都是虚函数。这意味着,如果应用程序需要改变初始化序列,可以直接在应用程序中覆盖这两个函数。start_cpu0
默认会根据 menuconfig
中的选项使能/初始化对应的组件。具体请在 components/esp32/cpu_start.c
中参考该函数的实现。注意,应用程序中的所有 C++ 全局构造器都会在这个阶段被调用。当所有必要组件都初始化后,会创建 主任务(main task) 并启动 FreeRTOS 的调度器。
当 PRO CPU 在函数 start_cpu0
中执行初始化时,APP CPU 会在函数 start_cpu1
中自旋,等待 PRO CPU 启动调度器。当 PRO CPU 启动调度器后,在 APP CPU 上面的代码也会启动调度器。
主任务就是运行函数 app_main
的任务。主任务的栈大小和优先级都可以通过 menuconfig
配置。应用程序可以利用这个任务做一些应用程序相关的初始化,例如启动其它任务。应用程序也可以使用主任务做事件循环以及其它的通过工作。如果函数 app_main
返回了,主任务会被删除。
应用程序内存布局¶
ESP32 芯片具有灵活的内存映射功能。本节描述 ESP-IDF 在默认情况下是如何使用这些功能的。
在 ESP-IDF 中的应用程序代码可以放到下列的内存区域内。
IRAM (指令 RAM)¶
ESP-IDF 从 Internal SRAM0`(在技术参考手册中定义的) 中分配了部分区域作为指令 RAM。除前 64 kB 块用于 PRO 和 APP CPU cache 之外,这段内存的剩余部分(即从 ``0x40080000` 到 0x400A0000
)用于存储需要直接从 RAM 中运行的应用程序。
ESP-IDF 中的少量组件和部分 WiFi 协议栈就是通过链接脚本放置到这个区域的。
如果某些应用程序的代码需要放置到 IRAM,可以使用 IRAM_ATTR
进行定义
#include "esp_attr.h"
void IRAM_ATTR gpio_isr_handler(void* arg)
{
// ...
}
下面是一些应用程序可能需要放置到 IRAM 中的例子。
- ISR handler 必须被放置到 IRAM。更进一步说,ISR handler 智只能调用放到 IRAM 中的函数和 ROM 中的函数。 Note 1: 当前所有的 FreeRTOS API 都是放置到 IRAM 中的,所以可以被 ISR handler 安全调用。Note 2: ISR handler 所使用的常量数据(包括但不限于
const char
)以及被 ISR 调用的函数都必须通过DRAM_ATTR
放到 DRAM 中。 - 某些对时间敏感的代码需要放知道 IRAM 中,这样可以减小从 flash 加载代码的时间。ESP32 通过一个 32 kB 的 cache 读取代码和数据。在某些情况下,将函数放到 IRAM 中可以减小 cache 缺失所造成的延迟。
IROM (从 Flash 执行的代码)¶
如果函数没有被明确指明需要放到 IRAM 或者 RTC 内存中,则它会被默认放到 flash 中。 关于使用 flash MMU 来允许从 flash 中执行代码的机制请查阅技术参考手册。ESP-IDF 将需要从 flash 中执行的代码放到 0x400D0000 — 0x40400000
范围内。启动的时候,第二阶段的 bootloader 会初始化 flash MMU,将 flahs 中代码所处的位置映射到这段区域的起始处。对这段范围的访问将会被显示地缓存到 0x40070000
— 0x40080000
范围内的两个 32kB 块。
注意,位于 0x40000000 — 0x40400000
范围之外的代码不可由 Window ABI CALLx
指令获得,因此,如果应用程序使用了 0x40400000 — 0x40800000
或 0x40800000 — 0x40C00000
范围,需要特别注意。ESP-IDF 默认不会使用这些区域。
DRAM (数据 RAM)¶
非常量静态数据和以 0 初始化的数据别链接器放到一个 256 kB 的范围 0x3FFB0000 — 0x3FFF0000
内。注意,如果使用了蓝牙协议栈,则则个范围会被缩减到 64 kB(通过将起始位置移位到 0x3FFC0000
),如果使用了内存跟踪技术,这个范围的长度会被进一步缩减到 16 kB 或者 32 kB。放置静态数据后所剩余的所有空间将被用于运行时的堆空间。
常量数据也可以被放置到 DRAM 中,例如如果它用于 ISR handler 中(参考上面的 IRAM 章节)。要达到此目的,需要使用 DRAM_ATTR
进行定义
DRAM_ATTR const char[] format_string = "%p %x";
char buffer[64];
sprintf(buffer, format_string, ptr, val);
不言而喻的是,不用在 ISR handler 中使用 printf
和其它输出函数。如果需要调试,可以在 ISR 中使用宏 ESP_EARLY_LOGx
来记录日志。在这种情况下,请确保将 TAG
和格式化字符串都放入 DRAM
中。
DROM (存储在 Flash 中的数据)¶
默认情况下,常量数据会被链接器放到一个 4 MB(0x3F400000 — 0x3F800000
) 的范围内,ESP32 通过 Flash MMU 和 cache 在该范围内访问外部 flash。字面量常数是一个例外,它们会被编译器内嵌到应用程序的代码中。
构建系统¶
本节阐释了乐鑫 IoT 开发框架的编译系统以及 “组件(components)” 的概念。
如果你想知道如何组织已给新的 ESP-IDF 工程的话,请继续阅读本文档。
我们推荐你使用 esp-idf-template 工程作为你的工程的起点。
使用构建系统¶
esp-idf 的 README 文件包含了如何使用构建系统构建你自己的工程的描述。
概述¶
ESP-IDF 工程可以看做大量组件构成的集合。例如,一个显示当前空气湿度的 webserver 可能包括:
- ESP32 基本库(libc,rom bindings 等)
- WiFi drivers
- TCP/IP 协议栈
- FreeRTOS 操作系统
- webserver
- 湿度传感器
- 将它们集成到一个的主代码
ESP-IDF 中组件的概念非常清晰明确,且是可配置的。当编译工程时,构建环境将查找 ESP-IDF 目录下面的所有组件、工程目录以及额外自定义的目录(可选)。它允许用户通过一个基于文本 的菜单系统对 ESP-IDF 工程进行配置,以自定义每个组件。当工程中的组件被配置后,构建过程将会编译工程。
概念¶
- “工程(project)” 是一个目录,它包含需要编译成 “app”(以及一些额外支持的输出,例如分区表,数据/文件系统分区,bootloader)的所有文件和配置。
- “工程配置(Project configuration)” 是一个位于工程根目录的叫做 sdkconfig 的文件。这个配置文件可以通过
make menuconfig
来自定义工程的配置项。单个工程确切地包含一个工程配置。 - “应用程序(app)” 是一个由 esp-idf 编译成的可执行文件。单个工程通常会被编译成两个 app - 一个 “工程 app” (主可执行文件,即你的自定义固件)和一个 “bootloader app”(加载工程 app 的初始化 bootloader 程序)。
- “组件(component)” 是由相对独立的代码构成的模块,它们会被编译乘静态库(.a 文件)并被链接到 app 中。某些组件是由 esp-idf 自身提供的,另外一些组件可能在其它地方。
下面这些东西不属于工程的内容:
- “ESP-IDF” 不是工程的一部分,而是一个相对独立的代码,通过环境变量
IDF_PATH
链接到工程。这能减小 IED 框架与工程直接的耦合性。 - 用于编译的工具链不是工程的一部分。工具链应当安装在系统命令行的 PATH 中,或者工程配置中所配置的工具链前缀所对应的路径中。
示例工程¶
一个示例工程目录大概如下
- myProject/
- Makefile
- sdkconfig
- components/ - component1/ - component.mk
- Kconfig
- src1.c
- component2/ - component.mk
- Kconfig
- src1.c
- include/ - component2.h
- main/ - src1.c
- src2.c
- component.mk
- build/
这个示例 “myProject” 包含如下元素:
- 一个顶层工程 Makefile。这个 Makefile 设置变量
PROJECT_NAME
,并(可选)定义项目范围内的其它 make 变量。 它包含了核心 makefile$(IDF_PATH)/make/project.mk
,这个核心 makefile 实现了 ESP-IDF 构建系统的余下部分。 - “sdkconfig” 工程配置文件。这个文件会在运行 “make menuconfig” 时被创建/更新,它包含了工程中的所有组件(包括 esp-idf 自身)。”sdkconfig” 可以被添加到工程的源码控制系统中,也可以不添加到工程的源码控制系统中。
- 可选的 “组件(components)” 目录包含了一些组件,这些组件属于工程的一部分。工程并非必须包含这种自定义的组件,但是这通常有利于构架可充用的代码或者包含不属于 ESP-IDF 的第三方组件。
- “main” 目录是一个特殊的 “虚拟组件”,它包含工程自身的源代码。”main” 是一个特殊的名字,Makefile 变量
SRCDIRS
默认就是这个值。用于也可以通过设置该变量让构建系统在其它目录来查找这个虚拟组件。 - “build” 是构架系统所创建的构建输出目录。运行 make 命令后,这个变量将包含临时目标文件、库文件和最终的二进制输出文件。该目录通常不会添加到源代码控制系统中,或者不会随着工程源代码一起发布。
组件目录包含一个组件 makefile - component.mk
。它里面可能包含用于控制组件编译过程的变量定义,被集成到整个工程。更多细节请参考 Component Makefiles。
每个组件可以包含一个 Kconfig
文件,用于定义可以通过工程配置进行设置的 组件配置 选项。
一些组件可能还包括 Kconfig.projbuild
和 Makefile.projbuild
—— 用于 覆盖构成的某一部分 的特殊文件。
工程 Makefile¶
每个工程都有一个包含整个工程构建设置的 Makefile。默认情况下,工程的 Makefile 非常简单。
最小的 Makefile 示例¶
PROJECT_NAME := myProject
include $(IDF_PATH)/make/project.mk
强制的工程变量¶
PROJECT_NAME
: 工程的名字。二进制输出文件会使用这个名字 - 即 myProject.bin, myProject.elf。
可选的工程变量¶
下面的这些变量都有一个默认值,但是你可以覆盖它们来实现一些自定义的行为。具体的实现细节请查看 make/project.mk
。
PROJECT_PATH
: Top-level project directory. Defaults to the directory containing the Makefile. Many other project variables are based on this variable. The project path cannot contain spaces.BUILD_DIR_BASE
: The build directory for all objects/libraries/binaries. Defaults to$(PROJECT_PATH)/build
.COMPONENT_DIRS
: Directories to search for components. Defaults to $(IDF_PATH)/components, $(PROJECT_PATH)/components andEXTRA_COMPONENT_DIRS
. Override this variable if you don’t want to search for components in the esp-idf & projectcomponents
directories.EXTRA_COMPONENT_DIRS
: Optional list of additional directories to search for components. Components themselves are in sub-directories of these directories, this is a top-level directory containing the component directories.COMPONENTS
: A list of component names to build into the project. Defaults to all components found in the COMPONENT_DIRS directories.SRCDIRS
: Directories under the main project directory which contain project-specific “pseudo-components”. Defaults to ‘main’. The difference between specifying a directory here and specifying it underEXTRA_COMPONENT_DIRS
is that a directory inSRCDIRS
is a component itself (contains a file “component.mk”), whereas a directory inEXTRA_COMPONENT_DIRS
contains component directories which contain a file “component.mk”. See the Example Project for a concrete case of this.
组件的 Makefile¶
Each project contains one or more components, which can either be part of esp-idf or added from other component directories.
A component is any sub-directory that contains a component.mk file [1].
Minimal Component Makefile¶
The minimal component.mk
file is an empty file(!). If the file is empty, the default component behaviour is set:
- All source files in the same directory as the makefile (
*.c
,*.cpp
,*.S
) will be compiled into the component library - A sub-directory “include” will be added to the global include search path for all other components.
- The component library will be linked into the project app.
See example component makefiles for more complete component makefile examples.
Note that there is a difference between an empty component.mk
file (which invokes default component build behaviour) and no component.mk
file (which means no default component build behaviour will occur.) It is possible for a component to have no component.mk file, if it only contains other files which influence the project configuration or build process.
Preset Component Variables¶
The following component-specific variables are available for use inside component.mk
, but should not be modified:
COMPONENT_PATH
: The component directory. Evaluates to the absolute path of the directory containingcomponent.mk
. The component path cannot contain spaces.COMPONENT_NAME
: Name of the component. Defaults to the name of the component directory.COMPONENT_BUILD_DIR
: The component build directory. Evaluates to the absolute path of a directory inside $(BUILD_DIR_BASE) where this component’s source files are to be built. This is also the Current Working Directory any time the component is being built, so relative paths in make targets, etc. will be relative to this directory.COMPONENT_LIBRARY
: Name of the static library file (relative to the component build directory) that will be built for this component. Defaults to$(COMPONENT_NAME).a
.
The following variables are set at the project level, but exported for use in the component build:
PROJECT_NAME
: Name of the project, as set in project MakefilePROJECT_PATH
: Absolute path of the project directory containing the project Makefile.COMPONENTS
: Name of all components that are included in this build.CONFIG_*
: Each value in the project configuration has a corresponding variable available in make. All names begin withCONFIG_
.CC
,LD
,AR
,OBJCOPY
: Full paths to each tool from the gcc xtensa cross-toolchain.HOSTCC
,HOSTLD
,HOSTAR
: Full names of each tool from the host native toolchain.IDF_VER
: Git version of ESP-IDF (produced bygit describe
)
If you modify any of these variables inside component.mk
then this will not prevent other components from building but it may make your component hard to build and/or debug.
Optional Project-Wide Component Variables¶
The following variables can be set inside component.mk
to control build settings across the entire project:
COMPONENT_ADD_INCLUDEDIRS
: Paths, relative to the component directory, which will be added to the include search path for all components in the project. Defaults toinclude
if not overridden. If an include directory is only needed to compile this specific component, add it toCOMPONENT_PRIV_INCLUDEDIRS
instead.COMPONENT_ADD_LDFLAGS
: Add linker arguments to the LDFLAGS for the app executable. Defaults to-l$(COMPONENT_NAME)
. If adding pre-compiled libraries to this directory, add them as absolute paths - ie $(COMPONENT_PATH)/libwhatever.aCOMPONENT_DEPENDS
: Optional list of component names that should be compiled before this component. This is not necessary for link-time dependencies, because all component include directories are available at all times. It is necessary if one component generates an include file which you then want to include in another component. Most components do not need to set this variable.COMPONENT_ADD_LINKER_DEPS
: Optional list of component-relative paths to files which should trigger a re-link of the ELF file if they change. Typically used for linker script files and binary libraries. Most components do not need to set this variable.
The following variable only works for components that are part of esp-idf itself:
COMPONENT_SUBMODULES
: Optional list of git submodule paths (relative to COMPONENT_PATH) used by the component. These will be checked (and initialised if necessary) by the build process. This variable is ignored if the component is outside the IDF_PATH directory.
Optional Component-Specific Variables¶
The following variables can be set inside component.mk
to control the build of that component:
COMPONENT_PRIV_INCLUDEDIRS
: Directory paths, must be relative to the component directory, which will be added to the include search path for this component’s source files only.COMPONENT_EXTRA_INCLUDES
: Any extra include paths used when compiling the component’s source files. These will be prefixed with ‘-I’ and passed as-is to the compiler. Similar to theCOMPONENT_PRIV_INCLUDEDIRS
variable, except these paths are not expanded relative to the component directory.COMPONENT_SRCDIRS
: Directory paths, must be relative to the component directory, which will be searched for source files (*.cpp
,*.c
,*.S
). Defaults to ‘.’, ie the component directory itself. Override this to specify a different list of directories which contain source files.COMPONENT_OBJS
: Object files to compile. Default value is a .o file for each source file that is found inCOMPONENT_SRCDIRS
. Overriding this list allows you to exclude source files inCOMPONENT_SRCDIRS
that would otherwise be compiled. See Specifying source filesCOMPONENT_EXTRA_CLEAN
: Paths, relative to the component build directory, of any files that are generated using custom make rules in the component.mk file and which need to be removed as part ofmake clean
. See Source Code Generation for an example.COMPONENT_OWNBUILDTARGET
& COMPONENT_OWNCLEANTARGET: These targets allow you to fully override the default build behaviour for the component. See Fully Overriding The Component Makefile for more details.CFLAGS
: Flags passed to the C compiler. A default set ofCFLAGS
is defined based on project settings. Component-specific additions can be made viaCFLAGS +=
. It is also possible (although not recommended) to override this variable completely for a component.CPPFLAGS
: Flags passed to the C preprocessor (used for .c, .cpp and .S files). A default set ofCPPFLAGS
is defined based on project settings. Component-specific additions can be made viaCPPFLAGS +=
. It is also possible (although not recommended) to override this variable completely for a component.CXXFLAGS
: Flags passed to the C++ compiler. A default set ofCXXFLAGS
is defined based on project settings. Component-specific additions can be made viaCXXFLAGS +=
. It is also possible (although not recommended) to override this variable completely for a component.
To apply compilation flags to a single source file, you can add a variable override as a target, ie:
apps/dhcpserver.o: CFLAGS += -Wno-unused-variable
This can be useful if there is upstream code that emits warnings.
Component Configuration¶
Each component can also have a Kconfig file, alongside component.mk
. This contains contains
configuration settings to add to the “make menuconfig” for this component.
These settings are found under the “Component Settings” menu when menuconfig is run.
To create a component KConfig file, it is easiest to start with one of the KConfig files distributed with esp-idf.
For an example, see Adding conditional configuration.
Preprocessor Definitions¶
ESP-IDF build systems adds the following C preprocessor definitions on the command line:
ESP_PLATFORM
— Can be used to detect that build happens within ESP-IDF.IDF_VER
— Defined to a git version string. E.g.v2.0
for a tagged release orv1.0-275-g0efaa4f
for an arbitrary commit.
Build Process Internals¶
Top Level: Project Makefile¶
- “make” is always run from the project directory and the project makefile, typically named Makefile.
- The project makefile sets
PROJECT_NAME
and optionally customises other optional project variables - The project makefile includes
$(IDF_PATH)/make/project.mk
which contains the project-level Make logic. project.mk
fills in default project-level make variables and includes make variables from the project configuration. If the generated makefile containing project configuration is out of date, then it is regenerated (via targets inproject_config.mk
) and then the make process restarts from the top.project.mk
builds a list of components to build, based on the default component directories or a custom list of components set in optional project variables.- Each component can set some optional project-wide component variables. These are included via generated makefiles named
component_project_vars.mk
- there is one per component. These generated makefiles are included intoproject.mk
. If any are missing or out of date, they are regenerated (via a recursive make call to the component makefile) and then the make process restarts from the top. - Makefile.projbuild files from components are included into the make process, to add extra targets or configuration.
- By default, the project makefile also generates top-level build & clean targets for each component and sets up app and clean targets to invoke all of these sub-targets.
- In order to compile each component, a recursive make is performed for the component makefile.
To better understand the project make process, have a read through the project.mk
file itself.
Second Level: Component Makefiles¶
- Each call to a component makefile goes via the
$(IDF_PATH)/make/component_wrapper.mk
wrapper makefile. - The
component_wrapper.mk
is called with the current directory set to the component build directory, and theCOMPONENT_MAKEFILE
variable is set to the absolute path tocomponent.mk
. component_wrapper.mk
sets default values for all component variables, then includes the component.mk file which can override or modify these.- If
COMPONENT_OWNBUILDTARGET
andCOMPONENT_OWNCLEANTARGET
are not defined, default build and clean targets are created for the component’s source files and the prerequisiteCOMPONENT_LIBRARY
static library file. - The
component_project_vars.mk
file has its own target incomponent_wrapper.mk
, which is evaluated fromproject.mk
if this file needs to be rebuilt due to changes in the component makefile or the project configuration.
To better understand the component make process, have a read through the component_wrapper.mk
file and some of the component.mk
files included with esp-idf.
Running Make Non-Interactively¶
When running make
in a situation where you don’t want interactive prompts (for example: inside an IDE or an automated build system) append BATCH_BUILD=1
to the make arguments (or set it as an environment variable).
Setting BATCH_BUILD
implies the following:
- Verbose output (same as
V=1
, see below). If you don’t want verbose output, also setV=0
. - If the project configuration is missing new configuration items (from new components or esp-idf updates) then the project use the default values, instead of prompting the user for each item.
- If the build system needs to invoke
menuconfig
, an error is printed and the build fails.
Debugging The Make Process¶
Some tips for debugging the esp-idf build system:
- Appending
V=1
to the make arguments (or setting it as an environment variable) will cause make to echo all commands executed, and also each directory as it is entered for a sub-make. - Running
make -w
will cause make to echo each directory as it is entered for a sub-make - same asV=1
but without also echoing all commands. - Running
make --trace
(possibly in addition to one of the above arguments) will print out every target as it is built, and the dependency which caused it to be built. - Running
make -p
prints a (very verbose) summary of every generated target in each makefile.
For more debugging tips and general make information, see the GNU Make Manual.
Overriding Parts of the Project¶
Makefile.projbuild¶
For components that have build requirements that must be evaluated in the top-level
project make pass, you can create a file called Makefile.projbuild
in the
component directory. This makefile is included when project.mk
is evaluated.
For example, if your component needs to add to CFLAGS for the entire
project (not just for its own source files) then you can set
CFLAGS +=
in Makefile.projbuild.
Makefile.projbuild
files are used heavily inside esp-idf, for defining project-wide build features such as esptool.py
command line arguments and the bootloader
“special app”.
Note that Makefile.projbuild
isn’t necessary for the most common component uses - such as adding include directories to the project, or LDFLAGS to the final linking step. These values can be customised via the component.mk
file itself. See Optional Project-Wide Component Variables for details.
Take care when setting variables or targets in this file. As the values are included into the top-level project makefile pass, they can influence or break functionality across all components!
KConfig.projbuild¶
This is an equivalent to Makefile.projbuild for component configuration KConfig files. If you want to include
configuration options at the top-level of menuconfig, rather than inside the “Component Configuration” sub-menu, then these can be defined in the KConfig.projbuild file alongside the component.mk
file.
Take care when adding configuration values in this file, as they will be included across the entire project configuration. Where possible, it’s generally better to create a KConfig file for component configuration.
Example Component Makefiles¶
Because the build environment tries to set reasonable defaults that will work most of the time, component.mk can be very small or even empty (see Minimal Component Makefile). However, overriding component variables is usually required for some functionality.
Here are some more advanced examples of component.mk
makefiles:
Adding source directories¶
By default, sub-directories are ignored. If your project has sources in sub-directories
instead of in the root of the component then you can tell that to the build
system by setting COMPONENT_SRCDIRS
:
COMPONENT_SRCDIRS := src1 src2
This will compile all source files in the src1/ and src2/ sub-directories instead.
Specifying source files¶
The standard component.mk logic adds all .S and .c files in the source
directories as sources to be compiled unconditionally. It is possible
to circumvent that logic and hard-code the objects to be compiled by
manually setting the COMPONENT_OBJS
variable to the name of the
objects that need to be generated:
COMPONENT_OBJS := file1.o file2.o thing/filea.o thing/fileb.o anotherthing/main.o
COMPONENT_SRCDIRS := . thing anotherthing
Note that COMPONENT_SRCDIRS
must be set as well.
Adding conditional configuration¶
The configuration system can be used to conditionally compile some files
depending on the options selected in make menuconfig
:
Kconfig
:
config FOO_ENABLE_BAR
bool "Enable the BAR feature."
help
This enables the BAR feature of the FOO component.
component.mk
:
COMPONENT_OBJS := foo_a.o foo_b.o
ifdef CONFIG_FOO_BAR
COMPONENT_OBJS += foo_bar.o foo_bar_interface.o
endif
See the GNU Make Manual for conditional syntax that can be used use in makefiles.
Source Code Generation¶
Some components will have a situation where a source file isn’t supplied with the component itself but has to be generated from another file. Say our component has a header file that consists of the converted binary data of a BMP file, converted using a hypothetical tool called bmp2h. The header file is then included in as C source file called graphics_lib.c:
COMPONENT_EXTRA_CLEAN := logo.h
graphics_lib.o: logo.h
logo.h: $(COMPONENT_PATH)/logo.bmp
bmp2h -i $^ -o $@
In this example, graphics_lib.o and logo.h will be generated in the current directory (the build directory) while logo.bmp comes with the component and resides under the component path. Because logo.h is a generated file, it needs to be cleaned when make clean is called which why it is added to the COMPONENT_EXTRA_CLEAN variable.
Cosmetic Improvements¶
Because logo.h is a generated file, it needs to be cleaned when make clean is called which why it is added to the COMPONENT_EXTRA_CLEAN variable.
Adding logo.h to the graphics_lib.o
dependencies causes it to be
generated before graphics_lib.c
is compiled.
If a a source file in another component included logo.h
, then this
component’s name would have to be added to the other component’s
COMPONENT_DEPENDS
list to ensure that the components were built
in-order.
Embedding Binary Data¶
Sometimes you have a file with some binary or text data that you’d like to make available to your component - but you don’t want to reformat the file as C source.
You can set a variable COMPONENT_EMBED_FILES in component.mk, giving the names of the files to embed in this way:
COMPONENT_EMBED_FILES := server_root_cert.der
Or if the file is a string, you can use the variable COMPONENT_EMBED_TXTFILES. This will embed the contents of the text file as a null-terminated string:
COMPONENT_EMBED_TXTFILES := server_root_cert.pem
The file’s contents will be added to the .rodata section in flash, and are available via symbol names as follows:
extern const uint8_t server_root_cert_pem_start[] asm("_binary_server_root_cert_pem_start");
extern const uint8_t server_root_cert_pem_end[] asm("_binary_server_root_cert_pem_end");
The names are generated from the full name of the file, as given in COMPONENT_EMBED_FILES. Characters /, ., etc. are replaced with underscores. The _binary prefix in the symbol name is added by objcopy and is the same for both text and binary files.
For an example of using this technique, see protocols/https_request - the certificate file contents are loaded from the text .pem file at compile time.
Fully Overriding The Component Makefile¶
Obviously, there are cases where all these recipes are insufficient for a
certain component, for example when the component is basically a wrapper
around another third-party component not originally intended to be
compiled under this build system. In that case, it’s possible to forego
the esp-idf build system entirely by setting COMPONENT_OWNBUILDTARGET and
possibly COMPONENT_OWNCLEANTARGET and defining your own targets named build
and clean
in component.mk
target. The build target can do anything as long as it creates
$(COMPONENT_LIBRARY) for the project make process to link into the app binary.
(Actually, even this is not strictly necessary - if the COMPONENT_ADD_LDFLAGS variable is set then the component can instruct the linker to link other binaries instead.)
[1] | Actually, some components in esp-idf are “pure configuration” components that don’t have a component.mk file, only a Makefile.projbuild and/or Kconfig.projbuild file. However, these components are unusual and most components have a component.mk file. |
Custom sdkconfig defaults¶
For example projects or other projects where you don’t want to specify a full sdkconfig configuration, but you do want to override some key values from the esp-idf defaults, it is possible to create a file sdkconfig.defaults
in the project directory. This file will be used when running make defconfig
, or creating a new config from scratch.
To override the name of this file, set the SDKCONFIG_DEFAULTS
environment variable.
调试¶
为 ESP32 设置 OpenOCD¶
ESP321 和 ESP32 带有两个功能强劲的 Xtensa 核,支持大量的程序架构。ESP-IDF 中的 FreeRTOS 具有多核抢占式多线程功能,支持以最直观的方式编写代码。
当然这也带来一个弊端,即当没有合适的工具时,程序的调试变得更加艰难:如果一个 bug 是由两个线程引起的,这两个线程可能会同时运行在两个 CPU 核上,如果你所仅能使用 printf 语句,则调试过程可能会花费你的大量时间。调试这种问题的更好的以及更快速(大多数情形下)的方法是使用一个调试器,将它连接到处理器的调试端口。
乐鑫已经将 OpenOCD 和多核 FreeRTOS 移植到 ESP32 处理器上,并添加了一些 OpenOCD 原生并未支持的有用功能。这些都是免费的,本文档就是用于描述如何安装并使用它们。
JTAG 适配器硬件¶
你需要一个电压值既兼容 ESP32 又兼容 OpenOCD 软件的 JTAG 适配器。ESP32 上面的 JTAG 端口是一个工业级的没有(也不需要)TRST 引脚的 JTAG 端口。JTAG 的 I/O 引脚都通过 VDD_3P3_RTC 引脚进行供电(通常是 3.3 V),因此 JTAG 适配器和 JTAG 引脚应该能在该电压范围内正常工作。在软件方面,OpenOCD 支持大量的 JTAG 适配器,具体的适配器列表(不是太完整)请查阅 http://openocd.org/doc/html/Debug-Adapter-Hardware.html。 该页面也列举了 SWD 兼容的适配器;需要说明的是,ESP32 不支持 SWD。
在乐鑫,我们已经测试了 TIAO USB Multi-protocol 适配器电路板以及 Flyswatter2,这二者都是 USB2.0 的高速设备,具有良好的吞吐量。我们还测试了 J-Link 兼容的适配器以及 EasyOpenJTAG 适配器,它们都能正常工作,不过速度有点慢。
JTAG 工作所需要的最少信号线包括 TDI、TDO、TCK、TMS 和 Gnd。某些 JTAG 适配器还需要将 ESP32 的电源线连接到一根叫做 Vtar 的信号线上,以提供工作电压。另外,还可以将 SRST 可选地连接到 ESP32 的 CH_PD 引脚,OpenOCD 中很少使用该信号线。
安装 OpenOCD¶
ESP32 的变体版 OpenOCD 的源码位于 Espressifs Github,你可以使用下面的命令下载该源码
git clone --recursive https://github.com/espressif/openocd-esp32.git
cd openocd-esp32
具体的编译步骤请参考 openocd-esp32 目录下的 README、README.OSX 和 README.Windows。当然,你也可以跳过 make install
这一步。
在 OpenOCD 中配置 ESP32 目标¶
当 OpenOCD 编译(以及可选地安装)完,JTAG 适配器连接到 ESP32 开发板后,使用 OpenOCD 就以及基本准备就绪了。此外,OpenOCD 还需要知道使用的是什么 JTAG 适配器,以及适配器所连接的是什么开发板和处理器。实现该目的的最简单的方式是使用一个配置文件。在本文档的同一目录下包含一个配置文件模板,你可以这样使用它:
- 将 esp32.cfg 拷贝到 openocd-esp32 目录。
- 编辑所拷贝的文件 esp32.cfg。最重要的是修改
source [find interface/ftdi/tumpa.cfg]
这一行,它用于说明所连接的物理 JTAG 适配器。 - 打开一个终端,
cd
到 openocd-esp32 目录。 - 运行
./src/openocd -s ./tcl -f ./esp32.cfg
启动 OpenOCD。
然后你将看到类似下面的输出
user@machine:~/esp32/openocd-esp32$ ./src/openocd -s ./tcl/ -f ../openocd-esp32-tools/esp32.cfg
Open On-Chip Debugger 0.10.0-dev-00446-g6e13a97-dirty (2016-08-23-16:36)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
none separate
adapter speed: 200 kHz
Info : clock speed 200 kHz
Info : JTAG tap: esp32.cpu0 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
Info : JTAG tap: esp32.cpu1 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
Info : esp32.cpu0: Debug controller was reset (pwrstat=0x5F, after clear 0x0F).
Info : esp32.cpu0: Core was reset (pwrstat=0x5F, after clear 0x0F).
- 如果你碰到了关于权限的问题,请查阅 OpenOCD README 文档中的 ‘Permissions delegation’。
- 如果你碰到了错误 (…all ones/…all zeroes),请检查你的连线,并确实是否已上电。
将调试器连接到 OpenOCD¶
OpenOCD 现在已经准备接受 gdb 连接了。如果你使用 Crosstool-NG 编译好了 ESP32 的工具链,或者从乐鑫官方下载了预编译的工具链,则该工具链中已包含 xtensa-esp32-elf-gdb,你可以直接用该 gdb 进行调试。首先,确保你的想要调试的工程已经被编译并烧写到 ESP32 的 SPI flahs 中了。然后,在另一个控制台(而非运行 OpenOCD 的控制台)中运行 gdb。例如,对于 template app
cd esp-idf-template
xtensa-esp32-elf-gdb -ex 'target remote localhost:3333' ./build/app-template.elf
然后它应该会显示 gdb 提示符。
FreeRTOS 的支持¶
OpenOCD 已经明确地支持 ESP-IDF FreeRTOS 了;可以在 esp32.conf 中禁止 FreeRTOS 检测。如果使能了 FreeRTOS 检测,gdb 则会将 FreeRTOS 任务当做线程处理。查看这些线程可以使用 gdb 命令 i threads
,切换到某个线程可以使用命令 thread x
,其中 x 是线程的数字。可以切换到除了正在另一个 CPU 上运行的线程之前的其它所有线程,更多信息请参考 ESP32 quirks
。
ESP32 quirks¶
常规的 gdb 断点(b myFunction
)只能设置在 IRAM 中,因为这段内存是可写的。在 flash 中的代码中设置这种类型的代码是无效的。它还可以支持两个观察点,因此可以使用 gdb 命令 watch myVariable
来观察/读取两个变量的改动。
你可以通过改变端口号将 gdb 连接到 APP CPU 或者 PRO CPU。target remote localhost:3333
可以连接到 PRO CPU,target remote localhost:3334
可以连接到 APP CPU。硬件方面,当某个 CPU 由于调试原因被挂起时,另一个 CPU 也会被挂起;恢复也是同时发生的。
由于 gdb 只能看到以所选 CPU 的视角所对应的系统,只有挂起的任务和正在 gdb 所连接的 CPU 上面运行的任务会被正确地显示。另一个 cpu 上面的活动的任务也可以被查看,不过它的状态可能非常不连续。
ESP-IDF 针对 OpenOCD 的各种功能提供了对应的编译选项:可以在第一个线程启动后停止执行执行;当抛出 panic 或者未处理异常后打断系统。这两个选项默认都是使能的,但是可以使用 esp-idf 配置选项对其进行禁止,更多细节请参考 make menuconfig
菜单。
正常情况下,在 OpenOCD 下面,可以通过向 ddb 中输入 ‘mon reset’ 或 ‘mon reset halt’ 对开发板进行复位。对于 ESP32,这些功能基本都能工作,但是有一些负面影响。首先,OpenoCD 复位只会复位 CPU 核,不会复位外设,因此如果软件依赖了外设复位后的状态,则可能导致产生未定的行为。其次,’mon reset halt’ 会在 freeRTOS 初始化前停止,而 OpenOCD 会假设 FreeRTOS 正在运行(默认情况,你也可以编辑 esp32.cfg 进行修改),然后它会变得混淆。
ESP32 的 Core Dump¶
ESP-IDF 支持在遇到不可恢复的软件错误时产生 core dump。这项有用的技术允许发生错误后再分析软件的状态。程序一旦崩溃,系统将进入 panic 状态,打印一些信息并挂起或者重启系统(依赖于配置)。用户可以选择产生 core dump 文件,从而可以在随后在 PC 上分析失败的原因。Core dump 中包含失败的那一刻系统中所有任务的快照。快照包括导致系统崩溃的线程的调用栈(callstack)。 ESP-IDF 提供了一个特殊的脚本 espcoredump.py 用于帮助用户恢复和分析 core dump。该工具提供了两个用于分析 core dump 的命令:
- info_corefile - 打印崩溃任务的寄存器、调用栈、系统有效任务列、内存区域以及存储在 core dump 中的内存中的内容(任务控制块 TCB 和栈)。
- dbg_corefile - 创建 core dump ELF 文件,并使用这个文件运行 GDB 调试会话。用户可以人工检查内存、变量和任务状态。需要注意的是,由于不是所有的内容都存放在 cour dump 中,只有分配到栈上的变量值才有意义。
配置¶
存在许多与 core dump 相关的配置选项,用户可以在应用程序的配置菜单中进行选择(make menuconfig)。
- Core dump 数据目的地 (Components -> ESP32-specific config -> Core dump destination):
- 禁止产生 core dump
- 将 core dump 保存到 flash
- 将 core dump 打印到 UART
- core dump 模块的日志级别 (Components -> ESP32-specific config -> Core dump module logging level)。该值是一个从 0(无输出)到 5(最多输出)之间的一个数字。
- 将 core dump 打印到 UART 之前的延迟 (Components -> ESP32-specific config -> Core dump print to UART delay)。该值以 ms 为单位。
保存 core dump 到 flash¶
当该值被选择时,core dump 会被保存到 flash 上面的某个特殊分区。当使用 ESP-IDF 提供的默认分区表文件时,它将在 flash 上面自动分配所需空间。但是如果用户希望使用自己的带有 core dump 功能的布局文件,则应当像下面这样定义独立的分区表
# Name, Type, SubType, Offset, Size
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
nvs, data, nvs, 0x9000, 0x6000
phy_init, data, phy, 0xf000, 0x1000
factory, app, factory, 0x10000, 1M
coredump, data, coredump,, 64K
分区表名没有特殊的需求,它可以根据用户应用程序的需要进行选择,但是分区表类型应当选择为 ‘data’,子类型应当选择为 ‘coredump’。此外,选择分区表大小的时候需要注意,core dump 的数据结构会引进一些额外的开销,包括固定 20 字节加上每个任务 12 字节。这个开销不包括每个任务的 TCB 大小和栈空间。因此,分区表的大小应当至少为 20 + 最大任务数量 x (12 + TCB 大小 + 任务最大栈大小) 字节。
从 flash 上面分析 core dump 的常用命令是: espcoredump.py -p </path/to/serial/port> info_corefile </path/to/program/elf/file> 或者 espcoredump.py -p </path/to/serial/port> dbg_corefile </path/to/program/elf/file>
打印 core dump 到 UART¶
当该选项被选择时,系统 panic 时会将按照 base64 编码的 core dump 打印到 UART 上。在这种情况下,用户需要手工将这些 core dump 文本的 body 保存到某个文件中,然后运行如下的目录: espcoredump.py info_corefile -t b64 -c </path/to/saved/base64/text> </path/to/program/elf/file> 或者 espcoredump.py dbg_corefile -t b64 -c </path/to/saved/base64/text> </path/to/program/elf/file>
按照 base64 编码的 core dump 的 body 位于下面的头部和尾部之间
================= CORE DUMP START =================
<body of base64-encoded core dump, save it to file on disk>
================= CORE DUMP END ===================
运行 ‘espcoredump.py’¶
命令的常用语法:
espcoredump.py [options] command [args]
Script Options: |
|
---|---|
Commands: |
|
Command Arguments: | |
|
分区表¶
概述¶
单个 ESP32 flash 可以包含多个应用程序,以及多种数据(校验数据、文件系统、参数存储器等)。基于这个原因,在 flash 的偏移地址 0x8000 处烧写了一个分区比表。
分区表的长度是 0xC00 字节(最多 95 个分区表条目)。如果分区表由于 安全启动 被签名,则签名会追加到表格的数据后面。
分区表的每个条目都包含名字(标签)、类型(app、data 等)、子类型以及在 flash 中的偏移量(分区表被加载的地址)。
使用分区表最简单的方法是使用 make menuconfig,然后选择一个简单的预定义的分区表:
- “Single factory app, no OTA”
- “Factory app, two OTA definitions”
在这两种情况下,工厂应用程序都会被烧写到偏移量 0x10000 处。如果你运行 make partition_table,控制台则会打印出分配表的情况。
内置分区表¶
下面是配置 “Single factory app, no OTA” 所打印出的信息
# Espressif ESP32 Partition Table
# Name, Type, SubType, Offset, Size
nvs, data, nvs, 0x9000, 0x6000
phy_init, data, phy, 0xf000, 0x1000
factory, app, factory, 0x10000, 1M
- flash 的偏移地址 0x10000 (64KB) 处是标记为 “factory” 的应用程序。bootloader 默认会运行这里的应用程序。
- 分区表中还定义了连个数据区域,用于存储 NVS 库分区和 PHY 初始化数据。
下面是配置 “Factory app, two OTA definitions” 所打印出的信息
# Espressif ESP32 Partition Table
# Name, Type, SubType, Offset, Size
nvs, data, nvs, 0x9000, 0x4000
otadata, data, ota, 0xd000, 0x2000
phy_init, data, phy, 0xf000, 0x1000
factory, 0, 0, 0x10000, 1M
ota_0, 0, ota_0, , 1M
ota_1, 0, ota_1, , 1M
- 存在三个应用程序分区的定义。
- 这三个的类型都是 “app”,但是子类型不同,工厂 app 位于 0x10000 处,剩余两个是 “OTA” app。
- 这里还有一个新的 “ota data”,它用于保存 OTA 更新的一些信息。bootloader 会使用这些数据来判断指定哪个应用程序。如果 “ota data” 是空的,它会执行工厂应用程序。
创建自定义分区表¶
如果你在配置菜单中选择 “Custom partition table CSV”,你需要输入用于保存你的分区表的 CSV 文件的名字(在工程目录中)。CSV 可以根据你的需要描述任意数量的定义。
CVS 的格式与上面所打印的信息的格式是类似的。不过,不是所有的字段都需要。例如,这是一个 OTA 分区表的 “input” CSV
# Name, Type, SubType, Offset, Size
nvs, data, nvs, 0x9000, 0x4000
otadata, data, ota, 0xd000, 0x2000
phy_init, data, phy, 0xf000, 0x1000
factory, app, factory, 0x10000, 1M
ota_0, app, ota_0, , 1M
ota_1, app, ota_1, , 1M
- 字段间的空格会被忽略,以 # 开始的行(注释)也会被忽略。
- CSV 文件的每个非注释行都是一个分区定义。
- 只提供了第一个分区的偏移量。工具 gen_esp32part.py 会自动根据前一个分区的参数来填充偏移量。
名字(Name)字段¶
名字字段可以是任意有意义的名字。这对 ESP32 是无关紧要的。长度大于 16 个字符的名字将会被截断。
Type 字段¶
分区类型字段可以指定为 app(0)或者 data(1)。它也可以是 0-254(0x00-0xFE)之间的数字。类型 0x00-0x3F 被保留用于 esp-idf 的核心功能。
如果你的应用程序需要存储数据,请添加一个类型在 0x40-0xFE 范围的自定义分区。
bootloader 会忽略所有类型不是 app(0) & data(1) 的分区。
App 子类型¶
当类型是 “app” 时,子类型可以是 factory (0), ota_0 (0x10) … ota_15 (0x1F) 或 test (0x20)。
- factory (0) 是默认的 app 分区。如果这里没有 data/ota 类型的分区,它会默认执行工厂 app,否则会读取该分区来判断启动哪个 OTA 镜像。
- OTA 永远不会更新工厂分区。
- 如果你想在 OTA 工程中保护 flash 的使用,你可以移除工厂分区并使用 ota_0 代替。
- ota_0 (0x10) … ota_15 (0x1F) 是 OTA 应用程序插槽(slot)。更多细节请参考 OTA 文档,然后使用 OTA 数据分区来配置让给 bootloader 启动哪个插槽。如果使用 OTA,应用程序应当至少包括两个 OTA 应用程序插槽(ota_0 & ota_1)。更多细节请参考 OTA 文档。
- test (0x2) 是用于工厂测试过程的保留子类型。esp-idf bootloader 当前不支持这种子类型。
Data 子类型¶
当类型是 “data”时,子类型可以是 ota (0), phy (1), nvs (2)。
- ota (0) 是 OTA 数据分区,用于存储当前所选择的 OTA 应用程序的信息。这个分区的大小固定为 0x2000 字节。更多细节请参考 OTA 文档。
- phy (1) 用于存储 PHY 初始化数据。这样可以为每个设备(而不是在固件中)配置 PHY。
- 在默认的配置中,phy partition 未被使用,PHY 初始化数据被编译到应用程序自身中。对于这种过情况,可以将这个分区从分区表中移除,以节约空间。
- 要从这个分区表中加载 PHY 数据,运行
make menuconfig
并使能 “Component Config” -> “PHY” -> “Use a partition to store PHY init data”。你还需要给你的设备烧写 phy 初始化数据,因为 esp-idf 的编译系统默认不会自动完成该操作。
- nvs (2) 用于 非易失性存储器 (NVS) API。
- NVS 用于存储每个设备的 PHY 校验数据(与初始化数据不同)。
- NVS 用于存储 Wifi 数据(如果使用了 esp_wifi_set_storage(WIFI_STORAGE_FLASH) 初始函数)。
- NVS 也可以用于其它应用程序数据。
- 强烈建议在你的工程中包含一个大于 0x3000 字节的 NVS 分区。
- 如果想要使用 NVS API 来存储大量数据,请增加 NVS 分区表的大小(默认是 0x6000 字节)。
其它数据子类型保留。
偏移量 & 大小¶
只有第一个偏移字段是需要的(我们推荐使用 0x10000)。偏移量为空白的分区将会自动跟在前一个分区的后面。
应用程序分区必须对齐到 0x10000 (64K)。如果它的偏移量字段为空白,工具将会自动让给分区对齐。如果你指定了一个未对齐的偏移量,工具将会返回一个错误。
大小和偏移量可以以十进制形式指定,也可以以 0x 为前缀的十六进制形式指定,或者以 K 或 M 作为单位指定(分别是 1024 和 1024*1024 字节)。
产生二进制分区表¶
烧写到 ESP32 中的分区表是二进制格式的,而不是 CSV。工具 partition_table/gen_esp32part.py 可用于将分区表在 CSV 和二进制格式之间进行转化。
如果你在``make menuconfig`` 中配置了 CSV 名字,然后 make partition_table
,则在编译过程会自动进行转化。
手工将 CSV 转化为二进制格式
python gen_esp32part.py --verify input_partitions.csv binary_partitions.bin
将二进制转换回 CSV
python gen_esp32part.py --verify binary_partitions.bin input_partitions.csv
如果需要在标志输出中显示二进制分区表的内容(这就是运行 make partition_table 时所产生的信息)
python gen_esp32part.py binary_partitions.bin
gen_esp32part.py
有一个可选参数 --verify
,它会在转化期间校验分区表(检查重叠分区、为对齐分区等)。
烧写分区表¶
make partition_table-flash
: 将会使用 esptool.py 烧写分区表。make flash
: 将会烧写包括分区表在内的所有东西。
make partition_table
时也会打印手工烧写命令。
注意,更新分区表不会擦除老的分区表所存储的数据。你可以使用命令 make erase_flash
(或 esptool.py erase_flash
) 擦除整个 flash 的内容。
Flash 加密¶
Flash 加密功能可用于加密 ESP32 所连接的 SPI flash 上面的内容。当 flash 加密被使能后,从 SPI flash 上面读出的数据不足以用于恢复 flash 上面所存储的大多数内容。
Falsh 加密是与 安全启动 相独立的另一个功能,你可以在不使能安全加密的情况下单独使用 flash 加密功能。不过,为了有一个更加安全的环境,我们推荐同时使用这两种技术。
**IMPORTANT: 使能 flash 加密将会限制你今后可以对 ESP32 进行更新的次数。请确保仔细阅读本文档(包括 Flash 加密的限制)并充分理解使能 flash 加密的含义。 **
背景¶
- flash 的内容使用秘钥长度为 256 比特的 AES 进行加密。flash 的加密密钥存储在芯片内部的 efuse 中,且(默认)被保护,以免软件访问呢。
- 通过 ESP32 的 flash cache 映射功能对 flash 的访问是透明的 - 读取时,所有被映射到这段地址空间的 flash 区域都会被透明地解密。
- 加密是通过给 ESP32 烧写明码文本数据、然后由 bootloader 在第一次启动准备就绪后对这些数据进行加密完成的(如果加密被使能)。
- 不是所有的 flash 都会被加密。下列 flash 数据不会被加密:
- Bootloader
- 安全启动 bootloader digest (如果安全启动被使能)
- 分区表
- 所有的 “app” 类型的分区
- 在分区表中所有标记了 “encrypt” 的分区
为了易于访问,或者为了使用 flash 友好的更新算法(数据加密后对算法有影响),有时候需要某些数据分区不被加密。非易失型存储器的 “NVS” 分区不能被加密。
- flash 的加密秘钥存储在 ESP32 芯片内部的 efuse 密钥块 1 中。默认情况下,这个密钥是读/写保护的,因此软件不能访问或者修改它。
- flash 加密算法 使用的是 AES-256,其密钥是通过 flash 的 32 字节的块的偏移地址进行调整的。这意味着,每 32 字节的块(两个连续的 16 字节 AES 块)是通过由 flash 加密密钥推断出来的唯一的密钥(unique key)进行加密的。
- 尽管运行在芯片上的软件可以透明地对 flash 上面的内容进行解密,但是当 falsh 加密被使能后,UART bootloader(默认)不能对数据进行加密/解密。
- 如果 flash 加密被使能,当程序员在 使用加密的 flash 写代码时必须进行更加周详的考虑。
Flash 加密的初始化¶
这里描述的是 flash 加密初始化的默认(且推荐)过程。如果需要实现特殊的功能,也可以自定义该过程,具体细节请参考 Flash 加密高级功能。
IMPORTANT: 一旦在某次启动时使能 flash 加密后,随后通过串口对 flash 重新烧写最多只有三次机会。 且需要执行特殊的步骤(参考文档 串口烧写)才能进行烧写。
- 如果安全启动被使用,则再也不能在物理上进行重新烧写。
- OTA 可以用于更新 flash 上面的内容,没有受到这种限制。
- 当在开发过程中使能 flash 加密时,使用 预生成的 flash 加密密钥 可以在物理上对预加密的数据进行无数次的重新烧写。**
使能 flash 加密的过程:
- bootloader 在被编译时必须使能 flash 加密功能。在 ``make menuconfig``中,进入 “Security Features” 并给 “Enable flash encryption on boot” 选择 “Yes”。
- 如果同时还使能了安全启动,最好同时也选上这些选项。请先参考文档 安全启动。
- 像常规方法一样编译和烧写 bootloader、分区表和工厂 app。这些分区在初次被写入 flash 时是未被加密的。
- 第一次启动时,bootloader 将会看到 FLASH_CRYPT_CNT efuse 被设置为 0(工厂默认),然后它会使用硬件随机数发生器生成一个 falsh 加密密钥。这个密钥会被存储在 efuse 中,且具有软件读/写保护的功能。
- 所有的加密分区然后被 bootloader 加密。加密需要一段时间(大分区最多会需要一分钟)。
IMPORTANT: 当第一次启动在进行加密时,不要中断对 ESP32 的供电。如果供电被中断,flash 中的内容将会被破坏,然后需要使用未加密的数据进行重新烧写。这种重新烧写不会影响烧写次数限制。
- 当烧写完成后,efuses 会在 UART bootloader 运行期间禁止对加密 flash 的访问。请查看 使能 UART Bootloader 加密/解密 以了解高级特性。
- efuse
FLASH_CRYPT_CONFIG
被烧写为最大值(0xF
),以得到一个位数最大的密钥(在 flash 算法中被调整)。请查看 ref:setting-flash-crypt-config 以了解高级特性。 - 最后,FLASH_CRYPT_CNT efuse 被烧写为一个初始值 1。就是这个 efuse 激活了 flash 透明加密层并限制了随后可重新烧写的次数。关于 FLASH_CRYPT_CNT efuse 的更多细节请参考章节 更新加密的 Flash。
- bootloader 自身复位,并从新的被加密的 flash 重启。
使用加密的 Flash¶
ESP32 应用程序代码可以通过调用 esp_flash_encryption_enabled()
来检查当前是否使能了 flash 加密功能。
当 flash 加密被使能后, 从代码中访问 flash 上面的内容时需要考虑一些额外的东西。
Flash 加密的范围¶
无论什么时候,只要 FLASH_CRYPT_CNT efuse 被设置了一个新的奇数比特位,所有通过 MMU cache 访问的 flash 内容都会被透明地解密。这包括:
- flash 上面的应用程序可执行代码(IROM)
- 存储在 flash 中的所有只读数据(DROM)
- 所有通过
esp_spi_flash_mmap()
访问的数据 - 正在被 ROM bootloader 读取的软件 bootloader 镜像
IMPORTANT: MMU flash cache 会无条件地解码所有数据。在 flash 中存储的未加密数据会通过 flash cache 被透明地解密,然后对软件来说就是垃圾数据。
读取加密的 Flash¶
如果要在读取数据时不使用 flash cache MMU 映射,我们推荐使用分区读取函数 esp_partition_read()
。当使用这个函数时,只有从加密分区中读取的数据会被解密,其它分区读取的数据不会被解密。通过这种方法,软件可以以同一种方法访问加密和未加密的 falsh。
以其它 SPI 读 API 所读取的数据不会被解密:
- 通过
esp_spi_flash_read()
读取的数据不被解密。 - 通过 ROM 函数
SPIRead()
读取的数据不被解密(该函数不支持 esp-idf 应用程序)。 - 使用非易失性存储器 (NVS) API 存储的数据总是以解密形式进行存储/读取。
写加密的 Flash¶
只要可能,我们都推荐使用分区写函数 esp_partition_write
。当使用该函数时,只有往加密分区中写的数据会被加密,往其它分区写的数据不会被加密。通过这种方法,软件可以以同一种方法访问加密和未加密的 falsh。
当参数 write_encrypted 设置为 true 时,函数 esp_spi_flash_write
将以加密的形式写数据,否则则会以未加密的形式写数据。
ROM 函数 esp_rom_spiflash_write_encrypted
将会写加密数据到 flash,ROM 函数 SPIWrite
将会写未加密数据到 flash 中(这些函数不支持 esp-idf 应用程序)。
未加密数据的最小写尺寸是 4 字节(且是 4 字节对齐的)。由于数据加密是以块为单位的,加密数据的最小写尺寸是 16 字节(且是以 16 字节对齐的)。
更新加密的 Flash¶
OTA 更新¶
对加密分区进行 OTA 更新时,只要使用的函数是 esp_partition_write
,该分区就会被自动以加密的形式进行写。
串口烧写¶
如果没有使用安全启动,FLASH_CRYPT_CNT efuse 允许通过串口烧写的方式(或其它物理方式)对 flash 进行更新,但最多有三次额外的机会。
该过程涉及烧写明码文本数据、更改(bump):ref:FLASH_CRYPT_CNT 的值,从而引起 bootloader 对该数据进行重新加密。
有限的更新¶
这种情况下只有 4 次串口烧写机会,其中还包括初始加密 flash 在内的那次机会。
当第四次加密被禁止后,FLASH_CRYPT_CNT efuse 将拥有一个最大值 0xFF,加密被永久禁止。
使用 OTA 更新 或 通过预生成的 Flash 加密密钥重新烧写 可以绕过这种限制。
串口烧写的注意事项¶
- 当使用串口重新烧写时,需要重新烧写所有使用明码文本初始化的分区(包括 bootloader),但是可以跳过非 “当前所选择” 的那个 OTA 分区(除非在上面发现了明码文本应用程序镜像,否则不会待其进行重新加密)。不过,所有有 “加密” 标记的分区会被无条件地重新加密,这也意味着已被加密的数据会被再次加密而被破坏。
- 使用
make flash
会烧写所有需要烧写的分区。
- 使用
- 如果安全启动被使能,除非你的安全启动使用了 “重新烧写” 选项并烧写了预生成的密钥(参考 Secure Boot 文档),否则你不能使用串口进行串行烧写。在这种情况下,你可以在偏移地址 0x0 处重新烧写一个明码文本的安全启动 digest 和 bootloader 镜像。在烧写其它明码文本数据之前,必须要先烧写这个 digest。
串口重新烧写的过程¶
- 像平常一样编译应用程序。
- 像平常一样给设备烧写明码文本数据(
make flash
或esptool.py
命令),烧写之前的所有加密分区(包括 bootloader)。 - 此时,设备将不能启动(提示消息
flash read err, 1000
),这是因为它期望看到的是一个加密的 bootloader,而实际上却是一个明码文本。 - 使用命令
espefuse.py burn_efuse FLASH_CRYPT_CNT
烧写 FLASH_CRYPT_CNT efuse。espefuse.py 会自动给计数比特加 1,并禁止加密。 - 复位设备,然后设备会重新加密明码文本分区,然后再次烧写 FLASH_CRYPT_CNT efuse 以重新使能加密功能。
禁止串口更新¶
如果需要阻止今后使用串口更新明码文本,可以在 flash 加密被使能后(即第一次启动完成后)使用 espefuse.py 写保护 FLASH_CRYPT_CNT efuse
espefuse.py --port PORT write_protect_efuse FLASH_CRYPT_CNT
这将会禁止今后做任何改动,以禁止/重新使能 flash 加密。
通过预生成的 Flash 加密密钥重新烧写¶
你也可以在 PC 上面预生成一个 flash 加密密钥,然后将它烧写到 ESP32 的 efuse 密钥块中。这样做的好处是可以在主机对数据预加密,然后将加密后的数据烧写到 ESP32 上面,从而不需要明码文本烧写更新。
这在开发过程中是很有用的,因为它没有 4 次重烧的限制。此外,即使安全启动被使能,也可以无限次地重新烧写,因为 bootloader 不需要每次都被烧写。
IMPORTANT 这种方法只是为了方便开发,不要用于实际的产品设备。如果要为产品生成 flash 加密数据,请确保使用一个高质量的随机数源产生加密密钥,且不要在多个设备之间共享同一个 flash 加密密钥。
预生成 Flash 加密密钥¶
Flash 加密密钥是一个 32 字节的随机数。你可以使用 espsecure.py 生成一个随机密钥
espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin
(随机数的质量与 OS 以及 Python 所安装的随机数源相关。)
另外,如果你正在使用 安全启动,且有一个安全启动签名密钥,你可以生成一个安全启动私有签名密钥的 SHA-256 digest,并使用它作为 flash 加密密钥
espsecure.py digest_private-key --keyfile secure_boot_signing_key.pem my_flash_encryption_key.bin
(如果你在安全启动中使能了 可重新烧写模式,则这 32 字节的数据还将作为安全启动 digest 密钥。)
通过这种从全球启动签名密钥生成 flash 加密密钥的方式意味着你只需要存储一个密钥文件。不过,这种方法 完全不适用于 实际产品中的设备。
烧写 Flash 加密密钥¶
生成 flash 加密密钥后,你还需要将它烧写到 ESP32 的 efuse 密钥块中。这必须在加密启动前完成,否则 ESP32 将会产生一个随机密钥,导致软件不能访问/修改 flash 上的内容。
将密钥烧写到设备(只需要一次)
espefuse.py --port PORT burn_key flash_encryption my_flash_encryption_key.bin
使用预生成的密钥第一次烧写¶
烧写完密钥后,按照默认 Flash 加密的初始化 步骤进行操作,并为第一次启动烧写一个明码文本镜像。bootloader将会使用预先烧写的密钥使能 flash 加密并加密所有分区。
使用预生成的密钥重新烧写¶
当第一次启动使能加密后,重新烧写加密的镜像需要一步额外的手工步骤,即预加密我们需要烧写到 flash 中的数据。
假设这是你用于烧写明码文本数据的命令
esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash 0x10000 build/my-app.bin
二进制应用程序镜像 build/my-app.bin
被烧写到偏移地址 0x10000
处。这里的文件名和偏移地址要用于加密数据
espsecure.py encrypt_flash_data --keyfile my_flash_encryption_key.bin --address 0x10000 -o build/my-app-encrypted.bin build/my-app.bin
上面这条命令会使用所提供的密钥加密 my-app.bin
,并产生一个加密文件 my-app-encrypted.bin
。请确保这里的地址参数与你将要烧写二进制镜像的地址相匹配。
然后,使用 esptool.py 烧写加密后的二进制文件
esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash 0x10000 build/my-app-encrypted.bin
至此,已经不需要其它的步骤了,因为数据已经被加密并烧写完成了。
禁止 Flash 加密¶
如果你由于某些原因意外地把 flash 加密功能使能了, the next flash of plaintext data will soft-brick the ESP32 (设备将会连续重启,并打印错误 flash read err, 1000
)。
你可以通过写 FLASH_CRYPT_CNT efuse 再次禁止 flash 加密:
- 首先,运行
make menuconfig
并取消 “Security Features” 下面的复选框 “Enable flash encryption boot”。 - 退出配置菜单并保存新的配置。
- 再次运行
make menuconfig
,再次检查是否真的禁止了该选项!如果该选项被使能,bootloader 启动时会立即再次重新加密。 - 运行
make flash
to 编译并烧写 flash 加密未被使能的 bootloader 和应用程序。 - 运行
espefuse.py
(在components/esptool_py/esptool
下面) 禁止 FLASH_CRYPT_CNT efuse):: - espefuse.py burn_efuse FLASH_CRYPT_CNT
- 运行
给 ESP32 复位,此时 flash 加密功能会被禁止,bootloader 会像平常一样启动。
Flash 加密的限制¶
Flash 加密功能可以阻止读取加密的 flash 的内容,保护固件,使其不会在未授权时被读取和修改。如果打算使用 flash 加密系统,则非常有必要理解它的限制:
- Flash 加密的安全性完全由密钥决定。因此,我们推荐在设备第一次启动时由设备产生密钥(这是默认的行为)。如果密钥是在设备外产生的,请确保其过程的正确性。
- 不是所有的数据都会被加密存储。如果需要在 flash 上存储数据,请先检查你所使用的方法(库、API 等)是否支持 flash 加密。
- Flash 加密不能阻止知道 flash 顶层布局的攻击者。这是因为每一对相邻的 16 字节 AES 块使用的是同样的 AES 密钥。当这些相邻的 16 字节块包含相同的内容(例如空区域或填充(pading)区域)时,这些块将会加密生成匹配的加密块对,攻击者可以在加密设备间进行顶层比较(例如判断两个设备运行的固件是否是同一版本)。
- 同样的理由,攻击者还可以判断两个相连的 16 字节块(32 字节对齐的)是否包含相同的内容。因此一定要记住,如果你想在 flash 上面存储敏感的数据,需要对你的存储方法进行进行一定的设计,确保不会发生这样的事(每 16 个字节使用一个字节的计数器或者其它某些不同的值是足够的)。
- 仅使用 Flash 加密功能不能阻止攻击者修改设备的固件。如果要阻止设备运行未被授权的固件,需要结合使用 flash 加密功能和 安全启动 功能。
Flash 加密高级功能¶
下列信息用于描述 flash 加密的高级功能:
加密分区标志¶
某些分区默认被加密。否则,可以将任何分区标记为需要加密:
在描述 分区表 的 CSV 文件中,存在一个标志字段。该字段通常是空的。如果你在这个字段中写上 “encrypted”,则这个分区将会在分区表中被标记为”加密的”,写到这里的数据也被当当做加密的(与应用程序分区相同):
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x6000
phy_init, data, phy, 0xf000, 0x1000
factory, app, factory, 0x10000, 1M
secret_data, 0x40, 0x01, 0x20000, 256K, encrypted
- 默认的分区表不包含任何加密数据分区。
- “app” 分区不需要被标记为 “encrypted”,因为它们总是被当做加密的。
- 如果 flash 加密功能未被使能,则 “encrypted” 标志不会起任何作用。
- 如果你希望从物理上阻止访问/修改带有
phy_init
数据的phy
分区,你也可以将该分区标记为 “encrypted”。 nvs
分区不能被标记为 “encrypted”。
使能 UART Bootloader 加密/解密¶
默认情况下,在第一次启动时,flash 加密过程会烧写 efuses DISABLE_DL_ENCRYPT
、DISABLE_DL_DECRYPT
和 DISABLE_DL_CACHE
:
DISABLE_DL_ENCRYPT
,当运行在 UART bootloader 模式时,禁止 flash 加密功能。DISABLE_DL_DECRYPT
,当运行在 UART bootloader 模式时,即使 FLASH_CRYPT_CNT efuse 被设置为以正常操作使能 flash 透明解密,也禁止 flash 透明解密。DISABLE_DL_CACHE
,当运行在 UART bootloader 模式时,禁止整个 MMU flash cache。
可以只烧写其中一部分 efuses,让其它 efuses 在第一次启动前写保护(将其值复原为 0),例如
espefuse.py --port PORT burn_efuse DISABLE_DL_DECRYPT
espefuse.py --port PORT write_protect_efuse DISABLE_DL_ENCRYPT
(注意,通过一次写保护,这三个 efuses 都会被禁止。因此,有必要在写保护前设置所有的比特。)
IMPORTANT: 当前,对这些 efuses 写保护使其复原不是很有用,因为 esptool.py
不支持读/写加密的 flash。
IMPORTANT: 如果 DISABLE_DL_DECRYPT
被复原(0),这会使 flash 加密不起作用,因为进行物理访问的攻击者可以使用 UART bootloader 模式(使用自定义的桩代码)读出 flash 中的内容。
设置 FLASH_CRYPT_CONFIG¶
efuse FLASH_CRYPT_CONFIG
用于判断 flash 加密密钥的比特数,具体细节请参考 Flash 加密算法。
bootloader 在第一次启动时总是会将这个值设为最大值 0xF。
可以在第一次启动前对该 efuse 进行手工写,使其写保护,以选择不同的调整值。不过不推荐这样做。
强烈推荐当 FLASH_CRYPT_CONFIG
的值被设置为零时不要使其写保护。如果它被设置零,flash 加密密钥中没有比特会被调整,flash 加密算法与 AES ECB 模式相同。
技术细节¶
下面的章节将介绍 flash 加密操作的一些参考信息。
FLASH_CRYPT_CNT efuse¶
FLASH_CRYPT_CNT
是一个 8 比特的字段,用于控制 flash 加密。Flash 加密的使能/禁止就是基于该 efuse 中被设置为 “1” 的比特的数量。
- 当偶数比特(0,2,4,6,8)被设置时:Flash 加密被禁止,所有加密的数据将不能被解密。
- 如果在编译 bootloader 时选择了 “Enable flash encryption on boot”,则 bootloader 遇到的就是这种情形,它会立即对所找都的所有为加密数据进行加密,将 efuse 中的其它比特设置为 ‘1’,表示当前奇数比特被设置了。
- 第一次明码文本启动时,比特计数值是 0,bootloader 会将其修改为 1(值 0x1)。
- 在下一次明码文本更新后,比特计数值被手工设置 2(值 0x3)。重新加密后,bootloader 会将比特计数值改为 3(值 0x7)。
- 在下一次明码文本更新后,比特计数值被手工设置 4(值 0x0F)。重新加密后,bootloader 会将比特计数值改为 5(值 0x1F)。
- 在下一次明码文本更新后,比特计数值被手工设置 6(值 0x3F)。重新加密后,bootloader 会将比特计数值改为 7(值 0x7F)。
- 如果在编译 bootloader 时选择了 “Enable flash encryption on boot”,则 bootloader 遇到的就是这种情形,它会立即对所找都的所有为加密数据进行加密,将 efuse 中的其它比特设置为 ‘1’,表示当前奇数比特被设置了。
- 当奇数比特(1,3,5,7)被设置时:透明读取加密 flash 被使能。
- 当所有的 8 比特(efuse 值 0xFF)被设置后:透明地读加密 flash 被禁止,所有的加密数据将永久不可访问。bootloader 会检测到这个条件,然后挂起。如果要绕过这种状态来加载为授权的代码,必须使用安全启动或 FLASH_CRYPT_CNT efuse 被写保护。
Flash 加密算法¶
- AES-256 操作在数据的 16 字节块之上。flash 加密引擎以 32 字节块(两个 AES 块)加密/解密数据。
- AES 算法被用于逆向 falsh 加密,因此 flash 加密的加密操作就是 AES 的解密,解密操作就是 AES 加密。这样做是性能的原因,且不会改变算法的性能。
- 主 flash 加密密钥存储在 efuse (BLK2) 中,且默认具有写保护和软件读保护。
- 每 32 字节块(两个相连的 16 字节 AES 块)使用一个唯一的密钥进行加密。该密钥由 efuse 中的主 flash 加密密钥推断(与 flash 中该块的偏移量异或,这个偏移量又叫做 “密钥调整值”)而来。
- 还需要根据 efuse
FLASH_CRYPT_CONFIG
的值进行特殊调整。这是一个 4 比特的 efuse,其中每个比特都需要与密钥的某个范围内的比特进行异或:。- 比特 1 与密钥的比特 0-66 进行异或。
- 比特 2 与密钥的比特 67-131 进行异或。
- 比特 3 与密钥的比特 132-194 进行异或。
- 比特 4 与密钥的比特 195-256 进行异或。
推荐将 FLASH_CRYPT_CONFIG
保持为默认值 0xF,这样所有的比特都是直接与块的偏移量进行异或的。具体细节请查看 设置 FLASH_CRYPT_CONFIG。
- 块偏移量的高 19 比特(比特 5 ~ 比特 23)被用于与主 flash 加密密钥进行异或。选择这个比特范围有两个原因: flash 的最大容量是 16 MB(24 个比特);每个块是 32 字节的,因此最低 5 比特总是零。
- 19 比特的块偏移量与 flash 加密密钥之间存在一个特殊的映射,用于判断哪个比特是用于异或的。关于完整的映射关系,请查看 espsecure.py 源文件中的变量
_FLASH_ENCRYPTION_TWEAK_PATTERN
。 - 如果想要查看用 Python 语言写的完整的 flash 加密算法,请参考 espsecure.py 源文件中的函数 _flash_encryption_operation()。
Secure Boot¶
Secure Boot is a feature for ensuring only your code can run on the chip. Data loaded from flash is verified on each reset.
Secure Boot is separate from the Flash Encryption feature, and you can use secure boot without encrypting the flash contents. However we recommend using both features together for a secure environment.
重要
Enabling secure boot limits your options for further updates of your ESP32. Make sure to read this document throughly and understand the implications of enabling secure boot.
Background¶
- Most data is stored in flash. Flash access does not need to be protected from physical access in order for secure boot to function, because critical data is stored (non-software-accessible) in Efuses internal to the chip.
- Efuses are used to store the secure bootloader key (in efuse block 2), and also a single Efuse bit (ABS_DONE_0) is burned (written to 1) to permanently enable secure boot on the chip. For more details about efuse, see the (forthcoming) chapter in the Technical Reference Manual.
- To understand the secure boot process, first familiarise yourself with the standard ESP-IDF boot process.
- Both stages of the boot process (initial software bootloader load, and subsequent partition & app loading) are verified by the secure boot process, in a “chain of trust” relationship.
Secure Boot Process Overview¶
This is a high level overview of the secure boot process. Step by step instructions are supplied under How To Enable Secure Boot. Further in-depth details are supplied under Technical Details:
- The options to enable secure boot are provided in the
make menuconfig
hierarchy, under “Secure Boot Configuration”. - Secure Boot defaults to signing images and partition table data during the build process. The “Secure boot private signing key” config item is a file path to a ECDSA public/private key pair in a PEM format file.
- The software bootloader image is built by esp-idf with secure boot support enabled and the public key (signature verification) portion of the secure boot signing key compiled in. This software bootloader image is flashed at offset 0x1000.
- On first boot, the software bootloader follows the following process to enable secure boot:
- Hardware secure boot support generates a device secure bootloader key (generated via hardware RNG, then stored read/write protected in efuse), and a secure digest. The digest is derived from the key, an IV, and the bootloader image contents.
- The secure digest is flashed at offset 0x0 in the flash.
- Depending on Secure Boot Configuration, efuses are burned to disable JTAG and the ROM BASIC interpreter (it is strongly recommended these options are turned on.)
- Bootloader permanently enables secure boot by burning the ABS_DONE_0 efuse. The software bootloader then becomes protected (the chip will only boot a bootloader image if the digest matches.)
- On subsequent boots the ROM bootloader sees that the secure boot efuse is burned, reads the saved digest at 0x0 and uses hardware secure boot support to compare it with a newly calculated digest. If the digest does not match then booting will not continue. The digest and comparison are performed entirely by hardware, and the calculated digest is not readable by software. For technical details see Secure Boot Hardware Support.
- When running in secure boot mode, the software bootloader uses the secure boot signing key (the public key of which is embedded in the bootloader itself, and therefore validated as part of the bootloader) to verify the signature appended to all subsequent partition tables and app images before they are booted.
Keys¶
The following keys are used by the secure boot process:
- “secure bootloader key” is a 256-bit AES key that is stored in Efuse block 2. The bootloader can generate this key itself from the internal hardware random number generator, the user does not need to supply it (it is optionally possible to supply this key, see Re-Flashable Software Bootloader). The Efuse holding this key is read & write protected (preventing software access) before secure boot is enabled.
- “secure boot signing key” is a standard ECDSA public/private key pair (see Image Signing Algorithm) in PEM format.
- The public key from this key pair (for signature verificaton but not signature creation) is compiled into the software bootloader and used to verify the second stage of booting (partition table, app image) before booting continues. The public key can be freely distributed, it does not need to be kept secret.
- The private key from this key pair must be securely kept private, as anyone who has this key can authenticate to any bootloader that is configured with secure boot and the matching public key.
How To Enable Secure Boot¶
Run
make menuconfig
, navigate to “Secure Boot Configuration” and select the option “One-time Flash”. (To understand the alternative “Reflashable” choice, see Re-Flashable Software Bootloader.)Select a name for the secure boot signing key. This option will appear after secure boot is enabled. The file can be anywhere on your system. A relative path will be evaluated from the project directory. The file does not need to exist yet.
Set other menuconfig options (as desired). Pay particular attention to the “Bootloader Config” options, as you can only flash the bootloader once. Then exit menuconfig and save your configuration
The first time you run
make
, if the signing key is not found then an error message will be printed with a command to generate a signing key viaespsecure.py generate_signing_key
.IMPORTANT A signing key generated this way will use the best random number source available to the OS and its Python installation (/dev/urandom on OSX/Linux and CryptGenRandom() on Windows). If this random number source is weak, then the private key will be weak.
IMPORTANT For production environments, we recommend generating the keypair using openssl or another industry standard encryption program. See Generating Secure Boot Signing Key for more details.
Run
make bootloader
to build a secure boot enabled bootloader. The output ofmake
will include a prompt for a flashing command, usingesptool.py write_flash
.
When you’re ready to flash the bootloader, run the specified command (you have to enter it yourself, this step is not performed by make) and then wait for flashing to complete. Remember this is a one time flash, you can’t change the bootloader after this!.
Run
make flash
to build and flash the partition table and the just-built app image. The app image will be signed using the signing key you generated in step 4.NOTE:
make flash
doesn’t flash the bootloader if secure boot is enabled.Reset the ESP32 and it will boot the software bootloader you flashed. The software bootloader will enable secure boot on the chip, and then it verifies the app image signature and boots the app. You should watch the serial console output from the ESP32 to verify that secure boot is enabled and no errors have occured due to the build configuration.
NOTE Secure boot won’t be enabled until after a valid partition table and app image have been flashed. This is to prevent accidents before the system is fully configured.
- On subsequent boots, the secure boot hardware will verify the software bootloader has not changed (using the secure bootloader key) and then the software bootloader will verify the signed partition table and app image (using the public key portion of the secure boot signing key).
Re-Flashable Software Bootloader¶
Configuration “Secure Boot: One-Time Flash” is the recommended configuration for production devices. In this mode, each device gets a unique key that is never stored outside the device.
However, an alternative mode “Secure Boot: Reflashable” is also available. This mode allows you to supply a 256-bit key file that is used for the secure bootloader key. As you have the key file, you can generate new bootloader images and secure boot digests for them.
In the esp-idf build process, this 256-bit key file is derived from the app signing key generated during the generate_signing_key step above. The private key’s SHA-256 digest is used as the 256-bit secure bootloader key. This is a convenience so you only need to generate/protect a single private key.
NOTE: Although it’s possible, we strongly recommend not generating one secure boot key and flashing it to every device in a production environment. The “One-Time Flash” option is recommended for production environments.
To enable a reflashable bootloader:
- In the
make menuconfig
step, select “Bootloader Config” -> “Secure Boot” -> “Reflashable”. - Follow the steps shown above to choose a signing key file, and generate the key file.
- Run
make bootloader
. A 256-bit key file will be created, derived from the private key that is used for signing. Two sets of flashing steps will be printed - the first set of steps includes anespefuse.py burn_key
command which is used to write the bootloader key to efuse. (Flashing this key is a one-time-only process.) The second set of steps can be used to reflash the bootloader with a pre-calculated digest (generated during the build process). - Resume from Step 6 of the one-time flashing process, to flash the bootloader and enable secure boot. Watch the console log output closely to ensure there were no errors in the secure boot configuration.
Generating Secure Boot Signing Key¶
The build system will prompt you with a command to generate a new signing key via espsecure.py generate_signing_key
. This uses the python-ecdsa library, which in turn uses Python’s os.urandom() as a random number source.
The strength of the signing key is proportional to (a) the random number source of the system, and (b) the correctness of the algorithm used. For production devices, we recommend generating signing keys from a system with a quality entropy source, and using the best available EC key generation utilities.
For example, to generate a signing key using the openssl command line:
`
openssl ecparam -name prime256v1 -genkey -noout -out my_secure_boot_signing_key.pem
`
Remember that the strength of the secure boot system depends on keeping the signing key private.
Remote Signing of Images¶
For production builds, it can be good practice to use a remote signing server rather than have the signing key on the build machine (which is the default esp-idf secure boot configuration). The espsecure.py command line program can be used to sign app images & partition table data for secure boot, on a remote system.
To use remote signing, disable the option “Sign binaries during build”. The private signing key does not need to be present on the build system. However, the public (signature verification) key is required because it is compiled into the bootloader (and can be used to verify image signatures during OTA updates.
To extract the public key from the private key:
espsecure.py extract_public_key --keyfile PRIVATE_SIGNING_KEY PUBLIC_VERIFICATION_KEY
The path to the public signature verification key needs to be specified in the menuconfig under “Secure boot public signature verification key” in order to build the secure bootloader.
After the app image and partition table are built, the build system will print signing steps using espsecure.py:
espsecure.py sign_data --keyfile PRIVATE_SIGNING_KEY BINARY_FILE
The above command appends the image signature to the existing binary. You can use the –output argument to write the signed binary to a separate file:
espsecure.py sign_data --keyfile PRIVATE_SIGNING_KEY --output SIGNED_BINARY_FILE BINARY_FILE
Secure Boot Best Practices¶
- Generate the signing key on a system with a quality source of entropy.
- Keep the signing key private at all times. A leak of this key will compromise the secure boot system.
- Do not allow any third party to observe any aspects of the key generation or signing process using espsecure.py. Both processes are vulnerable to timing or other side-channel attacks.
- Enable all secure boot options in the Secure Boot Configuration. These include flash encryption, disabling of JTAG, disabling BASIC ROM interpeter, and disabling the UART bootloader encrypted flash access.
- Use secure boot in combination with flash encryption to prevent local readout of the flash contents.
Technical Details¶
The following sections contain low-level reference descriptions of various secure boot elements:
Secure Boot Hardware Support¶
The first stage of secure boot verification (checking the software bootloader) is done via hardware. The ESP32’s Secure Boot support hardware can perform three basic operations:
- Generate a random sequence of bytes from a hardware random number generator.
- Generate a digest from data (usually the bootloader image from flash) using a key stored in Efuse block 2. The key in Efuse can (& should) be read/write protected, which prevents software access. For full details of this algorithm see Secure Bootloader Digest Algorithm. The digest can only be read back by software if Efuse ABS_DONE_0 is not burned (ie still 0).
- Generate a digest from data (usually the bootloader image from flash) using the same algorithm as step 2 and compare it to a pre-calculated digest supplied in a buffer (usually read from flash offset 0x0). The hardware returns a true/false comparison without making the digest available to software. This function is available even when Efuse ABS_DONE_0 is burned.
Secure Bootloader Digest Algorithm¶
Starting with an “image” of binary data as input, this algorithm generates a digest as output. The digest is sometimes referred to as an “abstract” in hardware documentation.
For a Python version of this algorithm, see the espsecure.py
tool in the components/esptool_py directory (specifically, the digest_secure_bootloader
command).
Items marked with (^) are to fulfill hardware restrictions, as opposed to cryptographic restrictions.
- Prefix the image with a 128 byte randomly generated IV.
- If the image length is not modulo 128, pad the image to a 128 byte boundary with 0xFF. (^)
- For each 16 byte plaintext block of the input image: - Reverse the byte order of the plaintext input block (^) - Apply AES256 in ECB mode to the plaintext block. - Reverse the byte order of the ciphertext output block. (^) - Append to the overall ciphertext output.
- Byte-swap each 4 byte word of the ciphertext (^)
- Calculate SHA-512 of the ciphertext.
Output digest is 192 bytes of data: The 128 byte IV, followed by the 64 byte SHA-512 digest.
Image Signing Algorithm¶
Deterministic ECDSA as specified by RFC 6979.
- Curve is NIST256p (openssl calls this curve “prime256v1”, it is also sometimes called secp256r1).
- Hash function is SHA256.
- Key format used for storage is PEM.
- In the bootloader, the public key (for signature verification) is flashed as 64 raw bytes.
- Image signature is 68 bytes - a 4 byte version word (currently zero), followed by a 64 bytes of signature data. These 68 bytes are appended to an app image or partition table data.
Manual Commands¶
Secure boot is integrated into the esp-idf build system, so make
will automatically sign an app image if secure boot is enabled. make bootloader
will produce a bootloader digest if menuconfig is configured for it.
However, it is possible to use the espsecure.py
tool to make standalone signatures and digests.
To sign a binary image:
espsecure.py sign_data --keyfile ./my_signing_key.pem --output ./image_signed.bin image-unsigned.bin
Keyfile is the PEM file containing an ECDSA private signing key.
To generate a bootloader digest:
espsecure.py digest_secure_bootloader --keyfile ./securebootkey.bin --output ./bootloader-digest.bin build/bootloader/bootloader.bin
Keyfile is the 32 byte raw secure boot key for the device. To flash this digest onto the device:
esptool.py write_flash 0x0 bootloader-digest.bin
深度睡眠唤醒桩¶
ESP32 支持从深度睡眠中醒来后运行 “深度睡眠唤醒桩(stub)”,该函数会在芯片唤醒后立即执行 —— 在运行其它任何常规初始化、bootloader、ESP-IDF 代码之前。唤醒桩运行完成后,SoC 可以重新深度睡眠,或者继续正确启动 ESP-IDF。
深度睡眠唤醒桩的代码被加载到 “RTC 快速内存中”,它所使用的所有数据都必须被加载到 RTC 内存中。RTC 内存区域会在深度睡眠期间保留其内容。
唤醒桩的规则¶
编写唤醒桩代码时必须非常小心:
- 由于 SoC 才刚刚从睡眠中唤醒,大多数外设都处于复位状态。SPI flash 也未被映射。
- 唤醒桩代码只能调用在 ROM 中实现的函数或者被加载到 RTC 快速内存中的函数。
- 唤醒桩代码只能访问加载到 RTC 内存中的数据。其它的所有 RAM 都是未初始化的,其内容是随机的。唤醒桩可以使用其它 RAM 作为临时存储,但是其内容会在 SoC 重新睡眠或者启动 ESP-IDF 后被覆盖。
- RTC 内存必须包含桩所使用的所有只读数据(.rodata)。
- RTC 内存中的数据会在除从深度睡眠唤醒之外的其它所有 SoC 重启的时候被初始化。从深度睡眠唤醒时,之前存在的值在深度睡眠期间会继续保持不变。
- 唤醒桩代码是主 esp-idf 应用程序的一部分。在运行 esp-idf 期间,函数可以向常规程序一样调用唤醒桩函数/访问 RTC 内存。
桩的实现¶
Esp-idf 中的桩叫做 esp_wake_deep_sleep()
。SoC 每次从深度睡眠唤醒后都会运行该函数。esp-idf 默认实现了该函数,但是这个默认函数是一个虚链接函数,因此如果你的应用层中包含一个叫做 esp_wake_deep_sleep()
的函数的话,它将会覆盖这个默认函数。
如果要实现一个自定义的唤醒桩,需要做的第一件事应当是调用 esp_default_wake_deep_sleep()
。
如果只是为了实现深度睡眠,你不需要在你的应用程序中实现 esp_wake_deep_sleep()
。只有当你希望在唤醒后立即做一些特殊行为时才有需要。
如果你希望运行时交换两个不同的深度睡眠桩,你可以调用函数 esp_set_deep_sleep_wake_stub()
。如果你只使用了默认的 esp_wake_deep_sleep()
函数,则不需要。
上面这些函数定义在组件 components/esp32 的头文件 esp_deepsleep.h
中。
将代码加到 RTC 内存¶
唤醒桩代码必须位于 RTC 快速内存中。这可以通过两种方法实现。
第一种方法是使用属性 RTC_IRAM_ATTR
将一个函数放到 RTC 内存中
void RTC_IRAM_ATTR esp_wake_deep_sleep(void) {
esp_default_wake_deep_sleep();
// Add additional functionality here
}
第二种方法是将函数放到任意的名字以 rtc_wake_stub
开始的源代码中。以 rtc_wake_stub*
为名字的文件中的内容会被链接器自动放到 RTC 内存中。
第一种方法适用于非常简短的代码或者你想混合使用 “常规” 代码和 “RTC” 代码的源文件。第二种方法适用于比较长的 RTC 代码。
将数据加载到 RTC 内存¶
桩代码使用的数据必须存放到 RTC 慢速内存中。该内存也会被 ULP 使用。
指定这种数据也有两种方法:
第一种方法是是使用 RTC_DATA_ATTR
和 RTC_RODATA_ATTR
来指定需要加载到 RTC 慢速内存中的数据(分别对应于可写、只读数据)
RTC_DATA_ATTR int wake_count;
void RTC_IRAM_ATTR esp_wake_deep_sleep(void) {
esp_default_wake_deep_sleep();
static RTC_RODATA_ATTR const char fmt_str[] = "Wake count %d\n";
ets_printf(fmt_str, wake_count++);
}
不幸的是,按这种方法使用的字符串常量必须被申明为数组,且使用 RTC_RODATA_ATTR 进行标记,正如上面的例子中展示的那样。
第二种方法是将数据放到任意的以 rtc_wake_stub
开始的源代码中。
例如,同一个例子在 rtc_wake_stub_counter.c
中则是
int wake_count;
void RTC_IRAM_ATTR esp_wake_deep_sleep(void) {
esp_default_wake_deep_sleep();
ets_printf("Wake count %d\n", wake_count++);
}
如果你想要使用字符串或者写一些复杂的代码,推荐使用第二种方法。
ULP coprocessor programming¶
ULP coprocessor instruction set¶
This document provides details about the instructions used by ESP32 ULP coprocessor assembler.
ULP coprocessor has 4 16-bit general purpose registers, labeled R0, R1, R2, R3. It also has an 8-bit counter register (stage_cnt) which can be used to implement loops. Stage count regiter is accessed using special instructions.
ULP coprocessor can access 8k bytes of RTC_SLOW_MEM memory region. Memory is addressed in 32-bit word units. It can also access peripheral registers in RTC_CNTL, RTC_IO, and SENS peripherals.
All instructions are 32-bit. Jump instructions, ALU instructions, peripheral register and memory access instructions are executed in 1 cycle. Instructions which work with peripherals (TSENS, ADC, I2C) take variable number of cycles, depending on peripheral operation.
The instruction syntax is case insensitive. Upper and lower case letters can be used and intermixed arbitrarily. This is true both for register names and instruction names.
Note about addressing¶
ESP32 ULP coprocessor’s JUMP, ST, LD instructions which take register as an argument (jump address, store/load base address) expect the argument to be expressed in 32-bit words.
Consider the following example program:
entry:
NOP
NOP
NOP
NOP
loop:
MOVE R1, loop
JUMP R1
When this program is assembled and linked, address of label loop
will be equal to 16 (expressed in bytes). However JUMP instruction expects the address stored in register to be expressed in 32-bit words. To account for this common use case, assembler will convert the address of label loop from bytes to words, when generating MOVE
instruction, so the code generated code will be equivalent to:
0000 NOP
0004 NOP
0008 NOP
000c NOP
0010 MOVE R1, 4
0014 JUMP R1
The other case is when the argument of MOVE
instruction is not a label but a constant. In this case assembler will use the value as is, without any conversion:
.set val, 0x10
MOVE R1, val
In this case, value loaded into R1 will be 0x10
.
Similar considerations apply to LD
and ST
instructions. Consider the following code:
.global array
array: .long 0
.long 0
.long 0
.long 0
MOVE R1, array
MOVE R2, 0x1234
ST R2, R1, 0 // write value of R2 into the first array element,
// i.e. array[0]
ST R2, R1, 4 // write value of R2 into the second array element
// (4 byte offset), i.e. array[1]
ADD R1, R1, 2 // this increments address by 2 words (8 bytes)
ST R2, R1, 0 // write value of R2 into the third array element,
// i.e. array[2]
NOP - no operation¶
- Syntax:
- NOP
- Operands:
- None
- Description:
- No operation is performed. Only the PC is incremented.
Example:
1: NOP
ADD - Add to register¶
- Syntax:
ADD Rdst, Rsrc1, Rsrc2
ADD Rdst, Rsrc1, imm
- Operands:
- Rdst - Register R[0..3]
- Rsrc1 - Register R[0..3]
- Rsrc2 - Register R[0..3]
- Imm - 16-bit signed value
- Description:
- The instruction adds source register to another source register or to a 16-bit signed value and stores result to the destination register.
Examples:
1: ADD R1, R2, R3 //R1 = R2 + R3
2: Add R1, R2, 0x1234 //R1 = R2 + 0x1234
3: .set value1, 0x03 //constant value1=0x03
Add R1, R2, value1 //R1 = R2 + value1
4: .global label //declaration of variable label
Add R1, R2, label //R1 = R2 + label
...
label: nop //definition of variable label
SUB - Subtract from register¶
- Syntax:
SUB Rdst, Rsrc1, Rsrc2
SUB Rdst, Rsrc1, imm
- Operands:
- Rdst - Register R[0..3]
- Rsrc1 - Register R[0..3]
- Rsrc2 - Register R[0..3]
- Imm - 16-bit signed value
- Description:
- The instruction subtracts the source register from another source register or subtracts 16-bit signed value from a source register, and stores result to the destination register.
Examples::
1: SUB R1, R2, R3 //R1 = R2 - R3
2: sub R1, R2, 0x1234 //R1 = R2 - 0x1234
3: .set value1, 0x03 //constant value1=0x03
SUB R1, R2, value1 //R1 = R2 - value1
4: .global label //declaration of variable label
SUB R1, R2, label //R1 = R2 - label
....
label: nop //definition of variable label
AND - Logical AND of two operands¶
- Syntax:
AND Rdst, Rsrc1, Rsrc2
AND Rdst, Rsrc1, imm
- Operands:
- Rdst - Register R[0..3]
- Rsrc1 - Register R[0..3]
- Rsrc2 - Register R[0..3]
- Imm - 16-bit signed value
- Description:
- The instruction does logical AND of a source register and another source register or 16-bit signed value and stores result to the destination register.
Example:
1: AND R1, R2, R3 //R1 = R2 & R3
2: AND R1, R2, 0x1234 //R1 = R2 & 0x1234
3: .set value1, 0x03 //constant value1=0x03
AND R1, R2, value1 //R1 = R2 & value1
4: .global label //declaration of variable label
AND R1, R2, label //R1 = R2 & label
...
label: nop //definition of variable label
OR - Logical OR of two operands¶
- Syntax
OR Rdst, Rsrc1, Rsrc2
OR Rdst, Rsrc1, imm
- Operands
- Rdst - Register R[0..3]
- Rsrc1 - Register R[0..3]
- Rsrc2 - Register R[0..3]
- Imm - 16-bit signed value
- Description
- The instruction does logical OR of a source register and another source register or 16-bit signed value and stores result to the destination register.
Examples:
1: OR R1, R2, R3 //R1 = R2 \| R3
2: OR R1, R2, 0x1234 //R1 = R2 \| 0x1234
3: .set value1, 0x03 //constant value1=0x03
OR R1, R2, value1 //R1 = R2 \| value1
4: .global label //declaration of variable label
OR R1, R2, label //R1 = R2 \|label
...
label: nop //definition of variable label
LSH - Logical Shift Left¶
- Syntax
LSH Rdst, Rsrc1, Rsrc2
LSH Rdst, Rsrc1, imm
- Operands
- Rdst - Register R[0..3]
- Rsrc1 - Register R[0..3]
- Rsrc2 - Register R[0..3]
- Imm - 16-bit signed value
- Description
- The instruction does logical shift to left of source register to number of bits from another source register or 16-bit signed value and store result to the destination register.
Examples:
1: LSH R1, R2, R3 //R1 = R2 << R3
2: LSH R1, R2, 0x03 //R1 = R2 << 0x03
3: .set value1, 0x03 //constant value1=0x03
LSH R1, R2, value1 //R1 = R2 << value1
4: .global label //declaration of variable label
LSH R1, R2, label //R1 = R2 << label
...
label: nop //definition of variable label
RSH - Logical Shift Right¶
- Syntax
RSH Rdst, Rsrc1, Rsrc2
RSH Rdst, Rsrc1, imm
- Operands
- Rdst - Register R[0..3] Rsrc1 - Register R[0..3] Rsrc2 - Register R[0..3] Imm - 16-bit signed value
- Description
- The instruction does logical shift to right of source register to number of bits from another source register or 16-bit signed value and store result to the destination register.
Examples:
1: RSH R1, R2, R3 //R1 = R2 >> R3
2: RSH R1, R2, 0x03 //R1 = R2 >> 0x03
3: .set value1, 0x03 //constant value1=0x03
RSH R1, R2, value1 //R1 = R2 >> value1
4: .global label //declaration of variable label
RSH R1, R2, label //R1 = R2 >> label
label: nop //definition of variable label
MOVE – Move to register¶
- Syntax
MOVE Rdst, Rsrc
MOVE Rdst, imm
- Operands
- Rdst – Register R[0..3]
- Rsrc – Register R[0..3]
- Imm – 16-bit signed value
- Description
The instruction move to destination register value from source register or 16-bit signed value.
Note that when a label is used as an immediate, the address of the label will be converted from bytes to words. This is because LD, ST, and JUMP instructions expect the address register value to be expressed in words rather than bytes. To avoid using an extra instruction
Examples:
1: MOVE R1, R2 //R1 = R2 >> R3
2: MOVE R1, 0x03 //R1 = R2 >> 0x03
3: .set value1, 0x03 //constant value1=0x03
MOVE R1, value1 //R1 = value1
4: .global label //declaration of label
MOVE R1, label //R1 = address_of(label) / 4
...
label: nop //definition of label
ST – Store data to the memory¶
- Syntax
- ST Rsrc, Rdst, offset
- Operands
- Rsrc – Register R[0..3], holds the 16-bit value to store
- Rdst – Register R[0..3], address of the destination, in 32-bit words
- Offset – 10-bit signed value, offset in bytes
- Description
The instruction stores the 16-bit value of Rsrc to the lower half-word of memory with address Rdst+offset. The upper half-word is written with the current program counter (PC), expressed in words, shifted left by 5 bits:
Mem[Rdst + offset / 4]{31:0} = {PC[10:0], 5'b0, Rsrc[15:0]}
The application can use higher 16 bits to determine which instruction in the ULP program has written any particular word into memory.
Examples:
1: ST R1, R2, 0x12 //MEM[R2+0x12] = R1
2: .data //Data section definition
Addr1: .word 123 // Define label Addr1 16 bit
.set offs, 0x00 // Define constant offs
.text //Text section definition
MOVE R1, 1 // R1 = 1
MOVE R2, Addr1 // R2 = Addr1
ST R1, R2, offs // MEM[R2 + 0] = R1
// MEM[Addr1 + 0] will be 32'h600001
LD – Load data from the memory¶
- Syntax
- LD Rdst, Rsrc, offset
- Operands
Rdst – Register R[0..3], destination
Rsrc – Register R[0..3], holds address of destination, in 32-bit words
Offset – 10-bit signed value, offset in bytes
- Description
The instruction loads lower 16-bit half-word from memory with address Rsrc+offset into the destination register Rdst:
Rdst[15:0] = Mem[Rsrc + offset / 4][15:0]
Examples:
1: LD R1, R2, 0x12 //R1 = MEM[R2+0x12]
2: .data //Data section definition
Addr1: .word 123 // Define label Addr1 16 bit
.set offs, 0x00 // Define constant offs
.text //Text section definition
MOVE R1, 1 // R1 = 1
MOVE R2, Addr1 // R2 = Addr1 / 4 (address of label is converted into words)
LD R1, R2, offs // R1 = MEM[R2 + 0]
// R1 will be 123
JUMP – Jump to an absolute address¶
- Syntax
JUMP Rdst
JUMP ImmAddr
JUMP Rdst, Condition
JUMP ImmAddr, Condition
- Operands
- Rdst – Register R[0..3] containing address to jump to (expressed in 32-bit words)
- ImmAddr – 13 bits address (expressed in bytes), aligned to 4 bytes
- Condition:
- EQ – jump if last ALU operation result was zero
- OV – jump if last ALU has set overflow flag
- Description
- The instruction makes jump to the specified address. Jump can be either unconditional or based on an ALU flag.
Examples:
1: JUMP R1 // Jump to address in R1 (address in R1 is in 32-bit words)
2: JUMP 0x120, EQ // Jump to address 0x120 (in bytes) if ALU result is zero
3: JUMP label // Jump to label
...
label: nop // Definition of label
4: .global label // Declaration of global label
MOVE R1, label // R1 = label (value loaded into R1 is in words)
JUMP R1 // Jump to label
...
label: nop // Definition of label
JUMPR – Jump to a relative offset (condition based on R0)¶
- Syntax
- JUMPR Step, Threshold, Condition
- Operands
- Step – relative shift from current position, in bytes
- Threshold – threshold value for branch condition
- Condition:
- GE (greater or equal) – jump if value in R0 >= threshold
- LT (less than) – jump if value in R0 < threshold
- Description
- The instruction makes a jump to a relative address if condition is true. Condition is the result of comparison of R0 register value and the threshold value.
Examples:
1:pos: JUMPR 16, 20, GE // Jump to address (position + 16 bytes) if value in R0 >= 20
2: // Down counting loop using R0 register
MOVE R0, 16 // load 16 into R0
label: SUB R0, R0, 1 // R0--
NOP // do something
JUMPR label, 1, GE // jump to label if R0 >= 1
JUMPS – Jump to a relative address (condition based on stage count)¶
- Syntax
- JUMPS Step, Threshold, Condition
- Operands
- Step – relative shift from current position, in bytes
- Threshold – threshold value for branch condition
- Condition:
- EQ (equal) – jump if value in stage_cnt == threshold
- LT (less than) – jump if value in stage_cnt < threshold
- GT (greater than) – jump if value in stage_cnt > threshold
- Description
- The instruction makes a jump to a relative address if condition is true. Condition is the result of comparison of count register value and threshold value.
Examples:
1:pos: JUMPS 16, 20, EQ // Jump to (position + 16 bytes) if stage_cnt == 20
2: // Up counting loop using stage count register
STAGE_RST // set stage_cnt to 0
label: STAGE_INC 1 // stage_cnt++
NOP // do something
JUMPS label, 16, LT // jump to label if stage_cnt < 16
STAGE_RST – Reset stage count register¶
- Syntax
- STAGE_RST
- Operands
- No operands
- Description
- The instruction sets the stage count register to 0
Examples:
1: STAGE_RST // Reset stage count register
STAGE_INC – Increment stage count register¶
- Syntax
- STAGE_INC Value
- Operands
- Value – 8 bits value
- Description
- The instruction increments stage count register by given value.
Examples:
1: STAGE_INC 10 // stage_cnt += 10
2: // Up counting loop example:
STAGE_RST // set stage_cnt to 0
label: STAGE_INC 1 // stage_cnt++
NOP // do something
JUMPS label, 16, LT // jump to label if stage_cnt < 16
STAGE_DEC – Decrement stage count register¶
- Syntax
- STAGE_DEC Value
- Operands
- Value – 8 bits value
- Description
- The instruction decrements stage count register by given value.
Examples:
1: STAGE_DEC 10 // stage_cnt -= 10;
2: // Down counting loop exaple
STAGE_RST // set stage_cnt to 0
STAGE_INC 16 // increment stage_cnt to 16
label: STAGE_DEC 1 // stage_cnt--;
NOP // do something
JUMPS label, 0, GT // jump to label if stage_cnt > 0
HALT – End the program¶
- Syntax
- HALT
- Operands
- No operands
- Description
- The instruction halt the processor to the power down mode
Examples:
1: HALT // Move chip to powerdown
WAKE – wakeup the chip¶
- Syntax
- WAKE
- Operands
- No operands
- Description
The instruction sends an interrupt from ULP to RTC controller.
- If the SoC is in deep sleep mode, and ULP wakeup is enabled, this causes the SoC to wake up.
- If the SoC is not in deep sleep mode, and ULP interrupt bit (RTC_CNTL_ULP_CP_INT_ENA) is set in RTC_CNTL_INT_ENA_REG register, RTC interrupt will be triggered.
Examples:
1: WAKE // Trigger wake up
REG_WR 0x006, 24, 24, 0 // Stop ULP timer (clear RTC_CNTL_ULP_CP_SLP_TIMER_EN)
HALT // Stop the ULP program
// After these instructions, SoC will wake up,
// and ULP will not run again until started by the main program.
SLEEP – set ULP wakeup timer period¶
- Syntax
- SLEEP sleep_reg
- Operands
- sleep_reg – 0..4, selects one of
SENS_ULP_CP_SLEEP_CYCx_REG
registers.
- sleep_reg – 0..4, selects one of
- Description
- The instruction selects which of the
SENS_ULP_CP_SLEEP_CYCx_REG
(x = 0..4) register values is to be used by the ULP wakeup timer as wakeup period. By default, the value fromSENS_ULP_CP_SLEEP_CYC0_REG
is used.
Examples:
1: SLEEP 1 // Use period set in SENS_ULP_CP_SLEEP_CYC1_REG
2: .set sleep_reg, 4 // Set constant
SLEEP sleep_reg // Use period set in SENS_ULP_CP_SLEEP_CYC4_REG
WAIT – wait some number of cycles¶
- Syntax
- WAIT Cycles
- Operands
- Cycles – number of cycles for wait
- Description
- The instruction delays for given number of cycles.
Examples:
1: WAIT 10 // Do nothing for 10 cycles
2: .set wait_cnt, 10 // Set a constant
WAIT wait_cnt // wait for 10 cycles
TSENS – do measurement with temperature sensor¶
- Syntax
- TSENS Rdst, Wait_Delay
- Operands
- Rdst – Destination Register R[0..3], result will be stored to this register
- Wait_Delay – number of cycles used to perform the measurement
- Description
- The instruction performs measurement using TSENS and stores the result into a general purpose register.
Examples:
1: TSENS R1, 1000 // Measure temperature sensor for 1000 cycles,
// and store result to R1
ADC – do measurement with ADC¶
- Syntax
- ADC Rdst, Sar_sel, Mux, Cycles
- Operands
- Rdst – Destination Register R[0..3], result will be stored to this register
- Sar_sel – selected ADC : 0=SARADC0, 1=SARADC1
- Mux - selected PAD, SARADC Pad[Mux+1] is enabled
- Cycle – number of cycles used to perform measurement
- Description
- The instruction makes measurements from ADC.
Examples:
1: ADC R1, 0, 1, 100 // Measure value using ADC1 pad 2,
// for 100 cycles and move result to R1
REG_RD – read from peripheral register¶
- Syntax
- REG_RD Addr, High, Low
- Operands
- Addr – register address, in 32-bit words
- High – High part of R0
- Low – Low part of R0
- Description
The instruction reads up to 16 bits from a peripheral register into a general purpose register:
R0 = REG[Addr][High:Low]
.This instruction can access registers in RTC_CNTL, RTC_IO, and SENS peripherals. Address of the the register, as seen from the ULP, can be calculated from the address of the same register on the DPORT bus as follows:
addr_ulp = (addr_dport - DR_REG_RTCCNTL_BASE) / 4
Examples:
1: REG_RD 0x120, 2, 0 // load 4 bits: R0 = {12'b0, REG[0x120][7:4]}
REG_WR – write to peripheral register¶
- Syntax
- REG_WR Addr, High, Low, Data
- Operands
- Addr – register address, in 32-bit words.
- High – High part of R0
- Low – Low part of R0
- Data – value to write, 8 bits
- Description
The instruction writes up to 8 bits from a general purpose register into a peripheral register.
REG[Addr][High:Low] = data
This instruction can access registers in RTC_CNTL, RTC_IO, and SENS peripherals. Address of the the register, as seen from the ULP, can be calculated from the address of the same register on the DPORT bus as follows:
addr_ulp = (addr_dport - DR_REG_RTCCNTL_BASE) / 4
Examples:
1: REG_WR 0x120, 7, 0, 0x10 // set 8 bits: REG[0x120][7:0] = 0x10
Convenience macros for peripheral registers access¶
ULP source files are passed through C preprocessor before the assembler. This allows certain macros to be used to facilitate access to peripheral registers.
Some existing macros are defined in soc/soc_ulp.h
header file. These macros allow access to the fields of peripheral registers by their names.
Peripheral registers names which can be used with these macros are the ones defined in soc/rtc_cntl_reg.h
, soc/rtc_io_reg.h
, and soc/sens_reg.h
.
- READ_RTC_REG(rtc_reg, low_bit, bit_width)
Read up to 16 bits from rtc_reg[low_bit + bit_width - 1 : low_bit] into R0. For example:
#include "soc/soc_ulp.h" #include "soc/rtc_cntl_reg.h" /* Read 16 lower bits of RTC_CNTL_TIME0_REG into R0 */ READ_RTC_REG(RTC_CNTL_TIME0_REG, 0, 16)
- READ_RTC_FIELD(rtc_reg, field)
Read from a field in rtc_reg into R0, up to 16 bits. For example:
#include "soc/soc_ulp.h" #include "soc/sens_reg.h" /* Read 8-bit SENS_TSENS_OUT field of SENS_SAR_SLAVE_ADDR3_REG into R0 */ READ_RTC_REG(SENS_SAR_SLAVE_ADDR3_REG, SENS_TSENS_OUT)
- WRITE_RTC_REG(rtc_reg, low_bit, bit_width, value)
Write immediate value into rtc_reg[low_bit + bit_width - 1 : low_bit], bit_width <= 8. For example:
#include "soc/soc_ulp.h" #include "soc/rtc_io_reg.h" /* Set BIT(2) of RTC_GPIO_OUT_DATA_W1TS field in RTC_GPIO_OUT_W1TS_REG */ WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S + 2, 1, 1)
- WRITE_RTC_FIELD(rtc_reg, field, value)
Write immediate value into a field in rtc_reg, up to 8 bits. For example:
#include "soc/soc_ulp.h" #include "soc/rtc_cntl_reg.h" /* Set RTC_CNTL_ULP_CP_SLP_TIMER_EN field of RTC_CNTL_STATE0_REG to 0 */ READ_RTC_REG(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
Programming ULP coprocessor using C macros¶
In addition to the existing binutils port for the ESP32 ULP coprocessor, it is possible to generate programs for the ULP by embedding assembly-like macros into an ESP32 application. Here is an example how this can be done:
const ulp_insn_t program[] = {
I_MOVI(R3, 16), // R3 <- 16
I_LD(R0, R3, 0), // R0 <- RTC_SLOW_MEM[R3 + 0]
I_LD(R1, R3, 1), // R1 <- RTC_SLOW_MEM[R3 + 1]
I_ADDR(R2, R0, R1), // R2 <- R0 + R1
I_ST(R2, R3, 2), // R2 -> RTC_SLOW_MEM[R2 + 2]
I_HALT()
};
size_t load_addr = 0;
size_t size = sizeof(program)/sizeof(ulp_insn_t);
ulp_process_macros_and_load(load_addr, program, &size);
ulp_run(load_addr);
The program
array is an array of ulp_insn_t
, i.e. ULP coprocessor instructions. Each I_XXX
preprocessor define translates into a single 32-bit instruction. Arguments of these preprocessor defines can be register numbers (R0 — R3
) and literal constants. See ULP coprocessor instruction defines section for descriptions of instructions and arguments they take.
Load and store instructions use addresses expressed in 32-bit words. Address 0 corresponds to the first word of RTC_SLOW_MEM
(which is address 0x50000000 as seen by the main CPUs).
To generate branch instructions, special M_
preprocessor defines are used. M_LABEL
define can be used to define a branch target. Label identifier is a 16-bit integer. M_Bxxx
defines can be used to generate branch instructions with target set to a particular label.
Implementation note: these M_
preprocessor defines will be translated into two ulp_insn_t
values: one is a token value which contains label number, and the other is the actual instruction. ulp_process_macros_and_load
function resolves the label number to the address, modifies the branch instruction to use the correct address, and removes the the extra ulp_insn_t
token which contains the label numer.
Here is an example of using labels and branches:
const ulp_insn_t program[] = {
I_MOVI(R0, 34), // R0 <- 34
M_LABEL(1), // label_1
I_MOVI(R1, 32), // R1 <- 32
I_LD(R1, R1, 0), // R1 <- RTC_SLOW_MEM[R1]
I_MOVI(R2, 33), // R2 <- 33
I_LD(R2, R2, 0), // R2 <- RTC_SLOW_MEM[R2]
I_SUBR(R3, R1, R2), // R3 <- R1 - R2
I_ST(R3, R0, 0), // R3 -> RTC_SLOW_MEM[R0 + 0]
I_ADDI(R0, R0, 1), // R0++
M_BL(1, 64), // if (R0 < 64) goto label_1
I_HALT(),
};
RTC_SLOW_MEM[32] = 42;
RTC_SLOW_MEM[33] = 18;
size_t load_addr = 0;
size_t size = sizeof(program)/sizeof(ulp_insn_t);
ulp_process_macros_and_load(load_addr, program, &size);
ulp_run(load_addr);
Functions¶
-
esp_err_t
ulp_process_macros_and_load
(uint32_t load_addr, const ulp_insn_t *program, size_t *psize)¶ Resolve all macro references in a program and load it into RTC memory.
- Return
- ESP_OK on success
- ESP_ERR_NO_MEM if auxiliary temporary structure can not be allocated
- one of ESP_ERR_ULP_xxx if program is not valid or can not be loaded
- Parameters
load_addr
: address where the program should be loaded, expressed in 32-bit wordsprogram
: ulp_insn_t array with the programpsize
: size of the program, expressed in 32-bit words
-
esp_err_t
ulp_run
(uint32_t entry_point)¶ Run the program loaded into RTC memory.
- Return
- ESP_OK on success
- Parameters
entry_point
: entry point, expressed in 32-bit words
Error codes¶
-
ESP_ERR_ULP_BASE
¶ Offset for ULP-related error codes
-
ESP_ERR_ULP_SIZE_TOO_BIG
¶ Program doesn’t fit into RTC memory reserved for the ULP
-
ESP_ERR_ULP_INVALID_LOAD_ADDR
¶ Load address is outside of RTC memory reserved for the ULP
-
ESP_ERR_ULP_DUPLICATE_LABEL
¶ More than one label with the same number was defined
-
ESP_ERR_ULP_UNDEFINED_LABEL
¶ Branch instructions references an undefined label
-
ESP_ERR_ULP_BRANCH_OUT_OF_RANGE
¶ Branch target is out of range of B instruction (try replacing with BX)
ULP coprocessor registers¶
ULP co-processor has 4 16-bit general purpose registers. All registers have same functionality, with one exception. R0 register is used by some of the compare-and-branch instructions as a source register.
These definitions can be used for all instructions which require a register.
-
R0
¶ general purpose register 0
-
R1
¶ general purpose register 1
-
R2
¶ general purpose register 2
-
R3
¶ general purpose register 3
ULP coprocessor instruction defines¶
-
I_DELAY
(cycles_)¶ Delay (nop) for a given number of cycles
-
I_HALT
¶ Halt the coprocessor.
This instruction halts the coprocessor, but keeps ULP timer active. As such, ULP program will be restarted again by timer. To stop the program and prevent the timer from restarting the program, use I_END(0) instruction.
-
I_END
¶ Stop ULP program timer.
This is a convenience macro which disables the ULP program timer. Once this instruction is used, ULP program will not be restarted anymore until ulp_run function is called.
ULP program will continue running after this instruction. To stop the currently running program, use I_HALT().
-
I_ST
(reg_val, reg_addr, offset_)¶ Store value from register reg_val into RTC memory.
The value is written to an offset calculated by adding value of reg_addr register and offset_ field (this offset is expressed in 32-bit words). 32 bits written to RTC memory are built as follows:
- bits [31:21] hold the PC of current instruction, expressed in 32-bit words
- bits [20:16] = 5’b1
- bits [15:0] are assigned the contents of reg_val
RTC_SLOW_MEM[addr + offset_] = { 5’b0, insn_PC[10:0], val[15:0] }
-
I_LD
(reg_dest, reg_addr, offset_)¶ Load value from RTC memory into reg_dest register.
Loads 16 LSBs from RTC memory word given by the sum of value in reg_addr and value of offset_.
-
I_WR_REG
(reg, low_bit, high_bit, val)¶ Write literal value to a peripheral register
reg[high_bit : low_bit] = val This instruction can access RTC_CNTL_, RTC_IO_, and SENS_ peripheral registers.
-
I_RD_REG
(reg, low_bit, high_bit)¶ Read from peripheral register into R0
R0 = reg[high_bit : low_bit] This instruction can access RTC_CNTL_, RTC_IO_, and SENS_ peripheral registers.
-
I_BL
(pc_offset, imm_value)¶ Branch relative if R0 less than immediate value.
pc_offset is expressed in words, and can be from -127 to 127 imm_value is a 16-bit value to compare R0 against
-
I_BGE
(pc_offset, imm_value)¶ Branch relative if R0 greater or equal than immediate value.
pc_offset is expressed in words, and can be from -127 to 127 imm_value is a 16-bit value to compare R0 against
-
I_BXR
(reg_pc)¶ Unconditional branch to absolute PC, address in register.
reg_pc is the register which contains address to jump to. Address is expressed in 32-bit words.
-
I_BXI
(imm_pc)¶ Unconditional branch to absolute PC, immediate address.
Address imm_pc is expressed in 32-bit words.
-
I_BXZR
(reg_pc)¶ Branch to absolute PC if ALU result is zero, address in register.
reg_pc is the register which contains address to jump to. Address is expressed in 32-bit words.
-
I_BXZI
(imm_pc)¶ Branch to absolute PC if ALU result is zero, immediate address.
Address imm_pc is expressed in 32-bit words.
-
I_BXFR
(reg_pc)¶ Branch to absolute PC if ALU overflow, address in register
reg_pc is the register which contains address to jump to. Address is expressed in 32-bit words.
-
I_BXFI
(imm_pc)¶ Branch to absolute PC if ALU overflow, immediate address
Address imm_pc is expressed in 32-bit words.
-
I_ADDR
(reg_dest, reg_src1, reg_src2)¶ Addition: dest = src1 + src2
-
I_SUBR
(reg_dest, reg_src1, reg_src2)¶ Subtraction: dest = src1 - src2
-
I_ANDR
(reg_dest, reg_src1, reg_src2)¶ Logical AND: dest = src1 & src2
-
I_ORR
(reg_dest, reg_src1, reg_src2)¶ Logical OR: dest = src1 | src2
-
I_MOVR
(reg_dest, reg_src)¶ Copy: dest = src
-
I_LSHR
(reg_dest, reg_src, reg_shift)¶ Logical shift left: dest = src << shift
-
I_RSHR
(reg_dest, reg_src, reg_shift)¶ Logical shift right: dest = src >> shift
-
I_ADDI
(reg_dest, reg_src, imm_)¶ Add register and an immediate value: dest = src1 + imm
-
I_SUBI
(reg_dest, reg_src, imm_)¶ Subtract register and an immediate value: dest = src - imm
-
I_ANDI
(reg_dest, reg_src, imm_)¶ Logical AND register and an immediate value: dest = src & imm
-
I_ORI
(reg_dest, reg_src, imm_)¶ Logical OR register and an immediate value: dest = src | imm
-
I_MOVI
(reg_dest, imm_)¶ Copy an immediate value into register: dest = imm
-
I_LSHI
(reg_dest, reg_src, imm_)¶ Logical shift left register value by an immediate: dest = src << imm
-
I_RSHI
(reg_dest, reg_src, imm_)¶ Logical shift right register value by an immediate: dest = val >> imm
-
M_LABEL
(label_num)¶ Define a label with number label_num.
This is a macro which doesn’t generate a real instruction. The token generated by this macro is removed by ulp_process_macros_and_load function. Label defined using this macro can be used in branch macros defined below.
-
M_BL
(label_num, imm_value)¶ Macro: branch to label label_num if R0 is less than immediate value.
This macro generates two ulp_insn_t values separated by a comma, and should be used when defining contents of ulp_insn_t arrays. First value is not a real instruction; it is a token which is removed by ulp_process_macros_and_load function.
-
M_BGE
(label_num, imm_value)¶ Macro: branch to label label_num if R0 is greater or equal than immediate value
This macro generates two ulp_insn_t values separated by a comma, and should be used when defining contents of ulp_insn_t arrays. First value is not a real instruction; it is a token which is removed by ulp_process_macros_and_load function.
-
M_BX
(label_num)¶ Macro: unconditional branch to label
This macro generates two ulp_insn_t values separated by a comma, and should be used when defining contents of ulp_insn_t arrays. First value is not a real instruction; it is a token which is removed by ulp_process_macros_and_load function.
-
M_BXZ
(label_num)¶ Macro: branch to label if ALU result is zero
This macro generates two ulp_insn_t values separated by a comma, and should be used when defining contents of ulp_insn_t arrays. First value is not a real instruction; it is a token which is removed by ulp_process_macros_and_load function.
-
M_BXF
(label_num)¶ Macro: branch to label if ALU overflow
This macro generates two ulp_insn_t values separated by a comma, and should be used when defining contents of ulp_insn_t arrays. First value is not a real instruction; it is a token which is removed by ulp_process_macros_and_load function.
ULP (Ultra Low Power) coprocessor is a simple FSM which is designed to perform measurements using ADC, temperature sensor, and external I2C sensors, while main processors are in deep sleep mode. ULP coprocessor can access RTC_SLOW_MEM memory region, and registers in RTC_CNTL, RTC_IO, and SARADC peripherals. ULP coprocessor uses fixed-width 32-bit instructions, 32-bit memory addressing, and has 4 general purpose 16-bit registers.
Installing the toolchain¶
ULP coprocessor code is written in assembly and compiled using the binutils-esp32ulp toolchain.
1. Download the toolchain using the links listed on this page: https://github.com/espressif/binutils-esp32ulp/wiki#downloads
- Extract the toolchain into a directory, and add the path to the
bin/
directory of the toolchain to thePATH
environment variable.
Compiling ULP code¶
To compile ULP code as part of a component, the following steps must be taken:
- ULP code, written in assembly, must be added to one or more files with .S extension. These files must be placed into a separate directory inside component directory, for instance ulp/.
Modify the component makefile, adding the following:
ULP_APP_NAME ?= ulp_$(COMPONENT_NAME) ULP_S_SOURCES = $(COMPONENT_PATH)/ulp/ulp_source_file.S ULP_EXP_DEP_OBJECTS := main.o include $(IDF_PATH)/components/ulp/component_ulp_common.mk
Here is each line explained:
- ULP_APP_NAME
Name of the generated ULP application, without an extension. This name is used for build products of the ULP application: ELF file, map file, binary file, generated header file, and generated linker export file.
- ULP_S_SOURCES
List of assembly files to be passed to the ULP assembler. These must be absolute paths, i.e. start with
$(COMPONENT_PATH)
. Consider using$(addprefix)
function if more than one file needs to be listed. Paths are relative to component build directory, so prefixing them is not necessary.- ULP_EXP_DEP_OBJECTS
List of object files names within the component which include the generated header file. This list is needed to build the dependencies correctly and ensure that the generated header file is created before any of these files are compiled. See section below explaining the concept of generated header files for ULP applications.
- include $(IDF_PATH)/components/ulp/component_ulp_common.mk
Includes common definitions of ULP build steps. Defines build targets for ULP object files, ELF file, binary file, etc.
Build the application as usual (e.g. make app)
Inside, the build system will take the following steps to build ULP program:
- Run each assembly file (foo.S) through C preprocessor. This step generates the preprocessed assembly files (foo.ulp.pS) in the component build directory. This step also generates dependency files (foo.ulp.d).
- Run preprocessed assembly sources through assembler. This produces objects (foo.ulp.o) and listing (foo.ulp.lst) files. Listing files are generated for debugging purposes and are not used at later stages of build process.
- Run linker script template through C preprocessor. The template is located in components/ulp/ld directory.
- Link object files into an output ELF file (ulp_app_name.elf). Map file (ulp_app_name.map) generated at this stage may be useful for debugging purposes.
- Dump contents of the ELF file into binary (ulp_app_name.bin) for embedding into the application.
- Generate list of global symbols (ulp_app_name.sym) in the ELF file using esp32ulp-elf-nm.
- Create LD export script and header file (ulp_app_name.ld and ulp_app_name.h) containing the symbols from ulp_app_name.sym. This is done using esp32ulp_mapgen.py utility.
- Add the generated binary to the list of binary files to be emedded into the application.
Accessing ULP program variables¶
Global symbols defined in the ULP program may be used inside the main program.
For example, ULP program may define a variable measurement_count
which will define the number of ADC measurements the program needs to make before waking up the chip from deep sleep:
.global measurement_count
measurement_count: .long 0
/* later, use measurement_count */
move r3, measurement_count
ld r3, r3, 0
Main program needs to initialize this variable before ULP program is started. Build system makes this possible by generating a $(ULP_APP_NAME).h
and $(ULP_APP_NAME).ld
files which define global symbols present in the ULP program. This files include each global symbol defined in the ULP program, prefixed with ulp_
.
The header file contains declaration of the symbol:
extern uint32_t ulp_measurement_count;
Note that all symbols (variables, arrays, functions) are declared as uint32_t
. For functions and arrays, take address of the symbol and cast to the appropriate type.
The generated linker script file defines locations of symbols in RTC_SLOW_MEM:
PROVIDE ( ulp_measurement_count = 0x50000060 );
To access ULP program variables from the main program, include the generated header file and use variables as one normally would:
#include "ulp_app_name.h"
// later
void init_ulp_vars() {
ulp_measurement_count = 64;
}
Note that ULP program can only use lower 16 bits of each 32-bit word in RTC memory, because the registers are 16-bit, and there is no instruction to load from high part of the word.
Likewise, ULP store instruction writes register value into the lower 16 bit part of the 32-bit word. Upper 16 bits are written with a value which depends on the address of the store instruction, so when reading variables written by the ULP, main application needs to mask upper 16 bits, e.g.:
printf("Last measurement value: %d\n", ulp_last_measurement & UINT16_MAX);
Starting the ULP program¶
To run a ULP program, main application needs to load the ULP program into RTC memory using ulp_load_binary
function, and then start it using ulp_run
function.
Note that “Enable Ultra Low Power (ULP) Coprocessor” option must be enabled in menuconfig in order to reserve memory for the ULP. “RTC slow memory reserved for coprocessor” option must be set to a value sufficient to store ULP code and data. If the application components contain multiple ULP programs, then the size of the RTC memory must be sufficient to hold the largest one.
Each ULP program is embedded into the ESP-IDF application as a binary blob. Application can reference this blob and load it in the following way (suppose ULP_APP_NAME was defined to ulp_app_name
:
extern const uint8_t bin_start[] asm("_binary_ulp_app_name_bin_start");
extern const uint8_t bin_end[] asm("_binary_ulp_app_name_bin_end");
void start_ulp_program() {
ESP_ERROR_CHECK( ulp_load_binary(
0 /* load address, set to 0 when using default linker scripts */,
bin_start,
(bin_end - bin_start) / sizeof(uint32_t)) );
}
-
esp_err_t
ulp_load_binary
(uint32_t load_addr, const uint8_t *program_binary, size_t program_size)¶ Load ULP program binary into RTC memory.
ULP program binary should have the following format (all values little-endian):
- MAGIC, (value 0x00706c75, 4 bytes)
- TEXT_OFFSET, offset of .text section from binary start (2 bytes)
- TEXT_SIZE, size of .text section (2 bytes)
- DATA_SIZE, size of .data section (2 bytes)
- BSS_SIZE, size of .bss section (2 bytes)
- (TEXT_OFFSET - 16) bytes of arbitrary data (will not be loaded into RTC memory)
- .text section
- .data section
Linker script in components/ulp/ld/esp32.ulp.ld produces ELF files which correspond to this format. This linker script produces binaries with load_addr == 0.
- Return
- ESP_OK on success
- ESP_ERR_INVALID_ARG if load_addr is out of range
- ESP_ERR_INVALID_SIZE if program_size doesn’t match (TEXT_OFFSET + TEXT_SIZE + DATA_SIZE)
- ESP_ERR_NOT_SUPPORTED if the magic number is incorrect
- Parameters
load_addr
: address where the program should be loaded, expressed in 32-bit wordsprogram_binary
: pointer to program binaryprogram_size
: size of the program binary
Once the program is loaded into RTC memory, application can start it, passing the address of the entry point to ulp_run
function:
ESP_ERROR_CHECK( ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t)) );
-
esp_err_t
ulp_run
(uint32_t entry_point)¶ Run the program loaded into RTC memory.
- Return
- ESP_OK on success
- Parameters
entry_point
: entry point, expressed in 32-bit words
Declaration of the entry point symbol comes from the above mentioned generated header file, $(ULP_APP_NAME).h
. In assembly source of the ULP application, this symbol must be marked as .global
:
.global entry
entry:
/* code starts here */
ULP program flow¶
ULP coprocessor is started by a timer. The timer is started once ulp_run
is called. The timer counts a number of RTC_SLOW_CLK ticks (by default, produced by an internal 150kHz RC oscillator). The number of ticks is set using SENS_ULP_CP_SLEEP_CYCx_REG
registers (x = 0..4). When starting the ULP for the first time, SENS_ULP_CP_SLEEP_CYC0_REG
will be used to obtain the number of timer ticks. Later the ULP program can select another SENS_ULP_CP_SLEEP_CYCx_REG
register using sleep
instruction.
Once the timer counts the number of ticks set by the selected SENS_ULP_CP_SLEEP_CYCx_REG
register, ULP coprocessor powers up and starts running the program from the entry point set in the call to ulp_run
.
The program runs until it encounters a halt
instruction or an illegal instruction. Once the program halts, ULP coprocessor powers down, and the timer is started again.
To disable the timer (effectively preventing the ULP program from running again), clear the RTC_CNTL_ULP_CP_SLP_TIMER_EN
bit in the RTC_CNTL_STATE0_REG
register. This can be done both from ULP code and from the main program.
Unit Testing in ESP32¶
ESP-IDF comes with a unit test app based on Unity - unit test framework. Unit tests are integrated in the ESP-IDF repository and are placed in test
subdirectory of each component respectively.
Adding unit tests¶
Unit tests are added in the test
subdirectory of the respective component.
Tests are added in C files, a single C file can include multiple test cases.
Test files start with the word “test”.
The test file should include unity.h and the header for the C module to be tested.
Tests are added in a function in the C file as follows:
TEST_CASE("test name", "[module name]"
{
// Add test here
}
First argument is a descriptive name for the test, second argument is an identifier in square brackets. Identifiers are used to group related test, or tests with specific properties.
There is no need to add a main function with UNITY_BEGIN()
and UNITY_END()
in each test case.
unity_platform.c
will run UNITY_BEGIN()
, run the tests cases, and then call UNITY_END()
.
Each test subdirectory needs to include component.mk file with at least the following line of code:
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
See http://www.throwtheswitch.org/unity for more information about writing tests in Unity.
Building unit test app¶
Follow the setup instructions in the top-level esp-idf README. Make sure that IDF_PATH environment variable is set to point to the path of esp-idf top-level directory.
Change into tools/unit-test-app directory to configure and build it:
- make menuconfig - configure unit test app.
- make TESTS_ALL=1 - build unit test app with tests for each component having tests in the
test
subdirectory. - make TEST_COMPONENTS=’xxx’ - build unit test app with tests for specific components.
When the build finishes, it will print instructions for flashing the chip. You can simply run make flash
to flash all build output.
You can also run make flash TESTS_ALL=1
or make TEST_COMPONENTS='xxx'
to build and flash. Everything needed will be rebuilt automatically before flashing.
Use menuconfig to set the serial port for flashing.
Running unit tests¶
After flashing reset the ESP32 and it will boot the unit test app.
Unit test app prints a test menu with all available tests.
Test cases can be run by inputting one of the following:
- Test case name in quotation marks to run a single test case
- Test case index to run a single test case
- Module name in square brackets to run all test cases for a specific module
- An asterisk to run all test cases
资源¶
- esp32.com 论坛 是一个提问并发现社区资源的地方。
- 如果你发现了 bug 或者有新的功能需求,在 GitHub 上面进入 Issues 区域。在创建新 issue 前请先检查已存在的 Issues 。
- 如果你有兴趣给 ESP-IDF 贡献代码,请先查看 <no title>。
- 如果希望使用 Arduino 平台开应用程序,请参考 Arduino core for ESP32 WiFi chip。
- 其它与 ESP32 产品相关的信息,请参考 Espressif 的 文档 章节。
- 本文档存在一份镜像备份: https://dl.espressif.com/doc/esp-idf/latest/.
Copyrights and Licenses¶
Software Copyrights¶
All original source code in this repository is Copyright (C) 2015-2016 Espressif Systems. This source code is licensed under the Apache License 2.0 as described in the file LICENSE.
Additional third party copyrighted code is included under the following licenses:
- Newlib (components/newlib) is licensed under the BSD License and is Copyright of various parties, as described in the file components/newlib/COPYING.NEWLIB.
- Xtensa header files (components/esp32/include/xtensa) are Copyright (C) 2013 Tensilica Inc and are licensed under the MIT License as reproduce in the individual header files.
- esptool.py (components/esptool_py/esptool) is Copyright (C) 2014-2016 Fredrik Ahlberg, Angus Gratton and is licensed under the GNU General Public License v2, as described in the file components/esptool_py/LICENSE.
- Original parts of FreeRTOS (components/freertos) are Copyright (C) 2015 Real Time Engineers Ltd and is licensed under the GNU General Public License V2 with the FreeRTOS Linking Exception, as described in the file components/freertos/license.txt.
- Original parts of LWIP (components/lwip) are Copyright (C) 2001, 2002 Swedish Institute of Computer Science and are licensed under the BSD License as described in the file components/lwip/COPYING.
- KConfig (tools/kconfig) is Copyright (C) 2002 Roman Zippel and others, and is licensed under the GNU General Public License V2.
- wpa_supplicant Copyright (c) 2003-2005 Jouni Malinen and licensed under the BSD license.
- FreeBSD net80211 Copyright (c) 2004-2008 Sam Leffler, Errno Consulting and licensed under the BSD license.
- JSMN JSON Parser (components/jsmn) Copyright (c) 2010 Serge A. Zaitsev and licensed under the MIT license.
Where source code headers specify Copyright & License information, this information takes precedence over the summaries made here.
ROM Source Code Copyrights¶
ESP32 mask ROM hardware includes binaries compiled from portions of the following third party software:
- Newlib, as licensed under the BSD License and Copyright of various parties, as described in the file components/newlib/COPYING.NEWLIB.
- Xtensa libhal, Copyright (c) Tensilica Inc and licensed under the MIT license (see below).
- TinyBasic Plus, Copyright Mike Field & Scott Lawrence and licensed under the MIT license (see below).
- miniz, by Rich Geldreich - placed into the public domain.
- wpa_supplicant Copyright (c) 2003-2005 Jouni Malinen and licensed under the BSD license.
- TJpgDec Copyright (C) 2011, ChaN, all right reserved. See below for license.
Xtensa libhal MIT License¶
Copyright (c) 2003, 2006, 2010 Tensilica Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
TinyBasic Plus MIT License¶
Copyright (c) 2012-2013
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
TJpgDec License¶
TJpgDec - Tiny JPEG Decompressor R0.01 (C)ChaN, 2011 The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. This is a free software that opened for education, research and commercial developments under license policy of following terms.
Copyright (C) 2011, ChaN, all right reserved.
- The TJpgDec module is a free software and there is NO WARRANTY.
- No restriction on use. You can use, modify and redistribute it for personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
- Redistributions of source code must retain the above copyright notice.
About¶
This is documentation of ESP-IDF, the framework to develop applications for ESP32 chip by Espressif.
The ESP32 is 2.4 GHz Wi-Fi and Bluetooth combo, 32 bit dual core chip with 600 DMIPS processing power.

Espressif IoT Integrated Development Framework
The ESP-IDF, Espressif IoT Integrated Development Framework, provides toolchain, API, components and workflows to develop applications for ESP32 using Windows, Linux and Mac OS operating systems.