Загрузчик второй ступени ESP-IDF (second stage bootloader)
В ESP32 два загрузчика. Первый зашит в ПЗУ и умеет только одно: найти во флеш по адресу 0x1000 второй, загрузить его в RAM и передать управление. Всё остальное — таблица разделов, OTA, проверка подписи, шифрование — делает второй, который собирает ESP-IDF вместе с вашим проектом.
Обновлено Редакция GAW
Загрузчик второй ступени (second stage bootloader, bootloader.bin) — программа ESP-IDF, которую загрузчик из ПЗУ ESP32 (первая ступень) читает из флеш по адресу 0x1000, загружает в RAM и запускает. Именно она читает таблицу разделов, выбирает, какое приложение стартовать, проверяет и загружает его образ, а при необходимости включает secure boot и шифрование флеш. Что такое загрузчик вообще и как устроены загрузчики других микроконтроллеров — в статьях «Загрузчик (bootloader)» и «Режим загрузки STM32».
Что делает
По руководству ESP-IDF вторая ступень выполняет четыре задачи: минимальную начальную настройку модулей чипа; инициализацию шифрования флеш и secure boot, если они настроены; выбор раздела приложения по таблице разделов и данным ota_data; загрузку образа в RAM и передачу ему управления. Подробнее по шагам:
- Читает таблицу разделов с адреса 0x8000 (смещение настраивается). Находит разделы factory и OTA; если есть OTA-разделы — по
otadataрешает, какой запускать. - Для выбранного раздела читает образ по сегментам: сегменты с адресами в IRAM и DRAM копирует из флеш в RAM, сегменты IROM и DROM отображает через MMU флеш.
- Проверяет целостность приложения и переходит на его точку входа из заголовка образа. Дальше начинается запуск приложения — аналог того, что на Cortex-M делает код запуска.
Параллельно загрузчик перенастраивает SPI-флеш. ПЗУ читает режим и частоту флеш из заголовка самого загрузчика, но на пониженной частоте и не во всех режимах; вторая ступень затем берёт настройки из заголовка приложения, так что OTA-обновление может их сменить (до ESP-IDF 4.0 использовался заголовок загрузчика). Поэтому в логе ПЗУ видно mode:DIO, даже если проект собран под QIO — четырёхпроводной режим включает уже программный загрузчик.
Отличие от загрузчика ПЗУ
| Первая ступень (ПЗУ) | Вторая ступень (ESP-IDF) | |
|---|---|---|
| Где хранится | маска ПЗУ чипа, не меняется | флеш, адрес 0x1000 |
| Кто собирает | Espressif при производстве | ваш проект ESP-IDF |
| Что умеет | режим загрузки по strapping-выводам, загрузка по UART для esptool, чтение образа с 0x1000 | таблица разделов, OTA, secure boot, шифрование, factory reset, тестовый раздел |
| Обновление | только новая ревизия чипа | записью по 0x1000 через esptool; OTA его не обновляет |
Первый сектор флеш (4 КБ, адреса 0x0–0xFFF) при secure boot хранит вектор инициализации и дайджест загрузчика, иначе пустует.
Ограничения и настройки
- Размер. При таблице разделов на 0x8000 загрузчик должен уместиться в 0x8000 байт, иначе сборка падает с ошибкой «Bootloader binary size [..] is too large for partition table offset». Лечится уровнем лога (по умолчанию Info), оптимизацией по размеру или переносом таблицы разделов выше. При Secure Boot V2 есть абсолютный предел 48 КБ (0xC000) без учёта подписи 4 КБ.
- Сторожевой таймер. В загрузчике включён RTC_WDT (
CONFIG_BOOTLOADER_WDT_ENABLE), и если приложение не стартовало за 9 с (CONFIG_BOOTLOADER_WDT_TIME_MS), чип перезагружается — защита от зависаний при нестабильном питании. - Совместимость. Загрузчик запускает приложения, собранные более новыми ESP-IDF, но не более старыми.
- Factory reset и тестовый раздел. По удержанию GPIO заданное время (по умолчанию 5 с) загрузчик может стереть разделы данных и вернуться на factory-приложение или запустить раздел с подтипом test.
- Быстрый старт после глубокого сна.
CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEPсохраняет адрес приложения в RTC FAST memory и после пробуждения пропускает проверку образа. - Свой загрузчик. Проект может подключить хуки или полностью переопределить загрузчик (примеры
custom_bootloaderв ESP-IDF).
Как записать все три файла — загрузчик, таблицу разделов и приложение — и какие ошибки прошивки встречаются чаще всего, разобрано в статье «Прошивка ESP32 через esptool».
Частые вопросы
Почему bootloader.bin лежит по адресу 0x1000, а не 0x0?
По ESP-IDF для ESP32 загрузчик ПЗУ ищет образ второй ступени именно с адреса 0x1000; первый сектор флеш (4 КБ) при включённом secure boot хранит вектор инициализации и дайджест загрузчика, иначе не используется. Таблица разделов по умолчанию идёт следом по адресу 0x8000, а размер раздела bootloader считается как CONFIG_PARTITION_TABLE_OFFSET − 0x1000, то есть 0x7000 байт (наш расчёт).
Можно ли обновить загрузчик второй ступени по OTA?
Обычное OTA-обновление в ESP-IDF записывает новое приложение, но не загрузчик. Поэтому загрузчик умеет запускать приложения, собранные более новыми версиями ESP-IDF, а вот откат приложения на старую версию он не поддерживает: для таких устройств документация советует оставлять старый bootloader.bin. В таблице разделов есть тип bootloader с подтипами ota и recovery — они нужны для отдельного механизма обновления загрузчика, где адрес recovery-раздела прошит в eFuse.
Что означает Invalid header в логе загрузки ESP32?
Загрузчик ПЗУ попытался прочитать заголовок программного загрузчика по адресу 0x1000 и не получил осмысленных данных. По документации esptool причины такие: по 0x1000 ничего нет (записали не туда или флеш стёрта), плохой контакт или питание флеш, загрузчик открытый при включённом шифровании или зашифрованный при выключенном, выбран режим HSPI через GPIO2 или флеш 3,3 В оказалась запитана от 1,8 В из-за GPIO12.
Источники
- Espressif. ESP-IDF Programming Guide v6.1, ESP32: Bootloader — функции: минимальная начальная настройка модулей, инициализация шифрования флеш и secure boot, выбор раздела приложения по таблице разделов и ota_data, загрузка образа в RAM (IRAM и DRAM) и передача управления; расположен по адресу 0x1000; Bootloader Compatibility: OTA не может обновить загрузчик, загрузчик запускает приложения более новых версий ESP-IDF, но не более старых; SPI Flash Configuration: ПЗУ читает заголовок загрузчика (частота ниже, не все режимы), загрузчик затем перенастраивает флеш по заголовку выбранного приложения — так OTA может сменить настройки флеш; до ESP-IDF 4.0 использовался заголовок самого загрузчика; Log Level: по умолчанию Info, CONFIG_BOOTLOADER_LOG_LEVEL; Factory Reset: CONFIG_BOOTLOADER_FACTORY_RESET, GPIO и время удержания по умолчанию 5 с; Watchdog: в загрузчике RTC_WDT включён при CONFIG_BOOTLOADER_WDT_ENABLE и сбрасывает чип, если приложение не стартовало за 9 с (CONFIG_BOOTLOADER_WDT_TIME_MS); Bootloader Size: при таблице разделов на 0x8000 предел 0x8000 байт, при Secure Boot V2 абсолютный предел 48 КБ (0xC000) без 4 КБ подписи; Fast Boot from Deep-Sleep: CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP хранит адрес приложения в RTC FAST и пропускает проверку образа; Custom Bootloader: хуки и переопределение, примеры custom_bootloader
- Espressif. ESP-IDF Programming Guide v6.1, ESP32: Application Startup Flow; Partition Tables — ПЗУ загружает образ второй ступени в RAM с адреса 0x1000; при Secure Boot первый сектор 4 КБ хранит IV и дайджест загрузчика; ПЗУ переходит на точку входа из заголовка образа; загрузчик читает таблицу разделов с 0x8000 (настраивается), находит factory и OTA-разделы, по otadata выбирает, что запускать; сегменты IRAM и DRAM копируются из флеш, IROM и DROM отображаются через MMU флеш; MMU настраивается для обоих ядер, включается для PRO CPU; проверяет целостность приложения и переходит на его точку входа; Partition Tables: тип bootloader, подтип primary — вторая ступень по адресу 0x1000, размер CONFIG_PARTITION_TABLE_OFFSET − 0x1000, подтип recovery по адресу из eFuse
- Espressif. esptool Documentation (latest), ESP32: Boot Mode Selection — Invalid header — ПЗУ не прочитало заголовок программного загрузчика по адресу 0x1000: не записан, не туда записан, проблема с флеш, несоответствие шифрования; ПЗУ печатает load: сегменты и entry загрузчика; mode: DIO в выводе — режим из заголовка загрузчика, QIO/QOUT включает уже программный загрузчик
Нашли ошибку? ·
Смотрите также
- Загрузчик (bootloader)Прошивка МК без программатора через UART или USB
- Режим загрузки STM32 (BOOT0, BOOT1)Выводы, выбирающие, откуда стартует STM32
- Таблица разделов ESP32Карта флеш-памяти ESP32: где приложение, NVS, OTA и данные
- Безопасная загрузкаЗапуск только подписанной прошивки: подпись, ключи в OTP, откат версий
- Шифрование флеш-памятиПрошивка во внешней памяти в зашифрованном виде: XTS-AES, ключи в чипе
- Режимы SPI-флеш (QIO, QOUT, DIO, DOUT)Сколько линий и какие команды чтения использует ESP32 для флеш, когда выбирать dio
- Прошивка ESP32Загрузчик ПЗУ, GPIO0 и автосброс, write-flash и адреса, ошибки esptool и питание
- Код запускаТаблица векторов, Reset_Handler, .data и .bss, VTOR, FPU, .initN avr-libc