#include "includes.h" struct IAP_PRA IapPra; unsigned char Fota_Rcv_Pri_Flag=1;//IAP串口输出标志 unsigned short g_usTid=0; static unsigned char FileMD5[16];//={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint16_t ui_version; uint8_t resendPackage; //串口打印信息 const char No_Login_In[] = "Logout!\r\n"; const char Fota_Start[] = "Fota IAP start!\r\n"; const char Ver_Ok_Dat_Start[] = "Ver req ok data req start!\r\n"; const char Task_GoTo_App[] = "Task goto App!\r\n"; const char MD5_Error[] = "MD5 err!\r\n"; const char Len_Offset_Error[] = "len or offset err!\r\n"; const char CRC_Error[] = "CRC err!\r\n"; const char Resend_Package[] = "Resend last package!\r\n"; const char Wait_Package_Timeout[] = "Package wait timeout!\r\n"; const char Reboot[] = "Update done! rebooting\r\n"; const char OtherLen_error[] = "otherLen < 46\r\n"; const char Format_Not_Fit[] = "Invalid Header\r\n"; const char ReTry_Failed[] = "Re-Try 3 time failed! %d\r\n"; //语音部分 const char VO_NO_LOGIN[] = "AT+ZTTS=1,\"2A677B76555F\"\r";//未登陆 const char APP_CHECK [] = "AT+ZTTS=1,\"0B4E7D8F10629F52636B285721688C9A\"\r";//下载成功正在校验 const char UP_APP_VER [] = "AT+ZTTS=1,\"636B28570B4E7D8FF78B0D7A1950\"\r";//正在下载请稍候 const char UP_PRO_VER [] = "AT+ZTTS=1,\"636B2857B783D653B06548722C67\"\r";//正在获取新版本 const char VOIC_NO_VER[] = "AT+ZTTS=1,\"A16C0967EF53F466B06548722C67\"\r";//没有可更新版本 const char VOIC_REBOOT[] = "AT+ZTTS=1,\"2B52AD653575004E06529F94CD912F54\"\r";//别断电一分钟重启 //下面不改 const char App_Checking[] = " 下载成功正在校验 \r\n"; const char Ver_Invalid[] = " 没有可更新版本 \r\n"; const char Reboot_Mini[] = " 别断电一分钟重启 \r\n"; const char UP_LOADING [] = "正在下载,请稍候... "; const char UPDATE_ING [] = "正在处理,请稍候... "; const char VER_REQ_ING[] = "正在获取新版本... "; const char EXIT_CANCLE[] = " [EXIT]取消"; const char MESSG1 [] = "升级应用版本"; const char MESSG3 [] = "[OK]升级 [EXIT]退出"; static void MyIap_Init(void); static void NewTask(uint8_t); static void FotaSocketCtl(uint8_t); static void StartIAP(void); static void TickIAP(void); static void FotaSocketCtl(uint8_t); static void IapGetUpdateVersion_FOGA(void); static int MakeFoTaVersionReq(char *); static void ResetTimerCou(void); static void IapGetUpdateData_FOGA(uint32_t ); int MakeFoTaDataReq(char *,int ,int ); static void ChangeDataToHex(char *, uint16_t ); static int IapCheckFileMD5_SPI_Flash(uint8_t *,uint8_t,uint8_t); static void Door_Ctrl(uint8_t ); static void SaveNewMD5(char *, char *); static void SaveNewFileSize(char *); static char ChageAscii_To_Hex(char *); static void TryTimeCheck(uint8_t ); static void UI_Process_Update(void); static void HBD_Ui_Update(uint8_t ); static void IapAppStore(uint32_t , uint8_t *, uint16_t ); static uint8_t DownLoaded_DataProcess(void); static uint8_t CopyFileListToFlash(SUT_FILE_LIST *, uint8_t); static void ExitRightNow(void); static uint32_t SaveLengthInFormat(char *dat); int ModemSendUdpData_User(unsigned char ,unsigned char *,unsigned short ); static uint8_t SetMark(uint32_t ); ////启动IAP初始化 void MyIap_Init(void) { FotaSocketCtl(1); IapPra.Tick10ms=0; IapPra.TaskStart=0; IapPra.V_flag = 0; IapPra.timeTry = 0; IapPra.resetModemTime=0; resendPackage = 0; NewTask(TASK_WAIT); } ///////UI 选择 void SetUpAppricationVerPending(void) { //unsigned long key; //key=ListBoxResponse(&sutListBox); if(KEY_PANEL_EXIT == g_ulKeyValue){ ExitRightNow(); } if(!sutPocStatus.Logined){//未登陆退出 SpeakerEnable(); ModemSendAT((char *)VO_NO_LOGIN); //正在下载 ExitRightNow(); SlwTrace(INF, (char *)No_Login_In,0); return; } StartIAP(); TickIAP(); UI_Process_Update(); } ///////IAP状态切换 static void NewTask(uint8_t task) { IapPra.TaskStatus = task; IapPra.TaskStart = 1; if(task == TASK_FILE_CHECK){ IapPra.GotData_IPRECV = 3; return; } IapPra.GotData_IPRECV = 0; if(IapPra.TaskStatus == TASK_WAIT){ IapPra.V_flag = 0;//如果是重新下载-重置标志 SlwTrace(INF, (char *)Fota_Start,0); IapPra.u_filesize = 0; IapPra.u_req_offset = 0; IapPra.u_DownFilesize = 0; IapPra.iapUI.update = 0; } ResetTimerCou(); } static void StartIAP(void) { if(!IapPra.TaskStart) return; IapPra.TaskStart = 0; switch(IapPra.TaskStatus) { case TASK_WAIT: //如果版本未请求--请求版本 if(!IapPra.V_flag){ //版本请求 IapGetUpdateVersion_FOGA(); }else{}//do nothing break; case TASK_MODEM_UPDATE: SlwTrace(INF, (char *)Ver_Ok_Dat_Start,0); break; case TASK_FILE_CHECK: SlwTrace(INF, (char *)App_Checking,0); HBD_Ui_Update(2); break; case TASK_GOTO_APP: SlwTrace(INF, (char *)Task_GoTo_App,0); HBD_Ui_Update(4); break; case TASK_VERSION_ERROR: HBD_Ui_Update(3); ExitRightNow(); break; } } ///////IAP处理/////////////// static void TickIAP(void) { uint32_t len,offset; unsigned short crc,CRC16; char buf[50],temp[5]; if(++IapPra.Tick10ms > TICK_COUNT) { IapPra.Tick10ms = 0; IapPra.timeOut ++; //process switch(IapPra.TaskStatus) { case TASK_WAIT: //请求版本过程--检测是否超时--超明重新请求 if(0 == IapPra.V_flag) {//还未请求成功 if(IapPra.timeOut >= TIME_OUT_IAP) TryTimeCheck(1); }else { if(IapPra.GotData_IPRECV == 1) {//收到请求确认--请求数据包 SpeakerEnable(); ModemSendAT((char *)UP_APP_VER); //正在下载 GuiShowStr(0,40,UP_LOADING,1); NewTask(TASK_MODEM_UPDATE); IapGetUpdateData_FOGA(0); } } break; case TASK_MODEM_UPDATE: if(IapPra.GotData_IPRECV == 2) { //收到数据包请求数据回来,检查包数据 //1检查MD5是否一致 /////////////////////////////////// IapPra.resetModemTime=0;//说明数据通了,复位数清零 /////////////////////////////////// if(0 != strncmp((char *)FileMD5, IapPra.MD5, 16)){ SlwTrace(INF, (char *)MD5_Error,0); TryTimeCheck(2); return; } //2检查长度偏移 len=IapPra.u_length; offset=IapPra.u_offset; if(len < 2 || \ offset != IapPra.u_req_offset || (len+IapPra.u_req_offset) > (IapPra.u_filesize+2)) { SlwTrace(INF, (char *)Len_Offset_Error,0); TryTimeCheck(3); // { // char tbuf[60]; // sprintf(tbuf, "len:%d,offset:%d,re_offset:%d,filesize:%d\r\n",len, offset, IapPra.u_req_offset, IapPra.u_filesize); // SlwTrace(INF, tbuf); // } return; } //3.检查CRC len -= 2; CRC16=crc16_calc(0,IapPra.FOGA_buf, len); crc=((unsigned short)IapPra.FOGA_buf[len+1]&0xff)<<8; crc+=(unsigned short)IapPra.FOGA_buf[len]&0xff; if(crc!=CRC16){ SlwTrace(INF, (char *)CRC_Error,0); TryTimeCheck(4); return ; } //校验成功 //处理一包数据 IapAppStore(APP_FILE_DATA_ADDR+IapPra.u_req_offset, IapPra.FOGA_buf, len); //处理完 IapPra.u_DownFilesize += len; IapPra.u_req_offset += len; HBD_Ui_Update(1); sprintf(buf,"HBD=%d",IapPra.u_req_offset);//Has been downloaded SlwTrace(INF, buf,1); if(IapPra.u_DownFilesize >= IapPra.u_filesize){//下载结束 SpeakerEnable(); ModemSendAT((char *)APP_CHECK); IWDG_ReloadCounter(); os_dly_wait(200); NewTask(TASK_FILE_CHECK); return; } //未结束启动下一包 IapGetUpdateData_FOGA(IapPra.u_req_offset); resendPackage = 0; }else if(!IapPra.GotData_IPRECV) { if(IapPra.timeOut >= TIME_OUT_IAP){ SlwTrace(INF, (char *)Wait_Package_Timeout,0);//调试过程试过出现"NO CARRIER"即数据业务断开了 TryTimeCheck(6); } } break; case TASK_FILE_CHECK: //MD5总校验 switch(IapCheckFileMD5_SPI_Flash(FileMD5,2,0)) { case 0://OK NewTask(TASK_GOTO_APP); break; case 1://confinue SlwTrace(INF, (char *)MD5_Error,0); TryTimeCheck(5); break; } break; case TASK_GOTO_APP: SetMark(GOOD_UPDATE_STORAGE); SlwTrace(INF, (char *)Reboot,0); while(1); break; case TASK_EXIT: ExitRightNow(); break; } } } static uint32_t SaveLengthInFormat(char *dat) { uint32_t temp,i; temp = 0; for(i=0;i<4;i++){ temp <<= 8; temp |= (uint32_t)ChageAscii_To_Hex(dat+6-2*i); } return temp; } //针对FOTA升级时处理此终端UDP返回的数据 //对CDMA(如8332)格式为+ZIPRECVU:........ void FotaIap_Handle(char *msg) { char buf[60],kk[60],temp[10]; uint8_t i,j,dataIndex; uint16_t otherLength; uint8_t extraLen; if(!IapPra.FOTA_IS_ON) return; if(IapPra.GotData_IPRECV) return; //1,数据拆包 //1.1比较命令头,socket,IP,port,udp type //+ZIPRECVU:2, sprintf(buf, "+ZIPRECVU:%d,", FOTA_IAP_SOCKET); if(0 != strncmp(msg, buf, 12)) return; //1.2 取具体数据索引第二个逗号加1 j=0; for(i=0;i<20;i++){ if(*(msg+i) == ','){ j++; if(j >= 2) break; } } dataIndex = i+1; //1.2 get data len,最大16384五位数 otherLength = StrToNum(msg+12);//这里其实最大可以是5位十进制数--我们不可能传那么大数据-一般只有一两个K //1.3 比较版本请求头格式 if(otherLength < 46){ SlwTrace(INF, (char *)OtherLen_error,0); return; } MakeFoTaVersionReq(buf); if(0 != strncmp(buf, msg+dataIndex, 22) && \ 2 != *(msg+dataIndex+5)) { SlwTrace(INF, (char *)Format_Not_Fit,0); return; } //1.4 得到协议内具体数据长度 otherLength = (uint16_t)*(msg+dataIndex+25); otherLength <<= 8; otherLength |= (uint16_t)*(msg+dataIndex+24);//LSByte //1.5 区别版本或数据请求返回 if(otherLength == 20) { //是否已经请求过版本数据了 if(IapPra.V_flag){}//请求过了的 else { //第一次请求到了 IapPra.V_flag = 1; //保存文件MD5码 memcpy(kk, msg+dataIndex+26, 16); j=0; for(i=0;i<16;i++){ if(kk[i] == 0) j++; } if(16 == j){ SlwTrace(INF, (char *)Ver_Invalid,0); NewTask(TASK_VERSION_ERROR); return; } for(i=0;i<16;i++) memcpy(FileMD5, kk, 16); //保存文件长度 //IapPra.u_filesize = 0; for(i=0;i<4;i++){ IapPra.u_filesize <<= 8; IapPra.u_filesize |= *(msg+dataIndex+45-i);//文件数据在msg+dataIndex+42~45 } IapPra.iapUI.total_size = IapPra.u_filesize; IapPra.GotData_IPRECV = 1;//收到了版本请求返回 return; } }else if(otherLength > 20) { if(IapPra.V_flag) { //已经请求过版本了 //保存MD5 for(i=0;i<16;i++) memcpy(IapPra.MD5, msg+dataIndex+26, 16); //保存OFFSET for(i=0;i<4;i++){ IapPra.u_offset <<= 8; IapPra.u_offset |= *(msg+dataIndex+45-i);//文件数据在msg+dataIndex+42~45 } //保存LENGTH for(i=0;i<4;i++){ IapPra.u_length <<= 8; IapPra.u_length |= *(msg+dataIndex+49-i);//文件数据在msg+dataIndex+46~49 } //保存数据 memcpy(IapPra.FOGA_buf, msg+dataIndex+50, IapPra.u_length); IapPra.GotData_IPRECV = 2; }else {} } } //////////////版本请求///////////////////////////// static void IapGetUpdateVersion_FOGA(void) { int len; //重置状态 IapPra.GotData_IPRECV = 0; ResetTimerCou();//开始计数 len=MakeFoTaVersionReq((char *)TxBuffer3); ModemSendUdpData_User(FOTA_IAP_SOCKET,TxBuffer3,len); } /***************************************************************************************** MakeFoTaVersionReq ******************************************************************************************/ static int MakeFoTaVersionReq(char *txbuf) { update_version_req_t *pUpdateVersionReq; pUpdateVersionReq=(update_version_req_t *)txbuf; memset(pUpdateVersionReq,0,sizeof(update_version_req_t)); pUpdateVersionReq->hdr.magic=FOTA_MAGIC; pUpdateVersionReq->hdr.protocol=UPDATE_PROTOCOL; pUpdateVersionReq->hdr.code=UPDATE_CODE_VERSION_REQ; sprintf(pUpdateVersionReq->hdr.dev_id,"%lu",sutProductPara.PSN); pUpdateVersionReq->hdr.tid=++g_usTid; pUpdateVersionReq->hdr.count=sizeof(update_version_req_t)-sizeof(update_hdr_t); strcpy(pUpdateVersionReq->product,sutProductPara.ProductName); pUpdateVersionReq->version=--ui_version; //pUpdateVersionReq->version=PRODUCT_VERSION; return sizeof(update_version_req_t); } ////////////文件数据请求////////////// static void IapGetUpdateData_FOGA(uint32_t offset) { int len; //重置状态 IapPra.GotData_IPRECV = 0; ResetTimerCou();//开始计数 len=MakeFoTaDataReq((char *)TxBuffer3,offset,DATA_DRAT_SIZE_PER_TIME); ModemSendUdpData_User(FOTA_IAP_SOCKET,TxBuffer3,len); } /***************************************************************************************** MakeFoTaDataReq ******************************************************************************************/ int MakeFoTaDataReq(char *txbuf,int offset,int length) { update_data_req_t *pUpdateDataReq; pUpdateDataReq=(update_data_req_t *)txbuf; memset(pUpdateDataReq,0,sizeof(update_data_req_t)); pUpdateDataReq->hdr.magic=FOTA_MAGIC; pUpdateDataReq->hdr.protocol=UPDATE_PROTOCOL; pUpdateDataReq->hdr.code=UPDATE_CODE_DATA_WITH_CRC_REQ; sprintf(pUpdateDataReq->hdr.dev_id,"%lu",sutProductPara.PSN); pUpdateDataReq->hdr.tid=++g_usTid; pUpdateDataReq->hdr.count=sizeof(update_data_req_t)-sizeof(update_hdr_t); memcpy(pUpdateDataReq->version_md5,FileMD5,16); pUpdateDataReq->offset=offset; pUpdateDataReq->length=length; return sizeof(update_data_req_t); } int ModemSendUdpData_User(unsigned char socket,unsigned char *pData,unsigned short len) { int i; char buf[142]; char tmp[5]; tmp[0] = 0;// sprintf(buf,"AT+ZIPSENDU=%d,%d\r", socket, len);//这里的长度会不会超过两位数 if(len > 99)//three digit tmp[0] = 1; memcpy(buf+17+tmp[0], pData, len); ModemSendData((uint8_t *)buf, 17+tmp[0]+len); #if ENABL_FOGA_BACK_DATA_PRINT if(Fota_Rcv_Pri_Flag) //此句与下面的SlwTrace(INF, buf)一起用调试--中间不要插入其它语句 #endif SlwTrace(INF,buf,0); return 0; } ////////////////////相关子方法 //"3a" or "3A" to 0x3a static char ChageAscii_To_Hex(char *dat) { char temp[2]; uint8_t i; for(i=0;i<2;i++){ if(dat[i] >= '0' && dat[i] <= '9') temp[i] = dat[i] - 0x30; else if(dat[i] >= 'A' && dat[i] <= 'Z') temp[i] = dat[i] - 0x37; else if(dat[i] >= 'a' && dat[i] <= 'z') temp[i] = dat[i] - 0x57; } return ((temp[0]<<4) | temp[1]); } //保存以ASCII形式的数据为十六进制放回dat 实际数据长度减半 static void ChangeDataToHex(char *dat, uint16_t len) { uint16_t i; for(i=0;i 16 HEX static void SaveNewMD5(char *dat, char *des) { uint8_t i; for(i=0;i<16;i++) des[i] = ChageAscii_To_Hex(dat+2*i); } //保存版本请求回来的文件大小 static void SaveNewFileSize(char *dat) { char temp[4]; uint8_t i; for(i=0;i<4;i++) temp[i] = ChageAscii_To_Hex(dat+2*i); IapPra.u_filesize = (uint32_t)temp[3]<<24; IapPra.u_filesize |= (uint32_t)temp[2]<<16; IapPra.u_filesize |= (uint32_t)temp[1]<<8; IapPra.u_filesize |= (uint32_t)temp[0]; IapPra.iapUI.total_size = IapPra.u_filesize; } static void ExitRightNow(void) { FotaSocketCtl(0); UISetNextStatus(UIS_MENU_SYS_SET);//退出升级操作 } //重置计数器 static void ResetTimerCou(void){IapPra.timeOut = 0;} //IAP 重试检测 static void TryTimeCheck(uint8_t note) { char buf[25]; ResetTimerCou(); switch(note) { case 2: case 3: case 4: SlwTrace(INF, (char *)Resend_Package,0); IapGetUpdateData_FOGA(IapPra.u_req_offset); return; case 6: if(resendPackage <=3) { resendPackage ++; SlwTrace(INF, (char *)Resend_Package,0);//调试过程试过出现"NO CARRIER"即数据业务断开了 IapGetUpdateData_FOGA(IapPra.u_req_offset); return; }else//对于等不到数据并重发超过3次,就重新下载 {} break; } resendPackage = 0; if(++IapPra.timeTry > RETRY_TIME) {//重试3次失败退出 ExitRightNow(); sprintf(buf, ReTry_Failed, note); SlwTrace(INF, buf,0); }else NewTask(TASK_WAIT); //再次请求 } //FOTA 开关宏控制 //FOTA 打印宏控制 static void Door_Ctrl(uint8_t flag) { if(flag){ IapPra.FOTA_IS_ON = 1; Fota_Rcv_Pri_Flag = 0; ////////////////////////// g_uiGpsStat=0; }else{ IapPra.FOTA_IS_ON = 0; Fota_Rcv_Pri_Flag = 1; ////////////////////////// g_uiGpsStat=1; } } //SOCKET OPEN OR CLOSE static void FotaSocketCtl(uint8_t ctl) { char buf[50]; if(ctl){//open sprintf(buf, "AT+ZIPSETUPU=%d,%s,%d\r\n",FOTA_IAP_SOCKET,FOTA_IAP_SERVER_IP,FOTA_IAP_SERVER_PORT); Door_Ctrl(ctl); }else{//close sprintf(buf, "AT+ZIPCLOSE=%d\r\n", FOTA_IAP_SOCKET); Door_Ctrl(ctl); } ModemSendAT(buf); SlwTrace(INF, buf,0); } static void IapAppStore(uint32_t addr, uint8_t *buf, uint16_t len) { sFlash_Write(buf,addr,len); } //return 0 校验正确 //return 1 错误 //type 1 block 1 //type 2 block 2 //spical 0 no need to change first 4 bytes to 0 after read out //spical 1 need to change first 4 bytes to 0 after read out static int IapCheckFileMD5_SPI_Flash(uint8_t *MD,uint8_t type,uint8_t spical) { //总数据大小为 IapPra.u_filesize; MD5_CTX mdContext; uint32_t Read_file_size; uint32_t read_addr,startAddr; uint8_t buf[1024],finished_flag,temp; uint16_t read_len,i; char tempbuf[5]; uint8_t firstTime; firstTime = 0; if(type == 1) startAddr = FILE_INDEX_ADDR; else if(type == 2) startAddr = APP_FILE_DATA_ADDR; else return 1; Read_file_size = 0; read_addr = 0; finished_flag = 0; MD5Init(&mdContext); do{ if(IapPra.u_filesize - Read_file_size >= 1024) read_len = 1024; else{ read_len = IapPra.u_filesize - Read_file_size; finished_flag = 1; } sFlash_Read(buf, startAddr+read_addr, read_len); if(!firstTime){ firstTime ++; buf[0] = 0;buf[1] = 0;buf[2] = 0;buf[3] = 0; } Read_file_size += read_len; read_addr += read_len; MD5Update(&mdContext, buf, read_len); }while(!finished_flag); MD5Final(&mdContext); //check for(i=0;i<16;i++){ if(MD[i] != mdContext.digest[i]) break; } if(i<16) return 1; else return 0; } static void UI_Process_Update(void) { char buf[22]; uint8_t persent,showFlag; showFlag = 0; switch(IapPra.iapUI.update) { case 1: persent = 100*IapPra.iapUI.down_size/IapPra.iapUI.total_size; sprintf(buf, " 已下载百分之 %d \r\n", persent); showFlag ++; break; case 2: sprintf(buf, App_Checking); showFlag ++; break; case 3: sprintf(buf, Ver_Invalid); ModemSendAT((char *)VOIC_NO_VER); // SlwTrace(INF, "***B"); showFlag ++;break; case 4: sprintf(buf, Reboot_Mini); ModemSendAT((char *)VOIC_REBOOT); IWDG_ReloadCounter(); DelayMs(1000); IWDG_ReloadCounter(); showFlag ++;break; } if(showFlag) GuiShowStr(0,70,buf,1); IapPra.iapUI.update = 0; } static void HBD_Ui_Update(uint8_t type) { IapPra.iapUI.down_size = IapPra.u_DownFilesize; IapPra.iapUI.update = type; } void SetUpAppricationVerShow(int update) { char buf[19]; if(update){ ui_version = PRODUCT_VERSION+1; GuiClearAll(); ShowCaption(MESSG1,0); //升级应用版本 GuiDrawHLine(0,159,20,1); //sprintf(buf, " 是否升级到 V%d ", ui_version);//是否升级到 V%d //GuiShowStr(0,56,buf,1); sprintf(buf, " 当前版本: V%d ", PRODUCT_VERSION);//是否升级到 V%d GuiShowStr(0,44,buf,1);//当前版本 sprintf(buf, " 升级到:V%d ", ui_version); GuiShowStr(0,68,buf,1); //GuiReverseRect(96,68,24,16); GuiDrawHLine(0,159,104,1); GuiShowStr(0,110,MESSG3,0x01);//[OK]升级 [EXIT]退出 } } void SetUpAppricationVerResponse(void) { char buf[19],update; static char APP_Flag=0; if(KEY_PANEL_OK==g_ulKeyValue){//因为没有UDP指令,暂时没有此功能 // UISetNextStatus(UIS_UP_APP_PENDING); // GuiClearArea(0, 56, 160, 24); // SpeakerEnable(); // ModemSendAT((char *)UP_PRO_VER); //正在处理请稍候 // GuiShowStr(4,40,UPDATE_ING,0x01);//正在处理,请稍候... // GuiShowStr(4,70,VER_REQ_ING,0x01);// 版本请求中... // GuiShowStr(0,110,EXIT_CANCLE,0x01); // IWDG_ReloadCounter(); // os_dly_wait(200); // MyIap_Init(); }else if(KEY_PANEL_EXIT==g_ulKeyValue) UISetNextStatus(UIS_MENU_SYS_SET); else if(KEY_PANEL_MENU==g_ulKeyValue) UISetNextStatus(UIS_MENU_MAIN); else if(KEY_PANEL_UP == g_ulKeyValue || KEY_PANEL_DOWN == g_ulKeyValue) { update=0; if(KEY_PANEL_UP == g_ulKeyValue) { ui_version ++; update ++; }else if(KEY_PANEL_DOWN == g_ulKeyValue && ui_version > PRODUCT_VERSION+1) { ui_version --; update ++; } if(update) { sprintf(buf, " 升级到:V%d ", ui_version); GuiShowStr(0,68,buf,1); //GuiReverseRect(96,68,24,16); } } else if(KEY_P1_P3_UPDATE==g_ulKeyValue) { //对讲版本升级,长按P1+P3 3秒,可退出后再进入 if(APP_Flag == 0) { g_ucUKC=0; APP_Flag++; }else { if(g_ucUKC>3){ UISetNextStatus(UIS_UP_INTERCOM_VER); APP_Flag =0; } } } else APP_Flag=0; } //type 1, 文件索引保存到块1 //type 2, 文件索引保存到块2 static void SaveFileIndexCtl(uint8_t *p_sutFileList, uint8_t type) { if(type == 1) sFlash_Write(p_sutFileList,FILE_INDEX_ADDR,sizeof(SUT_FILE_LIST)); else if(type == 2) sFlash_Write(p_sutFileList,APP_FILE_DATA_ADDR,sizeof(SUT_FILE_LIST)); } static uint8_t SetMark(uint32_t value) { uint8_t buf[4],i; for(i=0;i<4;i++) buf[i] = value>>(i*8); sFlash_Write(buf, APP_FILE_DATA_ADDR, 4); }