/********************************************************************************** * File Name: IAP.c * Function Describe:In application program * Relate Module: * Explain: * Writer: ShiLiangWen * Date: 2015.6.9 *********************************************************************************************/ #include "includes.h" SUT_PRODUCT_PARA sutProductPara; update_hdr_t sutHeader; 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}; int g_ulFileLen=0;//文件长度 int g_ulDFileLen=0;//已下载文件长度 int g_ulOffset=0; int g_ulLength=0; uint8_t IapRxBuf[IAP_RX_BUF]; uint16_t IapRxLen; /***************************************************************************************** IapCheckFileMD5 成功返回1 失败返回0 ******************************************************************************************/ int IapCheckFileMD5(uint32_t FileLen,uint8_t MD5[]) { MD5_CTX mdContext; unsigned short temp; unsigned char data[1024]; char tembuf[5]; unsigned char RMD5[16]; uint32_t offset=0; uint32_t len; int i,j; //计算MD5 MD5Init(&mdContext); j=0; for(i=0;i>8)&0xff; if(j==1024){ MD5Update(&mdContext,data,1024); j=0; } } if(j!=0){ MD5Update(&mdContext,data,j); } MD5Final(&mdContext); #if 1 //debug trace md5 sprintf((char *)data,"FileSize=%d MD5=",FileLen); for(i=0;i<16;i++){ sprintf(tembuf,"%02X",mdContext.digest[i]); strcat((char *)data,tembuf); } strcat((char *)data,"\r\n"); IapTrace((char *)data); #endif //check for(i=0;i<16;i++){ if(MD5[i]!=mdContext.digest[i])break; } if(i<16)return 0; else return 1; } /***************************************************************************************** IapWriteFileData ******************************************************************************************/ int IapWriteFileData(uint32_t Offset,uint32_t Length,uint8_t *pData) { unsigned short iapbuf[1024]; uint16_t i,temp; uint16_t len=0; if(0!=(Offset%2))return 0; WritePageData(FLASH_APP1_ADDR+Offset,pData,Length); // for(i = 0; i < Length; i+=2) // { // //数据8位融合为16位 // temp = (((uint16_t)pData[i+1])<<8) + ((uint16_t)pData[i]); // iapbuf[len] = temp; // len++;//完成之后receiveDataCur++; // } // // STMFLASH_Write((FLASH_APP1_ADDR+Offset),iapbuf,len); // return 1; } /***************************************************************************************** MakeFoTaVersionReq ******************************************************************************************/ 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=sutProductPara.ProductVersion; return sizeof(update_version_req_t); } /***************************************************************************************** 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); } /***************************************************************************************** MakePcTaVersionReq ******************************************************************************************/ int MakePcTaVersionReq(char *txbuf) { update_version_req_t *pUpdateVersionReq; pUpdateVersionReq=(update_version_req_t *)txbuf; memset(pUpdateVersionReq,0,sizeof(update_version_req_t)); pUpdateVersionReq->hdr.magic=PCTA_MAGIC; pUpdateVersionReq->hdr.protocol=UPDATE_PROTOCOL; pUpdateVersionReq->hdr.code=UPDATE_CODE_VERSION_REQ; sprintf(pUpdateVersionReq->hdr.dev_id,"%lu",sutProductPara.PSN); pUpdateVersionReq->hdr.tid=sutProductPara.Rand;//对于PC升级,传输伪随机数用于加密 pUpdateVersionReq->hdr.count=sizeof(update_version_req_t)-sizeof(update_hdr_t); strcpy(pUpdateVersionReq->product,sutProductPara.ProductName); pUpdateVersionReq->version=sutProductPara.ProductVersion; g_usTid=0; return sizeof(update_version_req_t); } /***************************************************************************************** MakePcTaDataReq ******************************************************************************************/ int MakePcTaDataReq(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=PCTA_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); } /***************************************************************************************** IapGetUpdateData ******************************************************************************************/ void IapGetUpdateData(uint32_t magic,uint32_t offset) { int len; if(PCTA_MAGIC==magic){ len=MakePcTaDataReq((char *)TxBuffer1,offset,1024); Uart1Send((char *)TxBuffer1,len); }else if(FOTA_MAGIC==magic){ len=MakeFoTaDataReq((char *)TxBuffer3,offset,1024); ModemSendUdpData(0,TxBuffer3,len); } } /***************************************************************************************** IapGetUpdateVersion ******************************************************************************************/ void IapGetUpdateVersion(uint32_t magic) { int len; if(PCTA_MAGIC==magic){ len=MakePcTaVersionReq((char *)TxBuffer1); Uart1Send((char *)TxBuffer1,len); }else if(FOTA_MAGIC==magic){ len=MakeFoTaVersionReq((char *)TxBuffer3); ModemSendUdpData(0,TxBuffer3,len); } } /************************************************************************************ IapRecvMsgHandle 处理接收到的数据 *************************************************************************************/ int IapRecvMsgHandle(unsigned char *pData, unsigned short DataLen) { int i; char id[16]; unsigned short crc,CRC16; unsigned short ReadBuf[4]; char buf[100]; uint32_t len,offset; unsigned char code; unsigned short count; update_hdr_t *pHeader; update_version_rsp_t *pVersionRsp; update_data_rsp_t *pDataRsp; pHeader=(update_hdr_t *)pData; if(pHeader->magic != FOTA_MAGIC && pHeader->magic != PCTA_MAGIC)return -1; if(pHeader->protocol != UPDATE_PROTOCOL )return -2; sprintf(id,"%lu",sutProductPara.PSN); if(0!=strcmp(id,pHeader->dev_id))return -3; code= pHeader->code; count= pHeader->count; if(code==UPDATE_CODE_VERSION_REQ){ if(count!=(sizeof(update_version_rsp_t)-sizeof(update_hdr_t)))return -4; pVersionRsp= (update_version_rsp_t *)pData; memcpy(FileMD5,pVersionRsp->version_md5,16); g_ulFileLen=pVersionRsp->size; if(0==g_ulFileLen)return -5; g_ulOffset=0; g_ulLength=0; g_ulDFileLen=0; if(FOTA_MAGIC==pHeader->magic){ g_ucLoginServer=1; }else{ NewTask(TASK_PC_UPDATE); } IapGetUpdateData(pHeader->magic,g_ulOffset); return 1; }else if(code == UPDATE_CODE_DATA_WITH_CRC_REQ){ pDataRsp = (update_data_rsp_t*)pData; //判断MD5是否被更新 for(i=0;i<16;i++){ if(FileMD5[i]!=pDataRsp->version_md5[i])break; } if(i<16){//MD5被更新,申请重新下载 IapTrace("MD5 Modify!ReDO!\r\n"); IapGetUpdateVersion(pHeader->magic); return -6; } len=pDataRsp->length; offset=pDataRsp->offset; //length和offset不对,申请重新下载 if(len<2 || offset!=g_ulOffset || (len+g_ulOffset)>(g_ulFileLen+2)){ IapTrace("Length or Offset error!ReDO!\r\n"); IapGetUpdateVersion(pHeader->magic); return -7; } len-=2;//实际数据长度应去掉2字节的CRC //CRC校验 CRC16=crc16_calc(0,pDataRsp->data,len); crc=((unsigned short)pDataRsp->data[len+1]&0xff)<<8; crc+=(unsigned short)pDataRsp->data[len]&0xff; if(crc!=CRC16){ //校验错误,申请重新下载 IapTrace("Check CRC error!ReDO!\r\n"); IapGetUpdateData(pHeader->magic,g_ulOffset); return -8; } //==CRC校验成功,更新FLASH === //第一次更新,写修改IAP标志位 if(0==g_ulOffset){ sutProductPara.IapFlag=0x00; SaveProductParaToFlash(); } //对于PC传输,需要先解密 if(PCTA_MAGIC==pHeader->magic){ for(i=0;idata[i]=pDataRsp->data[i] ^ sutProductPara.Rand; } IapWriteFileData(g_ulOffset,len,pDataRsp->data); g_ulDFileLen+=len; g_ulOffset+=len; //判断是否结束? if(g_ulDFileLen>=g_ulFileLen){ //下载结束,检查MD5 if(0==IapCheckFileMD5(g_ulFileLen,FileMD5)){ //校验MD5错误,重新下载 IapTrace("Check MD5 error!ReDO!\r\n"); IapGetUpdateVersion(pHeader->magic); return -9; } //---校验成功,下载完成--- //修改标志位,以便可以运行APP sutProductPara.IapFlag=0x88; SaveProductParaToFlash(); return 0; } //未结束,启动下一包下载 sprintf(buf,"HBD=%d\r\n",g_ulOffset);//Has been downloaded IapTrace(buf); IapGetUpdateData(pHeader->magic,g_ulOffset); return 2; } } typedef void (*iapfun)(void); //定义一个函数类型的参数. iapfun jump2app; //设置栈顶地址 //addr:栈顶地址 __asm void MSR_MSP(u32 addr) { MSR MSP, r0 //set Main Stack value BX r14 } //跳转到应用程序段 //appxaddr:用户代码起始地址. void iap_load_app(u32 appxaddr) { // if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000) //检查栈顶地址是否合法.0x20000000是sram的起始地址,也是程序的栈顶地址 // { jump2app=(iapfun)*(vu32*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址) MSR_MSP(*(vu32*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) jump2app(); //跳转到APP. // } // else // { // IapTrace("program in flash is error\r\n"); // } } //跳转到app区域运行 void iap_jump_app_s(void) { iap_load_app(FLASH_APP1_ADDR);//跳转到app的复位向量地址 } //设置app固化配置 void iap_set_flag_s(void) { // Test_Write(APP_CONFIG_ADDR,APP_CONFIG_SET_VALUE); // printf("ok\r\n"); } //清除app固化配置 void iap_clear_flag(void) { // Test_Write(APP_CONFIG_ADDR,APP_CONFIG_CLEAR_VALUE); // printf("ok\r\n"); } /***********************************************************************************/