mcuIap.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #include "mcuIap.h"
  2. #include "mallocSw.h"
  3. #include "ticket.h"
  4. #include "mcu.h"
  5. #include "crc.h"
  6. /*
  7. 业务逻辑
  8. 本应用在启动后的前N秒内只运行通用队列任务,且检测本地参数MCUIAPFLAG
  9. MCUIAPFLAG:1 则需要进行MCU升级流程,进入逻辑A
  10. MCUIAPFLAG:0 不需要进行MCU升级流程,进入逻辑B
  11. 逻辑A:
  12. 则会定时发APP_DOWNLOAD指令检测是否有MCU响应文件请求,如果有,则进入
  13. MCU的IAP升级APP逻辑,如果收到MCU响应升级完成 ,则复位MCUIAPFLAG;
  14. 如果没有,则执行正常的逻辑业务
  15. 逻辑B:
  16. 则会定时发检测MCU的版本号指令,如果检测到与应用中的MCU版本一致,则执
  17. 行正常的逻辑业务;如果不一致,则发一条指令(+FOTA:MCUIAP未定)到串口,同时
  18. 置位MCUIAPFLAG,同时等待被MCU复位,如果超时N秒还没有被复位,则复位
  19. MCUIAPFLAG,直接执行正常的业务逻辑
  20. 当超时N秒,如果MCUIAPFLAG已置位,则复位之,然后执行正常的业务逻辑
  21. MCU部份:
  22. APP:APP添加响应MCU版本指令以及+FOTA:MCUIAP指令,收到+FOTA:MCUIAP指令
  23. 后,将参数中的FOTAMODEM置位,然后马上复位MCU。
  24. IAP:IAP启动后,检测FOTAMODEM状态
  25. FOTAMODEM复位状态:按原来逻辑运行
  26. FOTAMODEM置位状态:先启动模块(同时考虑复位FOTAMODEM),然后运行原来的
  27. 逻辑,但在升级APP完成后,回发一条升级完成的指令给串口,让本应用复位
  28. MCUIAPFLAG
  29. */
  30. #define MIAP_TRIGGER_INFO "<<DOWNLOAD_APP\r\n"
  31. #define MIAP_PROTOCOL_INFO "PCTA"
  32. #define MIAP_COMPLETE_INFO "[MSG]Completed!\r\n"
  33. #define MIAP_MSG_INFO "[MSG]"
  34. typedef enum{
  35. MIAP_IDLE, //空闲
  36. MIAP_START, //定时发MIAP_TRIGGER_INFO
  37. MIAP_BUSY, //正在传输文件
  38. MIAP_DONE, //设备完成升级
  39. MIAP_STOP
  40. }MIAP_ENUM;
  41. static T_UINT8 iapStatus=MIAP_IDLE;
  42. #define MAX_WAIT_TIME_UPGRADE 5//升级模式下如果此时间内收不到版本或数据请求,则退出升级模式
  43. unsigned char mcuIapMode=0;//当前是否进入正常的IAP模式
  44. unsigned char mcuIapUpgradeCnt=0;//进入升级模式后的超时计数
  45. void mcuIapModeUpdate(unsigned char newmode){
  46. if(newmode==mcuIapMode) return;
  47. if(newmode==1) normalTaskStatus(FALSE);
  48. else normalTaskStatus(TRUE);
  49. mcuIapMode=newmode;
  50. }
  51. #define MAX_WAIT_VERSION_TIME 30
  52. T_UINT8 mcuCheckTimeCnt=0;//开机后MAX_WAIT_VERSION_TIME内接受MCU版本指令
  53. #define MAX_SEND_TRIGGER_TIME 5
  54. T_UINT8 mcuVersionSendCnt;//发送MIAP_TRIGGER_INFO时间计数
  55. static void isMcuIapTaskIdle(void){
  56. if(MIAP_IDLE==iapStatus) ticketVote(TICKET_PT_MCUIAP);
  57. else ticketDeVote(TICKET_PT_MCUIAP);
  58. }
  59. #define MSG_BUFFER_SIZE 512
  60. unsigned char msgPtr[MSG_BUFFER_SIZE];
  61. void miapStatusUpdate(MIAP_ENUM newstatus){
  62. if(newstatus==iapStatus) return;
  63. if(MIAP_START==newstatus){
  64. wlog_warn("mcu version start ok");
  65. }
  66. iapStatus=newstatus;
  67. }
  68. static void mcuVersionAcceptTime(void){
  69. if(mcuCheckTimeCnt<=MAX_WAIT_VERSION_TIME*2) mcuCheckTimeCnt++;
  70. if(MIAP_START==iapStatus){
  71. if(++mcuVersionSendCnt>=MAX_SEND_TRIGGER_TIME*2){
  72. miapStatusUpdate(MIAP_STOP);
  73. wlog_info("Mcu no ack for asking, timeout");
  74. }
  75. }else mcuVersionSendCnt=0;
  76. if(mcuIapMode==1){
  77. if(++mcuIapUpgradeCnt>=MAX_WAIT_TIME_UPGRADE*2){
  78. wlog_warn("Miap:timeout no version or data req");
  79. miapStatusUpdate(MIAP_STOP);
  80. }
  81. }else mcuIapUpgradeCnt=0;
  82. }
  83. PT_THREAD (ptMcuIapTask(pt_timer_t *ptPool, struct pt *pt)){
  84. static pt_timer_t ptTimer;
  85. PT_BEGIN(pt);
  86. while(1){
  87. switch(iapStatus){
  88. case MIAP_IDLE:
  89. break;
  90. case MIAP_START:
  91. msgToOutter(MIAP_TRIGGER_INFO);
  92. break;
  93. case MIAP_BUSY:
  94. break;
  95. case MIAP_DONE:
  96. break;
  97. case MIAP_STOP:
  98. wlog_info("MIAP_STOP");
  99. mcuIapModeUpdate(0);
  100. miapStatusUpdate(MIAP_IDLE);
  101. break;
  102. }
  103. mcuVersionAcceptTime();
  104. isMcuIapTaskIdle();
  105. PTTimerStart(ptPool, &ptTimer,50);
  106. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer));
  107. }
  108. PT_END(pt);
  109. }
  110. static int IapRecvMsgHandle(unsigned char *msg, unsigned int len);
  111. //处理由串口收到的数据包
  112. char miapRecvFromUart(unsigned char *data, int length){
  113. static unsigned int recvLen=0;
  114. unsigned int i,k;
  115. unsigned short len;
  116. unsigned char protocol;
  117. int plen=length;
  118. for(i=0;i<plen;i++){
  119. if(recvLen>=MSG_BUFFER_SIZE){
  120. wlog_error("maip recvbuf overflow,reset");
  121. recvLen=0;
  122. continue;
  123. }
  124. msgPtr[recvLen++]=data[i];
  125. if(recvLen<5) continue;
  126. if(0==memcmp(msgPtr, MIAP_PROTOCOL_INFO,strlen(MIAP_PROTOCOL_INFO))){
  127. protocol=msgPtr[4];
  128. if(recvLen<26) continue;
  129. len=(unsigned short)msgPtr[25]<<8;
  130. len+=(unsigned short)msgPtr[24];
  131. len+=26;
  132. if(recvLen<len) continue;
  133. if(UPDATE_PROTOCOL_APP==protocol){
  134. miapStatusUpdate(MIAP_BUSY);
  135. IapRecvMsgHandle(msgPtr,recvLen);
  136. }
  137. recvLen=0;
  138. }else if(0==memcmp(msgPtr, MIAP_MSG_INFO, strlen(MIAP_MSG_INFO))){
  139. for(k=0;k<recvLen;k++){
  140. if(msgPtr[k]<=0x0A){
  141. msgPtr[k]=0;
  142. break;
  143. }
  144. }
  145. if(k<recvLen){
  146. wlog_info("%s",msgPtr);
  147. if(0==memcmp(msgPtr, MIAP_COMPLETE_INFO,strlen(MIAP_COMPLETE_INFO))) miapStatusUpdate(MIAP_DONE);
  148. recvLen=0;
  149. }
  150. }else return 0;
  151. }
  152. return 1;
  153. }
  154. unsigned char *getMd5Data(void){
  155. static unsigned char md5[32];
  156. memcpy(md5, getMcuAppMD5(),32);
  157. restoreDataFormatByHex(md5,32);
  158. return md5;
  159. }
  160. static int IapRecvMsgHandle(unsigned char *pData, unsigned int Datalen){
  161. int i;
  162. unsigned char data;
  163. unsigned char code;
  164. unsigned short count;
  165. update_hdr_t *pHeader;
  166. update_version_req_t *pVersionReq;
  167. update_version_rsp_t VersionRsp;
  168. update_data_req_t *pDataReq;
  169. update_data_rsp_t DataRsp;
  170. static unsigned char m_Rand;
  171. unsigned char *m_FileMD5=getMd5Data();
  172. unsigned int m_FileSize=getMcuAppDataSize();
  173. unsigned char *m_FileData=getMcuAppData();
  174. pHeader=(update_hdr_t *)pData;
  175. if(pHeader->magic != PCTA_MAGIC)return -1;
  176. if(pHeader->protocol != UPDATE_PROTOCOL_APP )return -2;
  177. if(pHeader->code==UPDATE_CODE_VERSION_REQ){
  178. if(pHeader->count!=(sizeof(update_version_req_t)-sizeof(update_hdr_t)))return -3;
  179. //ShowMsg(_T("UPDATE_CODE_VERSION_REQ"));
  180. pVersionReq= (update_version_req_t *)pData;
  181. memcpy(&VersionRsp.hdr,&pVersionReq->hdr,sizeof(update_hdr_t));
  182. VersionRsp.hdr.count=sizeof(update_version_rsp_t)-sizeof(update_hdr_t);
  183. VersionRsp.size=m_FileSize;
  184. memcpy(VersionRsp.version_md5,m_FileMD5,16);
  185. m_Rand=pHeader->tid;
  186. //Send
  187. wlog_info("version req ok, feed back");
  188. //showHexData((unsigned char *)&VersionRsp,sizeof(update_version_rsp_t));
  189. LSAPI_OSI_ThreadSleep(10);//不能太快发给MCU
  190. uartOutPut((unsigned char *)&VersionRsp,sizeof(update_version_rsp_t));
  191. return 1;
  192. }else if(pHeader->code == UPDATE_CODE_DATA_WITH_CRC_REQ){
  193. if(pHeader->count!=(sizeof(update_data_req_t)-sizeof(update_hdr_t)))return -3;
  194. //ShowMsg(_T("UPDATE_CODE_DATA_WITH_CRC_REQ"));
  195. pDataReq=(update_data_req_t *)pData;
  196. memcpy(&DataRsp.hdr,&pDataReq->hdr,sizeof(update_hdr_t));
  197. memcpy(DataRsp.version_md5,m_FileMD5,16);
  198. DataRsp.offset=pDataReq->offset;
  199. DataRsp.length=0;
  200. for(i=0;i<pDataReq->length;i++){
  201. if((DataRsp.offset+DataRsp.length)>=m_FileSize || DataRsp.length>=UPDATE_DATA_SIZE_MAX)break;
  202. data=m_FileData[DataRsp.offset+DataRsp.length];
  203. data^=m_Rand;//加密
  204. DataRsp.data[DataRsp.length]=data;
  205. DataRsp.length++;
  206. }
  207. //CRC
  208. unsigned short crc=crc16_calc(0,DataRsp.data,DataRsp.length);
  209. DataRsp.data[DataRsp.length++]=crc&0xff;
  210. DataRsp.data[DataRsp.length++]=crc>>8;
  211. DataRsp.hdr.count=DataRsp.length + 24 ;//长度
  212. //Send
  213. LSAPI_OSI_ThreadSleep(10);//不能太快发给MCU
  214. uartOutPut((unsigned char *)&DataRsp,DataRsp.hdr.count+sizeof(update_hdr_t));
  215. return 0;
  216. }
  217. return 0;
  218. }
  219. /*启动LTE进入MCU_IAP模式*/
  220. void McuIapStart(void){
  221. mcuIapModeUpdate(1);
  222. miapStatusUpdate(MIAP_START);
  223. mcuCheckTimeCnt=0xff;
  224. }
  225. /*MCU没有通过正常流程而是直接发PCTA消息过来时,需要启动MCUIAP*/
  226. void McuIapKeepOn(void){
  227. if(mcuIapMode!=0) return;
  228. McuIapStart();
  229. }
  230. //系统休眠后醒来要更新计数器
  231. void miapCntUpdate(T_INT32 value){
  232. T_INT32 temp;
  233. temp=MAX_WAIT_VERSION_TIME*2-mcuCheckTimeCnt;
  234. if(temp<=0) return;
  235. if(value>temp) mcuCheckTimeCnt=0xff;
  236. else mcuCheckTimeCnt += value;
  237. }
  238. T_INT32 getMaipCnt(void){
  239. T_INT32 temp;
  240. temp=MAX_WAIT_VERSION_TIME*2-mcuCheckTimeCnt;
  241. if(temp<=0) return NO_SLEEP_TIME;
  242. else return temp;
  243. }
  244. T_BOOL isMcuIapOff(void){
  245. if(mcuIapMode==0) return TRUE;
  246. else return FALSE;
  247. }