2025-05-21 15:35:29 +08:00
|
|
|
|
/*******************************************************************************
|
|
|
|
|
* the includes
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
#include "bootapp.h"
|
|
|
|
|
#include "norflash.h"
|
2025-05-26 10:37:37 +08:00
|
|
|
|
#include "stm32l4xx_hal_crc.h"
|
|
|
|
|
#include "stm32l4xx_hal_dma.h"
|
|
|
|
|
#include "stm32l4xx_hal_gpio.h"
|
|
|
|
|
#include "stm32l4xx_hal_uart.h"
|
2025-05-21 15:35:29 +08:00
|
|
|
|
#include "uartapp.h"
|
2025-05-26 10:37:37 +08:00
|
|
|
|
#include "stdio.h"
|
|
|
|
|
#include "hardware.h"
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
#include <stdio.h>
|
2025-05-21 15:35:29 +08:00
|
|
|
|
/*******************************************************************************
|
|
|
|
|
* the defines
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
#define ENABLE_INT() __set_PRIMASK(0) /* 使能全局中断 */
|
|
|
|
|
#define DISABLE_INT() __set_PRIMASK(1) /* 禁止全局中断 */
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
* the typedefs
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
uint32_t startflag;
|
|
|
|
|
uint32_t len;
|
|
|
|
|
uint32_t AppCRC;
|
|
|
|
|
uint32_t reverse;
|
|
|
|
|
} APPCRC_type;
|
2025-05-26 10:37:37 +08:00
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
uint32_t startflag;
|
|
|
|
|
uint32_t sBootloader_Req;
|
|
|
|
|
uint32_t reboot_times;
|
|
|
|
|
uint32_t hardfault_data;
|
|
|
|
|
uint32_t reverse[12];
|
|
|
|
|
}NO_INIT_DATA_Type;
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
uint8_t reqFlag;
|
|
|
|
|
uint8_t eraseState;
|
|
|
|
|
uint8_t eraseLen;
|
|
|
|
|
uint8_t eraseStep;
|
|
|
|
|
|
|
|
|
|
}EraseReq_Type;
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
|
BOOT_INIT,
|
|
|
|
|
BOOT_WAIT,
|
|
|
|
|
BOOT_APP_CHECK,
|
|
|
|
|
BOOT_APP_JUMP,
|
|
|
|
|
BOOT_STOP,
|
|
|
|
|
BOOT_ERASE,
|
|
|
|
|
BOOT_STATE_NUM,
|
|
|
|
|
}BOOT_STATE_Type;
|
2025-05-21 15:35:29 +08:00
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
* the globals
|
|
|
|
|
******************************************************************************/
|
2025-05-26 10:37:37 +08:00
|
|
|
|
volatile NO_INIT_DATA_Type noInitData __attribute__((section(".boot_flags")));
|
|
|
|
|
static uint8_t bootflag = 0;
|
|
|
|
|
static BOOT_STATE_Type bootState = BOOT_INIT;
|
|
|
|
|
extern UART_HandleTypeDef huart1;
|
|
|
|
|
extern DMA_HandleTypeDef hdma_usart1_rx;
|
|
|
|
|
extern CRC_HandleTypeDef hcrc;
|
|
|
|
|
static EraseReq_Type eraseReq;
|
2025-05-21 15:35:29 +08:00
|
|
|
|
/*******************************************************************************
|
|
|
|
|
* the const
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
* the functions
|
|
|
|
|
******************************************************************************/
|
2025-05-26 10:37:37 +08:00
|
|
|
|
static void bootApp_EraseTask(void);
|
|
|
|
|
|
2025-05-21 15:35:29 +08:00
|
|
|
|
|
2025-05-26 10:37:37 +08:00
|
|
|
|
|
|
|
|
|
static void BspQspiBoot_JumpToApp(void)
|
2025-05-21 15:35:29 +08:00
|
|
|
|
{
|
|
|
|
|
uint32_t i = 0;
|
|
|
|
|
void (*AppJump)(void); /* 声明一个函数指针 */
|
2025-05-26 10:37:37 +08:00
|
|
|
|
__IO uint32_t AppAddr = EX_FLASH_APP_ADDR; /* APP 地址 */
|
2025-05-21 15:35:29 +08:00
|
|
|
|
|
|
|
|
|
/* 关闭全局中断 */
|
|
|
|
|
DISABLE_INT();
|
|
|
|
|
|
|
|
|
|
/* 设置所有时钟到默认状态,使用HSI时钟 */
|
|
|
|
|
HAL_RCC_DeInit();
|
2025-05-26 10:37:37 +08:00
|
|
|
|
HAL_UART_DeInit(&huart1);
|
|
|
|
|
HAL_DMA_DeInit(&hdma_usart1_rx);
|
|
|
|
|
HAL_CRC_DeInit(&hcrc);
|
|
|
|
|
// __HAL_RCC_SPI1_FORCE_RESET();
|
|
|
|
|
// __HAL_RCC_SPI1_RELEASE_RESET();
|
|
|
|
|
// HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3|GPIO_PIN_5);
|
2025-05-21 15:35:29 +08:00
|
|
|
|
/* 关闭滴答定时器,复位到默认值 */
|
|
|
|
|
SysTick->CTRL = 0;
|
|
|
|
|
SysTick->LOAD = 0;
|
|
|
|
|
SysTick->VAL = 0;
|
|
|
|
|
|
|
|
|
|
/* 关闭所有中断,清除所有中断挂起标志 */
|
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
|
{
|
|
|
|
|
NVIC->ICER[i] = 0xFFFFFFFF;
|
|
|
|
|
NVIC->ICPR[i] = 0xFFFFFFFF;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 使能全局中断 */
|
|
|
|
|
ENABLE_INT();
|
|
|
|
|
|
|
|
|
|
/* 跳转到应用程序,首地址是MSP,地址+4是复位中断服务程序地址 */
|
|
|
|
|
AppJump = (void (*)(void))(*((uint32_t*)(AppAddr + 4)));
|
|
|
|
|
|
|
|
|
|
/* 设置主堆栈指针 */
|
|
|
|
|
__set_MSP(*(uint32_t*)AppAddr);
|
|
|
|
|
|
|
|
|
|
/* 在RTOS工程,这条语句很重要,设置为特权级模式,使用MSP指针 */
|
|
|
|
|
__set_CONTROL(0);
|
|
|
|
|
|
|
|
|
|
/* 跳转到系统BootLoader */
|
|
|
|
|
AppJump();
|
|
|
|
|
|
|
|
|
|
/* 跳转成功的话,不会执行到这里,用户可以在这里添加代码 */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WriteCRCInfo(uint32_t len, uint32_t crc)
|
|
|
|
|
{
|
|
|
|
|
APPCRC_type appcrc;
|
|
|
|
|
appcrc.startflag = 0xAA5555AA;
|
|
|
|
|
appcrc.len = len;
|
|
|
|
|
appcrc.AppCRC = crc;
|
|
|
|
|
appcrc.reverse = 0xAAAAAAAA;
|
2025-05-26 10:37:37 +08:00
|
|
|
|
NORFLASH_Write_NoCheck((uint8_t*)&appcrc, W26Q64_CRC_ADDR, 0x10);
|
2025-05-21 15:35:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t ReadCRCInfo(uint32_t* len, uint32_t* crc)
|
|
|
|
|
{
|
|
|
|
|
APPCRC_type* appcrc = (APPCRC_type*)EX_FLASH_CRC_ADDR;
|
|
|
|
|
if (appcrc->startflag == 0xAA5555AA)
|
|
|
|
|
{
|
|
|
|
|
*len = appcrc->len;
|
|
|
|
|
*crc = appcrc->AppCRC;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t Boot_checkApp(void)
|
|
|
|
|
{
|
|
|
|
|
uint32_t len, crc;
|
|
|
|
|
if (ReadCRCInfo(&len, &crc) == 1)
|
|
|
|
|
{
|
2025-05-26 10:37:37 +08:00
|
|
|
|
if (crc_calc(EX_FLASH_APPINFO_ADDR, len) == crc)
|
2025-05-21 15:35:29 +08:00
|
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
2025-05-26 10:37:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void bootApp_init(void)
|
|
|
|
|
{
|
|
|
|
|
if (noInitData.startflag != 0xAA5555AA) {
|
|
|
|
|
printf("init bootflag\n");
|
|
|
|
|
noInitData.startflag = 0xAA5555AA;
|
|
|
|
|
noInitData.sBootloader_Req = 0;
|
|
|
|
|
noInitData.reboot_times = 0;
|
|
|
|
|
noInitData.hardfault_data = 0;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
noInitData.reboot_times++;
|
|
|
|
|
printf("reboot_times = %d\n", noInitData.reboot_times);
|
|
|
|
|
if (noInitData.sBootloader_Req == 0x778899AA) {
|
|
|
|
|
noInitData.sBootloader_Req = 0;
|
|
|
|
|
bootflag = 1;
|
|
|
|
|
}
|
|
|
|
|
else {//if(noInitData.sBootloader_Req != 0)
|
|
|
|
|
printf("bootreq = %lx\n",noInitData.sBootloader_Req);
|
|
|
|
|
}
|
|
|
|
|
if (noInitData.hardfault_data != 0) {
|
|
|
|
|
printf("hardfault_data = %lx\n", noInitData.hardfault_data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void bootApp_mainTask(void)//1ms
|
|
|
|
|
{
|
|
|
|
|
static uint16_t timeout_count = 0,bootkey_delay=0;
|
|
|
|
|
switch (bootState) {
|
|
|
|
|
case BOOT_INIT: {
|
|
|
|
|
bootState = BOOT_WAIT;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case BOOT_WAIT: {
|
|
|
|
|
if (bootflag == 1) {
|
|
|
|
|
bootState = BOOT_STOP;
|
|
|
|
|
printf("get_bootreq,stop in boot\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (timeout_count++ > 100) {//100ms
|
|
|
|
|
timeout_count = 0;
|
|
|
|
|
bootState = BOOT_APP_CHECK;
|
|
|
|
|
NORFLASH_MemroyMapMode();
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (get_BOOTKEY() == 1) {
|
|
|
|
|
bootkey_delay++;
|
|
|
|
|
if (bootkey_delay > 5) {//5ms
|
|
|
|
|
bootkey_delay = 0;
|
|
|
|
|
bootState = BOOT_STOP;
|
|
|
|
|
printf("get_BOOTKEY,stop in boot\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
bootkey_delay = 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case BOOT_APP_CHECK: {
|
|
|
|
|
if (Boot_checkApp() == 1) {
|
|
|
|
|
bootState = BOOT_APP_JUMP;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
printf("app not found\n");
|
|
|
|
|
NORFLASH_QuitMemroyMapMode();
|
|
|
|
|
bootState = BOOT_STOP;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
case BOOT_APP_JUMP: {
|
|
|
|
|
printf("jump to app\n");
|
|
|
|
|
BspQspiBoot_JumpToApp();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case BOOT_STOP: {
|
|
|
|
|
timeout_count++;
|
|
|
|
|
if (timeout_count >= 10) {//1000ms
|
|
|
|
|
timeout_count = 0;
|
|
|
|
|
bootApp_EraseTask();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default: {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void bootApp_WriteHardFaultData(uint32_t data)
|
|
|
|
|
{
|
|
|
|
|
noInitData.hardfault_data = data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void bootApp_ReqErase(uint8_t block_len)
|
|
|
|
|
{
|
|
|
|
|
if (block_len > 128) {
|
|
|
|
|
printf("block_len error\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (eraseReq.eraseState != 0) {
|
|
|
|
|
printf("erase is running\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (block_len == 0) {
|
|
|
|
|
NORFLASH_Erase_Chip();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
NORFLASH_Erase_Block(0);
|
|
|
|
|
}
|
|
|
|
|
eraseReq.reqFlag = 1;
|
|
|
|
|
eraseReq.eraseState = 1;
|
|
|
|
|
eraseReq.eraseLen = block_len;
|
|
|
|
|
eraseReq.eraseStep = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void bootApp_EraseTask(void)//10ms task
|
|
|
|
|
{
|
|
|
|
|
static uint32_t erase_count = 0;
|
|
|
|
|
if (eraseReq.reqFlag == 1) {
|
|
|
|
|
if (NORFLASH_Check_Busy() == 0) {
|
|
|
|
|
eraseReq.eraseStep++;
|
|
|
|
|
if (eraseReq.eraseStep > eraseReq.eraseLen) {
|
|
|
|
|
eraseReq.reqFlag = 0;
|
|
|
|
|
eraseReq.eraseState = 0;
|
|
|
|
|
eraseReq.eraseLen = 0;
|
|
|
|
|
printf("erase finashed %d ms\n",erase_count*10);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
NORFLASH_Erase_Block(eraseReq.eraseStep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
erase_count++;
|
|
|
|
|
if (erase_count % 400 == 0) {
|
|
|
|
|
printf("wait erase\n");
|
|
|
|
|
}
|
|
|
|
|
if (erase_count > 3000) {
|
|
|
|
|
erase_count = 0;
|
|
|
|
|
eraseReq.reqFlag = 0;
|
|
|
|
|
eraseReq.eraseState = 0;
|
|
|
|
|
eraseReq.eraseLen = 0;
|
|
|
|
|
printf("erase timeout\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
erase_count = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|