Skip to content

johanngorban/stm32-bootloader

Repository files navigation

Загрузчик для stm32f103

Однобанковый загрузчик с двумя слотами под прошивки. Управляется по UART через CLI-утилиту boot с использованием протокола BCP. Поддерживает запись, верификацию и запуск образов.

Оглавление

Возможности

  • Хранение до двух прошивок одновременно в независимых слотах по 48 КБ
  • Верификация образа по CRC32/ISO-HDLC и магическому числу
  • Получение версии загрузчика и метаданных образов
  • Запись прошивки во флеш по протоколу FWP

Карта памяти

Регион Адрес начала Размер
Bootloader 0x08000000 20 КБ
Слот 1 0x08005000 48 КБ
Слот 2 0x08011000 48 КБ

Каждый слот начинается с заголовка образа размером 512 байт. Сразу за заголовком располагается тело прошивки, начиная с vector table.

Управление

Загрузчик работает по UART1 (PA9 TX, PA10 RX) с параметрами 115200 8N1, без управления потоком. После сброса загрузчик инициализируется и ожидает команд по протоколу BCP — асинхронному протоколу запрос/ответ. Передача тела прошивки в слот выполняется по протоколу FWP (свой аналог YMODEM) поверх того же UART.

Для управления используется CLI-утилита boot. Она инкапсулирует BCP и FWP и предоставляет команды записи, верификации, запуска и получения версии.

Полное описание протокола и сущностей:

Подготовка прошивки

Чтобы загрузчик мог запустить прошивку, она должна:

  1. Быть собрана для запуска с адреса слота (0x08005000 для слота 1).
  2. Содержать заголовок образа в первых 512 байтах.
  3. Быть пропатчена скриптом metadata.py после получения .bin — он проставит фактические размер и CRC.

Линкер-скрипт

В MEMORY указывается начало слота и его длина:

MEMORY
{
  RAM   (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
  FLASH (rx)  : ORIGIN = 0x08005000, LENGTH = 48K
}

В SECTIONS первой секцией размещается .image_metadata фиксированной длиной 512 байт. Сразу за ней должна идти .isr_vector:

SECTIONS
{
  .image_metadata :
  {
    . = ALIGN(4);
    __image_metadata_start = .;
    KEEP(*(.image_metadata))
    FILL(0x00);
    . = __image_metadata_start + 512;
  } >FLASH

  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector))
    . = ALIGN(4);
  } >FLASH

  /* остальные секции */
}

Порядок важен: загрузчик при запуске вычисляет адрес vector table как адрес слота + 512, поэтому ничего, кроме заголовка, перед .isr_vector быть не должно.

Заголовок образа

Структура заголовка соответствует определению в загрузчике:

#define IMAGE_METADATA_SIZE (512u)

typedef struct __attribute__((packed)) {
    uint32_t magic;
    uint32_t size;
    uint32_t crc;
    uint8_t  version_major;
    uint8_t  version_minor;
    uint8_t  version_patch;
    uint8_t  reserved[IMAGE_METADATA_SIZE - 15];
} image_metadata_t;

В прошивке необходимо объявить переменную этого типа и поместить её в секцию .image_metadata через атрибут:

__attribute__((section(".image_metadata")))
const image_metadata_t metadata = {
    .magic = 0xAAAAAAAAu,
    .version_major = 1,
    .version_minor = 0,
    .version_patch = 0,
};

Поля size и crc на этапе компиляции инициализируются нулями — их проставляет metadata.py после сборки, поэтому их можно не заполнять.

Поле magic обязано быть 0xAAAAAAAA, иначе образ будет признан невалидным.

Постобработка бинарника

metadata.py принимает на вход финальный .bin, проверяет магическое число в первых 4 байтах, считает CRC32/ISO-HDLC от тела образа (всех байт после 512-байтового заголовка) и записывает размер тела и CRC по фиксированным смещениям заголовка.

Интеграция в Makefile:

PYTHON ?= python3
PATCH_SCRIPT := tools/metadata.py

$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
	$(BIN) $< $@
	$(PYTHON) $(PATCH_SCRIPT) $@

После этого .bin готов к загрузке через boot flash.

Передача управления приложению

Запуск прошивки из выбранного слота выполняется по команде BCP RUN. Загрузчик:

  1. Вычисляет адрес тела образа как адрес слота + 512.
  2. Считывает по этому адресу начальное значение MSP и адрес Reset_Handler (стандартный заголовок Cortex-M vector table).
  3. Отключает прерывания, переставляет SCB->VTOR на тело образа, включает прерывания.
  4. Устанавливает MSP и передаёт управление на Reset_Handler приложения.

Прошивка должна корректно отрабатывать ситуацию, когда она запускается не с нулевого адреса флеша — в первую очередь правильно настраивать VTOR (если переопределяет его повторно) и не делать предположений о состоянии периферии после сброса, поскольку до запуска приложения работал загрузчик.

Ограничения

  • Поддерживается только STM32F103 (Cortex-M3, arm-none-eabi-gcc).
  • Максимальный размер образа — 48 КБ, включая заголовок 512 байт.
  • Заголовок образа имеет фиксированный размер 512 байт;
  • Возврат из приложения в загрузчик возможен только через перезагрузку питания

Документация

About

Lightweight UART bootloader for STM32F103 (Cortex-M3) with dual-slot firmware storage, CRC32 verification and BCP control protocol

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Contributors

Languages