#ifndef __BOOTLOADER_H #define __BOOTLOADER_H #include "boot_project_setup.h" #include "string.h" /* --- Настройка: подставьте значения для вашей MCU --- */ /* Адрес начала приложения (используется в вашем коде) */ #ifndef MAIN_APP_START_ADR #error "MAIN_APP_START_ADR must be defined" #endif /* Flash boundaries: подставьте реальные границы флеш-памяти вашего MCU */ #ifndef FLASH_START_ADR #define FLASH_START_ADR MAIN_APP_START_ADR #endif #ifndef FLASH_END_ADR #define FLASH_END_ADR FLASH_BASE + (*((uint16_t*)FLASHSIZE_BASE) * 1024U) #endif /* SRAM boundaries: подставьте реальные адреса SRAM вашей MCU */ #ifndef SRAM_START_ADR #define SRAM_START_ADR 0x20000000UL #endif #ifndef SRAM_END_ADR #define SRAM_END_ADR 0x2003FFFFUL #endif /** * @brief Значение ключа, указывающее что основное приложение записано */ #define BL_KEY_APP_WRITTEN 0xAAAA5555 /** @brief Получить сохранённый код ошибки из BKP */ #define GetErrorCode() BKP->DR1 /** @brief Получить счетчик ошибок из BKP */ #define GetErrorCnt() BKP->DR2 /** * @brief Сохранение кода ошибки и инкремент счетчика * @param code Код ошибки * @details * Включаем тактирование PWR и BKP (APB1) и разрешаем доступ к BKP domain * Записываем напрямую в регистры RCC/APB1ENR и PWR->CR * Записываем код ошибки и счётчик ошибок */ #define SaveErrorCode(code) do{ \ RCC->APB1ENR |= (RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN); \ PWR->CR |= PWR_CR_DBP; \ GetErrorCode() = code; \ GetErrorCnt() = GetErrorCnt() + 1; \ }while(0u); /** * @brief Очистка кода ошибки и счетчика ошибок */ #define ClearErrorCode(code) do{ \ RCC->APB1ENR |= (RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN); \ PWR->CR |= PWR_CR_DBP; \ GetErrorCode() = 0; \ GetErrorCnt() = 0; \ }while(0u); /** * @brief Команды для управления бутлоадером */ typedef enum { NO_CMD = 0x00, ///< Нет комманды CMD_ERASE = 0x01, ///< Команда на стирание прошивки CMD_START_RECEIVE, ///< Команда на старт приема прошивки CMD_WRITE, ///< Команда на запись блока прошивки CMD_GOTOAPP, ///< Команда на переход в приложение CMD_RESET, ///< Команда на переход в приложение CMD_GOTOBOOT, ///< Команда на переход в приложение CMD_PING = 0xAA, ///< Команда на пинг }BootloaderCommand_t; /** * @brief Состояния конечного автомата бутлоадера */ typedef enum { BL_STATE_INIT = 0, ///< Состояние: инициализация BL_STATE_JUMP_TO_APP, ///< Состояние: запуск приложения BL_STATE_IDLE, ///< Состояние: ожидание команд BL_STATE_ERASE, ///< Состояние: стирание флеша BL_STATE_RECEIVE_UART, ///< Состояние: прием прошивки по UART BL_STATE_RECEIVE_CAN, ///< Состояние: прием прошивки по CAN BL_STATE_WRITE, ///< Состояние: запись данных BL_STATE_ERROR, ///< Состояние: ошибка BL_STATE_RESET, ///< Состояние: сброс контролллера BL_STATE_JUMP_TO_BOOT, ///< Состояние: запуск приложения } BootloaderState_t; /** * @brief Ошибки бутлоадера */ typedef union { uint16_t all; ///< Все ошибки одним числом struct { unsigned hardfault_cycle:1; ///< Прерывание HardFault unsigned memmanage_cycle:1; ///< Прерывание MemManage unsigned watchdog_reset:1; ///< Watchdog сброс unsigned unknown_cmd:1; ///< Неизвестная команда unsigned erase_err:1; ///< Ошибка стирания unsigned write_err:1; ///< Ошибка записи unsigned verify_err:1; ///< Ошибка проверки прошивки unsigned overflow:1; ///< Слишком много данных unsigned timeout_receive:1; ///< Таймаут приёма unsigned crc_err:1; ///< Ошибка CRC } bit; } BootloaderError_t; /** * @brief Дескриптор бутлоадера */ typedef struct { BootloaderState_t state; ///< текущее состояние бутлоадера BootloaderError_t error; ///< ошибки бутлоадера uint32_t addr; ///< текущий адрес прошивки uint8_t fw_size; ///< размер прошивки uint8_t fw_buffer[PAGE_SIZE]; ///< буфер для приема прошивки (UART/CAN) uint32_t fw_len; ///< длина принятого пакета uint32_t fw_crc; ///< контрольная сумма прошивки UART_HandleTypeDef *huart; ///< хендлер UART CAN_HandleTypeDef *hcan; ///< хендер CAN CAN_TxHeaderTypeDef TxHeader; ///< Заголовок CAN сообщения для отправки BootloaderState_t prev_state; ///< предыдущее состояние бутлоадера } Bootloader_t; /* Основная задача бутлоадера */ void Bootloader_Task(Bootloader_t *bl); /* Настройка тактирования */ void Boot_SystemClock_Config(void); /* Хендлер ошибки */ void Error_Handler(void); /* CRC */ uint32_t CRC32_Compute(const uint8_t* data, uint32_t length); #endif //__BOOTLOADER_H