ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

esptool Flasher Stub 完全指南:原理、加速收益、版本回退与 `--no-stub` 禁用实战

esptool Flasher Stub 完全指南:原理、加速收益、版本回退与 `--no-stub` 禁用实战 开发工具嵌入式硬件开发【免费下载链接】esptoolSerial utility for flashing, provisioning, and interacting with Espressif SoCs项目地址https://gitcode.com/gh_mirrors/es/esptool点击查看免费下载esptool 通过向芯片 RAM 上传一个名为 Flasher Stub临时固件扩展的小程序来替代出厂固化、无法更新的 ROM 引导程序从而获得更快的 UART 传输、更丰富的 Flash 操作能力以及对 ROM 缺陷的规避。本文以官方文档 docs/en/esptool/flasher-stub.rst 为骨架结合 esptool 仓库源码esptool/loader.py、esptool/cmds.py、esptool/__init__.py与随发行版打包的 stub JSON 二进制完整讲解 Stub 的加载流程、新旧两代 Stub 的差异、底层 JSON 格式以及如何通过--no-stub关闭 Stub 并处理由此带来的功能限制帮助你准确判断开还是不开 Stub。Flasher Stub 是什么为什么需要一个临时引导程序esptool 是一款串口烧录工具它通过串口与 Espressif SoC 内部的 ROM 引导程序通信以加载用户应用程序或读取芯片数据。问题的关键在于ROM 引导程序是在芯片出厂时烧录的无法更新——只有发布新芯片修订版时才会随之更新。这意味着 esptool 无法指望 ROM 引导程序自我进化。为了绕开固定 ROM 引导程序带来的限制esptool 实现了 Flasher Stub也称作 stub loader 或简称 stub——一个体积很小、临时替代或扩展 ROM 引导程序的应用。它的工作方式是当 esptool 与芯片建立连接后先把 Stub 上传到芯片的 RAM 并执行Stub 实际上接管了原引导程序的职责此后所有烧录、读取、擦除等操作都由 Stub 完成而不是直接与 ROM 引导程序交互。用一句通俗的话概括Stub 是运行在芯片 RAM 里的临时代理原 ROM 引导程序只负责把它请进门。一次典型连接中 Stub 的完整加载流程从源码 esptool/loader.py 的run_stub()方法可以看出Stub 的启动分为清晰的几个阶段配合官方文档 docs/en/esptool/flashing-firmware.rst 中展示的典型终端输出Uploading stub flasher.../Running stub flasher...可以还原出完整调用链握手与复位esptool 通过 DTR/RTS 串口控制线或 USB-JTAG 复位序列将芯片复位进入下载模式并与 ROM 引导程序完成串口同步。检测是否已在运行run_stub()会检查self.sync_stub_detected——如果芯片当前已经运行着 Stub例如上一次操作使用了--after no-reset-stub就直接复用现有 Stub打印Stub flasher is already running. No upload is necessary.并跳过上传。分段上传Stub 二进制被拆成text代码段与data数据段两个 segment通过 ROM 引导程序提供的mem_begin/mem_block命令写入 RAM见_upload_segment()esptool/loader.py。如果启用了插件如nand插件代码段也会一并上传。跳转执行通过mem_finish(stub.entry)让 CPU 跳转到 Stub 的入口地址Stub 开始在芯片侧运行。握手确认esptool 等待 Stub 发来OHAI问候字节。若超时无响应会抛出Failed to start stub flasher. There was no response.若返回内容不是OHAI则报Unexpected response。这一握手是判断 Stub 是否真正启动成功的关键依据。返回 Stub 子类对象上传成功后run_stub()返回对应芯片的 Stub 子类如ESP32Stub、ESP8266Stub后续命令全部经由 Stub 的扩展命令集执行。值得注意的一个特殊分支ESP32-S3 在开启 Secure Boot 时存在 ROM 缺陷直接mem_finish启动 Stub 会失败。源码中的解决方式是劫持 ROM 中spiflash_legacy_funcs.read函数指针把它改写为 Stub 入口地址再触发一次READ_FLASH_SLOW命令让 ROM 跳转到 Stub最后恢复原函数指针esptool/loader.py。这也印证了文档所说的Stub 还能绕开 ROM 引导程序中的各种缺陷。整个上传与启动流程在 esptool 的 CLI 主流程中由 esptool/cmds.py 的run_stub()函数驱动它会在连接芯片之后、执行具体命令之前被调用esptool/init.py。在 docs/en/esptool/scripting.rst 的 Python 脚本接口中这一步对应from esptool.cmds import run_stub之后调用esp run_stub(esp)跳过该行则代表不使用 Stub。Stub 带来的收益文档明确指出 Stub 的核心价值更快的 Flash 操作Stub 行为与 ROM 引导程序一致但内部使用了经过高度优化的 UART 例程烧录flashing与部分其他操作如读取 Flash的性能明显提升。这也是为什么 esptool 默认数据压缩开启--compress为默认除非指定了--no-stub见 esptool/init.py——高波特率 压缩 优化例程的组合让大镜像烧录时间大幅缩短。绕开 ROM 缺陷由于 ROM 引导程序无法更新任何已知的 ROM 级 bug如上述 ESP32-S3 的 Secure Boot 启动问题都可以通过 Stub 在软件层面规避或修补而不需要更换芯片。从代码结构上看Stub 的能力边界比 ROM 引导程序更宽run_stub()返回的 Stub 子类对象会暴露额外的命令处理入口插件机制Plugin也依赖 Stub 运行——如果关闭 Stub插件命令会直接报错Plugin commands require the stub flasher见 esptool/init.py。两代 Stub默认新版与旧版 Legacy Stubesptool 仓库在 esptool/targets/stub_flasher/ 下维护着两个版本的 Stub 二进制目录这正是文档中falling back to the legacy stub回退到旧版 Stub的具体实现目录2/默认新版包含 esp32、esp32c2/c3/c5/c6/c61、esp32h2/h4、esp32p4、esp32s2/s3/s31、esp8266 等全系列芯片的 JSON 文件。根据 esptool/targets/stub_flasher/2/README.md这些二进制以Apache License 2.0 或 MIT 双许可发布对应esp-flasher-stub项目的 v1.1.0 版本。目录1/旧版 Legacy根据 esptool/targets/stub_flasher/1/README.md对应esptool-legacy-flasher-stub项目的 v1.11.1以GPL v2 或更高版本发布。部分芯片如 esp32c61、esp32h4、esp32s31 等较新型号只有新版 Stub目录1/中没有对应文件。源码 esptool/loader.py 中STUB_SUBDIRS [2, 1]定义了搜索顺序优先使用新版目录 2找不到时才回退到旧版目录 1并在回退时打印提示Using the deprecated legacy stub flasher. Support for this stub will be removed in a future release.——这正是文档所警告的legacy 支持将在未来版本中移除。如何指定 Stub 版本esptool 提供了一个隐藏参数--stub-version取值1或2可通过环境变量ESPTOOL_STUB_VERSION或命令行传入esptool/init.py# 强制使用旧版 Legacy Stub ESPTOOL_STUB_VERSION1 esptool flash-id # 或直接传参该选项为隐藏选项功能面向开发者与问题排查 esptool --stub-version 1 flash-id该选项被标记为非公开选项不受语义化版本策略约束not a public option and is not subject to the semantic versioning policy说明它是为开发与排查设计的后门。另外当启用插件plugins时esptool 会优先把 Stub 目录切到2/因为只有新版 Stub 支持插件机制esptool/init.py。如果某个芯片在指定版本目录下找不到 Stub JSONesptool 会按顺序回退若全部缺失则报错Flasher stub data is missing for chip并提示这通常意味着 esptool 安装不完整或第三方发行包未附带 stub 文件请重新安装或从上游源码树恢复 stub 文件esptool/loader.py。Stub JSON 二进制格式详解预编译的 Stub 并非以裸 .bin 分发而是以 JSON 形式打包在仓库的 esptool/targets/stub_flasher/2/ 与 esptool/targets/stub_flasher/1/ 目录中。以esp32.json为例其核心字段如下esptool/targets/stub_flasher/2/esp32.jsonJSON 字段含义在源码中的用途entryStub 入口地址如1074434360即 0x400FFA38传给mem_finish(stub.entry)跳转执行textBase64 编码的代码段二进制base64.b64decode后经_upload_segment上传text_start代码段加载地址如1074429952指定mem_begin的目标 RAM 地址dataBase64 编码的数据段二进制解码为bytearray后上传可变插件在此原地打补丁data_start数据段加载地址同上bss_startBSS 段起始地址记录未初始化内存区域的起点源码 esptool/loader.py 中StubFlasher.__init__通过target.STUB_CLASS.stub_json_name(target)定位对应芯片的 JSON 文件解码出text/data后按text_start/data_start上传。注意data被特意解码为可变bytearray而不是不可变bytes——因为插件机制需要原地修改数据段_apply_plugins()会读取plugin_table_offset插件函数指针表偏移将每个插件的处理器地址通过struct.pack_into(I, ...)写入函数指针表对应槽位esptool/loader.py。禁用 Stub--no-stub的适用场景与副作用某些场景下需要关闭 Stub例如调试 ROM 引导程序自身行为。此时在 esptool 命令前加--no-stub参数所有操作将完全交给原始 ROM 引导程序处理。该选项在 esptool/init.py 中定义帮助信息为Disable launching the flasher stub, only talk to ROM bootloader. Some features will not be available.什么时候需要--no-stub结合官方文档 docs/en/esptool/advanced-options.rst 与 docs/en/esptool/advanced-commands.rst典型场景包括调试 ROM 引导程序行为希望绕过 Stub 的优化例程SDC 安全数字卡相关命令如verify-sdc-certificate、read-sdc-chip-info加锁的 SDC 设备只接受 ROM 引导程序命令会拒绝 Stub 上传。esptool 会主动拦截并提示must be run with --no-stubesptool/init.pyload-ram加载程序与软件加载器在 RAM 中冲突因为 Stub 本身驻留 IRAM/DRAM若目标程序区域与 Stub 重叠会报错加--no-stub可规避旧版 esptool 甚至可能挂起Secure Download Mode安全下载模式此模式下 esptool 自动禁用 Stub 并打印警告Stub flasher is not supported in Secure Download Mode加--no-stub可抑制该警告esptool/cmds.pyESP32-C3 开启 Secure Boot时 Stub 不可用同样自动禁用并提示esptool/cmds.py个别芯片尚未支持源码显示 ESP32-H21、ESP32-E22 目前仍不支持 StubStub flasher is not yet supported on ...见 esptool/cmds.py。--no-stub带来的功能限制文档明确警告--no-stub会禁用部分选项因为并非所有功能都在每款芯片的 ROM 引导程序中实现。结合源码可以列出以下具体影响数据压缩默认关闭--compress帮助信息写明Compress data during transfer (default unless --no-stub is specified)对应--no-compress是Disable data compression during transfer (default if --no-stub is specified)esptool/init.py。也就是说关闭 Stub 后默认走不压缩传输速率明显下降。插件命令不可用启用插件时若同时加--no-stub直接报FatalErroresptool/init.py。SPI 连接配置回退正常情况下 esptool 使用 eFuse 中记录的 SPI Flash 引脚但在--no-stub下eFuse 值被忽略--spi-connection默认回退为SPI见 docs/en/esptool/advanced-options.rst。read-flash需要显式指定--flash-size在 ROM 引导程序即启用--no-stub下读取 Flash 内容时可能必须加--flash-size才能正确读取见 docs/en/esptool/basic-commands.rst。波特率变更可能失败某些 ROM 不支持change_baudesptool 会打印警告并保持在初始波特率esptool/init.py。与--no-stub配合的常用选项--before no-reset-no-sync当芯片已经在运行 Stub 时跳过 DTR/RTS 控制与串口同步避免再次复位并重复上传 Stubdocs/en/esptool/advanced-options.rst。--after no-reset-stub操作完成后不做复位让芯片停留在 Stub 引导程序中方便后续命令复用 Stubdocs/en/esptool/advanced-options.rst。两者组合即形成一次上传、多次操作的工作流第一次用默认参数跑完之后用--before no-reset-no-sync --after no-reset-stub继续在 Stub 环境下操作。常见问题排查与问题上报指南自动禁用场景的警告解读从 esptool/cmds.py 的run_stub()分支可以看出esptool 在以下情况会自动静默禁用 Stub 并打印警告而不是报错Secure Download Mode、ESP32-C3 Secure Boot、ESP32-H21/ESP32-E22 尚未支持、以及为兼容性而禁用。这些警告都建议Set --no-stub to suppress this warning——如果你确定要强制走 ROM 路径加--no-stub即可消除警告噪音。Stub 启动失败若 Stub 上传后没有收到OHAI握手响应esptool 会报Failed to start stub flasher. There was no response.esptool/loader.py。源码注释提示这是 Stub 开发中的常见现象。另外在 macOS 上若使用 CH9102 USB 转串口桥PID 0x55D4esptool 会额外提示安装 WCH 官方驱动esptool/cmds.py。问题应报给哪个项目官方文档给出了清晰的分工这也是开源协作中常见的双项目边界模型Stub 自身行为——包括芯片支持、Stub 内的 Flash 读/写/擦除、Stub 崩溃或结果错误应上报给esp-flasher-stub项目的 issue 跟踪器因为问题出在 Stub 固件侧。esptool 集成层——包括 Stub 的上传与启动、CLI 选项、esptool 与 Stub 的交互应上报给 esptool 项目的 issue 跟踪器。新旧 Stub 行为差异——如果问题只出现在默认的新版 Stub而回退到旧版 Legacy Stub 后消失则应上报给esp-flasher-stub项目以便在新版 Stub 上修复后再移除 legacy 支持这正是先修新版再退役旧版的过渡策略。源码与开发脉络Stub 固件本身在独立的esp-flasher-stub项目中开发esptool 发行版随包附带预编译的 Stub 二进制即上文所述 JSON 文件构建方法、源码与发布说明都在该独立仓库中。esptool 侧的集成代码则集中在esptool/loader.pyStubFlasher类——Stub JSON 的定位、解码、插件应用与 legacy 回退逻辑esptool/loader.pyrun_stub()方法——分段上传、OHAI握手与 ESP32-S3 Secure Boot 特殊启动路径esptool/cmds.pyCLI 层的run_stub()入口——自动禁用条件与平台相关提示esptool/init.py--no-stub与--stub-version选项定义esptool/targets/stub_flasher/两代 Stub 的 JSON 二进制与各自的 LICENSE 说明1/README.md、2/README.md。总结Flasher Stub 是 esptool 性能与功能的核心支柱它以 RAM 中的临时程序替换固定 ROM 引导程序换取更快的 UART 烧录、更丰富的 Flash 操作与对 ROM 缺陷的软件级绕行。理解 Stub 的加载流程、两代 Stub 的目录回退机制、JSON 二进制格式以及--no-stub触发的各项功能降级能让你在调试、SDC 场景、Secure Boot 设备与高性能烧录之间做出正确取舍。当遇到 Stub 相关故障时按Stub 行为报 esp-flasher-stub、集成问题报 esptool、新旧差异优先修新版的原则上报可以最大化开源协作的效率。赞分享开发工具嵌入式硬件开发【免费下载链接】esptoolSerial utility for flashing, provisioning, and interacting with Espressif SoCs项目地址https://gitcode.com/gh_mirrors/es/esptool点击查看免费下载相关推荐sinon stub.yields() 完全指南让 Stub 自动调用第一个回调参数的原理与实战sinon stub.yields 完全指南让 Stub 自动调用第一个回调参数的原理与实战 导读 stub.yields 是 Sinon.JS 中用于模拟测试开发工具Sinon stub.rejects() 完全指南让 Stub 返回拒绝rejectedPromise 的四种姿势与底层原理Sinon stub.rejects 完全指南让 Stub 返回拒绝rejectedPromise 的四种姿势与底层原理 stub.rejects 是 S测试开发工具Sinon sandbox.restore() 完全指南一键还原全部 fake、spy 与 stubSinon sandbox.restore 完全指南一键还原全部 fake、spy 与 stub sandbox.restore 是 Sinon 测试隔离体系测试开发工具上一篇5分钟掌握Dolphin让复杂PDF文档一键变Markdown下一篇终极指南GetX国际化如何让日期、时间和数字自动适配全球用户创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表