Files
templates/c/protocan-boot/ports/stm32-common
Andrey c6390ae1c9 feat(protocan-boot): Добавь порты MCU и сервисы загрузки
Обеспечь единый процесс обновления для STM32F103/F407/G474 и TMS320F2812/F28335: discovery, служебные ответы, BUSY, тайм-аут сессии и подтверждение приложения. Добавь самостоятельные проекты CCS, аппаратные хранилища и Python-клиент.

Совместимость: структуры конфигурации и порта расширены, поэтому потребители должны пересобраться и обнулить новые поля. Для C28x callbacks используют pcan_boot_byte_t; периодический pcan_boot_poll обслуживает discovery и настроенный тайм-аут.
2026-10-23 14:16:19 +03:00
..

STM32: общий слой ProtoCAN Boot v1

Порты F103C8, F407VE и G474VE подключают bxCAN/FDCAN и Flash к текущему pcan_boot. F103/F407 предоставляют как лёгкий CMSIS boot main для существующих проектов, так и независимый HAL-порт. G474 использует HAL FDCAN/Flash. pcan_boot_stm32.inc включается семейным .c; отдельно его компилировать не надо. Сохраните рядом каталоги stm32-common и нужного семейства.

Reusable pcan_boot_stm32*.c не содержит main или startup. Готовые boot_main.c и вход из приложения находятся в семейных каталогах. Для F103/F407 общая CMSIS-реализация транспорта, callbacks и безопасного handoff — boot_native.inc; G474 также содержит boot_startup.c для исходных Keil/GCC-сборок. Тактирование платы, linker и привязка USB/CAN-приложения остаются в проектах.

KONOR, climate и CANdle G474 уже подключены через свои submodule: локальные boot main/control заменены include-обёртками, состав Keil/CMake обновлён. UART использует общий rs485-boot с сохранением SETGUI v1 wire-протокола. Схема подключённых проектов и проверки сборок.

Подключение reusable HAL-портов F103/F407

  1. Добавьте в сборку src/pcan_boot.c и семейный pcan_boot_stm32f103.c либо pcan_boot_stm32f407.c; в include paths — include, каталог порта, CMSIS, HAL и каталог вашего stm32f1xx_hal_conf.h / stm32f4xx_hal_conf.h.
  2. В HAL включите CAN, FLASH, RCC, GPIO и CORTEX. Выполните HAL_Init, настройте тактирование, SysTick и GPIO, вызовите HAL_CAN_Init для CAN1. Настройка скорости шины принадлежит проекту; исходные устройства используют 500 кбит/с.
  3. Выделите CAN1, FIFO0 и банки фильтров 0/1 загрузчику. Перед вызовом init CAN должен находиться в состоянии READY, без чужих активных фильтров. Init настраивает адресный фильтр и broadcast discovery, затем вызывает HAL_CAN_Start. Оба приоритета ProtoCAN разрешены, standard и remote кадры отвергаются.
  4. Не включайте CAN TX/RX IRQ для этого handle и не отправляйте через него кадры из других контекстов: порт использует опрос и сам читает TXOK до reset.
  5. Вызывайте семейный poll из основного цикла только после успешного init. Стирание Flash выполняется синхронно; вызов из IRQ не допускается.
  6. Linker приложения, VTOR и переход после reset должны соответствовать карте выбранного профиля. Изменение адресов требует отдельного согласования геометрии стирания, linker и host-клиента.

Пример для F103; hcan уже инициализирован проектом:

#include "pcan_boot_stm32f103.h" /* Подключает HAL-порт и текущий API общего автомата. */
static pcan_boot_stm32_t updater; /* Сохраняет состояние между итерациями главного цикла. */
static bool start_updater(CAN_HandleTypeDef *hcan) /* Вызывается после настройки CAN1, clock tree, GPIO и SysTick. */
{ /* Настройка идентичности прибора не зависит от аппаратной геометрии Flash. */
    pcan_boot_config_t config = {0}; /* Не зависит от порядка полей расширяемого API. */
    config.device_type = 7U; /* Пример: тип 7 должен совпадать с выбранным адресом в клиенте прошивки. */
    config.device_id = 13U; /* Пример: номер 13 повторяет исходный адрес загрузчика KONOR. */
    config.ack_window = 16U; /* Подтверждает каждые 16 CAN-блоков по восемь байт. */
    config.session_timeout_ms = 30000U; /* Пример: 30 секунд без активности прерывают RAM-сессию. */
    return pcan_boot_stm32f103_init(&updater, hcan, &config); /* Настраивает single-slot геометрию, фильтры 0/1 и запускает CAN. */
} /* После успеха основной цикл регулярно вызывает pcan_boot_stm32f103_poll(&updater). */

Product/HW/FW в примере равны нулю; для изделия задайте их явно и согласуйте с manifest клиента. Порт сохраняет ack_window и session_timeout_ms, но сам задаёт active_slot=0, slot_count=1, max_image_size по физическому профилю. Конфигурацию config можно создавать на стеке; состояние updater и hcan должно существовать всё время работы загрузчика.

Flash, подтверждения и reset

  • Запись последовательная, блоки по восемь байт; неполная аппаратная единица допустима только в конце образа и дополняется FF. CRC учитывает полезную длину.
  • HAL-ошибки и readback каждого слова проверяются; после erase/program Flash снова блокируется, включая обработанные отказы. На F407 перед readback вызывается FLASH_FlushCaches, чтобы соседние записанные слова не читались из устаревшей строки Flash-кэша; состояние включения кэшей сохраняется HAL.
  • VERIFY перечитывает Flash, сравнивает её CRC и проверяет MSP/Thumb reset vector. Точка входа должна принадлежать фактическому образу, MSP — основной SRAM, с выравниванием восемь байт. CCM F407 в данном профиле для стека не используется.
  • COMMIT повторно проверяет образ и устанавливает признак в RAM. REBOOT разрешён только в состоянии COMMITTED. Ответ перед reset должен завершиться с TXOK; отсутствие mailbox, ошибка шины или тайм-аут 100 мс не вызывают reset. Для этого HAL tick должен работать при ожидании TX.
  • BUSY перед стиранием, между секторами F407 и после erase сохраняет активность сессии. На однобанковой Flash код не исполняется во время аппаратного стирания; непрерывные ответы в этот интервал не гарантируются. Настройте тайм-аут клиента больше максимального времени стирания одной аппаратной операции.

Запуск приложения и потеря питания

Порт не меняет Option Bytes, защиту секторов и VDD; F407 требует 2,7..3,6 В для программирования x32. Переход из работающего приложения в загрузчик, backup/SRAM-флаг запроса, отключение периферии и безопасная замена MSP остаются в main и startup устройства.

*_vectors_valid() проверяет только векторы и диапазоны. После внешнего reset этого недостаточно для доказательства целостности образа: RAM-признак COMMIT потерян, а частично записанное приложение уже может иметь корректные векторы. Эти профили сохраняют исходную single-slot модель без постоянных метаданных, rollback, resume после питания и аутентификации. Для защищённого запуска проекту нужен отдельный постоянный manifest с полной проверкой образа.

Проверка

python tests/run_tests.py из корня protocan-boot запускает три production-порта с моделью HAL и Flash, наряду с существующими проверками ядра и TI-портов. Можно также использовать обычные CMake/CTest: цели test_stm32f103, test_stm32f407, test_stm32g474 работают на Windows и POSIX.

Проверяются все хвосты CAN-блока, полный ERASE/DATA/VERIFY/COMMIT/REBOOT, повреждение readback, отказы HAL/TX, фильтрация RX и сохранность памяти перед приложением и за верхней границей; для G474 проверяются оба DBANK-режима, переход между банками, запрет swap, ёмкость Flash и старое shifted-DLC HAL. Эти тесты не заменяют проверку на реальной плате с её linker, питанием, трансивером и SysTick.