RT_thread 使用4G模块Air720H对STM32进行OTA远程无线升级

    接上一篇博文,使用了在线升级的STM32程序的方法。此篇博文将利用4G模块Air720H,使用AT指令集,通过HTTP协议从云端服务器下载新版固件,从而实现对STM32的远程无线程序升级。

   前面关于前期准备工作,在此不再累述 具体可以参考上一篇博文https://blog.csdn.net/ylzmm/article/details/104234099,关于简易的HTTP服务器的搭建参考这篇博文https://blog.csdn.net/ylzmm/article/details/104311190

   本文在 RT_thread给出的HTTP升级的案例(具体参考https://www.rt-thread.org/document/site/application-note/system/rtboot/an0028-rtboot/中的源码实现部分),进行了部分修改。修改了为AT指令的方式获取固件。以下是整体的升级思路和在使用AT指令获取固件时需要注意的事项。

  1.AT指令获取固件 (未提供完整AT指令步骤,重点步骤提出)

发送:AT+HTTPACTION=0
应答:

OK

+HTTPACTION: 0,200,92240    /*200为正常的服务器返回状态 92240为固件大小*/



发送:AT+HTTPREAD=0,100    /*0表示获取固件从固件头开始,100表示获取前100个字节*/
应答:                     /*100,100 表示获取从固件的100字节开始,后面100个字节*/

+HTTPREAD: 100            /*本次获取的固件大小100*/
RBLk??^app2.0.000010203040506070809`?荱{qa苎餲噗?%2?  /*实际固件数据*/
OK

   通过AT指令依次循环获取固件数据,获取一批固件数据,写入FLASH,以此循环。   

  2.固件数据的接收与写入处理

   但是我在调试的过程中遇到了一个很奇特的问题。在升级固件时偶尔会出现升级失败的现象,提示固件的CRC校验错误,明显是固件数据出现了遗漏。开始的时候我一直觉得是HTTP通信的问题,通信上下载固件数据偶尔出现了掉数据,后面实际中测试发现某次固件升级不成功,他会一直不成功,无论你重复下载多少次。由此排除了通信遗漏数据问题。之前我遇到的问题可以参考论坛中这一篇https://www.rt-thread.org/qa/thread-423550-1-1.html

  采用论坛中网友的答复的方法,从而解决了这个问题。

  确实。我进行AT指令的应答处理中,我遗漏了一个很严重的问题。固件数据是一堆16进制的数据,如果我以读取到OK,或者\r\n

这样的判断方式来进行判断本次接收固件数据完毕,很容易出现误判,固件数据可能存在干扰。

   最后采用了以下方式成功做到了100%升级:

 /*仅仅发送 应答数据在URC函数中处理*/
 if (at_exec_cmd(NULL,"AT+HTTPREAD=%d,4096",len_fir) != RT_EOK)
 {
     LOG_E("AT+HTTPACTION=%d,4096, send commands failed , response error or timeout 
             !",len_fir);
     goto __exit;
 }
 /*发送邮件 下载的字节数*/
 rt_mb_send(&http_mb, (rt_uint32_t)4096);   
		 
 /* 等待http数据传回 信号量 */
 result = rt_sem_take(http_dysem, HTTP_OTA_OUTTIME);

AT指令只是发生下载的固件的指令,不进行返回值的判断处理。一直等待一个信号量。

/*HTTP固件信息数据处理*/
static void urc_http_func(struct at_client *client ,const char *data, rt_size_t size)
{
	  char *recv_buf = RT_NULL;
	  int  number = 0;
	  recv_buf = (char *)rt_calloc(1, 4096);
	  
	  if (rt_mb_recv(&http_mb, (rt_ubase_t *)&number, RT_WAITING_FOREVER) == RT_EOK)
	  {
	      at_client_obj_recv(client,recv_buf,number,number);  
//	      /*打印接收部分数据*/
//		  ulog_hexdump(LOG_TAG, 16, (rt_uint8_t *)recv_buf, number);
	      rt_memset(firmware_http,0,sizeof(firmware_http));
	      rt_memcpy(firmware_http,recv_buf,number);
          rt_sem_release(http_dysem);
      }
	  rt_free(recv_buf);
}


static struct at_urc urc_firmware[]= {
		{"+HTTPREAD:",   "\r\n",     urc_http_func},
};

通过注册URC回调函数,当接收到“+HTTPREAD:”数据时,表明了正在进入了固件下载时。于是在URC回调函数中进行接收指定的固件数的大小的数据字节即可。

更加具体的代码实现,可以去参考RT的底层上关于TCP接收服务器下发的数据的处理方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章