otaEvent.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. #include "otaEvent.h"
  2. #include "usart.h"
  3. #include "systick.h"
  4. #include "w25q32.h"
  5. #include "main.h"
  6. #include "ec800m.h"
  7. #include <stdio.h>
  8. #include "string.h"
  9. #define APPBLOCKNB 2 //下载的程序位于block的第3块中
  10. #define OTA_EVENT_BLOCKNB 1 //OTA事件完成标志存储的位置位于第2块中
  11. #define SOH 0x01 // XMOD协议帧头
  12. #define ACK 0X06 // 应答标志
  13. #define NAK 0x15 // 非应答标志
  14. #define EOT 0x04 // 结束标志
  15. int8_t xmodem(uint16_t timeout);
  16. OTA_T ota_data;
  17. uint16_t Xmodem_CRC16(uint8_t *data, uint16_t datalen);
  18. static OTA_MESSAGE ota_message;
  19. #if 0
  20. //测试用的
  21. int WaitForReadData(uint8_t* data,int timeout,int datalen)
  22. {
  23. uint32_t len = 0;
  24. bool timeoutFlag = false;
  25. if (timeout >= 0)
  26. {
  27. timeoutFlag = true;
  28. }
  29. while (1)
  30. {
  31. delay_1ms(50);
  32. if (UART0_RX_STAT > 0)
  33. {
  34. UART0_RX_STAT = 0;
  35. char *p = strstr((char *)&UART0_RX_BUF, "CONNECT ");
  36. if (p)
  37. {
  38. p += 8;
  39. sscanf(p, "%u\r", &len); // 读取长度
  40. if(len == datalen)
  41. {
  42. p = strchr(p, '\n') + 1; // 跳过换行
  43. memcpy(data,p,datalen);
  44. Clear_DMA_Buffer();
  45. return datalen;
  46. }
  47. else
  48. {
  49. Clear_DMA_Buffer();
  50. return len;
  51. }
  52. }
  53. }
  54. timeout -= 50;
  55. if (timeoutFlag == true && timeout <= 0)
  56. {
  57. Clear_DMA_Buffer();
  58. return -1;
  59. }
  60. }
  61. }
  62. static uint8_t app_programmer[1024];
  63. void read_ota_DATA(uint32_t app_byte)
  64. {
  65. /* 打开UFS:otaDATA.txt */
  66. EC800MSendCmd(CLOSE_otaDATA_FILE,strlen(CLOSE_otaDATA_FILE));
  67. WaitResponse("QFCLOSE",1000);
  68. EC800MSendCmd(OPEN_otaDATA_FILE,strlen(OPEN_otaDATA_FILE));
  69. if(WaitResponse("QFOPEN:", 2000) == 0)
  70. return;
  71. for(uint8_t i=0;i<app_byte/1024;i++) //一次读1KB
  72. {
  73. task_fwdgt_reload();
  74. memset(app_programmer,0,1024);
  75. // uint32_t addr=APP_PROGRAMMER_BLOCK*64*1024+i*1024; //其在w25q32中的地址
  76. // W25Q32_Read(app_programmer,addr,1024);
  77. while(1)
  78. {
  79. int x = 0;
  80. EC800MSendCmd(READ_otaDATA_FILE,strlen(READ_otaDATA_FILE));
  81. x = WaitForReadData(app_programmer,2000,1024);
  82. if((x != 1024) && (x != -1))
  83. {
  84. char* SEEK_otaDATA_FILE = "";
  85. sprintf(SEEK_otaDATA_FILE,"AT+QFSEEK=1,%d,2\r\n",x);
  86. EC800MSendCmd(SEEK_otaDATA_FILE,strlen(SEEK_otaDATA_FILE)); //出错的话文件指针向左偏移1024个字节
  87. }
  88. else if(x == 1024)
  89. {
  90. break;
  91. }
  92. }
  93. delay_1ms(50);
  94. }
  95. //将不满1024数据单独写入
  96. if(app_byte % 1024 != 0)
  97. {
  98. uint32_t startAddress=(app_byte/1024)*1024;
  99. memset(app_programmer,0,1024);
  100. // uint32_t addr=APP_PROGRAMMER_BLOCK*64*1024+(app_byte/1024)*1024; //其在w25q32中的地址
  101. // W25Q32_Read(app_programmer,addr,app_byte%1024);
  102. while(1)
  103. {
  104. int x = 0;
  105. EC800MSendCmd(READ_otaDATA_FILE,strlen(READ_otaDATA_FILE));
  106. x = WaitForReadData(app_programmer,2000,app_byte % 1024);
  107. if(x != (app_byte % 1024) && (x != -1))
  108. {
  109. char* SEEK_otaDATA_FILE = "";
  110. sprintf(SEEK_otaDATA_FILE,"AT+QFSEEK=1,%d,2\r\n",x);
  111. EC800MSendCmd(SEEK_otaDATA_FILE,strlen(SEEK_otaDATA_FILE)); //出错的话文件指针向左偏移读取字节数
  112. }
  113. else if(x == (app_byte % 1024))
  114. {
  115. break;
  116. }
  117. }
  118. delay_1ms(50);
  119. }
  120. // 关闭保存UFS文件
  121. while(1)
  122. {
  123. EC800MSendCmd(CLOSE_otaDATA_FILE,strlen(CLOSE_otaDATA_FILE));
  124. if(WaitResponse("OK", 2000) == 1)
  125. {
  126. break;
  127. }
  128. }
  129. }
  130. #endif
  131. /*
  132. * 函数名:uint8_t check_ota_event()
  133. * 输入参数:无
  134. * 输出参数:无
  135. * 返回值:无
  136. * 函数作用:判断ota事件是否产生是否要进入更新部分
  137. */
  138. int8_t check_ota_event()
  139. {
  140. //关闭看门狗
  141. // 当标志位为1时证明ota事件产生,将进入ota升级路线
  142. if (ota_data.ota_flag == 1)
  143. {
  144. // W25Q32_Erase64K(APPBLOCKNB); //程序文件在第三block以后
  145. // EC800MSendCmd(DEL_otaDATA_FILE, strlen(DEL_otaDATA_FILE)); //清空OTA数据文件
  146. int8_t recvSta = xmodem(1000); //在1000秒内解决OTA更新
  147. if (recvSta == 0)
  148. {
  149. return 0;
  150. }
  151. else
  152. {
  153. // read_ota_DATA(ota_message.XmodemByte);
  154. NVIC_SystemReset();
  155. }
  156. }
  157. else
  158. return 0;
  159. }
  160. /**
  161. * @brief 专门用来解析往文件里写数据的响应数据
  162. *
  163. * @param timeout 超时时间(ms)
  164. * @return uint8_t 实际写入字节数
  165. */
  166. uint8_t WaitResponse_value(int timeout)
  167. {
  168. bool timeoutFlag = false;
  169. if (timeout >= 0)
  170. {
  171. timeoutFlag = true;
  172. }
  173. while (1)
  174. {
  175. delay_1ms(50);
  176. if (UART0_RX_STAT > 0)
  177. {
  178. UART0_RX_STAT = 0;
  179. char *p = strstr((char *)&UART0_RX_BUF, ": ") + 2;
  180. if (p)
  181. {
  182. uint8_t ret = 0;
  183. ret = strtol(p, &p, 10);
  184. Clear_DMA_Buffer();
  185. return ret;
  186. }
  187. }
  188. timeout -= 50;
  189. if (timeoutFlag == true && timeout <= 0)
  190. {
  191. Clear_DMA_Buffer();
  192. return 0;
  193. }
  194. };
  195. }
  196. int8_t xmodem(uint16_t timeout)
  197. {
  198. int startTime = gettick();
  199. ota_data.done=0;
  200. OTA_flag data_flag;
  201. data_flag.flag=0;
  202. data_flag.xmodemNB=0;
  203. while(1)
  204. {
  205. task_fwdgt_reload(); //喂狗
  206. if(gettick()-startTime>timeout*1000)return 0; //如果一直得不到上位机的xmode数据相应,超时则跳出本函数
  207. usart_data_transmit(COM_232, 'C'); //向上位机发送'C',表明请求xmodem数据
  208. delay_1ms(1000);
  209. if(ota_data.done==1)
  210. {
  211. //打开otaData.txt文件
  212. EC800MSendCmd(CLOSE_otaDATA_FILE,strlen(CLOSE_otaDATA_FILE));
  213. WaitResponse("QFCLOSE",1000);
  214. EC800MSendCmd(OPEN_otaDATA_FILE,strlen(OPEN_otaDATA_FILE));
  215. if(WaitResponse("QFOPEN:", 2000) == 0)
  216. return 0;
  217. break; //如果上位机响应请求则跳出循环等待
  218. }
  219. }
  220. // 判断数据帧头是否符合标准
  221. while (gettick() - startTime < timeout * 1000)
  222. {
  223. if (ota_data.done == 1)
  224. {
  225. task_fwdgt_reload(); //喂狗
  226. if (ota_data.data[0] == SOH && ota_data.data_cnt == 133) //如果xmodem数据包是满的128个字节
  227. {
  228. uint16_t XCRC = Xmodem_CRC16(ota_data.data + 3, 128);
  229. if (XCRC == ota_data.data[131] * 256 + ota_data.data[132]) // 经过校验的数据一致时将进行数据处理
  230. {
  231. data_flag.xmodemNB++; //xmodem数据包计数
  232. // W25Q32_PageWrite(w25q32_data,APPBLOCKNB*256+(data_flag.xmodemNB-1)/2);
  233. uint8_t sed_flg = 0;
  234. while(sed_flg < 2)
  235. {
  236. EC800MSendCmd(WRITE_otaDATA_FILE,strlen(WRITE_otaDATA_FILE));
  237. if(WaitResponse("CONNECT", 2000) == 0)
  238. {
  239. sed_flg++;
  240. }
  241. else
  242. {
  243. sed_flg = 0;
  244. break;
  245. }
  246. }
  247. while(sed_flg < 2)
  248. {
  249. EC800MSendCmd(ota_data.data + 3,128);
  250. // EC800MSendCmd(TEST_DATA,128);
  251. int x = WaitResponse_value(2000);
  252. if(x != 128)
  253. {
  254. sed_flg++;
  255. char* QFSEEK_CMD;
  256. sprintf(QFSEEK_CMD,"AT+QFSEEK=1,%d,2\r\n",x);
  257. EC800MSendCmd(QFSEEK_CMD,strlen(QFSEEK_CMD)); //出错的话文件指针向左偏移x个字节
  258. }
  259. else
  260. {
  261. sed_flg = 0;
  262. break;
  263. }
  264. }
  265. ota_data.data_cnt = 0;
  266. memset(ota_data.data, 0, 133);
  267. ota_data.done = 0;
  268. usart_data_transmit(COM_232, ACK);
  269. }
  270. else
  271. {
  272. ota_data.data_cnt = 0;
  273. memset(ota_data.data, 0, 133);
  274. ota_data.done = 0;
  275. usart_data_transmit(COM_232, NAK);
  276. }
  277. }
  278. //进入结束的包处理
  279. else if (ota_data.data[0] == EOT && ota_data.data_cnt == 1)
  280. {
  281. // if(data_flag.xmodemNB%2!=0) //将可能为奇数的数据写入进去
  282. // {
  283. // W25Q32_PageWrite(w25q32_data,APPBLOCKNB*256+(data_flag.xmodemNB-1)/2);
  284. // }
  285. // 保存UFS文件
  286. uint8_t sed_flg = 0;
  287. while(sed_flg < 2)
  288. {
  289. EC800MSendCmd(CLOSE_otaDATA_FILE,strlen(CLOSE_otaDATA_FILE));
  290. if(WaitResponse("OK", 2000) == 0)
  291. {
  292. sed_flg++;
  293. }
  294. else
  295. {
  296. sed_flg = 0;
  297. break;
  298. }
  299. }
  300. usart_data_transmit(COM_232, ACK);
  301. //完成xmodem协议的交互将完成的标志存储到内存中
  302. ota_message.Completion_flag=1U;
  303. ota_message.XmodemByte=data_flag.xmodemNB*128;//后续补齐的0x1A还需要进一步考虑
  304. while(sed_flg < 2)
  305. {
  306. EC800MSendCmd(CLOSE_otaDATA_FILE,strlen(CLOSE_otaDATA_FILE));
  307. WaitResponse("QFCLOSE",1000);
  308. EC800MSendCmd(OPEN_otaMSG_FILE,strlen(OPEN_otaMSG_FILE));
  309. if(WaitResponse("QFOPEN:", 2000) == 0)
  310. {
  311. sed_flg++;
  312. }
  313. else
  314. {
  315. sed_flg = 0;
  316. break;
  317. }
  318. }
  319. while(sed_flg < 2)
  320. {
  321. EC800MSendCmd(WRITE_otaMSG_FILE,strlen(WRITE_otaMSG_FILE));
  322. if(WaitResponse("CONNECT", 2000) == 0)
  323. {
  324. sed_flg++;
  325. }
  326. else
  327. {
  328. sed_flg = 0;
  329. break;
  330. }
  331. }
  332. while(sed_flg < 2)
  333. {
  334. EC800MSendCmd((uint8_t *)&ota_message,sizeof(OTA_MESSAGE));
  335. // delay_1ms(3000);
  336. int x = WaitResponse_value(2000);
  337. if(x != sizeof(OTA_MESSAGE))
  338. {
  339. sed_flg++;
  340. char* QFSEEK_CMD;
  341. sprintf(QFSEEK_CMD,"AT+QFSEEK=1,%d,2",x);
  342. EC800MSendCmd(QFSEEK_CMD,strlen(QFSEEK_CMD)); //出错的话文件指针向左偏移x个字节
  343. }
  344. else
  345. {
  346. sed_flg = 0;
  347. break;
  348. }
  349. }
  350. while(sed_flg < 2)
  351. {
  352. EC800MSendCmd(CLOSE_otaMSG_FILE,strlen(CLOSE_otaMSG_FILE));
  353. if(WaitResponse("OK", 2000))
  354. {
  355. sed_flg++;
  356. }
  357. else
  358. {
  359. sed_flg = 0;
  360. break;
  361. }
  362. }
  363. // W25Q32_Erase64K(OTA_EVENT_BLOCKNB);//擦除原先的数据
  364. // W25Q32_PageWrite((uint8_t *)&ota_message,OTA_EVENT_BLOCKNB*256);
  365. ota_data.data_cnt = 0;
  366. memset(ota_data.data, 0, 133);
  367. ota_data.done = 0;
  368. delay_1ms(50);
  369. // 写入事件完成标志后重启设备,其他状态页无需回滚,写入完成会执行重启指令
  370. return 1;
  371. }
  372. else
  373. {
  374. ota_data.data_cnt = 0;
  375. memset(ota_data.data, 0, 133);
  376. ota_data.done = 0;
  377. usart_data_transmit(COM_232, NAK);
  378. }
  379. }
  380. delay_1ms(1);
  381. }
  382. return 0;
  383. }
  384. /*-------------------------------------------------*/
  385. /*函数名:Xmodem_CRC16校验 */
  386. /*参 数:data:数据指针 datalen:数据长度 */
  387. /*返回值:校验后的数据 */
  388. /*-------------------------------------------------*/
  389. uint16_t Xmodem_CRC16(uint8_t *data, uint16_t datalen)
  390. {
  391. uint8_t i; // 用于for循环
  392. uint16_t Crcinit = 0x0000; // Xmdoem CRC校验的初始值,必须是0x0000
  393. uint16_t Crcipoly = 0x1021; // Xmdoem CRC校验的多项式,必须是0x1021
  394. while (datalen--)
  395. { // 根据datalen大小,有多少字节循环多少次
  396. Crcinit = (*data << 8) ^ Crcinit; // 先将带校验的字节,挪到高8位
  397. for (i = 0; i < 8; i++)
  398. { // 每个字节8个二进制位,循环8次
  399. if (Crcinit & 0x8000) // 判断BIT15是1还是0,是1的话,进入if
  400. Crcinit = (Crcinit << 1) ^ Crcipoly; // 是1的话,先左移,再异或多项式
  401. else // 判断BIT15是1还是0,是0的话,进入else
  402. Crcinit = (Crcinit << 1); // 是0的话,只左移
  403. }
  404. data++; // 下移,计算一个字节数据
  405. }
  406. return Crcinit; // 返回校验后的数据
  407. }