espflash — programator de firmware pentru bootloader-ul ROM al ESP32

Acest modul oferă o implementare minimală ESPFlash care comunică cu bootloader-ul ROM al ESP32 prin UART. Este destinat actualizărilor in-system ale firmware-ului ESP32 de pe modulele companion (de exemplu, modulul U-blox NINA-W10 folosit pe plăcile Arduino) și nu este un înlocuitor pentru utilitarul complet esptool. Funcțiile avansate (stub loader, alte cipuri ESP, deflate, secure boot etc.) nu sunt acceptate în mod intenționat.

Driverul comută RESET și GPIO0 pentru a pune ESP32 în modul de descărcare, apoi emite comenzi încadrate SLIP pentru a citi dimensiunea memoriei flash, a configura interfața SPI, a scrie imaginea firmware-ului și a o verifica printr-un digest MD5.

Exemplu pentru Arduino Nano RP2040 Connect (singura placă acceptată de OpenMV unde espflash este în prezent integrat în firmware). Pinii de reset și de boot-strap ai NINA-W102 sunt GPIO 3 și, respectiv, GPIO 2 ai RP2040, iar UART0 al NINA este cablat la UART1 al 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)

Construiește un obiect ESPFlash care controlează bootloader-ul ROM al ESP32.

  • reset este o instanță machine.Pin conectată la linia RESET a ESP32, configurată ca ieșire.

  • gpio0 este o instanță machine.Pin conectată la linia GPIO0 a ESP32, configurată ca ieșire.

  • uart este o instanță machine.UART conectată la pinii UART0 ai ESP32. Trebuie inițializată la 115200 baud cu un timeout de citire diferit de zero.

  • log_enabled activează jurnalizarea detaliată a cadrelor SLIP schimbate cu bootloader-ul. Utilă doar pentru depanare.

Constructorul va încerca să importe hashlib. Dacă hashlib.md5 este disponibil, digestul MD5 cumulativ folosit de ESPFlash.flash_verify_file() va fi calculat automat în timpul scrierii.

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

Schimbă rata baud a UART-ului bootloader-ului.

  • baudrate este noua rată baud la care se comută. Dacă diferă de rata baud activă în prezent, o comandă CHANGE_BAUDRATE este emisă către bootloader înainte ca UART-ul local să fie reconfigurat.

  • timeout este rezervat și momentan neutilizat.

Nu are niciun efect dacă obiectul UART subiacent nu implementează o metodă init().

bootloader(retry: int = 6) bool

Comută RESET și GPIO0 pentru a intra în modul de descărcare ROM al ESP32 și a se sincroniza cu bootloader-ul.

  • retry este numărul de încercări de reset/sincronizare înainte de a renunța.

Returnează True în caz de succes, altfel ridică o excepție Exception.

flash_read_size() int

Citește JEDEC ID-ul memoriei flash SPI și returnează dimensiunea memoriei flash în octeți.

Ridică o excepție Exception dacă biții de dimensiune raportați sunt în afara intervalului așteptat 0x12-0x19.

flash_attach() None

Se atașează la memoria flash SPI. Trebuie apelată o singură dată după bootloader() și înainte de orice operație de citire/scriere a memoriei flash.

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

Configurează parametrii memoriei flash SPI.

  • flash_size este dimensiunea totală a memoriei flash în octeți, de obicei valoarea returnată de flash_read_size().

Dimensiunile blocului, sectorului și paginii sunt fixate la 64 KiB, 4 KiB și, respectiv, 256 de octeți.

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

Scrie o imagine firmware în memoria flash începând de la offsetul 0.

  • path este calea în sistemul de fișiere a binarului firmware care urmează să fie scris în memoria flash.

  • blksize este dimensiunea în octeți a fiecărui bloc de date trimis către bootloader. Trebuie să fie un multiplu al dimensiunii sectorului.

Ultimul bloc este completat cu 0xFF până la un blksize întreg. Dacă suportul MD5 este disponibil, digestul MD5 cumulativ este actualizat în timpul scrierii astfel încât flash_verify_file() să poată fi apelată fără argumente.

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

Verifică conținutul memoriei flash în raport cu un fișier firmware.

  • path este calea în sistemul de fișiere a binarului firmware de referință; dimensiunea sa determină numărul de octeți care trebuie verificați.

  • digest este un digest MD5 opțional, precalculat și codificat hexazecimal, al fișierului. Dacă este None, se folosește digestul calculat în timpul celui mai recent apel flash_write_file().

  • offset este offsetul în octeți al memoriei flash de la care începe verificarea.

Ridică o excepție Exception dacă niciun digest nu este disponibil sau dacă conținutul memoriei flash nu corespunde digestului de referință.

reboot() None

Trimite o comandă FLASH_END care instruiește bootloader-ul ROM să repornească ESP32 și să ruleze firmware-ul tocmai scris. Nu se citește niciun răspuns.