espflash — прошивальщик прошивки через ROM-загрузчик ESP32

Этот модуль предоставляет минимальную реализацию ESPFlash, которая взаимодействует с ROM-загрузчиком ESP32 по UART. Он предназначен для внутрисистемного обновления прошивки ESP32 на сопутствующих модулях (например, на модуле U-blox NINA-W10, используемом на платах Arduino) и не является заменой полноценной утилиты esptool. Расширенные возможности (stub-загрузчик, другие чипы ESP, deflate, secure boot и т. д.) намеренно не поддерживаются.

Драйвер переключает RESET и GPIO0, чтобы перевести ESP32 в режим загрузки, после чего отправляет команды в SLIP-кадрах для чтения размера флеш-памяти, настройки интерфейса SPI, записи образа прошивки и его проверки по MD5-дайджесту.

Пример для Arduino Nano RP2040 Connect (единственная поддерживаемая OpenMV плата, где espflash в настоящее время вшит в прошивку). Выводы сброса и начальной загрузки NINA-W102 подключены к GPIO 3 и GPIO 2 RP2040 соответственно, а UART0 модуля NINA подключён к UART1 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)

Создаёт объект ESPFlash, управляющий ROM-загрузчиком ESP32.

  • reset — экземпляр machine.Pin, подключённый к линии RESET ESP32 и настроенный как выход.

  • gpio0 — экземпляр machine.Pin, подключённый к линии GPIO0 ESP32 и настроенный как выход.

  • uart — экземпляр machine.UART, подключённый к выводам UART0 ESP32. Он должен быть инициализирован на скорости 115200 бод с ненулевым тайм-аутом чтения.

  • log_enabled включает подробное логирование SLIP-кадров, которыми обмениваются с загрузчиком. Полезно только для отладки.

Конструктор попытается импортировать hashlib. Если доступна функция hashlib.md5, текущий MD5-дайджест, используемый методом ESPFlash.flash_verify_file(), будет вычисляться автоматически во время записи.

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

Изменяет скорость передачи UART для загрузчика.

  • baudrate — новая скорость передачи, на которую нужно переключиться. Если она отличается от текущей активной скорости, перед перенастройкой локального UART загрузчику отправляется команда CHANGE_BAUDRATE.

  • timeout зарезервирован и в настоящее время не используется.

Не имеет эффекта, если нижележащий объект UART не реализует метод init().

bootloader(retry: int = 6) bool

Управляет линиями RESET и GPIO0 для входа в режим ROM-загрузки ESP32 и синхронизации с загрузчиком.

  • retry — число попыток сброса/синхронизации перед отказом.

Возвращает True в случае успеха, иначе генерирует Exception.

flash_read_size() int

Считывает JEDEC ID флеш-памяти SPI и возвращает её размер в байтах.

Генерирует Exception, если сообщённые биты размера выходят за пределы ожидаемого диапазона 0x12-0x19.

flash_attach() None

Подключается к флеш-памяти SPI. Должен быть вызван один раз после bootloader() и до любой операции чтения/записи флеш-памяти.

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

Настраивает параметры флеш-памяти SPI.

  • flash_size — общий размер флеш-памяти в байтах, обычно значение, возвращаемое методом flash_read_size().

Размеры блока, сектора и страницы фиксированы и равны 64 КиБ, 4 КиБ и 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 и запустить только что записанную прошивку. Ответ не читается.