#include "myBootloader.h" #include "flash.h" #include "stdio.h" #include "sys.h" #include "eventUnit.h" #include "myUart.h" #include "stm32f10x_it.h" #define POST_EVENT_TIMEOUT_QUIT_BOOTLOAD 7 #define BOOT_TIMEOUT_10MS 300 UPDATE_STATUS_te update_status = UPDATE_PRE; CMD_CTR_STEP cmd_ctr_flag=CMD_CTR_IDLE; CMD_DATA_STRUCT cmd_data_struct; CMD_DATA_STEP cmd_data_flag=CMD_DATA_IDLE; static uint8_t cmd_addr_cnt=0; static uint32_t cmd_data_cnt=0; static uint32_t timeOutCount=0; static uint32_t firm_len; static uint8_t spliteLen; const uint8_t ACK_OK[] = {0xCC, 0xDD}; const uint8_t ACK_ERROR[] = {0xEE, 0xFF}; const uint8_t IAP_START1[] = {0x5A, 0xA5}; const uint8_t IAP_START2[] = {0x5A, 0x01}; const uint8_t IAP_DATA_DONE[] = {0x5A, 0x02}; static uint8_t setDataSrc=0; iapfun jump2app; extern void recoveryQuitBootloadEvent(void); // extern void clearQuitBootloadEvent(void); // extern void bootloadOverGotoApp(void); //跳转到应用程序段 //appxaddr:用户代码起始地址. #if defined (__CC_ARM) #pragma O0 //IAP_Load_APP不进行优化 #elif defined (__ICCARM__) #pragma optimize=s none #endif void myFlash_setBootloadFlag(void) { uint16_t flag = IAP_UPGRADE_FLAG; FLASH_Write(IAP_UPGRADE_FLAG_ADDR, (uint16_t *)flag, 2); } void myFlash_clearBootloadFlag(void) { uint16_t flag = 0; FLASH_Write(IAP_UPGRADE_FLAG_ADDR, (uint16_t *)flag, 2); } bool myFlash_checkFlag(void) { return ((*(vu32*)IAP_UPGRADE_FLAG_ADDR) == IAP_UPGRADE_FLAG ? true : false); } void IAP_Load_APP(uint32_t appxaddr) { if( ((*(vu32*)appxaddr)-0x20000000) < (SRAM_SIZE*1024) ) //检查栈顶地址是否合法. { jump2app=(iapfun)*(vu32*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址) MSR_MSP(*(vu32*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) jump2app(); //跳转到APP. } } void bootDelay(uint32_t time_ms) { uint32_t i, j; i = time_ms; while (i --) { for ( j = 0; j < 20000; j++) { ; } } } void Back_Ok( ) { bootDelay(10); myUart1_sendArray((uint8_t *)ACK_OK, 2); } void Back_Err( ) { bootDelay(10); myUart1_sendArray((uint8_t *)ACK_ERROR, 2); cmd_data_flag=CMD_DATA_IDLE; cmd_ctr_flag=CMD_CTR_IDLE; update_status=UPDATE_PRE; cmd_addr_cnt=0; cmd_data_cnt=0; // TIME_IRA_CNT=0; // GetDaraFromUSART_Flag=0; // myPrintf2("Back_Err\r\n"); } void Back_FirmErr( ) { bootDelay(10); myUart1_sendArray((uint8_t *)ACK_ERROR, 2); cmd_data_flag=CMD_DATA_IDLE; cmd_addr_cnt=0; cmd_data_cnt=0; // myPrintf2("Back_FirmErr\r\n"); } // #define myPrintf2(args...) //do{{printf("\r\ndecodeBootLoadData-\r\n");printf(args);}}while(0) uint8_t decodeBootLoadData(uint8_t *src, uint16_t len) { static uint8_t ret = CMD_PRO_IDLE; switch (update_status) { case UPDATE_PRE: { switch (cmd_ctr_flag) { case CMD_CTR_IDLE: { if (len == 2 && (memcmp(src, IAP_START1, 2) == 0)) { //1、准备开始固件升级 cmd_ctr_flag = CMD_CTR_INIT; // myPrintf2("begin bootload\r\n"); Back_Ok(); timeOutCount = BOOT_TIMEOUT_10MS; ret = CMD_PRO_START; } }break; case CMD_CTR_INIT: { if (len == 7 && (memcmp(src, IAP_START2, 2) == 0)) { //2、开始固件升级 cmd_ctr_flag = CMD_CTR_IDLE; update_status = UPDATE_ING; spliteLen = src[2]; firm_len = (src[3]<<24)+(src[4]<<16)+(src[5]<<8)+src[6]; Back_Ok(); timeOutCount = BOOT_TIMEOUT_10MS; // myPrintf2("start bootload\r\n"); ret = CMD_PRO_GET_INIT; } }break; default: break; } }break; case UPDATE_ING: { switch(cmd_data_flag) { case CMD_DATA_IDLE: { if(src[0]==0x31) { //3、接收IAP写入地址 cmd_data_flag = CMD_DATA_ADDR; // myPrintf2("begin receive addr\r\n"); Back_Ok(); timeOutCount = BOOT_TIMEOUT_10MS; } if (len == 2 && (memcmp(src, IAP_DATA_DONE, 2) == 0)) { break; } } case CMD_DATA_ADDR: { uint32_t addr; //4、成功接收IAP写入地址,准备接收固件数据 memcpy(cmd_data_struct.cmd_addr, src+1, 4); cmd_data_flag = CMD_DATA_BUF; addr = (cmd_data_struct.cmd_addr[0]<<24)+(cmd_data_struct.cmd_addr[1]<<16)+(cmd_data_struct.cmd_addr[2]<<8)+cmd_data_struct.cmd_addr[3]; len = len - 5; ret = CMD_PRO_GET_OFFSET_ADDR; } break; case CMD_DATA_BUF: { ret = CMD_PRO_RECV_ING; //5、接收固件数据,满2k字节写入一次IAP timeOutCount = BOOT_TIMEOUT_10MS; memcpy(cmd_data_struct.cmd_buf+cmd_data_cnt, src, len); cmd_data_cnt += len; if(cmd_data_cnt == 2048) { //6、满2k字节后先校验数据 cmd_data_flag=CMD_DATA_CHACK; cmd_data_cnt=0; Back_Ok(); } else { //接收固件数据包时必须整包接收 //否则认为是错误包, if (len == spliteLen) { Back_Ok(); } else { Back_FirmErr(); } } } break; case CMD_DATA_CHACK: { uint8_t Val,checksum; u16 i; timeOutCount = BOOT_TIMEOUT_10MS; //7、检验数据 checksum=0x31; for(i=0;i<4;i++) { checksum+=cmd_data_struct.cmd_addr[i]; } for(i=0;i<2048;i++) { checksum+=cmd_data_struct.cmd_buf[i]; } if(checksum==src[0]) { //8、IAP写入固件 uint32_t write_addr=0; write_addr = (cmd_data_struct.cmd_addr[0]<<24)+(cmd_data_struct.cmd_addr[1]<<16)+(cmd_data_struct.cmd_addr[2]<<8)+cmd_data_struct.cmd_addr[3]; if((write_addr>=APP_START_ADDR)&&(write_addrAPB1RSTR = 0xFFFFFFFF; RCC->APB2RSTR = 0xFFFFFFFF; RCC->APB1RSTR = 0x00000000; RCC->APB2RSTR = 0x00000000; IAP_Load_APP(APP_START_ADDR);//执行FLASH APP代码 } else { ret = CMD_PRO_ADDR_ERROR; Back_Err(); } } }break; case UPDATE_DONE: { }break; default: break; } return ret; } static irqCallback_ts myIrqCallback_tim1; /** * @brief tim1中断函数 * 通过API@TIM1_callbackRegiste注册到@stm32f10x_it.c中的真正的中断函数 * * @param status * @param param */ static void tim1_callback(uint8_t status, uint32_t param) //TIM1中断 { static uint8_t timeCnt_1ms = 0; if(timeCnt_1ms ++ == 50) { timeCnt_1ms = 0; if(timeOutCount) { timeOutCount --; if (timeOutCount == 0) { Back_Err(); } } } } void bootloader_init(void) { myIrqCallback_tim1.thisCb = tim1_callback; TIM1_callbackRegiste(&myIrqCallback_tim1); }