/******************************************************************************* * the includes ******************************************************************************/ #include "bootapp.h" #include "norflash.h" #include "stm32l4xx_hal_crc.h" #include "stm32l4xx_hal_dma.h" #include "stm32l4xx_hal_gpio.h" #include "stm32l4xx_hal_uart.h" #include "uartapp.h" #include "stdio.h" #include "hardware.h" #include #include /******************************************************************************* * 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; 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; /******************************************************************************* * the globals ******************************************************************************/ 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; /******************************************************************************* * the const ******************************************************************************/ /******************************************************************************* * the functions ******************************************************************************/ static void bootApp_EraseTask(void); static void BspQspiBoot_JumpToApp(void) { uint32_t i = 0; void (*AppJump)(void); /* 声明一个函数指针 */ __IO uint32_t AppAddr = EX_FLASH_APP_ADDR; /* APP 地址 */ /* 关闭全局中断 */ DISABLE_INT(); /* 设置所有时钟到默认状态,使用HSI时钟 */ HAL_RCC_DeInit(); 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); /* 关闭滴答定时器,复位到默认值 */ 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; NORFLASH_Write_NoCheck((uint8_t*)&appcrc, W26Q64_CRC_ADDR, 0x10); } 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) { if (crc_calc(EX_FLASH_APPINFO_ADDR, len) == crc) { return 1; } else { return 0; } } return 0; } 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; } }