Перейти к содержанию

Загрузчик второй ступени 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 и передачу ему управления. Подробнее по шагам:

  1. Читает таблицу разделов с адреса 0x8000 (смещение настраивается). Находит разделы factory и OTA; если есть OTA-разделы — по otadata решает, какой запускать.
  2. Для выбранного раздела читает образ по сегментам: сегменты с адресами в IRAM и DRAM копирует из флеш в RAM, сегменты IROM и DROM отображает через MMU флеш.
  3. Проверяет целостность приложения и переходит на его точку входа из заголовка образа. Дальше начинается запуск приложения — аналог того, что на 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.

Источники

  1. 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
  2. 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
  3. Espressif. esptool Documentation (latest), ESP32: Boot Mode Selection — Invalid header — ПЗУ не прочитало заголовок программного загрузчика по адресу 0x1000: не записан, не туда записан, проблема с флеш, несоответствие шифрования; ПЗУ печатает load: сегменты и entry загрузчика; mode: DIO в выводе — режим из заголовка загрузчика, QIO/QOUT включает уже программный загрузчик
Страница помогла?

Нашли ошибку? ·