TCP/IP协议学习(一) LWIP实现网络远程IAP下载更新
最近需要实现通过TCP/IP远程IAP在线更新功能,忙了2周终于在原有嵌入式服务器的基础上实现了该功能,这里就记录下实现的过程。
IAP又称在应用编程,其实说简单点就是实现不需要jlink,仅通过芯片自带接口如CAN,USB,Ethernet即可实现下载功能.以我用过的stm32f207芯片为例,就有三种启动方式,SRAM启动,User boot(即flash地址启动,用户应用执行),System boot(即系统地址启动,用于串口下载),看到这是否明白点什么,System boot模式下载实现的过程就是IAP应用编程,不过这段程序一般都是芯片公司烧好在内部固定地址的(一般不允许修改)。而本例中的网络远程下载更新也是实现这个过程,不过执行将完全在user boot(即flash)中。 上面讲的都是IAP的概念,下面进入正题:
第一步:了解ARM的启动过程(这个网上有很清晰的说明,这里就粗略讲下)
上电,复位,STM32芯片根据boot引脚将中断向量表地址(起始地址)置于0x80000000,同时将PC指针置于该地址0x80000000处(这里的0x80000000是由flash地址0x08000000映射的),即起始是跳转到flash首地址,之后完成的就是建立堆栈,最后跳转到_main函数(启动文件中,当然stm32f2xx的头文件是先跳到SystemInit),此时程序正式执行。其实了解了上面的知识,IAP的实现就比较好理解了(因为我实际操作与STM32提供的方案(见STM32F2x7_ETH_IAP)有区别,这里先以stm32提供的方案做介绍),首先肯定要有能够实现下载的程序(也就是所谓的引导guidance程序)和用户实际执行的程序,经过初步设计,在flash中结构如下图:
其中guidance区域用于实现升级引导,user application就是用户实际运行的代码。规划好代码在整个flash中的地址,下面就是具体的实现了。由上可知guidance程序就是整个IAP实现的核心程序,它需要实现两个功能:
(1)一般情况下跳转user application, 执行用户代码
(2)特殊情况下进入IAP模式,可以更新用户代码(一般是按键,当然也可接收外部指令进入IAP模式)
1. 跳转代码
官方例程有标准代码可以直接使用,它实现的就是将PC指针跳转到0x08008000,此时user application处代码开始执行。
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress; JumpAddress = *(__IO uint32_t*) (USER_APPLICATION_FIRST_ADDRESS + );
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) USER_APPLICATION_FIRST_ADDRESS);
Jump_To_Application();
注意:user application程序的main函数中需要将中断向量表重新定位到user application首地址。
即需要添加NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x08008000);(一般NVIC初始化时会重定义到0x0,注意注释掉)否则应用代码的中断会不响应,这与中断响应的机制有关,默认地址为0x0,此时中断产生时查找向量表获得的地址是guidance程序中断对应地址,执行就会出错。
2.远程网络IAP实现
远程网络IAP的实现是基于lwip的,因为lwip中网络接口层,IP,TCP层的配置与正常的网络通信并没有区别,且知识复杂,这里不在赘述,主要讲述http层代码的处理.http层代码处理包含两部分,
1.http首部的处理
2.正文代码的处理(即接收数据的处理)
以官方例程为例,上面两部分的处理都是在http_recv函数中实现的,想了解http发送的实际过程,那么通过抓包分析就是最简洁的方式,这里使用的就是WireShark软件。
1.上图是浏览器执行升级时发送的http首部,既然知道首部格式,那么在服务器中就可以对接收数据进行处理,上面框中数据就是需要处理的字段。首先将TCP层接收的数据存储
data中,Post/upload.cgi为http包含了http的方式,url,则通过比较strncmp(data,“Post /upload.cgi”,16) == 0即可判断是否进入升级(cgi)模式。Content-Length为正文的长度,因为传输的时候都是以字符传输的,因此将接收到的字符还要转化成数字,例程中是通过Parse_Content_Length实现的。
当然也可以利用strstr函数获得正文长度,代码如下:
/*读取Content-Length的首地址*/
if((ContentLengthStart= strstr(data, "Content-Length: ")) != NULL)
{
ptr = &ContentLengthStart[];
}
获得ptr即为Content-Length: 后数字字符首地址,后续即可将字符数组转换成数字,见示例程序,不在赘述。 2.首部处理完毕后,下面便是http正文的处理。处理http正文,当然也需要对浏览器发送的包进行分析,以下图为例
http发送起始包(728字节)
http发送起始包实际内容
与上面的首部做比较即可知第一个接收到的数据包728字节仅包含http首部,其中结尾的0d 0a 0d 0a即\r\n\r\n(休止符),即确定为upload.cgi时,修改标志位(UploadSymbol),解锁flash,擦除指定地址的flash(本例中擦除sector2,3,4),获得正文长度后即可跳出,等待下个数据包的接收,下面真正开始正文的处理。如何处理正文,还是以发送的实际数据包为准判断,其中首页和尾页要特殊处理,当然这也是根据实际传输的数据包得出的,如下。
正文首页:
正文尾页:
看到上面两段数据报文,就可以清晰的知晓,真正的程序起始是从87.I那一行开始的,程序的结尾到community那一行结束,当然红色部分整个都包含在正文数据中,这就需要我们写入flash时要去掉数据中附加的信息,因为这里比较重要,我就贴上我的处理代码:
char *httpHeadEndStart; //首部末地址
char *postContent; //正文首地址
char *pstr; //接收到数据包首地址
int TotalReceived = ; //接收到的数据包
int len; //实际接收到数据包的长度
TotalReceived+= p->tot_len; //后面参数为每一次接收到的数据包总长度
len= p->tot_len; if(UploadSymbol== ) //正文接收的第一个数据包
{
if((pstr = strstr(pstr,"\r\n\r\n"))!= NULL)//去除http附加信息
{
pstr = &pstr[]; //87.行首地址
len = len - (pstr - psl); //减去附加信息长度,即实际数据长度
}
}
if(TotalReceived== ContentLength) //末尾去除http附加信息,正文接收的最后一个包
{
if((psl = strstr(psl, "\r\n--"))!=NULL)
{
len = psl - pstr;
}
If(len)
{
IAP_HTTP_writedata (pstr,len); //将数据写入flash中
TotalReceived = ;
UploadDateSymbol = ;
FLASH_Lock();
}
}
else
{
If(len)
IAP_HTTP_writedata (pstr, len); //将数据写入flash中
}
UploadSymbol++;
如上,就将整个数据完整的写入flash中,当然实际工作远不只如此,如flash的解锁,写入和加锁,其中如果按照4字节即word写入,还要考虑接收到的数据包不是4的倍数的情况,这时需要从后续数据包里拿出数据凑足4字节,这部分的代码都是由IAP_HTTP_writedata函数实现,方法很巧妙,想了解的人也可以自己去解读这部分代码。
上面主要都是正常操作数据怎么处理,但有一句话说,好的代码是错误操作时也要给予合适的应对,那么客户如果没上传文件就点升级按钮了怎么办,当然了,还是老办法,先抓包分析,在给出解决办法,抓包图如下:
看到和上面有什么区别没,filename=””中间为空,那么就好办了,这里我就给出例程中的处理办法:
for (i=;i<len;i++)
{
if (strncmp ((char*)(data+i),"filename=", )==)
{
FilenameOffset = i+; //获得filename=“后字符偏移量
break;
}
}
i =;
if (FilenameOffset)
{
while((*(data+FilenameOffset + i)!=0x22)&&(i<)) //去查ASCII表很容易就知晓0x22代表字符" "
{
filename[i] = *(data+FilenameOffset + i);
i++;
}
filename[i] = ‘\’;
}
若i == 0则跳出,表示没有接收到文件,发送出错文件,或者直接跳回当前网页都可以(具体可以看官方例程).
TCP/IP协议学习(一) LWIP实现网络远程IAP下载更新的更多相关文章
- TCP/IP协议学习(二) LWIP用户自定义配置文件解析
LWIP协议支持用户配置,可以通过用户裁剪实现最优化配置,LWIP默认包含opts.h作为系统默认配置,不过通过添加lwipopts.h文件并包含在opts.h头文件之前就可以对lwip进行用户裁剪, ...
- TCP/IP协议学习(五) 基于C# Socket的C/S模型
TCP/IP协议作为现代网络通讯的基石,内容包罗万象,直接去理解理论是比较困难的:然而通过实践先理解网络通讯的理解,在反过来理解学习TCP/IP协议栈就相对简单很多.C#通过提供的Socket API ...
- TCP/IP协议学习之实例ping命令学习笔记
TCP/IP协议学习之实例ping命令学习笔记(一) 一. 目的为了让网络协议学习更有效果,在真实网络上进行ping命令前相关知识的学习,暂时不管DNS,在内网中,进行2台主机间的ping命令的整个详 ...
- TCP/IP协议学习(四) 协议概述
生活中有舒适区,借口成为懒惰的护身符,学习也有舒适区,逃避便是阻止进步的最大障碍. 经过半年多嵌入式方面的工作和学习,我提高了很多,但同时我也对自己所面临的问题逐渐清晰: 1. 偏于实践,理论基础不牢 ...
- TCP/IP协议学习笔记
计算机网络基础知识复习汇总:计算机网络基础知识复习 HTTP协议的解析:剖析 HTTP 协议 一个系列的解析文章: TCP/IP详解学习笔记(1)-- 概述 TCP/IP详解学习笔记(2)-- 数据链 ...
- tcp/ip协议学习笔记一
一. 简述 以前在学校学习计算机网络的时候学习多是网络7层模型OSI,了解了一些基本的计算机网络概念和协议通信格式,但是一直没弄明白其中的原理,包括各层之间的关系,应用,还有一些常见的令牌环网到底是什 ...
- TCP/IP协议学习-1.概述
目录 TCP/IP协议概述 分层 延伸知识 FTP例子 为什么需要网络层和传输层 TCP/IP的分层 封装 分用 总结 本文主要摘抄自书籍<TCP/IP详解卷一:协议>与TCP协议相关内容 ...
- Tcp/Ip协议族简单解读及网络数据包/报/帧数据格式及封装及解包;
http://www.creseek.cn/products-install/install_on_bsd_linux/ 中文检索 离线cloudera ecosystem components: h ...
- TCP/IP协议学习和理解
TCP:Transmission Control Protocol-传输控制协议 IP:Internet Protocol-网络协议 TCP/IP 不是一个协议,而是一个协议族的统称,里面包括了 IP ...
随机推荐
- Winform中如何实现父窗体传递数据到子窗体并刷新子窗体
原理:利用委托和事件,本文将以图文并茂的例子讲述,告诉我们So Easy --------------------------------------------------------------- ...
- YTU 3008: 链串的基本运算
3008: 链串的基本运算 时间限制: 1 Sec 内存限制: 128 MB 提交: 1 解决: 1 题目描述 编写一个程序,实现链串的各种基本运算,主函数已给出,请补充每一种方法. 1.建立串s ...
- PHP获取手机相关信息
该PHP操作类实现获取手机号手机头信息,取UA,取得手机类型,判断是否是opera,判断是否是m3gate,取得HA,取得手机IP 代码如下: <?php /** * @desc 手机操作类 获 ...
- Linux下统计出现次数最多的指定字段值
假设桌面上有一个叫“data.txt”的文本,内容如下: {id='xxx' info='xxx' kk='xxx' target='111111' dd='xxx'}{id='xxx' info=' ...
- OS开发(Objective-C)常用库索引
code4app.com 这网站不错,收集各种 iOS App 开发可以用到的代码示例 cocoacontrols.com/ 英文版本的lib收集 objclibs.com/ 精品lib的收集网站 h ...
- 【项目管理和构建】十分钟教程,eclipse配置maven + 创建maven项目(三)
[项目管理和构建]十分钟教程,eclipse配置maven + 创建maven项目(三) 上篇博文中我们介绍了maven下载.安装和配置(二),这篇博文我们配置一下eclipse,将它和maven结合 ...
- response.sendRedirect()重新定向的乱码问题
这里response.sendRedirect("YPbianhaoModify.jsp?jinhuoshang="+jinhuoshang+"&jinhuori ...
- 获取指定的系统路径 SHGetSpecialFolderPath
1.获取桌面的系统路径 TCHAR szLink[MAX_PATH + ] = { }; SHGetSpecialFolderPath(,szLink,CSIDL_DESKTOPDIRECTORY,) ...
- HTML DOM简介
HTML DOM简介 1.当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model),HTML DOM模型被创建为对象的树.如下所示: 2.通过可编程的对象模型,Ja ...
- pt-query-digest怎么分析慢查询日志分析数据
在进行使用linux系统作为服务器的情况,那几需要进行对linux的服务器进行性能上数据进行抓取之后,就需要对数据中内容进行分析,看数据库中内容是否存在瓶颈上的问题,在进行获取到的数据的慢查日志,将使 ...