uart для платы вэп + структурирован чуть проект и описан бутлоадер
Но надо еще его дорабатывать + заготовка для протокола приема (не работает скорее всего, просто из чатгпт вставил)
This commit is contained in:
parent
0e834dfe3d
commit
c61c438b8c
@ -5,7 +5,16 @@
|
||||
|
||||
extern CAN_HandleTypeDef hcan_boot;
|
||||
|
||||
extern CAN_TxHeaderTypeDef TxHeaderBoot;
|
||||
extern CAN_RxHeaderTypeDef RxHeaderBoot;
|
||||
extern uint32_t TxMailBoxBoot;
|
||||
extern uint8_t TXDataBoot[8];
|
||||
|
||||
/* Инициализация CAN */
|
||||
void MX_BOOT_CAN_Init(void);
|
||||
/* Приём команды по CAN по протоколу */
|
||||
BootloaderCommand_t Bootloader_CAN_Receive(Bootloader_t *bl);
|
||||
/* Приём CAN: страница + CRC */
|
||||
void Bootloader_CAN_Receive_Page(Bootloader_t *bl);
|
||||
|
||||
#endif //__BOOT_CAN_H
|
@ -32,20 +32,19 @@
|
||||
|
||||
// Макросы для включения тактирования периферии бутлоадера
|
||||
#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_UART_BOOT_CLK_ENABLE() __HAL_RCC_UART4_CLK_ENABLE() // тактирование UART
|
||||
#define __RCC_UART_PORT_CLK_ENABLE() __HAL_RCC_GPIOC_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
|
||||
#define UART_BOOT UART4
|
||||
#define UART_SPEED 115200
|
||||
|
||||
// Порт и пины UART
|
||||
#define UART_PORT GPIOB
|
||||
#define UART_PORT GPIOC
|
||||
#define UART_PIN_TX GPIO_PIN_10
|
||||
#define UART_PIN_RX GPIO_PIN_11
|
||||
|
||||
|
@ -5,7 +5,11 @@
|
||||
|
||||
extern UART_HandleTypeDef huart_boot;
|
||||
|
||||
/* Инициализация UART */
|
||||
void MX_BOOT_UART_Init(void);
|
||||
/* Приём команды по UART по протоколу */
|
||||
BootloaderCommand_t Bootloader_UART_Receive(Bootloader_t *bl);
|
||||
/* Приём UART: страница + CRC */
|
||||
void Bootloader_UART_Receive_Page(Bootloader_t *bl);
|
||||
|
||||
#endif //__BOOT_UART_H
|
@ -71,12 +71,14 @@
|
||||
* @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;
|
||||
|
||||
/**
|
||||
@ -108,6 +110,7 @@ typedef union {
|
||||
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;
|
||||
@ -119,7 +122,7 @@ typedef union {
|
||||
*/
|
||||
typedef struct {
|
||||
BootloaderState_t state; ///< текущее состояние бутлоадера
|
||||
BootloaderError_t error;
|
||||
BootloaderError_t error; ///< ошибки бутлоадера
|
||||
|
||||
uint32_t addr; ///< текущий адрес прошивки
|
||||
|
||||
@ -141,5 +144,7 @@ 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
|
@ -3,6 +3,12 @@
|
||||
|
||||
CAN_HandleTypeDef hcan_boot;
|
||||
|
||||
CAN_TxHeaderTypeDef TxHeaderBoot;
|
||||
CAN_RxHeaderTypeDef RxHeaderBoot;
|
||||
uint32_t TxMailBoxBoot = 0;
|
||||
uint8_t TXDataBoot[8] = {0};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Инициализация CAN для бутлоадера
|
||||
*/
|
||||
@ -68,69 +74,89 @@ void MX_BOOT_CAN_Init(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Приём команды по CAN по протоколу:
|
||||
* @param bl: указатель на структуру бутлоадера
|
||||
* @retval BootloaderCommand_t — принятая команда или NO_CMD
|
||||
*/
|
||||
BootloaderCommand_t Bootloader_CAN_Receive(Bootloader_t *bl)
|
||||
{
|
||||
BootloaderCommand_t cmd = NO_CMD;
|
||||
uint8_t canData[8];
|
||||
if (HAL_CAN_GetRxFifoFillLevel(bl->hcan, CAN_RX_FIFO0) > 0)
|
||||
{
|
||||
if (HAL_CAN_GetRxMessage(bl->hcan, CAN_RX_FIFO0, &RxHeaderBoot, canData) == HAL_OK)
|
||||
{
|
||||
cmd = canData[0]; // предполагаем, что команда в первом байте
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Приём CAN: страница + CRC
|
||||
* @param bl: указатель на структуру бутлоадера
|
||||
*/
|
||||
void Bootloader_CAN_Receive_Page(Bootloader_t *bl)
|
||||
{
|
||||
uint16_t bytes_received = 0;
|
||||
CAN_RxHeaderTypeDef canHeader;
|
||||
uint8_t canData[8];
|
||||
uint32_t start_tick = HAL_GetTick();
|
||||
uint16_t bytes_received = 0;
|
||||
CAN_RxHeaderTypeDef canHeader;
|
||||
uint8_t canData[8];
|
||||
uint32_t start_tick = HAL_GetTick();
|
||||
|
||||
// Приём страницы прошивки
|
||||
while(bytes_received < PAGE_SIZE)
|
||||
{
|
||||
if(HAL_CAN_GetRxFifoFillLevel(bl->hcan, CAN_RX_FIFO0) > 0)
|
||||
{
|
||||
if(HAL_CAN_GetRxMessage(bl->hcan, CAN_RX_FIFO0, &canHeader, canData) == HAL_OK)
|
||||
{
|
||||
uint8_t len = canHeader.DLC;
|
||||
if(bytes_received + len > PAGE_SIZE)
|
||||
len = PAGE_SIZE - bytes_received;
|
||||
// Приём страницы прошивки
|
||||
while(bytes_received < PAGE_SIZE)
|
||||
{
|
||||
if(HAL_CAN_GetRxFifoFillLevel(bl->hcan, CAN_RX_FIFO0) > 0)
|
||||
{
|
||||
if(HAL_CAN_GetRxMessage(bl->hcan, CAN_RX_FIFO0, &canHeader, canData) == HAL_OK)
|
||||
{
|
||||
uint8_t len = canHeader.DLC;
|
||||
if(bytes_received + len > PAGE_SIZE)
|
||||
len = PAGE_SIZE - bytes_received;
|
||||
|
||||
memcpy(&bl->fw_buffer[bytes_received], canData, len);
|
||||
bytes_received += len;
|
||||
start_tick = HAL_GetTick(); // сброс таймаута
|
||||
LED_BOOT_TOOGLE();
|
||||
}
|
||||
}
|
||||
memcpy(&bl->fw_buffer[bytes_received], canData, len);
|
||||
bytes_received += len;
|
||||
start_tick = HAL_GetTick(); // сброс таймаута
|
||||
LED_BOOT_TOOGLE();
|
||||
}
|
||||
}
|
||||
|
||||
// проверка таймаута
|
||||
if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS)
|
||||
{
|
||||
bl->error.bit.timeout_receive = 1;
|
||||
bl->state = BL_STATE_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Приём CRC (4 байта)
|
||||
start_tick = HAL_GetTick(); // сброс таймаута
|
||||
while(1)
|
||||
{
|
||||
if(HAL_CAN_GetRxFifoFillLevel(bl->hcan, CAN_RX_FIFO0) > 0)
|
||||
{
|
||||
if(HAL_CAN_GetRxMessage(bl->hcan, CAN_RX_FIFO0, &canHeader, canData) == HAL_OK)
|
||||
{
|
||||
// CRC в первых 4 байтах пакета
|
||||
bl->fw_crc = (canData[0] << 24) |
|
||||
(canData[1] << 16) |
|
||||
(canData[2] << 8) |
|
||||
canData[3];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// проверка таймаута
|
||||
if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS)
|
||||
{
|
||||
bl->error.bit.timeout_receive = 1;
|
||||
bl->state = BL_STATE_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Приём CRC (4 байта)
|
||||
start_tick = HAL_GetTick(); // сброс таймаута
|
||||
while(1)
|
||||
{
|
||||
if(HAL_CAN_GetRxFifoFillLevel(bl->hcan, CAN_RX_FIFO0) > 0)
|
||||
{
|
||||
if(HAL_CAN_GetRxMessage(bl->hcan, CAN_RX_FIFO0, &canHeader, canData) == HAL_OK)
|
||||
{
|
||||
// CRC в первых 4 байтах пакета
|
||||
bl->fw_crc = (canData[0] << 24) |
|
||||
(canData[1] << 16) |
|
||||
(canData[2] << 8) |
|
||||
canData[3];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Таймаут
|
||||
if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS)
|
||||
{
|
||||
bl->error.bit.timeout_receive = 1;
|
||||
bl->state = BL_STATE_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Таймаут
|
||||
if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS)
|
||||
{
|
||||
bl->error.bit.timeout_receive = 1;
|
||||
bl->state = BL_STATE_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bl->fw_len = PAGE_SIZE;
|
||||
bl->state = BL_STATE_IDLE;
|
||||
bl->fw_len = PAGE_SIZE;
|
||||
bl->state = BL_STATE_IDLE;
|
||||
}
|
||||
|
||||
|
@ -15,12 +15,16 @@ void MX_BOOT_UART_Init(void)
|
||||
__RCC_UART_PORT_CLK_ENABLE();
|
||||
|
||||
/* Настройка GPIO TX/RX */
|
||||
GPIO_InitStruct.Pin = UART_PIN_TX | UART_PIN_RX;
|
||||
GPIO_InitStruct.Pin = UART_PIN_TX;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
HAL_GPIO_Init(UART_PORT, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = UART_PIN_RX;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(UART_PORT, &GPIO_InitStruct);
|
||||
|
||||
/* Настройка UART */
|
||||
huart_boot.Instance = UART_BOOT;
|
||||
huart_boot.Init.BaudRate = UART_SPEED;
|
||||
@ -37,9 +41,96 @@ void MX_BOOT_UART_Init(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Приём команды по UART по протоколу:
|
||||
* [SOH][CMD][LEN_H][LEN_L][DATA ...][CRC32_H..CRC32_L]
|
||||
* Idle — не блокируется до SOH
|
||||
* После SOH — блокирующий приём всего пакета
|
||||
* @param bl: указатель на структуру бутлоадера
|
||||
* @retval BootloaderCommand_t — принятая команда или NO_CMD
|
||||
*/
|
||||
BootloaderCommand_t Bootloader_UART_Receive(Bootloader_t *bl)
|
||||
{
|
||||
BootloaderCommand_t cmd;
|
||||
uint8_t byte = 0;
|
||||
HAL_StatusTypeDef res;
|
||||
|
||||
// -----------------------------
|
||||
// 1. Ждём SOH в неблокирующем режиме
|
||||
res = HAL_UART_Receive(bl->huart, &byte, 1, 1); // 1 ms таймаут
|
||||
if(res != HAL_OK)
|
||||
return NO_CMD; // пакета нет
|
||||
|
||||
if(byte != 0xAA)
|
||||
return NO_CMD; // игнорируем мусор
|
||||
|
||||
// -----------------------------
|
||||
// 2. Блокирующий приём CMD + LEN_H + LEN_L
|
||||
uint8_t header[3];
|
||||
res = HAL_UART_Receive(bl->huart, header, 3, FW_RECEIVE_TIMEOUT_MS);
|
||||
if(res != HAL_OK)
|
||||
{
|
||||
bl->error.bit.timeout_receive = 1;
|
||||
bl->state = BL_STATE_ERROR;
|
||||
return NO_CMD;
|
||||
}
|
||||
|
||||
cmd = (BootloaderCommand_t)header[0];
|
||||
bl->fw_len = ((uint16_t)header[1] << 8) | header[2];
|
||||
|
||||
if(bl->fw_len > PAGE_SIZE)
|
||||
{
|
||||
bl->error.bit.overflow = 1;
|
||||
bl->state = BL_STATE_ERROR;
|
||||
return NO_CMD;
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// 3. Блокирующий приём DATA
|
||||
for(uint16_t i = 0; i < bl->fw_len; i++)
|
||||
{
|
||||
res = HAL_UART_Receive(bl->huart, &bl->fw_buffer[i], 1, FW_RECEIVE_TIMEOUT_MS);
|
||||
if(res != HAL_OK)
|
||||
{
|
||||
bl->error.bit.timeout_receive = 1;
|
||||
bl->state = BL_STATE_ERROR;
|
||||
return NO_CMD;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// 4. Приём CRC32
|
||||
uint8_t crc_buf[4];
|
||||
res = HAL_UART_Receive(bl->huart, crc_buf, 4, FW_RECEIVE_TIMEOUT_MS);
|
||||
if(res != HAL_OK)
|
||||
{
|
||||
bl->error.bit.timeout_receive = 1;
|
||||
bl->state = BL_STATE_ERROR;
|
||||
return NO_CMD;
|
||||
}
|
||||
bl->fw_crc = (crc_buf[0]<<24) | (crc_buf[1]<<16) | (crc_buf[2]<<8) | crc_buf[3];
|
||||
|
||||
// -----------------------------
|
||||
// 5. Проверка CRC по всему пакету (CMD + LEN + DATA)
|
||||
uint32_t crc_calc = CRC32_Compute(header, 3); // CMD + LEN
|
||||
crc_calc = CRC32_Compute(bl->fw_buffer, bl->fw_len) ^ crc_calc; // DATA
|
||||
|
||||
if(crc_calc != bl->fw_crc)
|
||||
{
|
||||
bl->error.bit.crc_err = 1;
|
||||
bl->state = BL_STATE_ERROR;
|
||||
return NO_CMD;
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// 6. Всё верно — возвращаем команду
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Приём UART: страница + CRC
|
||||
* @param bl: указатель на структуру бутлоадера
|
||||
*/
|
||||
void Bootloader_UART_Receive_Page(Bootloader_t *bl)
|
||||
{
|
||||
|
@ -40,17 +40,12 @@
|
||||
// Глобальные переменные для HAL-периферии
|
||||
// -----------------------------------------------------------------------------
|
||||
HAL_StatusTypeDef res_hal;
|
||||
CAN_TxHeaderTypeDef TxHeaderBoot;
|
||||
CAN_RxHeaderTypeDef RxHeaderBoot;
|
||||
uint32_t TxMailBoxBoot = 0;
|
||||
uint8_t TXDataBoot[8] = {0};
|
||||
uint32_t led_err_lasttick = 0;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Локальные (static) функции
|
||||
// -----------------------------------------------------------------------------
|
||||
static uint8_t Receive_FW_Command(Bootloader_t *bl);
|
||||
static uint32_t CRC32_Compute(const uint8_t* data, uint32_t length);
|
||||
|
||||
/**
|
||||
* @brief Проверка после сброса MCU.
|
||||
@ -72,7 +67,8 @@ void Bootloader_StartCheck(Bootloader_t *bl)
|
||||
// Чтение сохранённого кода ошибки и количества сбоев
|
||||
ErrCodeBoot = GetErrorCode();
|
||||
ErrCntBoot = GetErrorCnt();
|
||||
// Если ошибок было больше 5, фиксируем тип ошибки
|
||||
// Если ошибок было больше 5, фиксируем тип ошибки и уходим в бутлоадер
|
||||
// Данные ошибки фиксируются только в прерываниях бутлоадера. Hardfault в прерывании приложения не считается
|
||||
if(ErrCntBoot > 5)
|
||||
{
|
||||
ClearErrorCode();
|
||||
@ -385,6 +381,8 @@ static uint8_t SetBootState(Bootloader_t *bl, BootloaderCommand_t cmd, uint8_t u
|
||||
return 0x00;
|
||||
case CMD_GOTOBOOT: // команда: прыжок в бутлоадер
|
||||
bl->state = BL_STATE_JUMP_TO_BOOT;
|
||||
case CMD_PING: // команда: пинг, отправка текущего состояния бутлоадера
|
||||
bl->prev_state = 0; // обнуляем предыдущее состоояние, чтобы снова отправить комманду с текущим состоянием
|
||||
return 0x00;
|
||||
|
||||
default:
|
||||
@ -406,8 +404,8 @@ static uint8_t Receive_FW_Command(Bootloader_t *bl)
|
||||
// ---------------------------
|
||||
// Чтение команды по UART
|
||||
// ---------------------------
|
||||
res = HAL_UART_Receive(bl->huart, &cmd, 1, 10); // таймаут 10 ms
|
||||
if (res == HAL_OK)
|
||||
cmd = Bootloader_UART_Receive(bl); // таймаут 10 ms
|
||||
if (cmd != NO_CMD)
|
||||
{
|
||||
ret_val = SetBootState(bl, cmd, 1);
|
||||
}
|
||||
@ -415,14 +413,10 @@ static uint8_t Receive_FW_Command(Bootloader_t *bl)
|
||||
// ---------------------------
|
||||
// Чтение команды по CAN
|
||||
// ---------------------------
|
||||
uint8_t canData[8];
|
||||
if (HAL_CAN_GetRxFifoFillLevel(bl->hcan, CAN_RX_FIFO0) > 0)
|
||||
cmd = Bootloader_CAN_Receive(bl);
|
||||
if (cmd != NO_CMD)
|
||||
{
|
||||
if (HAL_CAN_GetRxMessage(bl->hcan, CAN_RX_FIFO0, &RxHeaderBoot, canData) == HAL_OK)
|
||||
{
|
||||
cmd = canData[0]; // предполагаем, что команда в первом байте
|
||||
ret_val = SetBootState(bl, cmd, 0);
|
||||
}
|
||||
ret_val = SetBootState(bl, cmd, 0);
|
||||
}
|
||||
|
||||
#ifdef TEST_CAN
|
||||
@ -451,7 +445,7 @@ static uint8_t Receive_FW_Command(Bootloader_t *bl)
|
||||
* @param length: длина массива в байтах
|
||||
* @retval CRC32 вычисленное значение
|
||||
*/
|
||||
static uint32_t CRC32_Compute(const uint8_t* data, uint32_t length)
|
||||
uint32_t CRC32_Compute(const uint8_t* data, uint32_t length)
|
||||
{
|
||||
const uint32_t polynomial = 0x04C11DB7;
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
|
16
MDK-ARM/bootloader/uksvep_2_2_v1.sct
Normal file
16
MDK-ARM/bootloader/uksvep_2_2_v1.sct
Normal file
@ -0,0 +1,16 @@
|
||||
; *************************************************************
|
||||
; *** Scatter-Loading Description File generated by uVision ***
|
||||
; *************************************************************
|
||||
|
||||
LR_IROM1 0x0800C000 0x00040000 { ; load region size_region
|
||||
ER_IROM1 0x0800C000 0x00040000 { ; load address = execution address
|
||||
*.o (RESET, +First)
|
||||
*(InRoot$$Sections)
|
||||
.ANY (+RO)
|
||||
.ANY (+XO)
|
||||
}
|
||||
RW_IRAM1 0x20000000 0x0000C000 { ; RW data
|
||||
.ANY (+RW +ZI)
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@
|
||||
<TargetOption>
|
||||
<CLKADS>8000000</CLKADS>
|
||||
<OPTTT>
|
||||
<gFlags>1</gFlags>
|
||||
<gFlags>0</gFlags>
|
||||
<BeepAtEnd>1</BeepAtEnd>
|
||||
<RunSim>0</RunSim>
|
||||
<RunTarget>1</RunTarget>
|
||||
@ -103,7 +103,7 @@
|
||||
<bEvRecOn>1</bEvRecOn>
|
||||
<bSchkAxf>0</bSchkAxf>
|
||||
<bTchkAxf>0</bTchkAxf>
|
||||
<nTsel>4</nTsel>
|
||||
<nTsel>0</nTsel>
|
||||
<sDll></sDll>
|
||||
<sDllPa></sDllPa>
|
||||
<sDlgDll></sDlgDll>
|
||||
@ -114,34 +114,9 @@
|
||||
<tDlgDll></tDlgDll>
|
||||
<tDlgPa></tDlgPa>
|
||||
<tIfile></tIfile>
|
||||
<pMon>Segger\JL2CM3.dll</pMon>
|
||||
<pMon>BIN\UL2CM3.DLL</pMon>
|
||||
</DebugOpt>
|
||||
<TargetDriverDllRegistry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>ARMRTXEVENTFLAGS</Key>
|
||||
<Name>-L70 -Z18 -C0 -M0 -T1</Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>DLGTARM</Key>
|
||||
<Name>(1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)</Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>ARMDBGFLAGS</Key>
|
||||
<Name></Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>DLGUARM</Key>
|
||||
<Name></Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>JL2CM3</Key>
|
||||
<Name>-U11111118 -O14 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight JTAG-DP") -D00(3BA00477) -L00(4) -N01("Unknown JTAG device") -D01(06414041) -L01(5) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_512.FLM -FS08000000 -FL080000 -FP0($$Device:STM32F103RC$Flash\STM32F10x_512.FLM)</Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>UL2CM3</Key>
|
||||
@ -149,81 +124,18 @@
|
||||
</SetRegEntry>
|
||||
</TargetDriverDllRegistry>
|
||||
<Breakpoint/>
|
||||
<WatchWindow1>
|
||||
<Ww>
|
||||
<count>0</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>input</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>1</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>Inputs</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>2</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>duty_cycle,0x0A</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>3</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>frequency,0x0A</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>4</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>uwTick,0x0A</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>5</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>modbus</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>6</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>msgData[0]</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>7</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>CMD_GOTOBOOT</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>8</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>hcan</ItemText>
|
||||
</Ww>
|
||||
</WatchWindow1>
|
||||
<MemoryWindow1>
|
||||
<Mm>
|
||||
<WinNumber>1</WinNumber>
|
||||
<SubType>0</SubType>
|
||||
<ItemText>0x0800c000</ItemText>
|
||||
<AccSizeX>0</AccSizeX>
|
||||
</Mm>
|
||||
</MemoryWindow1>
|
||||
<MemoryWindow2>
|
||||
<Mm>
|
||||
<WinNumber>2</WinNumber>
|
||||
<SubType>0</SubType>
|
||||
<ItemText>0x08009800</ItemText>
|
||||
<AccSizeX>0</AccSizeX>
|
||||
</Mm>
|
||||
</MemoryWindow2>
|
||||
<Tracepoint>
|
||||
<THDelay>0</THDelay>
|
||||
</Tracepoint>
|
||||
<DebugFlag>
|
||||
<trace>0</trace>
|
||||
<periodic>1</periodic>
|
||||
<aLwin>1</aLwin>
|
||||
<periodic>0</periodic>
|
||||
<aLwin>0</aLwin>
|
||||
<aCover>0</aCover>
|
||||
<aSer1>0</aSer1>
|
||||
<aSer2>0</aSer2>
|
||||
<aPa>0</aPa>
|
||||
<viewmode>1</viewmode>
|
||||
<viewmode>0</viewmode>
|
||||
<vrSel>0</vrSel>
|
||||
<aSym>0</aSym>
|
||||
<aTbox>0</aTbox>
|
||||
@ -254,27 +166,9 @@
|
||||
<pszMrulep></pszMrulep>
|
||||
<pSingCmdsp></pSingCmdsp>
|
||||
<pMultCmdsp></pMultCmdsp>
|
||||
<SystemViewers>
|
||||
<Entry>
|
||||
<Name>System Viewer\BKP</Name>
|
||||
<WinId>35902</WinId>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Name>System Viewer\CAN</Name>
|
||||
<WinId>35904</WinId>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Name>System Viewer\GPIOB</Name>
|
||||
<WinId>35905</WinId>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Name>System Viewer\IWDG</Name>
|
||||
<WinId>35903</WinId>
|
||||
</Entry>
|
||||
</SystemViewers>
|
||||
<DebugDescription>
|
||||
<Enable>1</Enable>
|
||||
<EnableFlashSeq>0</EnableFlashSeq>
|
||||
<EnableFlashSeq>1</EnableFlashSeq>
|
||||
<EnableLog>0</EnableLog>
|
||||
<Protocol>2</Protocol>
|
||||
<DbgClock>10000000</DbgClock>
|
||||
@ -386,7 +280,7 @@
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>DLGTARM</Key>
|
||||
<Name>(1010=-1605,104,-1155,661,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)</Name>
|
||||
<Name>(1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)</Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
@ -413,70 +307,25 @@
|
||||
<Bp>
|
||||
<Number>0</Number>
|
||||
<Type>0</Type>
|
||||
<LineNumber>1300</LineNumber>
|
||||
<LineNumber>368</LineNumber>
|
||||
<EnabledFlag>1</EnabledFlag>
|
||||
<Address>134222082</Address>
|
||||
<Address>134230816</Address>
|
||||
<ByteObject>0</ByteObject>
|
||||
<HtxType>0</HtxType>
|
||||
<ManyObjects>0</ManyObjects>
|
||||
<SizeOfObject>0</SizeOfObject>
|
||||
<BreakByAccess>0</BreakByAccess>
|
||||
<BreakIfRCount>1</BreakIfRCount>
|
||||
<Filename>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_can.c</Filename>
|
||||
<Filename>..\Core\Bootloader\Src\bootloader.c</Filename>
|
||||
<ExecCommand></ExecCommand>
|
||||
<Expression>\\bootloader\../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_can.c\1300</Expression>
|
||||
<Expression>\\bootloader\../Core/Bootloader/Src/bootloader.c\368</Expression>
|
||||
</Bp>
|
||||
</Breakpoint>
|
||||
<WatchWindow1>
|
||||
<Ww>
|
||||
<count>0</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>boot,0x10</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>1</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>Inputs</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>2</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>duty_cycle,0x0A</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>3</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>frequency,0x0A</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>4</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>uwTick,0x0A</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>5</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>GoToApp</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>6</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>app_jump_adr</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>7</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>TXDataBoot</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>8</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>\\bootloader\../Core/Bootloader/boot_main.c\boot.error.bit.unknown_cmd</ItemText>
|
||||
</Ww>
|
||||
<Ww>
|
||||
<count>9</count>
|
||||
<WinNumber>1</WinNumber>
|
||||
<ItemText>\\bootloader\../Core/Bootloader/boot_main.c\boot.error.bit.write_err</ItemText>
|
||||
<ItemText>boot</ItemText>
|
||||
</Ww>
|
||||
</WatchWindow1>
|
||||
<MemoryWindow1>
|
||||
@ -537,15 +386,9 @@
|
||||
<pszMrulep></pszMrulep>
|
||||
<pSingCmdsp></pSingCmdsp>
|
||||
<pMultCmdsp></pMultCmdsp>
|
||||
<SystemViewers>
|
||||
<Entry>
|
||||
<Name>System Viewer\GPIOB</Name>
|
||||
<WinId>35905</WinId>
|
||||
</Entry>
|
||||
</SystemViewers>
|
||||
<DebugDescription>
|
||||
<Enable>1</Enable>
|
||||
<EnableFlashSeq>0</EnableFlashSeq>
|
||||
<EnableFlashSeq>1</EnableFlashSeq>
|
||||
<EnableLog>0</EnableLog>
|
||||
<Protocol>2</Protocol>
|
||||
<DbgClock>10000000</DbgClock>
|
||||
@ -555,7 +398,7 @@
|
||||
|
||||
<Group>
|
||||
<GroupName>Application/MDK-ARM</GroupName>
|
||||
<tvExp>1</tvExp>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<cbSel>0</cbSel>
|
||||
<RteFlg>0</RteFlg>
|
||||
@ -575,7 +418,7 @@
|
||||
|
||||
<Group>
|
||||
<GroupName>Application/User/Core</GroupName>
|
||||
<tvExp>1</tvExp>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<cbSel>0</cbSel>
|
||||
<RteFlg>0</RteFlg>
|
||||
@ -982,8 +825,8 @@
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\Core\Bootloader\Src\bootloader.c</PathWithFileName>
|
||||
<FilenameWithoutPath>bootloader.c</FilenameWithoutPath>
|
||||
<PathWithFileName>..\Core\Bootloader\Src\boot_main.c</PathWithFileName>
|
||||
<FilenameWithoutPath>boot_main.c</FilenameWithoutPath>
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
@ -994,8 +837,8 @@
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\Core\Bootloader\Src\boot_main.c</PathWithFileName>
|
||||
<FilenameWithoutPath>boot_main.c</FilenameWithoutPath>
|
||||
<PathWithFileName>..\Core\Bootloader\Src\bootloader.c</PathWithFileName>
|
||||
<FilenameWithoutPath>bootloader.c</FilenameWithoutPath>
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
@ -1006,6 +849,18 @@
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\Core\Bootloader\Src\boot_uart.c</PathWithFileName>
|
||||
<FilenameWithoutPath>boot_uart.c</FilenameWithoutPath>
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>5</GroupNumber>
|
||||
<FileNumber>36</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\Core\Bootloader\Src\boot_can.c</PathWithFileName>
|
||||
<FilenameWithoutPath>boot_can.c</FilenameWithoutPath>
|
||||
<RteFlg>0</RteFlg>
|
||||
@ -1013,7 +868,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>5</GroupNumber>
|
||||
<FileNumber>36</FileNumber>
|
||||
<FileNumber>37</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@ -1025,7 +880,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>5</GroupNumber>
|
||||
<FileNumber>37</FileNumber>
|
||||
<FileNumber>38</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@ -1037,7 +892,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>5</GroupNumber>
|
||||
<FileNumber>38</FileNumber>
|
||||
<FileNumber>39</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@ -1047,18 +902,6 @@
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>5</GroupNumber>
|
||||
<FileNumber>39</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\Core\Bootloader\Src\boot_uart.c</PathWithFileName>
|
||||
<FilenameWithoutPath>boot_uart.c</FilenameWithoutPath>
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
</Group>
|
||||
|
||||
<Group>
|
||||
|
@ -667,11 +667,6 @@
|
||||
<FileType>5</FileType>
|
||||
<FilePath>..\Core\Bootloader\Inc\boot_project_setup.h</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>bootloader.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\Core\Bootloader\Src\bootloader.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>boot_main.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
@ -728,6 +723,16 @@
|
||||
</FileArmAds>
|
||||
</FileOption>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>bootloader.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\Core\Bootloader\Src\bootloader.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>boot_uart.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\Core\Bootloader\Src\boot_uart.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>boot_can.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
@ -799,11 +804,6 @@
|
||||
</FileArmAds>
|
||||
</FileOption>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>boot_uart.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\Core\Bootloader\Src\boot_uart.c</FilePath>
|
||||
</File>
|
||||
</Files>
|
||||
</Group>
|
||||
<Group>
|
||||
@ -854,13 +854,13 @@
|
||||
<NotGenerated>0</NotGenerated>
|
||||
<InvalidFlash>1</InvalidFlash>
|
||||
</TargetStatus>
|
||||
<OutputDirectory>.\</OutputDirectory>
|
||||
<OutputDirectory>.\bootloader\</OutputDirectory>
|
||||
<OutputName>bootloader</OutputName>
|
||||
<CreateExecutable>1</CreateExecutable>
|
||||
<CreateLib>0</CreateLib>
|
||||
<CreateHexFile>1</CreateHexFile>
|
||||
<DebugInformation>1</DebugInformation>
|
||||
<BrowseInformation>1</BrowseInformation>
|
||||
<BrowseInformation>0</BrowseInformation>
|
||||
<ListingPath></ListingPath>
|
||||
<HexFormatSelection>1</HexFormatSelection>
|
||||
<Merge32K>0</Merge32K>
|
||||
@ -1490,15 +1490,20 @@
|
||||
<FileType>5</FileType>
|
||||
<FilePath>..\Core\Bootloader\Inc\boot_project_setup.h</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>boot_main.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\Core\Bootloader\Src\boot_main.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>bootloader.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\Core\Bootloader\Src\bootloader.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>boot_main.c</FileName>
|
||||
<FileName>boot_uart.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\Core\Bootloader\Src\boot_main.c</FilePath>
|
||||
<FilePath>..\Core\Bootloader\Src\boot_uart.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>boot_can.c</FileName>
|
||||
@ -1520,11 +1525,6 @@
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\Core\Bootloader\Src\boot_jump.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>boot_uart.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\Core\Bootloader\Src\boot_uart.c</FilePath>
|
||||
</File>
|
||||
</Files>
|
||||
</Group>
|
||||
<Group>
|
||||
|
95
README.md
Normal file
95
README.md
Normal file
@ -0,0 +1,95 @@
|
||||
# STM32 Bootloader (Beta)
|
||||
|
||||
## Описание
|
||||
Этот бутлоадер для STM32 реализован как **машина состояний (state machine)**.
|
||||
Его задача — управлять обновлением прошивки по UART или CAN, а также обеспечивать безопасный переход между приложением и бутлоадером.
|
||||
|
||||
---
|
||||
|
||||
## Общение с бутлоадером
|
||||
В [гите](https://git.arktika.cyou/Razvalyaev/boot_terminal) есть терминалка на C# для общения с бутом через SlCan (uart там не сделан).
|
||||
А вообще реализованы следующие команды
|
||||
- `0x01` — стирание прошивки во Flash — (`CMD_ERASE`)
|
||||
- `0x02` — запуск процедуры приёма страницы — (`CMD_START_RECEIVE`)
|
||||
- `0x03` — запись блока прошивки — (`CMD_WRITE`)
|
||||
- `0x04` — переход в приложение — (`CMD_GOTOAPP`)
|
||||
- `0x05` — сброс микроконтроллера — (`CMD_RESET`)
|
||||
- `0x06` — принудительный переход в бутлоадер — (`CMD_GOTOBOOT`)
|
||||
- `0xAA` — проверка связи (ping) — (`CMD_PING`)
|
||||
|
||||
|
||||
Бутлоадер уже содержит каркас для работы как с **CAN** (и некоторые наработки для **UART**, но не проверенные).
|
||||
Для расширения функционала и поддержки новых протоколов нужно доопределить следующие функции.
|
||||
|
||||
- Приём команды:
|
||||
```c
|
||||
BootloaderCommand_t Bootloader_UART_Receive(Bootloader_t *bl); //boot_uart.c
|
||||
BootloaderCommand_t Bootloader_CAN_Receive(Bootloader_t *bl); //boot_can.c
|
||||
```
|
||||
- Читает 1 байт команды и возвращает её (`CMD_ERASE`, `CMD_WRITE`, и т.п.) или, если нет команды, `NO_CMD`.
|
||||
- Приём страницы прошивки:
|
||||
```c
|
||||
void Bootloader_UART_Receive_Page(Bootloader_t *bl); //boot_uart.c
|
||||
void Bootloader_CAN_Receive_Page(Bootloader_t *bl); //boot_can.c
|
||||
```
|
||||
- Принимает блок данных длиной `PAGE_SIZE` байт.
|
||||
- Принимает CRC32 (4 байта).
|
||||
- Заполняет поля `bl->fw_buffer`, `bl->fw_len`, `bl->fw_crc`.
|
||||
|
||||
---
|
||||
|
||||
## Как работает бутлоадер
|
||||
1. После сброса бутлоадер проверяет сохранённые ошибки и "ключ" прошивки.
|
||||
- Если приложение корректное — выполняется переход в него.
|
||||
- Если приложение повреждено или нет ключа — остаётся в бутлоадере.
|
||||
2. В состоянии `IDLE` бутлоадер слушает команды.
|
||||
3. Прошивка отправляется страницами, каждая страница проверяется по CRC32.
|
||||
4. По завершению записи устанавливается "ключ приложения", и возможен переход в основное приложение.
|
||||
5. При ошибках — возврат в состояние `ERROR`, уведомление хоста и мигание LED. Для сброса ошибок надо перезапустить МК.
|
||||
|
||||
|
||||
---
|
||||
## Основные особенности бута
|
||||
- Реализован как конечный автомат со следующими состояниями:
|
||||
- `INIT` — проверка ключа, и далее переход в приложение или инициализация бута
|
||||
- `IDLE` — ожидание команды
|
||||
- `RECEIVE_UART` / `RECEIVE_CAN` — приём страницы прошивки
|
||||
- `WRITE` — запись принятой страницы во Flash
|
||||
- `ERASE` — стирание приложения
|
||||
- `JUMP_TO_APP` — переход к основному приложению
|
||||
- `JUMP_TO_BOOT` — возврат в бутлоадер
|
||||
- `RESET` — программный сброс
|
||||
- `ERROR` — обработка ошибок
|
||||
- Проверка целостности прошивки с помощью **CRC32**
|
||||
- Учёт ошибок (hardfault, memmanage, watchdog и т.п.)
|
||||
- Индикация состояния через LED:
|
||||
- мигает раз в 500 мс при ошибке
|
||||
- включается при приеме комады и выключается, когда команда выполнена
|
||||
|
||||
---
|
||||
|
||||
## Интеграция в проект
|
||||
Здесь бутлоадер и основное приложение реализованы как отдельные таргеты:
|
||||
|
||||
- **Таргет приложения**
|
||||
Исключает `main()` бутлоадера и компилирует только само приложение.
|
||||
Адрес загрузки приложения: `0x0800C000`.
|
||||
|
||||
- **Таргет бутлоадера**
|
||||
Исключает код приложения и компилирует только бутлоадер.
|
||||
Адрес загрузки бутлоадера: `0x08000000`.
|
||||
|
||||
Чтобы в основном приложении можно было управлять бутлоадером:
|
||||
1. Подключить `boot_jump.h` и `boot_jump.c` для взаимодействия с бутлоадером:
|
||||
```c
|
||||
#include "boot_jump.h"
|
||||
```
|
||||
2. В начале `main()` вызвать `App_Init()`, чтобы установить VTOR на
|
||||
начало приложения:
|
||||
```c
|
||||
App_Init();
|
||||
```
|
||||
3. Для перехода в бутлоадер (например, при ошибке или обновлении):
|
||||
```c
|
||||
JumpToBootloader();
|
||||
```
|
Loading…
Reference in New Issue
Block a user