Но надо еще его дорабатывать + заготовка для протокола приема (не работает скорее всего, просто из чатгпт вставил)
150 lines
6.1 KiB
C
150 lines
6.1 KiB
C
#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
|