第 2 章 搭建开发环境:从源码到芯片的全流程
本章回答三个底层问题①工具链里的每个工具到底在干什么②环境变量/PATH 是什么、为什么要有③烧录和监视器的底层机制是什么然后动手三件事把 ESP-IDF装上电脑2.2b、把终端环境配好2.3、把建工程 → 编译 → 烧录 → 看日志完整走通一次。2.1 工具链一条流水线上的五个角色把main.cpp变成芯片里跑的指令要经过一条流水线。每个工具只干一件事main.cpp ──► 预处理器 ──► 编译器 ──► 汇编器 ──► 链接器 ──► .elf ──► 打包 ──► .bin (人话) (贴头文件) (翻译成汇编) (变成机器码) (拼零件) (烧录格式)工具具体做什么报错特征预处理器 cpp把#include的内容原文贴入展开宏宏 用#define给一段文本起的别名展开时原文替换5.1 正式讲No such file: xxx.h编译器 gcc每个 .cpp → 汇编代码人读的芯片指令error: ...语法错汇编器 as汇编 → 机器指令.o 文件二进制少见链接器 ld把很多 .o 库拼成一个完整程序.elfundefined referenceCMake Ninja安排整个流程按顺序执行CMake Error/ninja: build stoppedesptool把 .bin 通过串口写进 FlashCould not open port排查第一原则先分辨报错来自哪一环再对症下药。【知识框】交叉编译cross compile注意上面这条流水线跑在你的 Windows 上产物却是给 ESP32-S3 执行的芯片指令——在 A 机器上生成只能在 B 类芯片上运行的程序就叫交叉编译。所以工具链里全部是xtensa-esp32-elf-开头的专用编译器“elf” 指产物格式它们和你电脑上装的标准 gcc 互不干涉、各干各的。2.2 ESP-IDF 是什么驱动 系统 构建ESP-IDFEspressif IoT Development Framework乐鑫物联网开发框架IoT Internet of Things物联网是一个大集合驱动driverGPIO、LEDCLED Controller硬件 PWM 发生器第 7 章细讲、UART 等硬件模块的封装函数——我们不用直接写寄存器第 0 章说过函数背后是寄存器操作FreeRTOS一个微型操作系统提供任务、延时、互斥锁等第 13 章系统讲解构建系统基于 CMake 的整套工程框架component 机制官方示例每个外设都有例程。版本很重要API 在不同版本可能不同比如第 7 章会提到ledc_fade_func_install这类函数的存在与用法本书基于ESP-IDF v6.0.1。遇到不懂的以C:\esp\v6.0.1\esp-idf里的头文件为准——源码就在你电脑上是最终权威。2.2b 安装 ESP-IDFWindows两条路推荐第一条前面 2.1/2.2 讲了装的是个什么东西这一节解决怎么把它装上电脑。两条路殊途同归最后都是C:\esp\v6.0.1\esp-idf源码C:\Espressif工具这套目录后面章节的命令都以它为准。⚠️ 先排一个雷你在网上搜到的教程凡是让你去 GitHub 下载espressif/esp-idf-installer那个.exe离线安装器的对 v6.0 已经失效——该仓库已下线本书写作时实测其 GitHub 页面返回 404也没有 v6.0.1 版本。v6.0 起官方 Windows 安装器换成了EIMEspressif Installation Manager乐鑫安装管理器见方式 A。方式 A推荐官方 EIM 安装器一路 Next推荐它的三个理由官方 v6.0 默认路线自动搞定工具链/Python/环境变量装完还给你做好开箱即用的终端快捷方式。下载到官方下载页https://dl.espressif.com/dl/eim/取 Windows 的 GUI 版文件名形如eim-gui-windows-x64.exe。有在线版装时才下载组件包小和离线版组件全打包在里面网不好就选它两种普通网络下在线版即可也可以用winget install Espressif.EIM一条命令装 EIM 本身。选择版本打开 eim在New Installation里点Start Installation选Custom Installation把版本钉为v6.0.1Easy Installation会装当时的最新版可能不是 v6.0.1——本书不用它。路径默认安装路径就是本书统一的C:\esp\v6.0.1\esp-idf工具在C:\Espressif一路下一步即可前提是你的用户名和路径不含中文和空格。等待完成看到Installation Complete页面即成功。EIM 会在桌面建一个形如IDF_v6.0.1_Powershell的快捷方式——双击它就是 2.3 要的“已配好环境的终端”。命令行党等价操作eim install -i v6.0.1成功时最后几行有Successfully installed IDF。方式 Bgit clone 官方脚本想搞清每一步、或不想装安装器的选这条【动手框】① 在哪执行普通 PowerShell 窗口Win 键搜powershell回车此刻环境还没配任何窗口都一样裸。⚠️ 别用 Git 自带的 Git Bash——ESP-IDF 脚本检测到它会直接报MSys/Mingw is not supported实测。前置要求电脑上已有Git和Python ≥ 3.10都要能在 PowerShell里直接用git --version/python --version查到。② 敲什么路径选没有中文、没有空格的如C:\espcd C:\esp git clone--branch v6.0.1--depth 1--recursive https://github.com/espressif/esp-idf.git cd.\esp-idf.\install.ps1 esp32s3三个参数各管一件事--branch v6.0.1只取这个发布标签--depth 1不下载历史提交能省一大半体积--recursive连子模块一起拉下来缺了它编译必报错。install.ps1 esp32s3会去下载 S3 专用工具链、CMake、Ninja、Python 小环境——只装你要的芯片型号省时间。若 PowerShell 拒绝跑脚本“禁止运行脚本”执行一次Set-ExecutionPolicy -Scope CurrentUser RemoteSigned输入 Y再重敲。③ 预期看到关键四行中间滚动的下载/安装信息忽略INFO: Using IDF_PATH C:\esp\v6.0.1\esp-idf for installation. Installing ESP-IDF tools Setting up Python environment All done! You can now run: export.ps1④ 没看到a) 报python不是内部命令 → 装 Python 并勾选“Add python.exe to PATH”重开窗口b)git clone卡住 → 网络到GitHub 不通改用方式 A 的离线安装器c) 脚本乱码/权限错误 →检查路径是否有中文空格、执行策略是否已改。装完之后呢方式 A 双击桌面快捷方式方式 B 手动跑export.ps1——不管哪种进入可用终端的完整流程见下一节 2.3 开头的【动手框】。2.3 环境变量与 PATH为什么需要export【动手框】打开一个能用的终端四步① 在哪执行方式 A 装的双击桌面IDF_v6.0.1_Powershell快捷方式或打开eim →Manage Installations→Open Dashboard→Open IDF Terminal跳到 ③方式 B 装的Win 键搜 PowerShell 回车然后——② 敲什么方式 Bcd C:\esp\v6.0.1\esp-idf.\export.ps1③ 预期看到方式 B 的窗口末尾出现下面两行省略号处滚过若干行python/工具检查信息无视即可Setting IDF_PATH to C:\esp\v6.0.1\esp-idf. ... Done! You can now compile ESP-IDF projects.方式 A 的窗口一打开就有这样一段不用你敲——快捷方式内部替你跑好了激活脚本省略号处还有若干行工具路径无视即可IDF PowerShell Environment ------------------------- Environment variables set: IDF_PATH: C:\esp\v6.0.1\esp-idf ... Python environment activated. You can now use IDF commands and Python tools.两种窗口里再敲一句验收idf.py --version回ESP-IDF v6.0.1就说明环境通了。本书后面所有 idf.py 命令都在这种窗口里敲——VS Code 用户用扩展自带的 ESP-IDF 终端2.4 讲窗口全程别关。④ 没看到a)idf.py不是内部命令 → export 那步没成功或换了普通PowerShell 窗口重做 ②b)expression after . produced invalid object→ 见本节末尾踩坑清单第 1 条c) 一打开就报MSys/Mingw is not supported→ 你在 Git Bash 里跑的换 PowerShell。PATH 是什么命令行输入idf.py时电脑会在PATH列出的目录里找idf.py程序。PATH 一张去哪找程序的目录清单。PATH C:\Windows\System32; C:\Espressif\tools\python\v6.0.1\venv\Scripts ↑ 系统默认找这里 ↑ export 加进来的工具目录不止这一个export 在做什么export.ps1/export.sh干两件事把 ESP-IDF 的所有工具目录加进 PATH让idf.py能找到设置环境变量IDF_PATH源码在哪、IDF_TOOLS_PATH工具在哪、IDF_PYTHON_ENV_PATHPython 小环境在哪。IDF_PATH C:\esp\v6.0.1\esp-idf 源码 IDF_TOOLS_PATH C:\Espressif 工具 IDF_PYTHON_ENV_PATH C:\Espressif\tools\python\v6.0.1\venv Python 专属环境每次新开命令行都要重新 export——因为新窗口没有继承上一个窗口的变量。⚠️ 本书踩过的环境坑export.ps1要求python在 PATH 中否则报expression after . produced invalid object。把C:\Espressif\tools\python\v6.0.1\venv\Scripts加进 PATH 再执行。espidf.constraints.v6.0.txt找不到时把C:\Espressif\tools\内的该文件复制到C:\Espressif\根目录。用 VS Code 的 ESP-IDF 扩展就不用手动 export——扩展替你设好了这是推荐扩展的根本原因。2.4 VS Code 扩展图形界面的一键三连安装三步① 点 VS Code 左侧竖排的扩展图标四个小方块快捷键CtrlShiftX② 搜索框输入ESP-IDF③ 认准发布者为Espressif Systems的官方扩展标识符espressif.esp-idf-extension别装成第三方仿名的点Install。装好后在设置Ctrl,搜idf或打开 settings.json里填idf.espIdfPath:C:\\esp\\v6.0.1\\esp-idf,idf.toolsPath:C:\\Espressif,idf.pythonBinPath:C:\\Espressif\\tools\\python\\v6.0.1\\venv\\Scripts\\python.exe,idf.portWin:COM3路径以你 2.2b 实际装的位置为准。扩展会在底部状态栏提供按钮编译、烧录、监视器。它内部做的事情和命令行完全一样只是帮你把 export 和参数都准备好了。想在 VS Code 里敲命令就别开普通终端——按CtrlShiftP打开命令面板输入ESP-IDF: Open ESP-IDF Terminal得到的才是环境配好的终端相当于 2.3 那个【动手框】的图形版。2.5 串口从电脑到芯片的两条路芯片的日志要从 USB 口到达电脑硬件上有两条路。本书指定的ESP32-S3-DevKitC-1 板子上两条都有两个 USB 座先认清楚再插。路 A芯片自带的 USBUSB-Serial-JTAG本书主用ESP32-S3 芯片内部就有 USB 控制器占用GPIO19/20不需要任何转接芯片电脑 USB ──► 芯片自己的 USB 外设USB-Serial-JTAGGPIO19/20插到板上标注USB的那个口。设备管理器里会出现“USB-JTAG/Serial debug unit”Windows 10/11 一般免驱COM 号就挂在它下面。原生 USB 的两个小脾气知道即可不影响正常使用①芯片复位/崩溃瞬间 USB 会短暂断开COM 口闪没一下很正常②进下载模式靠芯片内部的 USB-JTAG/Serial 完成而不是传统串口的RTS/DTR 拉线——idf.py flash照常工作只是别被中途掉线吓到。路 BUSB 转串口芯片CP2102 / CH340 等板子上另有一颗转接芯片把 USB 协议翻译成 UART 协议再接到芯片的 UART0TX/RX引脚电脑 USB ──► USB转串口芯片 ──► 芯片的 UART0 引脚TX/RX插板上标注COM/UART的那个口。电脑要认识这颗芯片需要装驱动芯片驱动名CP210xSilicon LabsCP210x Universal Windows DriverCH340 / CH343CH341SERCOM 口 电脑给这个串口设备起的门牌号。本书后续命令统一写COM3以你设备上实际显示的号码为准。怎么判断自己走的是哪条路设备管理器端口COM 和 LPT里新出现的条目名字带USB-JTAG/Serial debug unit→ 路 A名字带CP210x / CH340 / USB-SERIAL→ 路 B或者拔插一次 USB、换板上另一个座看 COM 号跟着哪个座变化。看不到 COM 口按顺序检查①线是不是只能充电无数据线芯②换个 USB 口③路 B 才需要驱动——设备管理器有未知设备就是驱动没装路 A 则先在 Windows 更新里装 USB 驱动。2.6 烧录的底层机制esptool 在做什么烧录不是把文件拖进去而是一段协议交互esptool 打开 COM 口用低波特率和芯片出厂自带的ROM 引导程序打招呼控制芯片的BOOT/EN 引脚路 B 通过串口的 RTS/DTR 线路 A 的原生 USB 则由芯片内部 USB-JTAG/Serial 代发效果一样让芯片进入下载模式所以有些板子要按 BOOT 键协商波特率把构建产出的三个 .bin分别写入 Flash 上各自的地址每个文件切成 1024 字节的编程块esptool 对 S3 的默认块大小逐块传输并带校验和读回校验Hash of data verified复位芯片Hard resetting via RTS pin...芯片开始运行新固件。三个 .bin、各写各的地址来自本书工程真实的build/flash_args烧录文件地址内容bootloader.bin0x0S3 如此老 ESP32 是 0x1000二级引导0.8 章启动链的第②步partition-table.bin0x8000分区表户型图第 3 章l298n.bin0x10000我们的应用程序所以idf.py flash一次烧的是三件套0x10000 起只是 app 的地址。这一整套是有线烧录。不插线、通过网络升级固件叫OTA分区要求和升级流程见第 18 章。常见失败与原因底层角度报错底层原因解决Could not open port/PermissionError(13)端口被别的程序占用监视器没关关闭占用程序再烧Failed to connect芯片没进下载模式 / 线不通按 BOOT 键换数据线烧到一半失败供电不足/线质量差换线、插主板 USB 口Failed to connect时手动把芯片按进下载模式三步板子上两个键按住 BOOT 不放 ──► 点按一下 EN复位键松开即弹起──► 松开 BOOT此刻芯片停在 ROM 下载模式里等着idf.py flash就能连上烧完再点一下 EN退出下载模式、开始跑新固件。2.7 监视器把芯片的话显示出来idf.py -p COM3 monitor做的事打开同一个 COM 口按约定波特率115200持续接收 UART 帧第 0 章讲过帧格式把收到的字节还原成文字显示在屏幕上也可以反向你敲键盘 → 发回芯片。监视器占用 COM 口——烧录前必须先关掉它否则端口被占用这就是PermissionError(13)的常见来源本书真踩过。2.8 完整走一遍建工程 → 编译 → 烧录 → 看日志第 1 步建工程idf.py create-project blinkcdblinkcreate-project生成的是一个空骨架入口文件的名字跟着工程名走blink 工程生成的就是main/blink.cv6.0.1 实测里面的app_main()函数体是空的——一行代码都没有开机什么也不打。官方的 blink 例程在 ESP-IDF 目录的examples/get-started/blink里面有blink_example_main.c和新建工程是两回事。点灯 嵌入式Hello World——别急第 4 章我们自己从零写点灯每一行都讲透比抄例程更踏实。第 2 步编译idf.py build首次编译要扫描依赖 全量编译5~15 分钟都正常机械硬盘更久满屏滚动的编译输出不是报错是它在一件件干活。成功标志blink 工程的示例输出Project build complete.屏幕后面还会跟着几行To flash, run…的命令提示以及一行体积报告。本书环境实测 blink 空骨架的那行长这样blink.bin binary size 0x280b0 bytes. Smallest app partition is 0x100000 bytes. 0xd7f50 bytes (84%) free.注意一个反直觉的事实空骨架的 bin 就有 16 万字节——因为固件的大头是 IDF 系统本身启动代码、驱动、FreeRTOS你的应用只占零头。作为对照本书后面的l298n 工程的完整报告行长这样真实值每个数字的含义第 5 章拆l298n.bin binary size 0x2a150 bytes. Smallest app partition is 0x100000 bytes. 0xd5eb0 bytes (84%) free.一个能跑的空骨架和一个功能完整的电机工程体积只差约 5%——第 5 章会把这笔账算给你看。第 3 步烧录idf.py-pCOM3 flashflash会自动先 build。成功标志Hash of data verifiedDone。第 4 步看日志idf.py-pCOM3 monitor按Ctrl]退出监视器之后才能再次烧录。一上电或点一下 EN 键你会滚出几十行开机日志骨架和 2.9 节完全一样最后落到这一行毫秒数以你屏幕为准I (749) main_task: Calling app_main()然后就安静了——这是正常的空骨架的app_main()里一行代码都没有当然一个字也不打印。成功的宣告是看到Calling app_main()就等于编译器→链接器→esptool 烧录→bootloader→FreeRTOS→你的函数整条链从头到尾全部打通。从第 4 章起这行之后就该有你自己的输出了。2.9 开机日志逐行解读从底层看每一行从上电到app_main屏幕会滚出几十行日志但骨架就是第 0 章的4 步启动链。下面按 4 步各挑出代表性的一批行引的都是本书板子的真实输出括号里的毫秒数你机器上会略有不同中间其余的技术行先无视第 11 章后你能一眼看懂它们① ROM 引导出厂程序不可改写 ESP-ROM:esp32s3-20210327 ← 出厂 ROM 引导的版本 rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT) ← 复位原因上电启动模式从 Flash 快速启动 mode:DIO, clock div:1 ← Flash 通信模式 DIO时钟不分频 ② 二级引导刚才是谁把它烧在 0x0还记得吗——就是 2.6 的三件套 I (24) boot: ESP-IDF v6.0.1 2nd stage bootloader ← 二级引导开始跑 I (31) boot.esp32s3: Boot SPI Speed : 80MHz ← Flash 总线 80MHz I (35) boot.esp32s3: SPI Flash Size : 16MB ← 认出 16MB Flash ③ 初始化外设与内存 I (147) octal_psram: Found 8MB PSRAM device ← 认出 8MB PSRAM第 10 章 I (628) cpu_start: cpu freq: 160000000 Hz ← CPU 主频 160MHz ④ 进入我们的程序 I (719) main_task: Started on CPU0 ← 系统主任务启动FreeRTOS 的第一个任务第 13 章 I (749) main_task: Calling app_main() ← 调用你的 app_mainI (749)等级信息开机后第 749 毫秒Calling app_main() 固件已在运行。后面再有错误是程序 bug不是烧录问题第 0 章重点务必记牢。2.10 工程目录速览第 3 章细讲blink/ ├── CMakeLists.txt # 工程说明名字、依赖 ├── sdkconfig # 实际配置自动生成别手改 ├── sdkconfig.defaults # 你的默认配置 ├── main/ │ ├── CMakeLists.txt # 组件说明编哪些文件 │ └── blink.c # 代码create-project 用工程名命名入口文件 │ # 内容是空 app_main本书工程统一用 .cpp └── build/ # 编译产物可整体删除重建2.11 常见问题速查环境层现象底层原因解决压根还没装 ESP-IDF—按 2.2b 走一条路idf.py找不到PATH 没 export按 2.2b/2.3 激活环境 / 用扩展终端2.4编译报头文件缺失REQUIRES 没声明依赖检查组件依赖编译报未定义引用.cpp 没进 SRCS检查 CMakeLists烧录端口找不到驱动/线/端口占用按 2.6 表排查日志乱码波特率不一致统一 1152002.12 想一想 小测验想一想为什么每次新开命令行都要 export 一次监视器开着时为什么不能烧录Calling app_main()说明烧录成功了吗能说明程序没问题吗小测验工具链里负责把 .cpp 翻译成机器指令的是____。PATH 环境变量的作用是什么烧录时报PermissionError(13)最可能的原因是什么监视器默认波特率是多少2.13 本章总结工具链是一条流水线预处理 → 编译 → 汇编 → 链接 → 打包安装 ESP-IDF2.2b推荐 EIM 官方安装器v6.0 起 Windows 默认路线备选 git clone install.ps1殊途同归于 C:\esp\v6.0.1\esp-idfPATH/export 告诉电脑工具在哪原生 USBUSB-JTAG/Serial debug unit或 USB 转串口芯片 驱动 电脑认识板子烧录 esptool 与 ROM 引导程序对话把三件套bootloader 0x0、分区表 0x8000、app 0x10000写入 Flash 并校验监视器 按波特率收 UART 帧显示占用端口所以烧录前要关。环境跑通后下一章我们解剖工程文件看看构建系统怎么知道要编什么。