编译烧录与预编译固件 - hongligongsi/Consumables-storage-temperature-and-humidity GitHub Wiki
编译烧录与预编译固件
环境要求
- PlatformIO(CLI 或 VSCode 插件)
- 平台锁版本
[email protected]
为什么锁版本:
platformio.ini里写的是[email protected]而不是^6.7.0。 项目热控 PWM 仍使用ledcSetup()/ledcAttachPin()旧 API,而 Arduino core 3.x 已移除这套接口。^6.7.0会解析到 6.13.0(core 3.x)导致编译失败。升级平台前 必须先迁移 ledc 调用。
常用命令
pio run # 仅编译
pio run -t upload # 编译并烧录
pio device monitor -b 115200
仓库另带一组自检工具(详见 docs/development.md):
python tools/run_host_tests.py # 主机端单元测试(纯逻辑层)
python tools/doc_check.py # 文档一致性 + 字库覆盖 + 固件台账校验
烧录预编译固件
仓库中的 firmware/firmware.bin 是某一次构建的快照,不是「永远等于当前源码」。
它对应哪个源码提交、体积与 SHA-256 是多少,以同目录的 BUILD.txt 为准
(python tools/publish_firmware.py --check 可直接打印并核对)。要得到与本地源码
严格对应的镜像,先 pio run 再 python tools/publish_firmware.py,不要手工复制。
下面把 COM3 换成实际串口。
参数说明
| 片段 | 含义 |
|---|---|
pio pkg exec -p tool-esptoolpy -- |
借用 PlatformIO 内置的 esptool(实测 v4.11.0)。esptool.py 不在系统 PATH 中,直接调用会报「无法识别」,故经此转发;-- 之后才是传给 esptool 的参数 |
--chip esp32s3 |
目标芯片型号,必须与实物一致 |
--port COM3 |
串口设备名。Windows 形如 COM3,Linux/macOS 形如 /dev/ttyUSB0、/dev/cu.usbserial-* |
--baud 921600 |
写入波特率,仅影响刷写速度;write_flash 之外的命令不必带 |
write_flash |
子命令,其后参数两两成组:先是偏移,再是文件 |
只更新应用
板上已有可用的 bootloader 与分区表,例如日常升级:
pio pkg exec -p tool-esptoolpy -- esptool.py --chip esp32s3 --port COM3 write_flash 0x10000 firmware/firmware.bin
从空片全新烧录
需要完整四件套,其中 bootloader.bin 与 partitions.bin 由 pio run 生成于
.pio/build/esp32-s3-n16r8/:
pio pkg exec -p tool-esptoolpy -- esptool.py --chip esp32s3 --port COM3 --baud 921600 write_flash `
0x0 .pio/build/esp32-s3-n16r8/bootloader.bin `
0x8000 .pio/build/esp32-s3-n16r8/partitions.bin `
0xe000 "$env:USERPROFILE\.platformio\packages\framework-arduinoespressif32\tools\partitions\boot_app0.bin" `
0x10000 firmware/firmware.bin
命令块中不能写
#行内注释:PowerShell 的多行续行符`必须是行尾最后一个 字符,注释会截断续行导致命令被拆成多条。
生成合并镜像(对外分发)
对外发布/量产时,若想让对方「只烧一次」,可用 esptool.py merge_bin 把引导器、分区表
与应用拼成一个 merged.bin(约 1.2 MB),发送单个文件即可完成全新烧录:
pio pkg exec -p tool-esptoolpy -- esptool.py `
--chip esp32s3 merge_bin `
--flash_mode qio --flash_freq 80m --flash_size 16MB `
--target-offset 0x0 `
-o firmware/firmware-merged.bin `
0x0 .pio/build/esp32-s3-n16r8/bootloader.bin `
0x8000 .pio/build/esp32-s3-n16r8/partitions.bin `
0xe000 "$env:USERPROFILE\.platformio\packages\framework-arduinoespressif32\tools\partitions\boot_app0.bin" `
0x10000 firmware/firmware.bin
合并镜像的烧录只有一个偏移 0x0:
pio pkg exec -p tool-esptoolpy -- esptool.py --chip esp32s3 --port COM3 --baud 921600 write_flash 0x0 firmware/firmware-merged.bin
两种分发形态:日常 OTA 升级只需单个
firmware.bin(网页/ArduinoOTA 在线写应用 槽);而「拆分 3 个文件(bootloader/partitions/app)」或「合并 1 个 merged.bin」都用 于空片或量产,烧录路径等价。合并镜像最大的好处是boot_app0.bin也一并打进, 不依赖框架路径。
擦除
烧录失败或分区表错乱时,先整片擦除再重烧:
pio pkg exec -p tool-esptoolpy -- esptool.py --chip esp32s3 --port COM3 erase_flash
分区表偏移含义
取自 board_build.partitions 指定的 default_16MB.csv:
| 偏移 | 写入的文件 | 用途 |
|---|---|---|
0x0 |
bootloader.bin |
二级引导,上电后最先执行 |
0x8000 |
partitions.bin |
分区表,描述各分区的起止地址 |
0xe000 |
boot_app0.bin |
otadata 槽,记录 OTA 应从哪个 app 槽启动 |
0x10000 |
firmware.bin |
应用镜像,写入 app0 |
分区表中 otadata 的尺寸为 0x2000,与 boot_app0.bin 的 8192 字节一致。
该分区表含 app0/app1 双槽,是 ArduinoOTA 能工作的前提;缺少 otadata
会让设备在 OTA 后无法引导。
firmware.bin是纯应用镜像,只能写入0x10000。烧到0x0会覆盖 bootloader, 设备将无法启动。
boot_app0.bin 的路径
boot_app0.bin 不由本工程生成,来自 Arduino 框架包。本机可能同时存在
framework-arduinoespressif32、[email protected]、[email protected]+sha.dcc1105b
等多个目录,上面的命令用的是无版本后缀那个。若该路径不存在,用下式取其实际位置后替换:
Get-ChildItem "$env:USERPROFILE\.platformio\packages\framework-arduinoespressif32*" -Recurse -Filter boot_app0.bin | Select-Object -First 1 -ExpandProperty FullName
烧录后确认
首次上电若设备进入 FilamentChamber-Setup 配置热点,说明烧录成功。连上该热点
配网后,可由 ArduinoOTA 继续无线升级(OTA 主机名 chamber,每台设备的独立
密码可在 http://chamber.local/ 查看,详见 联网功能)。
注意 COM4(UART0)上看不到应用日志:-DARDUINO_USB_CDC_ON_BOOT=1 让
Serial 走板载 USB-CDC 口,COM4 只剩 ESP-ROM/IDF 日志。要抓 chamber= 周期上报、
AHT20 检测等应用日志,请用板载 USB 口那一路串口。
串口写入中途中断(PermissionError 13)
典型现象 —— 镜像写到九成左右突然断掉:
Writing at 0x0013354a... (93 %)
A serial exception error occurred: Cannot configure port, something went wrong.
Original message: PermissionError(13, '拒绝访问。', None, 5)
这不是 esptool 或固件的问题,是 Windows 串口句柄在传输途中失效了。
write_flash 每写一段都要重新配置串口,一旦句柄被夺走或设备从总线掉下来,
SetCommState 就返回拒绝访问。注意此时 app0 已被写入大半、内容不完整,
设备上电校验不过会回滚到 app1;若 app1 为空则反复重启,必须重新烧录一次。
按下面顺序排查,多数情况第 1、2 条就能解决:
- 关掉所有占用串口的程序:
pio device monitor、VSCode 串口监视器、串口助手、 PuTTY,以及上一次残留的 esptool。不确定就拔插一次 USB 后立刻烧录。 - 降低写入波特率。
platformio.ini已设upload_speed = 460800;用原始 esptool 命令时把--baud 921600改成--baud 460800。仍失败就改115200复测 —— 若 115200 能一次写完,说明瓶颈在 USB 链路而不是驱动。 - 换线、换口、去掉集线器:用短一点的数据线直插主机后置 USB 口,避开 USB hub
和延长线。ESP32-S3-DevKitC-1 有两个 USB-C 口,优先用标着
UART的那个 (板载 CP2102/CH340 桥),比标着USB的原生 USB-CDC 口稳定得多。 先用pio device list看清端口对应的芯片型号再动手。 - 关掉 Windows 的 USB 节能:设备管理器 → 端口 → 对应 COM 口 → 属性 → 电源管理 → 取消勾选「允许计算机关闭此设备以节约电源」;电源选项 → 高级设置 → USB 设置 → USB 选择性暂停 → 已禁用。该项会在长时间传输中途挂起设备,正是 「写到一半拒绝访问」的常见成因。
- 手动进下载模式:按住
BOOT→ 点一下RST→ 松开BOOT,让芯片稳定停在 下载模式,再执行烧录,避开自动复位的时序竞争。必要时给 esptool 加--before no_reset。 - 暂时停掉杀毒/安全软件,或把 esptool 进程与串口加入白名单。
- 以上都无效时,先
erase_flash整片擦除再重烧;或改用无线 OTA 绕过 USB: 设备若能正常启动,打开http://chamber.local/直接上传firmware.bin。
判断设备是掉线还是被占用
- 烧录中 COM 号跳变(如 COM5 → COM7),或设备管理器里端口闪一下消失再出现 → 是 USB 掉线/重枚举,走第 3、4 条。
- COM 号不变、只是报拒绝访问 → 多半是别的进程占着,走第 1 条。