Files
templates/c/protocan-boot/ports/stm32f407/boot_control_hal.c
T
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

30 lines
4.7 KiB
C

#include "boot_control_hal.h" /* Подключает совместимый API приложения climate. */
#include "boot_profile.h" /* Получает общий адрес SRAM-запроса и карту Flash. */
#include "pcan_boot_config.h" /* Идентичность прибора остаётся настройкой проекта, общей для boot и app. */
HAL_StatusTypeDef CanBootControl_Start(CAN_HandleTypeDef *can) /* Сохраняет прежнюю настройку выделенного CAN приложения. */
{ /* Новые приложения с DeviceCan используют только Handle и собственные адресные фильтры. */
CAN_FilterTypeDef filter = {0}; /* Исключает неопределённые поля аппаратной конфигурации. */
if (can == NULL) return HAL_ERROR; /* Не обращается к отсутствующему HAL handle. */
filter.FilterBank = 0U; filter.FilterMode = CAN_FILTERMODE_IDMASK; filter.FilterScale = CAN_FILTERSCALE_32BIT; /* Сохраняет широкую фильтрацию старого выделенного канала; адрес проверяется программно. */
filter.FilterFIFOAssignment = CAN_RX_FIFO0; filter.FilterActivation = ENABLE; filter.SlaveStartFilterBank = 14U; /* Использует FIFO0 и штатное разделение банков CAN1/CAN2. */
if (HAL_CAN_ConfigFilter(can, &filter) != HAL_OK) return HAL_ERROR; /* Не запускает CAN с неподтверждённым фильтром. */
return HAL_CAN_Start(can); /* Возвращает вызывающему приложению фактический результат запуска. */
} /* Завершает совместимую настройку транспорта приложения. */
void CanBootControl_Poll(CAN_HandleTypeDef *can) /* Поддерживает старые приложения без отдельного распределителя входящих кадров. */
{ /* Приём ограничен одним кадром, чтобы не блокировать главный цикл. */
CAN_RxHeaderTypeDef header; uint8_t data[8]; /* Выделяет полный буфер classic CAN независимо от входящего DLC. */
if (can != NULL && HAL_CAN_GetRxFifoFillLevel(can, CAN_RX_FIFO0) != 0U && HAL_CAN_GetRxMessage(can, CAN_RX_FIFO0, &header, data) == HAL_OK) (void)CanBootControl_Handle(&header, data); /* Передаёт только успешно принятый кадр общему обработчику. */
} /* Завершает опрос канала совместимости. */
uint8_t CanBootControl_Handle(const CAN_RxHeaderTypeDef *header, const uint8_t data[8]) /* Запускает обновление только для собственного адреса и ненулевой сессии. */
{ /* Ответ ENTER_BOOT отправляет уже загрузчик после повторного запроса клиента. */
uint32_t id; /* Сохраняет проверенный расширенный CAN ID запроса. */
(void)data; /* ENTER_BOOT не содержит payload и не должен читать входной буфер. */
if (header == NULL || header->IDE != CAN_ID_EXT || header->RTR != CAN_RTR_DATA || header->DLC != 0U || header->ExtId > 0x1FFFFFFFUL) return 0U; /* Отвергает стандартные, remote и ошибочно дополненные запросы. */
id = header->ExtId; /* Извлекает идентификатор только после проверки внешнего заголовка. */
if (((id >> 27U) & 1U) != 0U || ((id >> 24U) & 7U) != PCAN_BOOT_DEVICE_TYPE || ((id >> 20U) & 15U) != PCAN_BOOT_DEVICE_ID || ((id >> 16U) & 15U) != 9U || (id & 255U) != 2U || ((id >> 8U) & 255U) == 0U) return 0U; /* Сопоставляет Route=0, адрес, BOOT_CONTROL=9, ENTER_BOOT=2 и SessionID != 0. */
*((volatile uint32_t *)(uintptr_t)PCAN_BOOT_REQUEST_ADDRESS) = PCAN_BOOT_REQUEST_MAGIC; /* Сохраняет одноразовый запрос в слове SRAM, исключённом из linker-стека. */
__DSB(); /* Дожидается записи SRAM перед системным reset. */
NVIC_SystemReset(); /* Передаёт управление общему загрузчику без подтверждения из приложения. */
return 1U; /* Позволяет тестовой модели и старому диспетчеру отметить обработанный запрос. */
} /* Завершает безопасную проверку входа в загрузчик. */