logo资料库

STM32 W5500(http) 使用IAP 实现OTA空中升级.pdf

第1页 / 共12页
第2页 / 共12页
第3页 / 共12页
第4页 / 共12页
第5页 / 共12页
第6页 / 共12页
第7页 / 共12页
第8页 / 共12页
资料共12页,剩余部分请下载后查看
手把手教你如何实现自动固件更新 ——嵌入式篇 常席正 魏文龙 我们在上期 “手把手教你如何实现自动固件更新——服务器篇”那篇文章中介绍了通过云服 务器更新固件的方法,并着重介绍了服务器端的前期准备以及软件设计。这次小熊和大家分享下 嵌入式端的软件设计。相对于服务器端的软件设计,嵌入式软件设计需要更为严谨,因为固件升 级出错的后果会非常严重,因为这个功能一般使用在批量的设备上,而固件是控制系统的核心软 件,因此固件更新出错的话,会造成设备大面积瘫痪。所以严重性不言而喻。 本期我们来介绍一下客户端的具体实现过程,如图 1 所示,根据我们的自动固件更新协议,在 与更新服务器建立连接后,服务器会要求客户端进行一系列验证,嵌入式设备在通过验证后,更 新服务器会告知此嵌入式设备的最新固件信息,嵌入式设备根据这些信息下载并更新固件。
图 1 自动固件更新协议 “下载并更新固件”几个字囊括了我们所要执行的所有步骤。我们将按照以下步骤分别介绍。 1.下载准备--对 Flash 进行分区 为了实现‘下载并更新固件’我们先要做一些准备工作,我们把 MCU 的 Flash 分为三个区 分别为 BOOT 区,APP 区和 Backup 区,如图 2 所示
图 2 内存空间分配 区域 地址范围 大小 ·作用 BOOT 区 0x08000000 ~ 0x08007FFF 32 KB 系统引导 APP 区 0x08008000 ~ 0x08023FFF 112 KB 主程序 Backup 区 0x08024000 ~ 0x0803FFFF 112 KB 存放更新的程序 了解了空间分配之后,我们再来看一下我们这个演示中各部分的主要功能: 1. BOOT 区:  清空 APP 区,为新 APP 写入做准备;  把暂存在 Backup 区的新版本程序拷贝到 APP 区; 2. APP 区 APP 区是应用程序运行区域,实现正常的网络连接,并更新固件。  配置网络参数;  在线固件升级;
每次上电都会从 Boot 区引导,若判断上层 APP 区载入程序是否成功,成功则直接从 Boot 区跳转到 APP 区,正常运行主程序。 3. Backup 区  从服务器接收并备份需要更新的新 App,也就是固件存储区域。 备注:由于Backup区的大小为112K,所以意味着APP的大小最大为 112K; 2. 程序流程设计 我们完成了对 Flash 的分区规划后,就要设计我们程序的流程,图 3 是程序执行的流程图。 图 3 嵌入式设备固件更新流程图 每次启动嵌入式设备,均从首地址开始执行程序: 启动进入 BOOT 区,若 BOOT 检测 APP 区的不为空,则跳转到 APP 区的首地址执行主程序; APP 内的代码主要实现:
配置网络参数:配置 IP 地址,MAC 地址,建立网络连接。 远程更新固件:客户端向服务器发送固件版本查询报文。条件符合设定则进入步骤 当 APP 将新版本的固件下载完成后,进入步骤 跳转到 BOOT 区,执行更新操作; BOOT 将 APP 区擦除,并将新 APP 从 Backup 区写入到 APP 区,写入完毕后擦除 Backup 区 的固件; 重启,重新执行程序。 我们将程序主要分为两个部分,分别为 BOOT 程序和 APP 程序。APP 程序即是我们的固件下载 程序对应流程图的步,BOOT 程序既是固件更新程序对应流程图的步: 3. APP 程序设计(固件验证与下载) APP 代码程序初始化网络配置参数,实现嵌入式设备与服务器的正常连接,下载固件到 Backup 区,图 4 描述的为嵌入式设备与服务器的通信过程。
图 4 服务器-嵌入式设备通信过程示意图 固件服务器-嵌入式设备的通信过程大致分为三步: 1. 连接:嵌入式设备分配 socket 并连接到服务器。 2. 通信:连接建立后。服务器在接收到来自嵌入式设备的请求后发送应答。 3. 关闭:请求/应答完成后关闭连接。 我们 APP 区的函数主要做的就是下载固件,在程序里我们是通过 w5500_version()和 w5500_update()两个函数来实现的,w5500_version()用来验证当前的版本号与服务器上的版本 号是否相同,如果当前版本号小于服务器上的版本号就进行更新。 01 void w5500_version(void) 02 { 03 uint8 recv_buffer[2048]; 04 uint8 version[10]; 05 switch (getSn_SR(W5500_UPDATE)) { 06 case SOCK_ESTABLISHED: 07 if (getSn_IR(W5500_UPDATE) & Sn_IR_CON) { 08 setSn_IR(W5500_UPDATE, Sn_IR_CON); 09 } 10 send(W5500_UPDATE,(const uint8 *)postH,sizeof(postH));//发送 验证 11 Delay_ms(5000); 12 if ((len = getSn_RX_RSR(W5500_UPDATE)) > 0) { 13 len = recv(W5500_UPDATE, (uint8*)recv_buffer, len); //接 收数据 14 if (strstr((char*)recv_buffer,"\"error\"")) { //报文内包含 error,就结束函数 15 printf("upload error\r\n"); 16 return; 17 } 18 printf("%s\r\n",recv_buffer);//打印服务器响应报文 19 mid((char*)recv_buffer,"\"version\":",",",(char*)version);//可以获取路 径 20 /*********读取版本号************/ 21 if (strncmp(ver_num,version,7)<0) { 22 update_flag=1;
23 mid((char*)recv_buffer,"\"http://W5500.com/fw_update/upload/","\",",( char*)bin_name);//可以获取路径 24 snprintf(post_msg,sizeof(post_msg), 25 "POST /fw_update/upload/%s HTTP/1.1\r\n"\ 26 "Host:w5500.com\r\n"\ "Accept:image/gif,image/x-xbitmap,image/jpeg,image/pjpeg,*/*\r\n"\ 27 "Pragma:no-cache\r\n"\ 28 "Accept-Encoding: gzip,deflate\r\n"\ 29 "Connection:keep-alive\r\n"\ 30 "\r\n",bin_name); 31 printf("The version is %s\r\n",ver_num); 32 } else { 33 printf("The version is %s\r\n",version); 34 printf("The version is no need to update\r\n"); 35 return; 36 } 37 } 38 close(W5500_UPDATE); 39 break; 40 case SOCK_CLOSE_WAIT: 41 break; 42 case SOCK_CLOSED: 43 socket(W5500_UPDATE,Sn_MR_TCP,30000,Sn_MR_ND); 44 break; 45 case SOCK_INIT: 46 connect(W5500_UPDATE, server_ip ,server_port); 47 break; 48 } 49 } 上述函数中 W5500 先与固件服务器建立 TCP Socket 连接,然后通过 send 函数发送固件 查询报文“postH”,该报文主要功能是把 W5500 的 MAC 地址发送给服务器。 01 char postH[]= { 02 "POST /fw_update/2.php HTTP1.1\r\n"\ 03 "Host:w5500.com\r\n"\ 04 "Accept:image/gif,image/x-xbitmap,image/jpeg,image/pjpeg,*/*\r\n"\ 05 "User-Agent: Mozilla/4.0 (compatible;MSTE 5.5;Windows 98)\r\n"\ 06 "Content-Length:21\r\n"\ 07 "Content-Type:application/x-www-form-urlencoded\r\n"\ 08 "Cache-Control:no-Cache\r\n"\ 09 "Connection:close\r\n"\
10 "\r\n"\ 11 "mac=00:08:DC:11:12:13"\ 12 }; 服务器端会根据传送的 MAC 地址检查设备是否注册以及是否有相关类型的固件。如果验证 不通过固件服务器就会向嵌入式设备发送 error 信息。如果验证通过服务器会向嵌入式设备回复 如图 5 所示的报文,报文中包含最新的版本号、下载路径、固件大小、文件 Hash 校验值等 4 个关键信息:{“version”:”X.X.X”,”path”:”…”,”size”:”XX”,”hash”:”…”},客户 端收到这 4 个关键信息后,先提取版本号与当前版本号比较如果比当前版本号新则置位更新标 志位并且拼接下载固件的报文。 图 5 查询报文 通过检查固件更新标志位,当发现此标志位置位后就运行 W5500_update()函数进行固件的 下载,首先我们要为嵌入式设备分配一个 Socket W5500_UPDATE,这个 Socket 初始状态为 SOCK_CLOSED,我们通过调用函数 socket(W5500_UPDATE, Sn_MR_TCP,30000,Sn_MR_ND), 打 开 Socket , Socket 状 态 改 变 为 SOCK_INIT, 打 开 Socket 后 调 用 connect(W5500_UPDATE,server_ip ,server_port)连接服务器,server_ip 和 server_port 分别为 服务器的 IP 地址和端口号,连接建立之后 Socket 状态变为 SOCK_ESTABLISHED,在此状态下 我们调用函数 Firmware_download()进行固件的下载,具体代码如下。 01 void Firmware_download(void)
分享到:
收藏