DownFiles.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /*****************************************************************************
  2. DownFiles.C
  3. *****************************************************************************/
  4. #include "includes.h"
  5. #include "DownFiles.h"
  6. #include "IAP.h"
  7. unsigned short newListIndex[FILE_COUNT_MAX];//临时保存置换位置后的索引
  8. //static SUT_FILE_LIST sutFileList;//临时文件列表 只用于传输文件用,注意不要与FileSys.c定义的g_sutFilesList混淆!
  9. static uint16_t sFileIndex; //当前传输的文件在文件列表中的索引位置
  10. static uint32_t sFileDataOffset; //当前传输的文件偏移
  11. static uint32_t sFileDataLength; //当前传输的文件长度
  12. /*****************************************************************************************
  13. MakePCTFlistReq
  14. 生成请求文件列表数据
  15. ******************************************************************************************/
  16. int MakePctflistReq(char *txbuf)
  17. {
  18. SUT_DF_LIST_REQ *pDFListReq;
  19. pDFListReq=(SUT_DF_LIST_REQ *)txbuf;
  20. memset(pDFListReq,0,sizeof(SUT_DF_LIST_REQ));
  21. pDFListReq->Head.magic=PCTA_MAGIC;
  22. pDFListReq->Head.protocol=UPDATE_PROTOCOL_RFILE;
  23. pDFListReq->Head.code=DOWNLOAD_FILE_LIST_REQ;
  24. pDFListReq->Head.tid=0;
  25. pDFListReq->Head.count=sizeof(SUT_DF_LIST_REQ)-sizeof(SUT_DF_HEAD);
  26. pDFListReq->FileCountMax=FILE_COUNT_MAX;
  27. pDFListReq->FileNameLenMax=FILE_NAME_LEN_MAX;
  28. pDFListReq->FileAllDataLenMax=FILE_ALL_DATA_LEN_MAX;
  29. return sizeof(SUT_DF_LIST_REQ);
  30. }
  31. /*****************************************************************************************
  32. DFGetFileList
  33. 请求文件列表
  34. ******************************************************************************************/
  35. void DFGetFileList(void)
  36. {
  37. int len;
  38. len=MakePctflistReq((char *)TxBuffer1);
  39. Uart1Send((char *)TxBuffer1,len);
  40. }
  41. /*****************************************************************************************
  42. MakePCTFlistReq
  43. 生成请求文件列表数据
  44. ******************************************************************************************/
  45. int MakePctfFileDataReq(char *txbuf,uint16_t FileIndex,uint32_t offset,uint32_t length)
  46. {
  47. SUT_DF_DATA_REQ *pFileDataReq;
  48. pFileDataReq=(SUT_DF_DATA_REQ *)txbuf;
  49. memset(pFileDataReq,0,sizeof(SUT_DF_DATA_REQ));
  50. pFileDataReq->Head.magic=PCTA_MAGIC;
  51. pFileDataReq->Head.protocol=UPDATE_PROTOCOL_RFILE;
  52. pFileDataReq->Head.code=DOWNLOAD_FILE_DATA_REQ;
  53. pFileDataReq->Head.tid=0;
  54. pFileDataReq->Head.count=sizeof(SUT_DF_DATA_REQ)-sizeof(SUT_DF_HEAD);
  55. #ifdef USE_NEW_FILE_SYSTEM
  56. pFileDataReq->FileIndex=newListIndex[FileIndex];
  57. #else
  58. pFileDataReq->FileIndex=FileIndex;
  59. #endif
  60. memcpy(&pFileDataReq->FileInfo,&g_sutFilesList.FileInfo[FileIndex],sizeof(SUT_FILE_INFO));
  61. pFileDataReq->length=length;
  62. pFileDataReq->offset=offset;
  63. return sizeof(SUT_DF_DATA_REQ);
  64. }
  65. /*****************************************************************************************
  66. DFGetFileData
  67. 请求文件数据
  68. ******************************************************************************************/
  69. void DFGetFileData(uint16_t FileIndex,uint32_t offset,uint32_t length)
  70. {
  71. int len;
  72. len=MakePctfFileDataReq((char *)TxBuffer1,FileIndex,offset,length);
  73. Uart1Send((char *)TxBuffer1,len);
  74. }
  75. /************************************************************************************
  76. *找出第一个不同的文件索引
  77. *************************************************************************************/
  78. int FindFirstDiffIndex(SUT_FILE_LIST *FileList)
  79. {
  80. int i;
  81. int j;
  82. for(i=0;i<g_sutFilesList.FileCount;i++){
  83. if(g_sutFilesList.FileInfo[i].FileLen!=FileList->FileInfo[i].FileLen)break;
  84. for(j=0;j<16;j++){
  85. if(g_sutFilesList.FileInfo[i].FileMD5[j]!=FileList->FileInfo[i].FileMD5[j])break;
  86. }
  87. if(j!=16)break;
  88. if(0!=strcmp(g_sutFilesList.FileInfo[i].FileName,FileList->FileInfo[i].FileName))break;
  89. }
  90. return i;
  91. }
  92. void RerangeList(SUT_FILE_LIST *FileList)
  93. {
  94. int i,j,w;
  95. SUT_FILE_INFO temp;
  96. for(w=0;w<FileList->FileCount;w++) newListIndex[w]=w;
  97. for(i=0;i<FileList->FileCount-1;i++){//如果刚好是最后那个是SYS_CONFIG,那不用置换了,故减1操作
  98. if(0==strcmp(FileList->FileInfo[i].FileName, SYS_CONFIG)){//找到了后,放在最后
  99. memcpy((unsigned char *)&temp, (unsigned char *)&FileList->FileInfo[i], sizeof(SUT_FILE_INFO));//备份
  100. for(j=i;j<FileList->FileCount-1;j++) memcpy((unsigned char *)&FileList->FileInfo[j], (unsigned char *)&FileList->FileInfo[j+1], sizeof(SUT_FILE_INFO));//结构体前移1
  101. memcpy((unsigned char *)&FileList->FileInfo[FileList->FileCount-1], (unsigned char *)&temp, sizeof(SUT_FILE_INFO));//备份的放最后
  102. for(w=i;w<FileList->FileCount-1;w++) newListIndex[w] = newListIndex[w+1];//文件索引前移1
  103. newListIndex[FileList->FileCount-1]=i;//备份索引放最后
  104. return;
  105. }
  106. }
  107. }
  108. void MakeTheEndFileIndicator(void)
  109. {
  110. //清除未使用的页,防止影响恢复逻辑
  111. SUT_FILE_PAGE_HEAD pageInfo;
  112. u32 endAddr;
  113. endAddr=g_sutFilesList.FileInfo[g_sutFilesList.FileCount-1].FileAddr+4096;
  114. endAddr += g_sutFilesList.FileInfo[g_sutFilesList.FileCount-1].FileLen;
  115. endAddr +=4096-(endAddr%4096) ;
  116. if(endAddr >= FILE_DATA_ADDR_END) return;//已到文件结尾,则不需要再生成结束标识
  117. pageInfo.mark=FILE_HEAD_END;
  118. sFlash_Write((unsigned char *)&pageInfo, endAddr, sizeof(SUT_FILE_PAGE_HEAD));
  119. }
  120. unsigned char buf[1024];//1024
  121. void CopyConfiToBckupFile(void)
  122. {
  123. unsigned int sourceAddr, desAddr, i,j;
  124. char ret=0;
  125. if(0 !=strcmp(g_sutFilesList.FileInfo[g_sutFilesList.FileCount-1].FileName, SYS_CONFIG)) ret=1;
  126. else if(g_sutFilesList.FileInfo[g_sutFilesList.FileCount-1].FileLen > 4096) ret=2;
  127. if(ret != 0){
  128. while(1){
  129. IapTrace("sys.ini err, stop\r\n");
  130. DelayMs(500);
  131. }
  132. }
  133. for(j=0;j<2;j++){
  134. sourceAddr=g_sutFilesList.FileInfo[g_sutFilesList.FileCount-1].FileAddr;
  135. desAddr=FILE_DATA_ADDR_END+1;
  136. if(j==0){//先拷贝数据区
  137. sourceAddr += 4096;
  138. desAddr += 4096;
  139. }
  140. for(i=0;i<4;i++){
  141. sFlash_Read(buf, sourceAddr, 1024);
  142. sFlash_Write(buf, desAddr, 1024);
  143. sourceAddr += 1024;
  144. desAddr += 1024;
  145. }
  146. }
  147. }
  148. /************************************************************************************
  149. IapRecvMsgHandle
  150. 处理接收到的数据
  151. *************************************************************************************/
  152. int DFRecvMsgHandle(unsigned char *pData, unsigned short DataLen)
  153. {
  154. int i,temp;
  155. unsigned short crc,CRC16;
  156. unsigned short ReadBuf[4];
  157. uint32_t addr,len,offset;
  158. unsigned char code;
  159. unsigned short count;
  160. #ifdef USE_NEW_FILE_SYSTEM
  161. SUT_FILE_PAGE_HEAD pageInfo;
  162. #endif
  163. SUT_DF_HEAD *pHeader;
  164. SUT_DF_LIST_RSP *pListRsp;
  165. SUT_DF_DATA_RSP *pDataRsp;
  166. pHeader=(SUT_DF_HEAD *)pData;
  167. if(pHeader->magic != PCTA_MAGIC)return -1;
  168. if(pHeader->protocol != UPDATE_PROTOCOL_RFILE )return -2;
  169. code= pHeader->code;
  170. count= pHeader->count;
  171. if(code==DOWNLOAD_FILE_LIST_REQ){//PC响应文件列表
  172. if(count!=(sizeof(SUT_DF_LIST_RSP)-sizeof(SUT_DF_HEAD)))return -4;
  173. pListRsp= (SUT_DF_LIST_RSP *)pData;
  174. CRC16=pListRsp->FileListCRC;
  175. crc=crc16_calc(0,(uint8_t *)&pListRsp->FileList,sizeof(SUT_FILE_LIST));
  176. if(crc!=CRC16)return -5;
  177. if(pListRsp->FileList.FileCount==0)return 0;//文件个数为0,不用更新,直接完成
  178. #ifdef USE_NEW_FILE_SYSTEM
  179. //重新对PC响应过来的文件列表进行排序,将SYS_CONFIG_A与SYS_CONFIG_B放在最后
  180. RerangeList(&pListRsp->FileList);
  181. #endif
  182. #ifdef DOWNLOAD_DIFFERENT_FILE_ONLY //跳过前面相同的文件,只从第一个不相同的文件开始更新
  183. sFileIndex=FindFirstDiffIndex(&pListRsp->FileList);//即将更新文件的索引
  184. if(sFileIndex >= pListRsp->FileList.FileCount){//没有需要更新的,结束
  185. g_sutFilesList.FileCount=pListRsp->FileList.FileCount;
  186. g_sutFilesList.Mark=STORAGE_MARK;
  187. FileSysSaveIndex();//保存索引
  188. return 0;
  189. }
  190. g_sutFilesList.FileCount=pListRsp->FileList.FileCount;
  191. #ifndef USE_NEW_FILE_SYSTEM
  192. memcpy(&g_sutFilesList.FileInfo[sFileIndex],&pListRsp->FileList.FileInfo[sFileIndex],(pListRsp->FileList.FileCount-sFileIndex)*sizeof(SUT_FILE_INFO));
  193. #endif
  194. #else //不判断是否文件相同都更新
  195. sFileIndex=0;
  196. #ifndef USE_NEW_FILE_SYSTEM
  197. memcpy(&g_sutFilesList,&pListRsp->FileList,sizeof(SUT_FILE_LIST));
  198. #endif
  199. #endif
  200. #ifdef USE_NEW_FILE_SYSTEM
  201. for(i=sFileIndex;i<g_sutFilesList.FileCount;i++){
  202. if(i==0) g_sutFilesList.FileInfo[i].FileAddr=0;//从页头开始
  203. else{//下一个文件的首地址是前一个文件首地址加上页头加上文件长度
  204. temp=g_sutFilesList.FileInfo[i-1].FileLen%4096;
  205. g_sutFilesList.FileInfo[i].FileAddr=g_sutFilesList.FileInfo[i-1].FileAddr+4096+g_sutFilesList.FileInfo[i-1].FileLen;
  206. if(temp !=0) g_sutFilesList.FileInfo[i].FileAddr += (4096-temp);//非4K页首,再向后偏移至4K页首
  207. }
  208. g_sutFilesList.FileInfo[i].FileLen=pListRsp->FileList.FileInfo[i].FileLen;
  209. memcpy(g_sutFilesList.FileInfo[i].FileMD5, pListRsp->FileList.FileInfo[i].FileMD5, sizeof(g_sutFilesList.FileInfo[i].FileMD5));
  210. memcpy(g_sutFilesList.FileInfo[i].FileName, pListRsp->FileList.FileInfo[i].FileName, sizeof(g_sutFilesList.FileInfo[i].FileName));
  211. }
  212. #endif
  213. sFileDataOffset=0;//即将更新文件数据的位置
  214. sprintf(buf,"RFile Count=%lu\r\n",g_sutFilesList.FileCount);
  215. IapTrace(buf);
  216. sprintf(buf,"RFile[%d]:%s len=%lu\r\n",newListIndex[sFileIndex],g_sutFilesList.FileInfo[sFileIndex].FileName,g_sutFilesList.FileInfo[sFileIndex].FileLen);
  217. IapTrace(buf);
  218. DFGetFileData(sFileIndex,sFileDataOffset,4096);
  219. return 1;
  220. }else if(code == DOWNLOAD_FILE_DATA_REQ){//PC响应文件数据申请
  221. pDataRsp = (SUT_DF_DATA_RSP*)pData;
  222. //sprintf(buf, "flen=%ld,%ld,index=%d,%d,%d,name=%s\r\n",pDataRsp->FileInfo.FileLen,g_sutFilesList.FileInfo[pDataRsp->FileIndex].FileLen,sFileIndex,newListIndex[sFileIndex],pDataRsp->FileIndex,pDataRsp->FileInfo.FileName);
  223. //IapTrace(buf);
  224. #ifdef USE_NEW_FILE_SYSTEM
  225. if(pDataRsp->FileInfo.FileLen!=g_sutFilesList.FileInfo[sFileIndex].FileLen ||
  226. #else
  227. if(pDataRsp->FileInfo.FileLen!=g_sutFilesList.FileInfo[pDataRsp->FileIndex].FileLen ||
  228. #endif
  229. pDataRsp->offset != sFileDataOffset ||
  230. newListIndex[sFileIndex]!=pDataRsp->FileIndex){//文件长度or 索引 or 偏移 不对?重新更新
  231. IapTrace("FLen or Offset err!ReDO!\r\n");
  232. DFGetFileData(sFileIndex,sFileDataOffset,4096);
  233. return -6;
  234. }
  235. len=pDataRsp->length;
  236. len-=2;//实际数据长度应去掉2字节的CRC
  237. //CRC校验
  238. CRC16=crc16_calc(0,pDataRsp->data,len);
  239. crc=((unsigned short)pDataRsp->data[len+1]&0xff)<<8;
  240. crc+=(unsigned short)pDataRsp->data[len]&0xff;
  241. if(crc!=CRC16){
  242. //校验错误,申请重新下载
  243. IapTrace("CRC err!ReDO!\r\n");
  244. DFGetFileData(sFileIndex,sFileDataOffset,4096);
  245. return -8;
  246. }
  247. //==CRC校验成功,更新FLASH ===
  248. #ifndef USE_NEW_FILE_SYSTEM
  249. sFlash_Write(pDataRsp->data,g_sutFilesList.FileInfo[sFileIndex].FileAddr+sFileDataOffset,len);
  250. #else
  251. sFlash_Write(pDataRsp->data,g_sutFilesList.FileInfo[sFileIndex].FileAddr+4096+sFileDataOffset,len);//数据内容要偏移出页头
  252. #endif
  253. if((len+sFileDataOffset)>=pDataRsp->FileInfo.FileLen){//完成当前文件下载
  254. #ifdef USE_NEW_FILE_SYSTEM
  255. //校验本文件的MD5码,看是否正确,如果不正确则重新下载本文件,如正确则切换下一文件
  256. if(0==FileCheckMD5(sFileIndex)){//MD5错误
  257. //重新下载
  258. sFileDataOffset=0;//即将更新文件数据的位置
  259. sprintf(buf,"RFile[%d]:%s len=%lu\r\n",newListIndex[sFileIndex],g_sutFilesList.FileInfo[sFileIndex].FileName,g_sutFilesList.FileInfo[sFileIndex].FileLen);
  260. IapTrace(buf);
  261. DFGetFileData(sFileIndex,sFileDataOffset,4096);
  262. }else{
  263. //MD5正确
  264. //更新信息页头并保存起来
  265. pageInfo.fLength=g_sutFilesList.FileInfo[sFileIndex].FileLen;
  266. memcpy(pageInfo.fName, g_sutFilesList.FileInfo[sFileIndex].FileName, sizeof(pageInfo.fName));
  267. memcpy(pageInfo.md5, g_sutFilesList.FileInfo[sFileIndex].FileMD5, sizeof(pageInfo.md5));
  268. pageInfo.mark=FILE_HEAD_MARK;
  269. if(sFileIndex==0) pageInfo.nextFileHeadAddr=FILE_INDEX_ADDR;
  270. else pageInfo.nextFileHeadAddr=g_sutFilesList.FileInfo[sFileIndex].FileAddr;
  271. temp=pageInfo.fLength%4096;
  272. pageInfo.nextFileHeadAddr += (pageInfo.fLength+4096);
  273. if(temp != 0) pageInfo.nextFileHeadAddr += (4096-temp);
  274. if((sFileIndex+1) >= g_sutFilesList.FileCount) pageInfo.nextFileHeadAddr=0;
  275. sFlash_Write((uint8_t *)&pageInfo, g_sutFilesList.FileInfo[sFileIndex].FileAddr, sizeof(SUT_FILE_PAGE_HEAD));
  276. if(++sFileIndex >= g_sutFilesList.FileCount){//判断所有文件是否下载完毕?
  277. //下载完毕,拷贝复制配置文件到备份区
  278. //CopyConfiToBckupFile();
  279. //结束
  280. return 0;
  281. }
  282. //未结束,启动下一个文件传输
  283. sFileDataOffset=0;//即将更新文件数据的位置
  284. sprintf(buf,"RFile[%d]:%s len=%lu\r\n",newListIndex[sFileIndex],g_sutFilesList.FileInfo[sFileIndex].FileName,g_sutFilesList.FileInfo[sFileIndex].FileLen);
  285. IapTrace(buf);
  286. DFGetFileData(sFileIndex,sFileDataOffset,4096);
  287. }
  288. #else //旧文件格式时有一个问题:最后一个文件没有校验MD5的正确性
  289. if(sFileIndex==(g_sutFilesList.FileCount-1)){//判断所有文件是否下载完毕?
  290. //所有文件下载完毕,结束
  291. g_sutFilesList.Mark=STORAGE_MARK;
  292. FileSysSaveIndex();//保存索引
  293. return 0;
  294. }else{
  295. //校验本文件的MD5码,看是否正确,如不正确则重新下载本文件,如正确则切换下一文件
  296. if(0==FileCheckMD5(sFileIndex)){//MD5错误
  297. //重新下载
  298. sFileDataOffset=0;//即将更新文件数据的位置
  299. sprintf(buf,"RFile[%d]:%s len=%lu\r\n",sFileIndex,g_sutFilesList.FileInfo[sFileIndex].FileName,g_sutFilesList.FileInfo[sFileIndex].FileLen);
  300. IapTrace(buf);
  301. DFGetFileData(sFileIndex,sFileDataOffset,4096);
  302. }else{//MD5正确
  303. //启动下一文件传输
  304. sFileIndex++;
  305. //下一个文件地址为上一个文件地址加上一个文件的长度
  306. g_sutFilesList.FileInfo[sFileIndex].FileAddr=g_sutFilesList.FileInfo[sFileIndex-1].FileAddr+g_sutFilesList.FileInfo[sFileIndex-1].FileLen;
  307. sFileDataOffset=0;//即将更新文件数据的位置
  308. sprintf(buf,"RFile[%d]:%s len=%lu\r\n",sFileIndex,g_sutFilesList.FileInfo[sFileIndex].FileName,g_sutFilesList.FileInfo[sFileIndex].FileLen);
  309. IapTrace(buf);
  310. DFGetFileData(sFileIndex,sFileDataOffset,4096);
  311. }
  312. }
  313. #endif
  314. }else{
  315. //本文件传输未结束,启动下一包下载
  316. sFileDataOffset+=len;
  317. sprintf(buf,"offset=%d %d%%\r\n",sFileDataOffset,100*sFileDataOffset/g_sutFilesList.FileInfo[sFileIndex].FileLen);
  318. //sprintf(buf,"offset=%d\r\n",sFileDataOffset);
  319. IapTrace(buf);
  320. DFGetFileData(sFileIndex,sFileDataOffset,4096);
  321. }
  322. return 2;
  323. }
  324. }