//*********************************************************************************** // Ver 1.0 // 2020.03.05 1、新建文件。 //*********************************************************************************** #include "config.h" IAP_Str IAP_Info; //KEY_Str KEY_Info; pFun IAP_App; //IAP升级,检查文件名的头部 const char FileName_Tab[] = {"PT-1724V2-"}; INT8U BQ769x0_PdTab[]={ 0x01, 0xf1, 0x02, 0xf8, }; void IAP_Sleep(void) { INT8U i; LED_D0Off(); for(i=0; i<3; i++) { I2CS_WriteMultiByte(I2CS0, BQ769x0_ADDR, 0x04, (INT8U *)&BQ769x0_PdTab[0], 2); I2CS_WriteMultiByte(I2CS0, BQ769x0_ADDR, 0x04, (INT8U *)&BQ769x0_PdTab[2], 2); DELAY_Ms(500); } I2CS_Pull1Up(DISABLE); KEY_WakeupCode = 0; do{ SLEEP(); //进入休眠 WDT_Clr(); //清看门狗 if (KEY_PlcdPinRead() != 0) { break; } }while(KEY_WakeupCode == 0); SystemInit(); OSC_Init(); I2CS_Pull1Up(ENABLE); YMODEM_Status = 0; } void IAP_Init(void) { KEY_PlcdInit(); IAP_JumpApp(); } void IAP_JumpApp(void) { if ((RTC_Bkp0IapFlag != BKP_VAR_IAP) && //检查是否为IAP模式,非IAP模式直接跳转到APP (*((uint32_t *)FLASH_APP_ADDR) != 0xffffffff) && (KEY_PlcdPinRead() == 0)) { IRQ_Disable(); //禁止中断 TASK_Tick(DISABLE); //关闭系统定时器 if(RTC_Bkp0IapFlag != BKP_VAR_INIT) { RTC_Bkp0IapFlag = BKP_VAR_INIT; RTC_Bkp0IapCnt = 0; RTC_SetBootFlag(RTC_Bkp0Value); } DELAY_Ms(10); IAP_App = (pFun)(*(__IO uint32_t*)(FLASH_APP_ADDR + 4)); __set_MSP(*(__IO uint32_t*) FLASH_APP_ADDR); IAP_App(); } //2022.02.09 增加IAP失败计数 if((RTC_Bkp0IapCnt >= 20) && (KEY_PlcdPinRead() != 0)) { IAP_Sleep(); } else { if(RTC_Bkp0IapCnt < 10) RTC_Bkp0IapCnt = 10; RTC_Bkp0IapCnt ++; RTC_SetBootFlag(RTC_Bkp0Value); } YMODEM_InfoInit(); IAP_InfoInit(); RS485_Init(); I2CS_Init(I2CS0, 10000); } void IAP_Choose(void) { if (IAP_RxLen > 0) { if (YMODEM_PacketRxEnd() != 0) { if (((IAP_RxData[0] == YMODEM_CMD_SOH) || (IAP_RxData[0] == YMODEM_CMD_STX)) && (IAP_RxData[1] == 0x00) && (IAP_RxData[2] == 0xff)) { IAP_Mode = IAP_COMM_RECEIVE; } //IAP_RxLen=0; } } else if (YMODEM_Status == YMODEM_STA_END) { YMODEM_SendChar(YMODEM_CMD_CA); } else { YMODEM_SendChar(YMODEM_CMD_C); #if 0 if (KEY_S1Read() == 0) { KEY_PressCnt++; if (KEY_PressCnt > 3) { Timers[TMR2] = 0; } } else { KEY_PressCnt = 0; } #endif } if (TASK_TimerState(TMR2) == TASK_STA_IDLE) { IAP_JumpApp(); TASK_TimerStart(TMR2, 10000); //while (1); } } INT8U IAP_EraseFlash(void) { INT32U i; FLASH_Status tFLASH_Status = FLASH_COMPLETE; FLASH_Unlock(); for (i = 0; (i < (1 + (FLASH_APP_SIZE / FLASH_PAGE_SIZE))); i++) { tFLASH_Status = FLASH_ErasePage(FLASH_APP_ADDR + (FLASH_PAGE_SIZE * i)); if (tFLASH_Status != FLASH_COMPLETE) { break; } } FLASH_Lock(); return (tFLASH_Status); } INT8U IAP_WriteFlash(INT16U *ptr, INT32U Addr, INT16U Len) { INT32U tAddr; ATOMIC_Start(); WDT_Clr(); FLASH_Unlock(); for (tAddr = Addr; tAddr < (Addr + Len); tAddr += 2) { FLASH_ProgramHalfWord(tAddr, *ptr++); } FLASH_Lock(); ATOMIC_Stop(); return (0); } INT8U IAP_ReceiveFile(void) { if ((YMODEM_PacketRxEnd() == 0) && (YMODEM_Status != YMODEM_STA_END)) { return (0); } YMODEM_Receive(YMODEM_RxBuff, &YMODEM_RxCnt, (INT8U *) & (IAP_Info.Buff[0]), &IAP_WriteSize); switch (YMODEM_FileSta) { case YMODEM_FILE_INFO: //接收到文件信息 if (MEM_Compare(YMODEM_Info.FILE_Name, (INT8U *)FileName_Tab, 10) == 0) //检查文件名称头部 { IAP_FlashAddr = FLASH_APP_ADDR; IAP_EraseFlash(); } else { IAP_Mode = IAP_COMM_CHOOSE; IAP_RxLen = 0; YMODEM_FileSta = YMODEM_STA_END; YMODEM_SendChar(YMODEM_CMD_CA); TASK_TimerStart(TMR2, 500); } break; case YMODEM_FILE_DATA: //接收文件数据,写入FLASH if (FLASH_APP_ADDR > IAP_FlashAddr) { IAP_Mode = IAP_COMM_CHOOSE; IAP_RxLen = 0; YMODEM_FileSta = YMODEM_STA_END; YMODEM_SendChar(YMODEM_CMD_CA); TASK_TimerStart(TMR2, 500); } else { IAP_WriteFlash((INT16U *) & (IAP_Info.Buff[0]), IAP_FlashAddr, IAP_WriteSize); IAP_FlashAddr += IAP_WriteSize; } break; case YMODEM_FILE_EXIT: //接收文件结束,退出 IAP_Mode = IAP_COMM_CHOOSE; IAP_RxLen = 0; YMODEM_FileSta = 0; if (YMODEM_FileSize < (IAP_FlashAddr - FLASH_APP_ADDR)) { RTC_Bkp0IapFlag = BKP_VAR_INIT; RTC_Bkp0IapCnt = 0; RTC_SetBootFlag(RTC_Bkp0Value); } TASK_TimerStart(TMR2, 200); break; } return (1); } INT8U IAP_CmdExec(void) { switch (IAP_Mode) { case IAP_COMM_CHOOSE: IAP_Choose(); break; case IAP_COMM_RECEIVE: IAP_ReceiveFile(); break; default: IAP_Mode = IAP_COMM_CHOOSE; break; } return (1); }