espflash — flasher del firmware del bootloader ROM dell’ESP32

Questo modulo fornisce un’implementazione minimale di ESPFlash che comunica con il bootloader ROM dell’ESP32 tramite una UART. È pensato per gli aggiornamenti in-system del firmware dell’ESP32 sui moduli companion (ad esempio, il modulo U-blox NINA-W10 usato sulle schede Arduino) e non sostituisce l’utility completa esptool. Le funzionalità avanzate (stub loader, altri chip ESP, deflate, secure boot, ecc.) non sono supportate intenzionalmente.

Il driver commuta RESET e GPIO0 per mettere l’ESP32 in modalità download, quindi invia comandi con framing SLIP per leggere la dimensione della flash, configurare l’interfaccia SPI, scrivere l’immagine del firmware e verificarla tramite un digest MD5.

Esempio per l’Arduino Nano RP2040 Connect (l’unica scheda supportata da OpenMV in cui espflash è attualmente incluso nel firmware). I pin di reset e boot-strap del NINA-W102 sono rispettivamente GPIO 3 e GPIO 2 dell’RP2040, e la UART0 del NINA è collegata alla UART1 dell’RP2040 (TX = GPIO 8, RX = 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)

Costruisce un oggetto ESPFlash che pilota il bootloader ROM dell’ESP32.

  • reset è un’istanza di machine.Pin connessa alla linea RESET dell’ESP32, configurata come output.

  • gpio0 è un’istanza di machine.Pin connessa alla linea GPIO0 dell’ESP32, configurata come output.

  • uart è un’istanza di machine.UART connessa ai pin UART0 dell’ESP32. Deve essere inizializzata a 115200 baud con un timeout di lettura diverso da zero.

  • log_enabled abilita il logging dettagliato dei frame SLIP scambiati con il bootloader. Utile solo per il debug.

Il costruttore tenterà di importare hashlib. Se hashlib.md5 è disponibile, il digest MD5 incrementale usato da ESPFlash.flash_verify_file() verrà calcolato automaticamente durante la scrittura.

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

Cambia il baudrate della UART del bootloader.

  • baudrate è il nuovo baudrate a cui passare. Se diverso dal baudrate attualmente attivo, viene inviato un comando CHANGE_BAUDRATE al bootloader prima che la UART locale venga riconfigurata.

  • timeout è riservato e attualmente non utilizzato.

Non ha effetto se l’oggetto UART sottostante non implementa un metodo init().

bootloader(retry: int = 6) bool

Pilota RESET e GPIO0 per entrare nella modalità download della ROM dell’ESP32 e sincronizzarsi con il bootloader.

  • retry è il numero di tentativi di reset/sync prima di rinunciare.

Restituisce True in caso di successo, altrimenti solleva un”Exception.

flash_read_size() int

Legge l’ID JEDEC della flash SPI e restituisce la dimensione della flash in byte.

Solleva un”Exception se i bit della dimensione riportata sono al di fuori dell’intervallo atteso 0x12-0x19.

flash_attach() None

Si collega alla flash SPI. Deve essere chiamato una volta dopo bootloader() e prima di qualsiasi operazione di lettura/scrittura della flash.

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

Configura i parametri della flash SPI.

  • flash_size è la dimensione totale della flash in byte, tipicamente il valore restituito da flash_read_size().

Le dimensioni di blocco, settore e pagina sono fisse rispettivamente a 64 KiB, 4 KiB e 256 byte.

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

Scrive un’immagine del firmware nella flash a partire dall’offset 0.

  • path è il percorso nel filesystem del binario del firmware da scrivere nella flash.

  • blksize è la dimensione in byte di ogni blocco di dati inviato al bootloader. Deve essere un multiplo della dimensione del settore.

L’ultimo blocco viene riempito con 0xFF fino a una blksize completa. Se il supporto MD5 è disponibile, il digest MD5 incrementale viene aggiornato durante la scrittura, in modo che flash_verify_file() possa essere chiamato senza argomenti.

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

Verifica il contenuto della flash rispetto a un file di firmware.

  • path è il percorso nel filesystem del binario del firmware di riferimento; la sua dimensione determina il numero di byte da verificare.

  • digest è un digest MD5 codificato in esadecimale, pre-calcolato e opzionale, del file. Se None, viene usato il digest calcolato durante l’ultima chiamata a flash_write_file().

  • offset è l’offset nella flash, in byte, da cui inizia la verifica.

Solleva un”Exception se nessun digest è disponibile o se il contenuto della flash non corrisponde al digest di riferimento.

reboot() None

Invia un comando FLASH_END che istruisce il bootloader ROM a riavviare l’ESP32 ed eseguire il firmware appena scritto. Nessuna risposta viene letta.