структуризирован бутлоадер. работает
надо по протоколу подумать еще, доработать его и описать
This commit is contained in:
11
Core/Bootloader/Inc/boot_can.h
Normal file
11
Core/Bootloader/Inc/boot_can.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef __BOOT_CAN_H
|
||||
#define __BOOT_CAN_H
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
extern CAN_HandleTypeDef hcan_boot;
|
||||
|
||||
void MX_BOOT_CAN_Init(void);
|
||||
void Bootloader_CAN_Receive_Page(Bootloader_t *bl);
|
||||
|
||||
#endif //__BOOT_CAN_H
|
||||
14
Core/Bootloader/Inc/boot_flash.h
Normal file
14
Core/Bootloader/Inc/boot_flash.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef __BOOT_FLASH_H
|
||||
#define __BOOT_FLASH_H
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
|
||||
// FOR APP FLASHING
|
||||
HAL_StatusTypeDef FLASH_Erase_App(void);
|
||||
HAL_StatusTypeDef FLASH_Write_Page(uint32_t *Address, uint8_t *Data, int Data_size);
|
||||
|
||||
// SERVICE
|
||||
HAL_StatusTypeDef FLASH_Write_Word(uint32_t Address, uint64_t Data);
|
||||
|
||||
#endif //__BOOT_FLASH_H
|
||||
14
Core/Bootloader/Inc/boot_gpio.h
Normal file
14
Core/Bootloader/Inc/boot_gpio.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef __BOOT_GPIO_H
|
||||
#define __BOOT_GPIO_H
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
|
||||
#define LED_BOOT_ON() CLEAR_BIT(LED_BOOT_GPIO_Port->ODR, LED_BOOT_Pin)
|
||||
#define LED_BOOT_OFF() SET_BIT(LED_BOOT_GPIO_Port->ODR, LED_BOOT_Pin)
|
||||
#define LED_BOOT_TOOGLE() LED_BOOT_GPIO_Port->ODR ^= LED_BOOT_Pin
|
||||
|
||||
|
||||
void MX_BOOT_GPIO_Init(void);
|
||||
|
||||
#endif //__BOOT_GPIO_H
|
||||
26
Core/Bootloader/Inc/boot_jump.h
Normal file
26
Core/Bootloader/Inc/boot_jump.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef __BOOT_JUMP_H
|
||||
#define __BOOT_JUMP_H
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
/* Инициализация приложения */
|
||||
void App_Init(void);
|
||||
/* Переход в бутлоадер */
|
||||
void JumpToBootloader(void);
|
||||
/* Переход к основному приложению */
|
||||
void JumpToApplocation(void);
|
||||
|
||||
/* Сброс ключа BOOT в Flash */
|
||||
void ResetKey(void);
|
||||
/* Установка ключа BOOT в Flash */
|
||||
void SetKey(void);
|
||||
/* Чтение ключа BOOT из Flash */
|
||||
uint32_t ReadKey(void);
|
||||
/* Стирание ключа BOOT в Flash */
|
||||
void EraseKey(void);
|
||||
|
||||
/* Проверка валидности прошивки перед переходом к приложению */
|
||||
HAL_StatusTypeDef Verify_Firmware(void);
|
||||
|
||||
|
||||
#endif //__BOOT_JUMP_H
|
||||
74
Core/Bootloader/Inc/boot_project_setup.h
Normal file
74
Core/Bootloader/Inc/boot_project_setup.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifndef __BOOT_SETUP_H
|
||||
#define __BOOT_SETUP_H
|
||||
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
// ======================== BOOTLOADER CONFIG ========================
|
||||
|
||||
// ---------- MAIN APPLICATION defines ----------
|
||||
// Адрес и страницы Flash для основного приложения
|
||||
// MAIN_APP_START_ADR – начало кода основного приложения
|
||||
#define MAIN_APP_START_ADR (uint32_t)0x0800C000UL
|
||||
#define MAIN_APP_PAGE 21 // страница, с которой начинается приложение
|
||||
#define MAIN_APP_NUM_OF_PAGE 250-MAIN_APP_PAGE // количество страниц, отведённых под приложение
|
||||
|
||||
// ---------- KEY defines ----------
|
||||
// Адрес и страница Flash для хранения ключа бутлоадера
|
||||
// Ключ используется для проверки, записано ли приложение корректно
|
||||
#define BOOTLOADER_KEY_ADR (uint32_t)0x08009800UL // физический адрес ключа
|
||||
#define BOOTLOADER_KEY_PAGE 20 // страница флеш, на которой хранится ключ
|
||||
|
||||
// ---------- RECEIVE defines ----------
|
||||
// Настройки приёма прошивки
|
||||
#define FW_RECEIVE_TIMEOUT_MS 500 // таймаут приёма одного байта прошивки (мс)
|
||||
#define PAGE_SIZE 2048 // размер блока (страницы) прошивки для приёма и записи в Flash
|
||||
// должен быть таким, чтобы размер страниц Flash был кратен ему
|
||||
|
||||
// ---------- LED defines ----------
|
||||
#define LED_BOOT_Pin GPIO_PIN_5
|
||||
#define LED_BOOT_GPIO_Port GPIOB
|
||||
|
||||
// ======================== RCC (CLOCK) defines ========================
|
||||
|
||||
// Макросы для включения тактирования периферии бутлоадера
|
||||
#define __RCC_LED_BOOT_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE() // тактирование UART
|
||||
#define __RCC_UART_BOOT_CLK_ENABLE() __HAL_RCC_USART3_CLK_ENABLE() // тактирование UART
|
||||
#define __RCC_UART_PORT_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE() // тактирование порта UART
|
||||
#define __RCC_CAN_BOOT_CLK_ENABLE() __HAL_RCC_CAN1_CLK_ENABLE() // тактирование CAN
|
||||
#define __RCC_CAN_PORT_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() // тактирование порта CAN
|
||||
|
||||
// ======================== UART defines ========================
|
||||
|
||||
// Аппаратный UART и скорость передачи
|
||||
#define UART_BOOT USART3
|
||||
#define UART_SPEED 256000
|
||||
#define UART_BOOT_IRQn USART3_IRQn
|
||||
|
||||
// Порт и пины UART
|
||||
#define UART_PORT GPIOB
|
||||
#define UART_PIN_TX GPIO_PIN_10
|
||||
#define UART_PIN_RX GPIO_PIN_11
|
||||
|
||||
// ======================== CAN defines ========================
|
||||
|
||||
// Аппаратный CAN и режим работы
|
||||
#define CAN_BOOT CAN1
|
||||
#define CAN_MODE CAN_MODE_NORMAL
|
||||
|
||||
// Настройка скорости CAN при 8 MHz
|
||||
// ------------|-----------|-----------|-----------
|
||||
// CAN speed | Prescaler | BS1 | BS2
|
||||
// ------------|-----------|-----------|-----------
|
||||
// 125 kbps | 4 | 13TQ | 2TQ
|
||||
// 250 kbps | 2 | 13TQ | 2TQ
|
||||
// 500 kbps | 1 | 13TQ | 2TQ
|
||||
#define CAN_SPEED_PRESCALER 4
|
||||
#define CAN_SPEED_BS1 CAN_BS1_13TQ
|
||||
#define CAN_SPEED_BS2 CAN_BS2_2TQ
|
||||
|
||||
// Порт и пины CAN
|
||||
#define CAN_PORT GPIOA
|
||||
#define CAN_PIN_RX GPIO_PIN_11
|
||||
#define CAN_PIN_TX GPIO_PIN_12
|
||||
|
||||
#endif //__BOOT_SETUP_H
|
||||
11
Core/Bootloader/Inc/boot_uart.h
Normal file
11
Core/Bootloader/Inc/boot_uart.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef __BOOT_UART_H
|
||||
#define __BOOT_UART_H
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
extern UART_HandleTypeDef huart_boot;
|
||||
|
||||
void MX_BOOT_UART_Init(void);
|
||||
void Bootloader_UART_Receive_Page(Bootloader_t *bl);
|
||||
|
||||
#endif //__BOOT_UART_H
|
||||
145
Core/Bootloader/Inc/bootloader.h
Normal file
145
Core/Bootloader/Inc/bootloader.h
Normal file
@@ -0,0 +1,145 @@
|
||||
#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 {
|
||||
CMD_ERASE = 0x01, ///< Команда на стирание прошивки
|
||||
CMD_START_RECEIVE, ///< Команда на старт приема прошивки
|
||||
CMD_WRITE, ///< Команда на запись блока прошивки
|
||||
CMD_GOTOAPP, ///< Команда на переход в приложение
|
||||
CMD_RESET, ///< Команда на переход в приложение
|
||||
CMD_GOTOBOOT, ///< Команда на переход в приложение
|
||||
}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 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);
|
||||
|
||||
#endif //__BOOTLOADER_H
|
||||
Reference in New Issue
Block a user