前言
在之前公司某项目开发中,团队选用 ESP32 模块为核心,我主导架构规划与核心模块开发时,需要先攻克工程编译环节,之后才能调试模块和审查相关同事代码。研读【ESP32 官方教程】发现,其内容虽全面但排布零散,对急需上手的开发者而言易陷入信息冗余的困扰。
我一贯主张“先落地应用,再深研细节”,这与校园“先学理论再实践”的模式不同。项目中开发者更需快速打通编译流程的实操方案,因此我结合本次开发经验,整理出这份聚焦实操的快速应用笔记。笔记省略冗余理论,直击编译关键步骤与技巧,助力读者快速实现工程编译,后续再逐步深挖技术细节。
一、工程几个重要文件夹
假设工程根目录为:esp32_xxx
假设现有用户工程:esp32_xxx/projs/aaa/
官方组件:esp32_xxx/esp-components/
IDF 工具:esp32_xxx/esp-idf-all-5.1/
一、安装工具
1
2
|
sudo apt-get install git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0
#安装全部所需软件包(具体过程这里不细述)(备注:无论操作系统还是工具都需要较新的版本,如:ESP-IDF 需要 CMake 3.16 或以上版本)
|
二、编译代码
1
2
3
4
5
6
7
8
9
10
11
|
#sudo chmod -R 777 esp32_xxx #强置【esp32_xxx】目录内所有文件具备【可读+写+执行】权限(防止因权限导致异常问题,★只需设置一次即可★)
cd esp32_xxx/projs/aaa #进入【用户工程】目录(本例应用工程为 esp32_xxx/projs/aaa/ ,其里面包含 main 应用文件夹)
. ../../esp-idf-all-5.1/export.sh #通过脚本设置当前环境变量,为运行`idf.py`准备(注意:最前面的`. `表示将环境变量导出到当前 shell 中,否则脚本所设置的环境在其运行完后就会消失)
#rm dependencies.lock #删除之前编译配置文件(★初次拷贝用户工程时才删除★)(当你更改工程文件夹【名称】或【路径】时,删除它并执行 idf.py fullclean 为重新全编译准备)
idf.py fullclean #清除之前编译所有文件(需要重新全编译才运行本命令)(它会删除用户工程目录下 build/ 里的所有文件(夹),所以用户不要在此文件夹放置有用的文件)
idf.py build #编译工程并且输出固件(固件输出至用户工程目录下:build/aaa.bin)
#idf.py size 命令将编译并显示应用程序大小,包括占用的 RAM 和 flash 及各部分的大小
#idf.py size-components 相比上面命令还会显示组件大小
#idf.py size-files 相比上面命令还会显示源文件大小
#idf.py --version 查看其版本号
#idf.py --help 可查更多命令
|
三、烧录固件
1
2
3
4
5
|
#sudo usermod -a -G dialout $USER #将用户添加到[dialout]组(配置串口写操作权限,★只需操作一次即可★)
#reboot #修改后要重启电脑 (配置串口写操作权限,★只需操作一次即可★)
idf.py -p /dev/ttyUSB0 flash #通过串口下载固件(比如 Windows 下的 COM3 串口,Linux 下的 /dev/ttyUSB0 串口)
idf.py -p /dev/ttyUSB0 monitor #通过串口监控调试(Ctrl+] 组合键退出监视)
|
PS:关于 dependencies.lock 引起的错误(点击展开)
因dependencies.lock配置文件会锁定组件的路径,若您修改了工程文件夹的名称或路径,则在执行编译时会出现错误。此时需将该文件中所有path:设置的组件路径更新为当前路径(原因:此前执行idf.py build会将组件路径记录为绝对路径)。解决方法示例如下:
1
2
3
4
5
6
7
8
9
|
# ------《方法一》------
# 将
path: /home/o2o/workspace/esp32_xxx/esp-components/espressif__esp-modbus
# 改为
path: ../../esp-components/espressif__esp-modbus
# ------《方法二》------
rm dependencies.lock
idf.py fullclean
|
备注:《方法一》只是说明错误产生原因,实际操作请使用《方法二》
PS:全编译成功最后面提示信息(点击展开)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
[100%] Built target aaa.elf
Scanning dependencies of target gen_project_binary
[100%] Generating binary image from built executable
esptool.py v4.10.0
Creating esp32c2 image...
Merged 1 ELF section
Successfully created esp32c2 image.
Generated /home/o2o/workspace/esp32_xxx/projs/aaa/build/aaa.bin
[100%] Built target gen_project_binary
Scanning dependencies of target app_check_size
aaa.bin binary size 0x1bd90 bytes. Smallest app partition is 0x100000 bytes. 0xe4270 bytes (89%) free.
[100%] Built target app_check_size
Scanning dependencies of target app
[100%] Built target app
Project build complete. To flash, run this command:
/home/o2o/.espressif/python_env/idf5.1_py3.8_env/bin/python ../../esp-idf-all-5.1/components/esptool_py/esptool/esptool.py -p (PORT) -b 460800 --before default_reset --after hard_reset --chip esp32c2 write_flash --flash_mode dio --flash_size 2MB --flash_freq 60m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/aaa.bin
or run 'idf.py -p (PORT) flash'
|
备注:最后提示烧录固件两种方法:
esptool.py命令适合量产烧录。因为可将esptool.py封装成esptool.exe工具,根据上面编译信息编写烧录脚本(如:Download_COM22.bat)!
idf.py命令适合调试烧录。
PS:重编译成功最后面提示信息(点击展开)
1
2
3
4
5
6
7
8
9
|
[100%] Built target aaa.elf
[100%] Built target gen_project_binary
aaa.bin binary size 0x1bd90 bytes. Smallest app partition is 0x100000 bytes. 0xe4270 bytes (89%) free.
[100%] Built target app_check_size
[100%] Built target app
Project build complete. To flash, run this command:
/home/o2o/.espressif/python_env/idf5.1_py3.8_env/bin/python ../../esp-idf-all-5.1/components/esptool_py/esptool/esptool.py -p (PORT) -b 460800 --before default_reset --after hard_reset --chip esp32c2 write_flash --flash_mode dio --flash_size 2MB --flash_freq 60m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/aaa.bin
or run 'idf.py -p (PORT) flash'
|
备注:最后提示烧录固件两种方法:
esptool.py命令适合量产烧录。因为可将esptool.py封装成esptool.exe工具,根据上面编译信息编写烧录脚本(如:Download_COM22.bat)!
idf.py命令适合调试烧录。
PS:关于量产烧录固件方法(点击展开)
编译完成后,提示可使用 esptool.py 命令烧录固件,该方法适用于量产场景。用户可将 esptool.py 封装为 esptool.exe 可执行文件,并配合编译信息编写自动化烧录脚本,以提升操作效率。您可下载并解压【ESP32固件烧录演示.zip】案例文件,查看在 Windows 环境下的具体烧录流程。其中,Download_COM22.bat 脚本及其参数说明如下:
1
2
3
4
5
6
|
@echo off
::-----------基于编译输出的最后信息复制并修改得出如下命令-----------
.\esptool.exe -p COM22 -b 460800 --before default_reset --after hard_reset --chip esp32c2 write_flash --flash_mode dio --flash_size 2MB --flash_freq 60m 0x0 bootloader.bin 0x8000 partition-table.bin 0x10000 aaa.bin
::-----------命令窗口不退出-----------
pause
exit
|
操作方法很简单:使用文本编辑工具打开Download_COM22.bat文件,将其中的COM22修改为电脑检测到的实际串口号,保存后双击Download_COM22.bat脚本即可执行烧录操作。
下面是参数和文件的详细解释:
基础参数
-p COM22:指定与 ESP32 连接的串口。Windows 系统用 COM* 表示,Linux 一般是 /dev/ttyUSB*。
-b 460800:设置烧录时的波特率,影响数据传输速度。
复位与芯片类型参数
--before default_reset:烧录前的复位操作,default_reset 会通过控制 DTR/RTS 引脚让 ESP32 复位并进入下载模式。
--after hard_reset:烧录完成后,通过硬件复位(重启)ESP32。
--chip esp32c2:明确目标芯片型号为 ESP32C2,工具会据此调整通信协议和参数。
闪存参数
write_flash:执行固件写入操作。
--flash_mode dio:设置闪存的工作模式,dio(双输入输出)是 ESP32 常用模式,支持更高数据传输率。
--flash_freq 60m:设置闪存的工作频率为 60MHz,影响数据读写速度。
--flash_size 2MB:指定闪存的总容量,需与硬件实际容量匹配。
分区与文件参数
0x1000 bootloader.bin:将引导加载程序写入地址 0x1000。
0x8000 partition-table.bin:分区表定义了闪存如何划分,需写入地址 0x8000。
0xd000 ota_data_initial.bin:OTA 数据初始化文件,写入地址 0xd000。
0x10000 littlefs.bin:把文件系统(如 LittleFS)烧录到地址0x10000。
0x40000 aaa.bin:将应用程序固件(如 aaa.bin)写入地址 0x40000。
这些地址按照 ESP32 官方规定的标准烧录位置(配置文件:esp32_xxx/projs/aaa/partitions.csv),一般情况下不要随意更改,否则可能导致设备无法启动或功能异常。
PS:直接复制示例工程(点击展开)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#sudo chmod -R 777 esp32_xxx #强置【esp32_xxx】目录内所有文件具备【可读+写+执行】权限(防止因权限导致异常问题,★只需设置一次即可★)
cd esp32_xxx/esp-idf-all-5.1/ #进入【ESP-IDF】工具目录
export IDF_GITHUB_ASSETS="dl.espressif.cn/github_assets" #设置临时环境变量,为运行`install.sh`时安装工具时优先选择 Espressif【国内】下载服务器(ESP-IDF 工具安装器会下载 Github 发布版本中附带的一些工具,因访问 Github 较为缓慢,所以临时修改。备注:国外服务器为 "dl.espressif.com/github_assets")
./install.sh esp32,esp32c2,esp32c3 #安装所支持的目标芯片(工具)(安装所有:./install.sh all)(可使用 idf.py --list-targets 可查看支持的所有目标芯片)
cp -r examples/get-started/hello_world ../projs/ #直接复制示例工程(文件夹)
cd ../projs/hello_world #进入用户工程(即工程目录为 esp32_xxx/projs/hello_world/),此时可发现包括 main 目录(默认源文件存放处)、CMakeLists.txt 等核心配置文件,可直接基于此结构进行代码开发
. ../../esp-idf-all-5.1/export.sh #通过脚本设置当前环境变量,为运行`idf.py`准备(注意:最前面的`. `表示将环境变量导出到当前 shell 中,否则脚本所设置的环境在其运行完后就会消失)
#idf.py set-target esp32c2 #选择具体一款目标芯片并恢复默认配置【只有新建工程才操作,★★否则破坏原工程与芯片强相关的配置★★】(hello_world 默认目标芯片是 esp32)(使用 idf.py --list-targets 可查看支持的所有目标芯片)(使用 idf.py docs 命令将在浏览器中打开工程[目标芯片]和[ESP-IDF版本]对应的文档)
idf.py menuconfig #进入图形配置界面可配置相关程序模块(例如 esp32c2 测试板的晶振是 26 MHz,需要修改配置:Component config ---> Hardware Settings ---> Main XTAL Config ---> Main XTAL frequency ---> 26 MHz,按 S 键保存,并按 Q 键退出)
idf.py reconfigure #重新运行 CMake【当从源代码树中添加或删除了文件,或需要修改 CMake 缓存变量时,将有必要使用该命令,★平时则不需要运行★】
#编译代码:略……(如 idf.py build)
#烧录固件:略……(如 idf.py -p /dev/ttyUSB0 flash)
|
PS:如果自己新建工程(点击展开)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#sudo chmod -R 777 esp32_xxx #强置【esp32_xxx】目录内所有文件具备【可读+写+执行】权限(防止因权限导致异常问题,★只需设置一次即可★)
cd esp32_xxx/esp-idf-all-5.1/ #进入【ESP-IDF】工具目录
export IDF_GITHUB_ASSETS="dl.espressif.cn/github_assets" #设置临时环境变量,为运行`install.sh`时安装工具时优先选择 Espressif【国内】下载服务器(ESP-IDF 工具安装器会下载 Github 发布版本中附带的一些工具,因访问 Github 较为缓慢,所以临时修改。备注:国外服务器为 "dl.espressif.com/github_assets")
./install.sh esp32,esp32c2,esp32c3 #安装所支持的目标芯片(工具)(安装所有:./install.sh all)(可使用 idf.py --list-targets 可查看支持的所有目标芯片)
. ./export.sh #通过脚本设置当前环境变量,为运行`idf.py`准备(注意:最前面的`. `表示将环境变量导出到当前 shell 中,否则脚本所设置的环境在其运行完后就会消失)
cd ../projs/ #进入用户自定义目录(目录为 esp32_xxx/projs/)
idf.py create-project aaa #新建工程(将得到应用工程为 esp32_xxx/projs/aaa/)
cd aaa/ #进入用户工程(即工程目录为 esp32_xxx/projs/aaa/),此时可发现包括 main 目录(默认源文件存放处)、CMakeLists.txt 等核心配置文件,可直接基于此结构进行代码开发
idf.py set-target esp32c2 #选择具体一款目标芯片并恢复默认配置【只有新建工程才操作,★★否则破坏原工程与芯片强相关的配置★★】(使用 idf.py --list-targets 可查看支持的所有目标芯片)(使用 idf.py docs 命令将在浏览器中打开工程[目标芯片]和[ESP-IDF版本]对应的文档)
idf.py menuconfig #进入图形配置界面可配置相关程序模块(本例 esp32c2 测试板的晶振是 26 MHz,需要修改配置:Component config ---> Hardware Settings ---> Main XTAL Config ---> Main XTAL frequency ---> 26 MHz,按 S 键保存,并按 Q 键退出)
idf.py reconfigure #重新运行 CMake【当从源代码树中添加或删除了文件,或需要修改 CMake 缓存变量时,将有必要使用该命令,★平时则不需要运行★】
#编译代码:略……(如 idf.py build)
#烧录固件:略……(如 idf.py -p /dev/ttyUSB0 flash)
|
PS:Linux 和 macOS 平台工具链的标准设置
PS:idf.py 前端工具
PS:快速入门
三、ESP32 工程在 Windows(Windows 10 专业版)环境下的编译
一、安装工具
1、直接打开【ESP-IDF 工具安装器】下载在线安装版;或者下移网页,在《Download links to available releases and mirrors.》表单里下载离线版本,例如【Offline Installer v5.1】。
2、点击安装文件(强烈建议使用默认安装路径),其中在《安装前系统检查》界面中如出现提示请点击〈应用修复〉,在《选择组件》界面中根据实际勾选组件(不清楚可全选)。
3、最后在安装完成界面勾选全部选项,即可完成安装并打开 CMD 和 PowerShell 两个命令窗口(备注:在电脑桌面会生成这两个快捷方式文件)。
4、正常情况下,两命令窗口会提示“您现在可以编译 ESP-IDF 项目,转到项目目录并运行idf.py build编译代码”。
二、编译代码
1、在桌面上复制粘贴【ESP-IDF 5.1 PowerShell】命令窗口快捷图标,再“右击/属性/快捷方式/起始位置”填写用户工程目录,例如【C:\Users\pc\Desktop\esp32_xxx\projs\aaa】,最后点“确定”保存退出。
2、双击刚才创建的命令窗口快捷图标,接着运行下面命令:
1
2
3
4
5
6
7
8
9
|
..\..\esp-idf-all-5.1\export.ps1 #通过脚本设置当前环境变量,为运行`idf.py`准备(如果是 ESP-IDF 5.1 CMD 命令窗口,脚本为 export.bat)
#rm dependencies.lock #删除之前编译配置文件(★初次拷贝用户工程时才删除★)(当你更改工程文件夹【名称】或【路径】时,删除它并执行 idf.py fullclean 为重新全编译准备)
idf.py fullclean #清除之前编译所有文件(需要重新全编译才运行本命令)(它会删除用户工程目录下 build/ 里的所有文件(夹),所以用户不要在此文件夹放置有用的文件)
idf.py build #编译工程并且输出固件(固件输出至用户工程目录下:build/aaa.bin)
#idf.py size 命令将编译并显示应用程序大小,包括占用的 RAM 和 flash 及各部分的大小
#idf.py size-components 相比上面命令还会显示组件大小
#idf.py size-files 相比上面命令还会显示源文件大小
#idf.py --version 查看其版本号
#idf.py --help 可查更多命令
|
三、烧录固件
1
2
3
|
idf.py -p COM3 flash #通过串口下载固件(比如 Windows 下的 COM3 串口,Linux 下的 /dev/ttyUSB0 串口)
idf.py -p COM3 monitor #通过串口监控调试(Ctrl+] 组合键退出监视)
|
PS:关于 dependencies.lock 引起的错误(点击展开)
因dependencies.lock配置文件会锁定组件的路径,若您修改了工程文件夹的名称或路径,则在执行编译时会出现错误。此时需将该文件中所有path:设置的组件路径更新为当前路径(原因:此前执行idf.py build会将组件路径记录为绝对路径)。直接执行下面命令解决:
1
2
|
rm dependencies.lock
idf.py fullclean
|
PS:在 Windows 系统下编译的时长和问题(点击展开)
- 在 Windows 系统下全编译有时耗时超过 30 分钟,因涉及版本和不稳定问题,建议在 Linux 下编译代码
- 命令窗口有时运行过程中会卡往不动,可能是稳定性问题引起,只能重新运行命令重试
PS:关于 ESP-IDF 工具的路径长度问题(点击展开)
- ESP-IDF 工具的路径不能超过 90 个字符,路径过长可能会导致构建失败!所以无论上面安装或用户项目工程的工具,都不能过长或有空格、特殊字符之类!
PS:安装 ESP-IDF 工具会安装以下组件(点击展开)
- 内置的 Python
- 交叉编译器
- OpenOCD
- CMake 和 Ninja 编译工具
- ESP-IDF
PS:Windows 平台工具链的标准设置
PS:idf.py 前端工具
PS:快速入门
四、工程重要文件解释
PS:sdkconfig(点击展开)
sdkconfig文件是项目的核心配置文件,用于存储 ESP-IDF(Espressif IoT Development Framework)的编译选项和参数。它决定了 ESP32 芯片的功能特性、外设配置、内存分配以及应用程序的行为。
备注:运行【idf.py set-target】命令将清除 build 目录,并重新生成sdkconfig文件,原来的 sdkconfig 文件保存为sdkconfig.old。此命令主要影响与芯片强相关的配置,其他配置会尽量保留,不会完全恢复到 “全新工程” 的默认状态。如果需要彻底重置配置,可以手动删除工程目录下的sdkconfig文件(该文件保存了所有配置项),之后重新执行【idf.py menuconfig】会生成全新的默认配置。
PS:CMakeLists.txt(点击展开)
CMakeLists.txt文件是用于指导 CMake 构建系统如何编译和链接项目代码(如:头文件搜索路径、源文件路径列表、项目名称等),在 ESP32 工程中会包含多个 CMakeLists.txt 文件。
PS:linker.lf(点击展开)
linker.lf(.ld后缀的文件)是链接脚本(Linker Script),用于指导链接器(如 GCC 的 ld)如何将编译后的目标文件(.o)和库文件组合成最终的可执行文件或固件。链接脚本的核心作用是定义内存布局和指定代码 / 数据段的放置位置。
PS:idf_component.yml(点击展开)
idf_component.yml是一个关键配置文件,用于定义和管理 ESP-IDF(Espressif IoT Development Framework)组件的元数据、依赖关系及构建参数。它是 ESP-IDF v4.0 及后续版本中组件管理系统的核心组成部分,替代了早期版本使用的 component.mk 和 Kconfig 文件的部分功能。
PS:dependencies.lock(点击展开)
dependencies.lock文件是用于锁定项目依赖组件版本和配置的重要文件,它确保项目在不同环境中构建时依赖的组件版本和来源保持一致,避免因依赖更新导致的兼容性问题。
备注:当dependencies.lock文件不存在时,执行【idf.py build】编译代码时会重新生成!
PS:partitions.csv(点击展开)
partitions.csv是一个关键配置文件,用于定义 flash 存储器的分区表。ESP32 的 flash 空间需要被划分为多个区域,分别存储程序代码、文件系统、OTA 更新数据、校准数据等。
备注:运行【idf.py build】过程中会调用【parttool.py】读取partitions.csv相关参数!
PS:Kconfig.projbuild(点击展开)
Kconfig.projbuild是一个关键的配置文件,用于定义项目级别的编译选项和配置项。它基于 Kconfig 系统,允许开发者通过菜单驱动的界面(如 idf.py menuconfig)交互式地配置项目参数,并将配置结果保存到sdkconfig文件中。