espflash --- ESP32 ROM 引导加载程序固件烧录工具

本模块提供了一个最小化的 ESPFlash 实现,通过 UART 与 ESP32 ROM 引导加载程序通信。它适用于对协处理模块(例如 Arduino 板上使用的 U-blox NINA-W10 模块)上的 ESP32 固件进行系统内更新,并不能替代完整的 esptool 工具。高级功能(stub 加载器、其他 ESP 芯片、deflate、安全启动等)有意不予支持。

该驱动通过切换 RESETGPIO0 使 ESP32 进入下载模式,然后发出 SLIP 封帧命令以读取闪存大小、配置 SPI 接口、写入固件镜像并通过 MD5 摘要进行校验。

适用于 Arduino Nano RP2040 Connect 的示例(这是目前唯一冻结了 espflash 的 OpenMV 支持板)。NINA-W102 的复位引脚和启动选择引脚分别为 RP2040 的 GPIO 3GPIO 2,NINA 的 UART0 接到 RP2040 的 UART1TX = GPIO 8RX = GPIO 9)::

from machine import Pin, UART
from espflash import ESPFlash

reset = Pin(3, Pin.OUT)                                    # NINA RESET
gpio0 = Pin(2, Pin.OUT)                                    # NINA GPIO0
uart = UART(1, 115200, timeout=1000)

esp = ESPFlash(reset, gpio0, uart)
esp.bootloader()
esp.set_baudrate(921600)
size = esp.flash_read_size()
esp.flash_attach()
esp.flash_config(size)
esp.flash_write_file("NINA_FW.bin")
esp.flash_verify_file("NINA_FW.bin")
esp.reboot()

class ESPFlash

class espflash.ESPFlash(reset: 'machine.Pin', gpio0: 'machine.Pin', uart: 'machine.UART', log_enabled: bool = False)

构造一个驱动 ESP32 ROM 引导加载程序的 ESPFlash 对象。

  • reset 是连接到 ESP32 RESET 线的 machine.Pin 实例,配置为输出。

  • gpio0 是连接到 ESP32 GPIO0 线的 machine.Pin 实例,配置为输出。

  • uart 是连接到 ESP32 UART0 引脚的 machine.UART 实例。它必须以 115200 波特率初始化,并设置非零的读超时。

  • log_enabled 启用与引导加载程序之间交换的 SLIP 帧的详细日志。仅在调试时有用。

构造函数会尝试导入 hashlib。如果 hashlib.md5 可用,则 ESPFlash.flash_verify_file() 所使用的运行中 MD5 摘要会在写入时自动计算。

set_baudrate(baudrate: int, timeout: int = 350) None

更改引导加载程序的 UART 波特率。

  • baudrate 是要切换到的新波特率。如果与当前活动的波特率不同,则会在重新配置本地 UART 之前向引导加载程序发出 CHANGE_BAUDRATE 命令。

  • timeout 为保留参数,目前未使用。

如果底层 UART 对象未实现 init() 方法,则此操作无效。

bootloader(retry: int = 6) bool

驱动 RESETGPIO0 以进入 ESP32 ROM 下载模式并与引导加载程序同步。

  • retry 是放弃之前的复位/同步尝试次数。

成功时返回 True,否则抛出 Exception

flash_read_size() int

读取 SPI 闪存的 JEDEC ID 并返回以字节为单位的闪存大小。

如果报告的大小位超出预期的 0x12-0x19 范围,则抛出 Exception

flash_attach() None

连接到 SPI 闪存。必须在 bootloader() 之后、任何闪存读/写操作之前调用一次。

flash_config(flash_size: int = 2 * 1024 * 1024) None

配置 SPI 闪存参数。

  • flash_size 是以字节为单位的总闪存大小,通常是 flash_read_size() 返回的值。

块、扇区和页大小分别固定为 64 KiB、4 KiB 和 256 字节。

flash_write_file(path: str, blksize: int = 0x1000) None

从偏移量 0 开始向闪存写入固件镜像。

  • path 是要烧录的固件二进制文件的文件系统路径。

  • blksize 是发送给引导加载程序的每个数据块的字节大小。必须是扇区大小的整数倍。

最后一个块会用 0xFF 填充至完整的 blksize。如果支持 MD5,运行中的 MD5 摘要会在写入期间更新,从而可以无参数调用 flash_verify_file()

flash_verify_file(path: str, digest: bytes | None = None, offset: int = 0) None

将闪存内容与固件文件进行校验。

  • path 是参考固件二进制文件的文件系统路径;其大小决定了要校验的字节数。

  • digest 是该文件可选的预先计算好的十六进制编码 MD5 摘要。如果为 None,则使用最近一次 flash_write_file() 调用期间计算出的摘要。

  • offset 是开始校验的闪存偏移量(以字节为单位)。

如果没有可用的摘要,或闪存内容与参考摘要不匹配,则抛出 Exception

reboot() None

发送一个 FLASH_END 命令,指示 ROM 引导加载程序重启 ESP32 并运行刚刚烧录的固件。不读取任何响应。