espflash --- ESP32 ROM 開機載入程式韌體燒錄工具

本模組提供一個極簡的 ESPFlash 實作,透過 UART 與 ESP32 ROM 開機載入程式(bootloader)通訊。它的用途是對搭配模組上的 ESP32 韌體進行系統內更新(例如 Arduino 開發板上使用的 U-blox NINA-W10 模組),並非完整 esptool 工具的替代品。進階功能(stub loader、其他 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 是要切換到的新鮑率。若與目前作用中的鮑率不同,會先向開機載入程式發出 CHANGE_BAUDRATE 命令,再重新設定本地端 UART。

  • 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 並執行剛剛燒錄的韌體。不會讀取任何回應。