esptool.py это утилита на языке Python, предназначенная для взаимодействия с ПЗУ-загрузчиком (ROM bootloader) чипов Espressif SoC (ESP32, ESP32-C3 и т. п.).
Утилиты esptool.py, espefuse.py и espsecure.py составляют полный набор инструментария для работы с чипами от Espressif. Они позволяют выполнять следующие операции:
• Читать, записывать, стирать и проверять двоичные данные, сохраненные в памяти flash. • Прочитать функциональную информацию чипа и другие связанные с ним данные, такие как MAC-адрес или идентификатор чипа (flash chip ID). • Прочитать и записатьRead однократно программируемые конфигурационные данные (one-time-programmable efuse, OTP). • Подготовить для прошивки двоичные исполняемые образы. • Анализировать, собирать и выполнять слияние двоичных образов.
Здесь описывается работа с esptool.py для чипа ESP32. Для дополнительной информации по использованию esptool.py, относящейся к конкретному типу, перейдите по ссылке [1] и в выпадающем списке в левом верхнем углу выберите интересующий тип SoC. Решение общих проблем, связанных с работой утилиты esptool, см. в статье [13].
[Установка]
1. Для установки выполните команду esptool.py:
$ pip install esptool
2. Подсоедините чип Espressif к компьютеру - либо напрямую, либо через переходник USB-UART (в зависимости от типа микроконтроллера. Например, для ESP32-C3 см. [2]).
После этого утилита esptool.py готова к использованию. Например, для того, чтобы прочитать информацию об SPI flash:
$ esptool.py -p PORT flash_id
Здесь PORT нужно заменить на имя используемого последовательного порта. Для Linux это может быть имя наподобие /dev/ttyUSB0, а для Windows имя порта может быть типа COM2 и т. п. Если не указывать -p PORT, то утилита сама попытается выбрать первый подходящий порт.
Замечание: esptool.py это программа (скрипт) на языке Python. Если ваша система не распознает расширение *.py для автоматического запуска интерпретатора Python, либо если по какой-то причине у скрипта не установлен атрибут, разрешающий выполнение, то запускайте esptool.py с помощью прямого вызова интерпретатора Python:
> python.exe esptool.py -p COM4 flash_id
Или:
> python3 ./esptool.py -p COM4 flash_id
Быструю подсказку по командной строке можно получить, если указать опцию -h.
esptool.py v3.3-dev - Espressif chips ROM Bootloader Utility
Позиционные аргументы (команды):
{load_ram,dump_mem,read_mem,write_mem,write_flash,run,image_info,make_image,elf2image,read_mac,
chip_id,flash_id,read_flash_status,write_flash_status,read_flash,verify_flash,erase_flash,
erase_region,merge_bin,get_security_info,version}
Запустите esptool {команда} -h для дополнительной подсказки
Команды:
load_ram Загрузить образ в RAM и запустить
dump_mem Дамп произвольной области памяти на диск
read_mem Чтение произвольной области памяти
write_mem Read-modify-write произвольной области памяти
write_flash Запуск двоичного файла (binary blob) в flash
run Запуск кода приложения, находящегося в flash
image_info Дамп заголовков из образа приложения
make_image Создание образа приложения из двоичных файлов
elf2image Создание образа приложения из ELF-файла
read_mac Прочитать MAC-адрес из OTP ROM
chip_id Прочитать идентификатор чипа (Chip) ID из OTP ROM
flash_id Прочитать идентификатор производителя SPI flash и её device ID
read_flash_status Прочитать регистр состояния SPI flash
write_flash_status Запись регистра состояния SPI flash
read_flash Чтение содержимого SPI flash
verify_flash Проверка соответствия бинарника (binary blob) и flash
erase_flash Выполнение стирания чипа SPI flash
erase_region Стирание области памяти flash
merge_bin Склейка нескольких сырых двоичных файлы в один для последующей прошивки
get_security_info Получение некоторых данных, относящихся к безопасности
version Напечатать версию esptool
Опциональные аргументы:
-h, --help Показать этот текст подсказки и выйти
--chip {auto,esp8266,esp32,esp32s2,esp32s3beta2,esp32s3,esp32c3,esp32c6beta,esp32h2beta1,
esp32h2beta2,esp32c2}, -c {auto,esp8266,esp32,esp32s2,esp32s3beta2,esp32s3,esp32c3,
esp32c6beta,esp32h2beta1,esp32h2beta2,esp32c2}
Тип целевого чипа
--port PORT, -p PORT Устройство последовательного порта
--baud BAUD, -b BAUD Скорость последовательного порта
--before {default_reset,usb_reset,no_reset,no_reset_no_sync}
Что делать перед подключением к чипу
--after {hard_reset,soft_reset,no_reset,no_reset_stub},
-a {hard_reset,soft_reset,no_reset,no_reset_stub}
Что делать после завершения работы esptool.py
--no-stub Запрет запуска flasher stub, работать только с ROM bootloader.
Некоторые функции будут недоступны [3].
--trace, -t Разрешить вывод отладочной трассировки протокола взаимодействия
esptool.py и чипа.
--override-vddsdio [{1.8V,1.9V,OFF}]
Отменить внутренний регулятор напряжения ESP32 VDDSDIO (используйте
с осторожностью)
--connect-attempts CONNECT_ATTEMPTS
Количество попыток для соединения. Отрицательное значение или 0
для бесконечных попыток. По умолчанию используется 7.
[Базовые команды esptool.py]
write_flash. Команда запишет двоичные данные ESP-чипа flash, например:
В одной командной строке можно указать несколько адресов flash и имен файлов.
Практический пример, записывающий загрузчик (bootloader.bin), образ приложения (my_app-0x01000.bin), таблицу разделов (partition-table.bin) и начальные данные OTA (ota_data_initial.bin). Обратите внимание, что имя порта подключения не указано (утилита esptool.py сама попытается выбрать подходящий), но указана скорость обмена (-b 460800) и параметры SPI (--flash_mode dio --flash_freq 20m --flash_size 4MB) и указаны другие опции, определяющие поведение утилиты и загрузчика (--before=default_reset --after=hard_reset):
Аргумент --chip указывать необязательно, когда записывается flash, esptool определит тип чипа, когда подключится через последовательный порт. Адреса могут быть указаны в HEX-формате (с префиксом 0x) или в десятичном формате (например, вместо 0x1000 можно указать 4096).
Установка режима и размера flash. Могут понадобиться специальные аргументы для режима памяти flash и её размера, если вы хотите поменять значения по умолчанию. Например:
Начиная с esptool версии v2.0 эти опции часто не нужны, поскольку по умолчанию используются режим и размер, сохраненные в файле образа (.bin). Подробнее про режимы flash см. [4].
Компрессия. По умолчанию последовательные данные передаются в сжатом виде, чтобы повысить производительность. Опция -u/--no-compress запрещает это поведение.
Стирание перед записью. Чтобы данные были успешно записаны в память flash, должны быть стерты все соответствующие сектора по 4096 байт (самая маленькая независимо стираемая область памяти). Как следствие, когда смещение записываемых данных не выровнено на адрес, нацело делящийся на 4096, потребуется стереть дополнительные блоки памяти. Esptool будет показывать информацию о том, какие будут стерты сектора памяти flash.
Используйте опцию -e/--erase-all, чтобы стереть перед программированием все сектора flash (не только те, которые подвергаются записи).
Защита загрузчика. Прошивка в регион загрузчика (0x0 .. 0x7FFF) по умолчанию запрещена, если было определено, что активирована функция Secure Boot [5]. Это мера безопасности для предотвращения случайной перезаписи защищенного загрузчика, что в конечном итоге может привести к "окирпичиванию" устройства.
Это поведение может быть отменено опцией --force. Используйте это только на свой страх и риск, и только если понимаете, что делаете!
Защита шифрованием flash. Перезапись зашифрованного firmware (bootloader, приложение, и т. д.) запрещена без указания опции --encrypt, если разрешена фича Flash Encryption [6], и запрещена функция Encrypted Download (установлен efuse-бит EFUSE_DISABLE_DL_ENCRYPT).
Эта мера безопасности предназначена для того, чтобы случайно не перезаписать зашифрованное firmware незашифрованным бинарником, что может полностью превратить устройство в "кирпич".
Это поведение можно отменить опцией --force. Используйте эту опцию при условии, что flash-ключ шифрования генерируется вне устройства, и можно выполнить шифрование на машине хоста.
Прошивка несовместимого образа. Утилита esptool.py перед прошивкой проверит каждый бинарник. Если было определено, что образ firmware допустимый, то в его заголовке проверяются поля идентификатора чипа (Chip) ID и минимальной ревизии чипа (Minimum chip revision) на соответствие значениям реально подключенного чипа. Если образ оказался несовместимым с чипом, или требует более новую ревизию чипа, то прошивка не производится.
Это поведение можно отменить опцией --force.
read_flash. Команда read_flash позволяет считать обратно содержимое flash. В этой команде аргументами указывается адрес, размер и имя файла для дампа. Например, чтобы полностью прочитать 2 мегабайта подключенной flash:
esptool.py -p PORT -b 460800 read_flash 0 0x200000 flash_contents.bin
Также можно автоматически определить размер flash, указав вместо размера ALL. Предыдущий пример с автодетектом размера:
esptool.py -p PORT -b 460800 read_flash 0 ALL flash_contents.bin
Замечание: если команда write_flash обновила режим (flash mode) образа загрузки (boot image), и во время прошивки указан размер flash, то прочитанные байты могут отличаться от записанных.
erase_flash и erase_region. Для полного стирания flash выполните команду (вся память чипа будет заполнена байтами 0xFF):
esptool.py erase_flash
Чтобы стереть область flash, начиная с адреса 0x20000, длиной 0x4000 байт (16 килобайт):
esptool.py erase_region 0x20000 0x4000
Адрес и длина области должны нацело делиться на размер сектора SPI flash. Этот размер сектора составляет 0x1000 (4096) байт для поддерживаемых чипов flash.
Защита flash. По умолчанию стирание чипа flash запрещено, если активна либо фича Secure Boot [5], либо Flash Encryption [6]. Эта мера безопасности предназначена для того, чтобы случайно не удалить защищенный загрузчик, что может полностью превратить устройство в "кирпич".
Это поведение можно отменить опцией --force. Используйте только на свой страх и риск, и только если понимаете, что делаете!
read_mac. Эта команда позволяет прочитать встроенный MAC-адрес чипа. Пример вывода:
$ python3 ./esptool.py flash_id
esptool.py v3.3-dev
Found 1 serial ports
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... ESP32-C3
Chip is ESP32-C3 (revision 3)
Features: Wi-Fi
Crystal is 40MHz
MAC: a0:76:4e:14:5a:3c
Uploading stub...
Running stub...
Stub running...
Manufacturer: 20
Device: 4016
Detected flash size: 4MB
Hard resetting via RTS pin...
Информацию об именах производителей чипов и типах чипов см. в заголовочном файле flashchips.h [7].
elf2image. Команда elf2image преобразует ELF-файл (результат работы компилятора и линкера) в двоичный исполняемый образ, который можно прошить в flash, и откуда может быть загружено и запущено приложение:
esptool.py --chip ESP32 elf2image my_app.elf
Для этой команды не требуется соединение с чипом.
Команда elf2image также принимает аргументы режима --flash_freq и --flash_mode, который могут использоваться для установки значений по умолчанию в заголовке образа. Это важно, когда генерируется образ, который будет запускаться напрямую загрузчиком чипа. Эти значения можно также переопределить командой write_flash (см. описание выше). Однако если вы хотите перезаписать эти значения командой write_flash, то используйте аргумент --dont-append-digest команды elf2image, чтобы пропустить добавление цифровой подписи SHA256 после образа. Цифровая подпись SHA256 станет недостоверной после перезаписи заголовка образа, что недопустимо.
По умолчанию elf2image использует секции в ELF-файле, чтобы сгенерировать каждый сегмент в двоичном исполняемом коде (binary executable). Чтобы вместо этого использовать сегменты (PHDR), передайте опцию --use_segments.
Для ESP32 команда elf2image создаст один двоичный файл образа исполняемого кода, "image file". По умолчанию у него будет то же самое имя, что и у входного ELF-файла, просто расширение файла .elf поменяется на .bin:
esptool.py --chip ESP32 elf2image my_esp_app.elf
В результате выполнения этой команды получится файл образа my_esp_app.bin.
image_info. Эта команда выведет некоторую информацию об образе (адрес загрузки, размеры и т. д.) в файле .bin, который был создан командой elf2image.
Чтобы посмотреть больше информации по файлу образа, такую как установленный размер flash, частоту тактов интерфейса SPI и режим подключения, или расширенную информацию заголовка, используйте опцию --version 2. Этот расширенный вывод в плане сделать выводом по умолчанию в будущих релизах утилиты esptool.
esptool.py image_info --version 2 my_esp_app.bin
Эта информация соответствует заголовкам, описанных в документации по формату образа прошивки, см. ниже врезку "Firmware Image Format".
Файлы образа (firmware) генерируются командой esptool.py elf2image. Файлы образа загружаются и запускаются встроенным ROM-загрузчиком SoC-чипа Espressif.
Файл firmware состоит из заголовка (header), расширенного заголовка (extended header), переменного количества сегментов данных и блока окончания (footer). Многобайтные поля хранятся в формате little-endian [10].
Заголовок файла. Заголовок состоит из 8 байт:
Байт
Описание
0
Магическое число (всегда 0xE9).
1
Количество сегментов.
2
Режим подключения памяти, SPI Flash Mode (0 = QIO, 1 = QOUT, 2 = DIO, 3 = DOUT).
Утилита esptool.py перезапишет 2-й и 3-й байт (начиная с 0 байта), в соответствии с информацией SPI flash, предоставленной опциями командной строки, но только если в конце файла образа не была добавлена цифровая подпись SHA256. Таким образом, если вы намереваетесь поменять параметры SPI flash во время процесса прошивки, например командой esptool.py write_flash, то генерируйте образы без цифровых подписей SHA256. Этого можно достичь запуском команды esptool.py elf2image с аргументом --dont-append-digest.
Расширенный заголовок файла. 16-байтный extended header идет сразу после заголовка образа:
Байт
Описание
0
Ножка WP, когда выводы SPI установлены через efuse (считывается кодом ROM bootloader).
1-3
Настройки нагрузочной способности ножек SPI flash (считывается кодом ROM bootloader).
4-5
Chip ID (обозначает устройство ESP, для которого предназначен этот образ).
6
Минимальная ревизия чипа, поддерживаемая образом (устарело, используйте следующее поле).
7-8
Минимальная ревизия чипа, поддерживаемая образом (в формате major * 100 + minor).
9-10
Максимальная ревизия чипа, поддерживаемая образом (в формате major * 100 + minor).
11-14
Зарезервированные байты в дополнительном пространстве заголовка, в настоящее время не используются.
15
Флаг добавления хэша (если 1, то после контрольной суммы добавляется цифровая подпись SHA256).
Сегмент
Байт
Описание
0-3
Смещение в памяти.
4-7
Размер сегмента.
8 .. n
Данные.
Footer. Файл добавляется нулями до тех пор, пока его размер не станет на 1 байт меньше числа, нацело делящегося на 16. Последний байт (который дополнит размер файла до минимального значения, нацело делящегося на 16) это контрольная сумма данных всех сегментов. Контрольная сумма определена как операция ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR) всех байт и байта 0xEF.
Если опция добавления хэша (байт 15 в расширенном заголовке) установлена в 0x01, то после контрольной суммы добавляется цифровая подпись SHA256 "simple hash" (от всего образа целиком). Эта цифровая подпись является отдельной для secure boot, и используется только для определения повреждения прошивки. Информация SPI flash не может быть изменена во время прошивки, если к образу добавлен хэш.
Если разрешена фича secure boot, то также добавляется соответствующая подпись (и simple hash включены в подписанные данные). Эта сигнатура образа различается для Secure Boot V1 и Secure Boot V2.
Чтобы проанализировать двоичный образ и получить полную информацию о его заголовках и сегментах, используйте команду image_info с опцией --version 2 option.
Если указанный двоичный файл образа является приложением, и в образе обнаружен правильный заголовок приложения ESP-IDF, то будут также показаны специфичные поля, описывающие приложение.
Если указанный двоичный образ образа это загрузчик (bootloader), и в образе был обнаружен правильный заголовок загрузчика ESP-IDF, то будут также показаны специфичные поля, описывающие загрузчик.
merge_bin. Команда merge_bin сольет друг с другом несколько двоичных файлов (любого вида) в один файл, который позже можно будет прошить в память flash устройства. Любые промежутки между файлами будут заполнены байтами 0xFF (такое же содержимое, как в чистых областях flash).
В этом примере будет сгенерирован файл merged-flash.bin, состоящий из 3 файлов. Этот файл может быть позже записан в память flash командой esptool.py write_flash 0x0 merged-flash.bin.
Описание используемых опций:
• Команда merge_bin поддерживает те же самые опции --flash_mode, --flash_size и --flash_freq, как и команда write_flash, чтобы переназначить соответствующие значение в заголовке flash загрузчика (подробности см. выше). Эти опции применяются для содержимого выходного файла таким же образом, как и при записи в память flash. Если используете эти опции, то убедитесь, что передали параметр --chip, поскольку и поддерживаемые значения, и смещение загрузчика зависят от типа чипа. • Опция --target-offset 0xNNN создаст сгенерированный двоичный образ, который должен быть прошит по указанному смещению вместо смещения 0x0. • Опция --fill-flash-size SIZE дополнит сгенерированный двоичный образ, который будет дополнен байтами 0xFF до полного указанного размера. Нарпример, --fill-flash-size 4MB создаст двоичный файл размером 4 мегабайта. • Существует возможность подключить опции из текстового файла @filename. Например, эта возможность для удобства может использоваться с системой сборки ESP-IDF [8], которая создает файл flash_args в директории build проекта:
cd build # Переход в директорию build проекта ESP-IDF
esptool.py --chip ESP32 merge_bin -o merged-flash.bin @flash_args
[Продвинутые команды]
Следующие команды используются реже, или могут быть интересны продвинутым пользователям (см. [9]).
• Verify Flash Data: verify_flash • Dump a Memory Region to File: dump_mem • Load a Binary to RAM: load_ram • Read or Write RAM: read_mem / write_mem • Read Flash Chip Registers: read_flash_status • Write Flash Chip Registers: write_flash_status