espflash — gravador de firmware do bootloader ROM do ESP32

Este módulo fornece uma implementação mínima de ESPFlash que se comunica com o bootloader ROM do ESP32 por meio de uma UART. Ele é destinado a atualizações in-system do firmware do ESP32 em módulos complementares (por exemplo, o módulo U-blox NINA-W10 usado nas placas Arduino), e não é um substituto para o utilitário completo esptool. Recursos avançados (stub loader, outros chips ESP, deflate, secure boot, etc.) intencionalmente não são suportados.

O driver alterna RESET e GPIO0 para colocar o ESP32 em modo de download e então emite comandos enquadrados em SLIP para ler o tamanho da flash, configurar a interface SPI, gravar a imagem de firmware e verificá-la por meio de um digest MD5.

Exemplo para o Arduino Nano RP2040 Connect (a única placa suportada pela OpenMV em que espflash está atualmente congelado). Os pinos de reset e boot-strap do NINA-W102 são os GPIO 3 e GPIO 2 do RP2040, respectivamente, e a UART0 do NINA está ligada à UART1 do 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)

Constrói um objeto ESPFlash que controla o bootloader ROM do ESP32.

  • reset é uma instância de machine.Pin conectada à linha RESET do ESP32, configurada como saída.

  • gpio0 é uma instância de machine.Pin conectada à linha GPIO0 do ESP32, configurada como saída.

  • uart é uma instância de machine.UART conectada aos pinos UART0 do ESP32. Ela deve ser inicializada a 115200 baud com um timeout de leitura diferente de zero.

  • log_enabled habilita o registro detalhado dos quadros SLIP trocados com o bootloader. Útil apenas para depuração.

O construtor tentará importar hashlib. Se hashlib.md5 estiver disponível, o digest MD5 acumulado usado por ESPFlash.flash_verify_file() será calculado automaticamente durante a gravação.

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

Altera a taxa de transmissão (baud rate) da UART do bootloader.

  • baudrate é a nova taxa de transmissão (baud rate) para a qual mudar. Se for diferente da taxa atualmente ativa, um comando CHANGE_BAUDRATE é emitido ao bootloader antes de a UART local ser reconfigurada.

  • timeout é reservado e atualmente não é utilizado.

Não tem efeito se o objeto UART subjacente não implementar um método init().

bootloader(retry: int = 6) bool

Aciona RESET e GPIO0 para entrar no modo de download da ROM do ESP32 e sincronizar com o bootloader.

  • retry é o número de tentativas de reset/sincronização antes de desistir.

Retorna True em caso de sucesso; caso contrário, levanta uma Exception.

flash_read_size() int

Lê o JEDEC ID da flash SPI e retorna o tamanho da flash em bytes.

Levanta uma Exception se os bits de tamanho reportados estiverem fora da faixa esperada de 0x12 a 0x19.

flash_attach() None

Conecta-se à flash SPI. Deve ser chamado uma vez após bootloader() e antes de qualquer operação de leitura/gravação na flash.

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

Configura os parâmetros da flash SPI.

  • flash_size é o tamanho total da flash em bytes, tipicamente o valor retornado por flash_read_size().

Os tamanhos de bloco, setor e página são fixos em 64 KiB, 4 KiB e 256 bytes, respectivamente.

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

Grava uma imagem de firmware na flash começando no offset 0.

  • path é o caminho no sistema de arquivos do binário de firmware a ser gravado.

  • blksize é o tamanho em bytes de cada bloco de dados enviado ao bootloader. Deve ser um múltiplo do tamanho do setor.

O último bloco é preenchido com 0xFF até completar um blksize inteiro. Se houver suporte a MD5, o digest MD5 acumulado é atualizado durante a gravação para que flash_verify_file() possa ser chamado sem argumentos.

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

Verifica o conteúdo da flash em relação a um arquivo de firmware.

  • path é o caminho no sistema de arquivos do binário de firmware de referência; seu tamanho determina o número de bytes a verificar.

  • digest é um digest MD5 opcional, pré-computado e codificado em hexadecimal, do arquivo. Se for None, o digest computado durante a chamada mais recente de flash_write_file() é utilizado.

  • offset é o offset na flash em bytes a partir do qual a verificação começa.

Levanta uma Exception se nenhum digest estiver disponível ou se o conteúdo da flash não corresponder ao digest de referência.

reboot() None

Envia um comando FLASH_END que instrui o bootloader ROM a reiniciar o ESP32 e executar o firmware recém-gravado. Nenhuma resposta é lida.