WIZnet2012

基于 HTTP的远程配置和固件更新

0
阅读(2564)

(已在《无线电》杂志第10期刊登)

对于HTTP的思考

你也许会问,既然通过一个上位机程序可以完成这个任务,为什么还要通过浏览器实现呢?其实这两个方法各有优缺点,用上位机程序,用户可以自己定制协议,但是用户不仅需要安装该上位机程序,而且还要考虑面对不同的操作系统下的兼容情况。然而通过网页更新的话,只需要设备内嵌一个HTTP服务器,便省去了编写上位机程序的负担,并无须考虑去兼容不同的操作系统。当然,上位机程序可以实现UDP广播寻址终端,无需知道终端IP地址即可找到同一网段下的多个终端。而使用网页的话就只能是预先知道终端IP地址并逐一配置。

其实,对于通过网页配置相信大家并不陌生,家里有无线路由器的朋友估计都有实践经验。通过浏览器键入路由器的默认IP,然后根据网页提示就可以一步步地实现设备信息配置,诸如WiFi密码、SSID等。今天,我们就是来探究一下这个应用的原理,在单片机里实现一个HTTP服务器,通过这个HTTP服务器来配置设备信息,并实现了设备固件更新。

当然,我这里的这个HTTP服务器没有家里的路由器那样的功能强大,在这里也只是抛砖引玉,希望大家能够从中获取启发,设计出更出色的产品。方便起见,我们仍旧延续上一篇文章的平台——基于Cortex-M3的W5200评估板(STM32F108C8 + W5200)。

 http1

图1 W5200评估板

该评估板单片机的系统资源:64KB的闪存和20KB的SRAM。

(W5200可以和任何单片机配合使用,如果用户想使用其他单片机+W5200来实现的话,需要您自行修改代码,这里暂不提供其他库。)

 

功能演示

在我们展开谈论基于HTTP的远程配置和固件更新的原理之前,先给大家看一下我们这个程序小样的功能演示。感兴趣的朋友可以在接下来的文章中,了解到具体该功能是如何实现的。

步骤1

用ISP工具烧录Boot(评估板SW2 调至PROP),不了解的话,可以参考我们上一个主题内容。

 http2

图2用FlashLoader烧录boot.bin

步骤2

将评估板上SW2 调到RUN模式,打开ConfigTool。点击按钮http3,可查找到当前设备,并可通过按钮http4,将app.bin程序上传至评估板中,右侧可看到当前设备的IP地址及版本号等信息,此时版本号为1.0,如图:

http5

图3 配置工具烧录app.bin成功

ConfigTool这里的工作也很简单,就是在第一次Boot启动时,把App传给单片机。当App运行时,ConfigTool就无用武之地了,因为用浏览器就可以完成ConfigTool的工作了。

(注:以上途径并不是必须的,仅为了方便演示,保证boot和app程序已经烧录好即可。)

步骤3

在浏览器中输入W5200评估板的IP地址,回车后出现Web界面。

如图可看到,界面分为Device Settings和Firmware Updating两部分,其中Device Settings中依次列出W5200评估板的硬件版本号、MAC地址、IP地址、子网掩码以及默认网关基本配置。

用户可以配置其他IP地址,子网掩码及网关,并点击’Save settings and Reboot’,设置并重启生效;

http6

图4 Web配置界面

如:

在WEB界面上,将IP地址192.168.1.2改为192.168.1.20。更改后保存,等待后更改成功:

http7

图5更改IP成功

步骤4

下面针对固件更新,点击“浏览”按钮,选择好要更新文件。http8;选好后开始上传,出现以下界面,更新过程需要6s.http9

图6等待升级完成

更新完成,可以看到新成功,版本号更改为5.0,IP地址以及界面颜色都进行了更新,如下图:

 http10

图7升级成功

是不是很简单?马上动手,也给你的设备加入一个HTTP服务器,实现远程配置升级功能吧。当然,配置和升级只是应用的一小部分,你也完全可以通过模拟/数字输入接入几个传感器,比如温度、湿度和PM2.5,这样打开浏览器就可以监视这些传感器数据了。

这个小样只是一个简单的功能及原理演示,下面就让我们来看一下这个基于 HTTP的远程配置和固件更新实现的思路及原理。

应用原理

1.        方框图

http11

图8 HTTP远程更新固件框图

每次重启,均从首地址开始执行程序:

1启动进入BOOT区,若BOOT检测APP区的不为空,则跳转到APP区的首地址执行主程序;

2浏览器访问APP区的网页服务器

l  配置网络参数:即将浏览器中键入的参数通过APP更新到Configure Information区

l  远程更新固件:即进入到以下步骤3

3浏览器访问APP主程序的网页服务器,并通过浏览器将即将更新的APP写入到Backup区;

4当APP检测到Backup区域已经有新的APP程序后,跳转到BOOT区,执行更新操作;

5BOOT将APP区擦除,并将新APP从Backup区写入到APP区;

重启,重新执行程序。

2.        内存图

http12

图9 W5200评估板内存空间分配

 

在我们要演示的程序中,将MCU闪存划分成了四个区:

http133.        各分区的主要功能

了解了空间分配之后,我们再来看一下我们这个演示中各部分的主要功能:

  1. BOOT区:
  • 清空APP区,为新APP写入做准备;
  • 把暂存在Backup区的新版本程序拷贝到APP区;
  • 与上位机程序通信,获取App;

备注:其实,这里Boot不必具备这个功能,只是我们编译完两个固件后,不想合并两个二进制文件,然后再通过ISP工具烧录,所以偷个懒,沿用了上次的上位机程序。

  1. APP区

APP区是应用程序运行区域,实现了HTTP服务器,并集成了一个简单的网页。

  • 配置网络参数;
  • 在线固件升级;

上电启动后,进入Boot区,若判断上层APP区的状态量成功,则直接从Boot区跳转到APP区,运行主程序。

备注:想修改网页的话,可以参考webpage.h,所有的HTML代码都在这个头文件里面。

  1. Backup区
  • 接收并备份需要更新的新App

备注:由于Backup区的大小为23K,所以意味着APP的大小最大为23KAPP区为24K,其实有1K是无数据存放的;

  1. Configure Information区
  • 存放IP地址,MAC地址,子网掩码等网络参数,以供App调用;
  • App可以再写入,更新该区域存放的网络配置参数;

程序开发

我们将App程序主要分为5个文件:

main.c实现HTTP固件更新的主流程;

httputil.c文件用于实现HTTP协议响应报文的发送;

httpd.c文件用于实现对HTTP请求报文的解析;

device.c文件用于实现W5200的初始化及单片机的基本配置;

webpage.h文件定义web界面的html语言。

这里我们重点介绍一下http()函数:

http()函数实现了Web服务器接受请求和回复响应的全过程,由于Web服务器在和浏览器通信时使用TCP协议工作,根据SOCK_HTTP之间状态的不同,执行不同的操作。

http14

图10 HTTP服务器通信过程示意图

HTTP服务器的通信过程大致分为三步:

  1. 连接:W5200分配socket到HTTP服务器,打开socket并监听。
  2. 通信:连接建立了。W5200在接收到来自客户端的HTTP请求后发送HTTP应答。
  3. 关闭:HTTP 请求/应答完成后关闭连接。

 

voiddo_http(void)

{

uint8 ch=SOCK_HTTP;                      //定义HTTP通信的socket端口变量

uint16len;

st_http_request *http_request;

memset(rx_buf,0×00,MAX_URI_SIZE);

http_request = (st_http_request*)rx_buf;       // 定义HTTP请求报文的结构指针

/* HTTP Server 状态之间的转换 */

switch(getSn_SR(ch))

{

case SOCK_INIT:                         //socket 初始化状态

listen(ch);                            //Web服务器监听

break;

case SOCK_LISTEN:                      //socket监听状态

break;

case SOCK_ESTABLISHED:                //socket建立连接成功

if(getSn_IR(ch) &Sn_IR_CON)

{

setSn_IR(ch, Sn_IR_CON);           //Sn_IR的第0位置1

}

if ((len = getSn_RX_RSR(ch)) > 0)

{

len = recv(ch, (uint8*)http_request, len);   //接收客户端的请求并存入http_request中

*(((uint8*)http_request)+len) = 0;

proc_http(ch, (uint8*)http_request);     //解析HTTP请求,并发送HTTP Response

disconnect(ch);                      //断开TCP连接

}

break;

case SOCK_CLOSE_WAIT:                  //socket等待关闭状态

if ((len = getSn_RX_RSR(ch)) > 0)

{

//printf(“close wait: %d\r\n”,len);

len = recv(ch, (uint8*)http_request, len);

*(((uint8*)http_request)+len) = 0;

proc_http(ch, (uint8*)http_request);   // 解析HTTP请求,并发送HTTP Response

}

disconnect(ch);                      // 断开TCP连接

break;

case SOCK_CLOSED:                    // socket 关闭状态

socket(ch, Sn_MR_TCP, 80, 0×00);       //初始化socket端口

break;

default:

break;

}

}

完整的程序代码请于以下地址下载:

http://pan.baidu.com/share/link?shareid=1808179627&uk=1930353891

 

后记

以上我们介绍了基于 HTTP的远程配置和固件更新的相关原理及思路。细心的朋友可能会发现,我们这里的网页是和APP程序放在一起的,均在APP区。也就是意味着,我们通过网页更新APP程序,其实也同时把网页本身更新了(参见更新前后网页背景颜色变化)。我们这样做的目的是方便以后用户对于网页架构等内容重新编辑时使用的,这样用户不仅可以更新APP,也可更新网页。当然,如果我们的网页已经是确定不变的话,可以将MCU的内存再单独分离出一块作为网页存贮区(形如‘Configure Information区’一般),这样用户就无需每次更新大量数据,只需针对性的更新APP即可。这个也是我们为读者留下的一个课题,供感兴趣的读者业余动手实践一下。

作者:Katrina,Jerry,Cillian 


感谢阅读!

更多信息请关注WIZnet官方微博:

http://weibo.com/wiznet2012