<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/ESA2GJK1DH1K_B/" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>
说明
这节测试一下STM32+Air302(NB-IOT)实现利用http远程更新STM32程序
我已经把固件文件放在了自己的服务器上
默认使用本人提供的下载路径测试
文件路径: 网站根目录->ota->hardware->STM32Air302BK
user_crc.bin:
是固件程序文件.
该固件程序文件并不是直接可以运行的文件
里面的数据每隔128字节后面增加2位CRC校验位
单片机下载以后每隔130字节校验一下数据,然后把前128字节写入Flash.
加入CRC校验让升级变的稳定可靠.
info.txt文件内容:
{"version":"0.0.1","size":16900,"url":"http://mnif.cn/ota/hardware/STM32Air302BK/user_crc.bin","info":"1.解决了部分BUG
2.优化了部分程序"}
version:0.0.1 云端固件程序版本
size:16900 固件程序大小(字节)
url:http://mnif.cn/ota/hardware/STM32Air302BK/user_crc.bin 固件程序下载地址
"info":"1.解决了部分BUG 2.优化了部分程序" 使用APP控制升级时,APP的提示信息.
升级过程:
注:使用TCP连接Web服务器,然后发送相应的GET指令获取文件!
用户程序里面每隔一定时间控制网络模块使用http的GET指令获取云端info.txt文件
然后从文件里面获取服务器里面的固件程序版本,固件程序大小和固件程序下载地址等信息
如果与自身版本号对比不一致,就把固件程序大小和固件程序下载地址写入flash,然后设置更新标志,重启,
重启执行BootLoader以后,BootLoader程序检测到更新标志,则提取固件下载的地址,
然后使用http下载程序文件,把程序文件写入flash,完成升级.
备份升级流程图
测试
1.插上手机卡和天线,使用杜邦线或者跳线帽短接单片机串口2和模组串口
以前版本连接如下:
3.0版本以后连接如下
2.下载BootLoader程序到开发板
3.下载以后打印如下
4.下载用户程序到开发板
上面已经下载了BootLoader程序,为了下载用户程序时不覆盖掉BootLoader程序
需要下载的时候做一下配置. 需要使用下载器 ST-Link / Jlink
提示:如果使用的串口下载,可以按照第一节把BootLoader和用户程序的hex文件合成一个hex文件下载到开发板
提示:如果使用的串口下载,可以按照第一节把BootLoader和用户程序的hex文件合成一个hex文件下载到开发板
提示:如果使用的串口下载,可以按照第一节把BootLoader和用户程序的hex文件合成一个hex文件下载到开发板
下面演示使用下载器下载
打开用户程序
调整用户程序的下载设置,只擦除使用的部分
注意检查下其它配置是否正确
然后点击下载
5.下载以后会看到程序先执行BootLoader 然后运行用户程序
6.用户程序里面发送get指令获取服务器上的固件信息文件 info.txt
如果固件版本不一致,存储固件下载地址和固件大小,设置升级标志,重启
7.重启后BootLoader检测到有升级标志,则备份源程序,然后发送http指令获取程序文件
8.升级完成以后,运行新程序.
9.云端的程序就是当前的用户程序,只不过版本设置的不一样
用户程序是每隔一段时间发送get指令获取info.txt文件,检测一下版本
应用到自己的服务器
1,首先确定好程序文件在服务器的路径
关于本人服务器文件夹解释:(自己随意就好,最后的文件夹命名建议使用产品的型号)
html:网站根目录
ota: ota升级
hardware : 硬件程序
STM32Air302BK: 作为产品的型号(根据自己的产品型号修改)
2.假设固件程序的名字为 user_crc.bin
把该固件文件放到上面的目录中
固件程序下载地址为:
http://服务器IP地址/ota/hardware/STM32Air302BK/user_crc.bin
3.假设记录固件程序信息文件的名字为 info.txt
把该文件放到上面的目录中
则文件下载地址为:
http://服务器IP地址/ota/hardware/STM32Air302BK/info.txt
4.修改 用户程序 的 IAP.C 文件
1.修改固件程序版本(可随意指定,我设置的为0.0.2)
2.修改产品型号(我设置的为STM32Air302BK)
3.修改记录云端固件信息文件下载地址(我的为:http://mnif.cn/ota/hardware/STM32Air302BK/info.txt)
5.修改BootLoader程序 的 IAP.c,设置下产品型号和默认的固件程序下载地址
6.编译用户程序
会在工程目录的bin文件夹生成 user.bin文件
7.打开OTA Tools上位机软件
提示:该软件是修改bin文件加入校验(使得升级稳定可靠)
8.按照红框选择配置
9.选择用户程序生成的 bin文件
10.点击 生成固件
11.将在user.bin目录生成user_crc.bin文件
12.把生成的user_crc.bin文件拷贝到服务器
13.还差一个info.txt文件
我准备了一个模板
14.修改版本号(和用户程序里面设置的一样)
15.修改固件程序大小(OTA Tools提示信息里面有这个大小)
16.修改固件程序下载地址(和服务器上面的保持一致)
17.最后的提示信息不需要更改,当前用不到
18.把info.txt文件也拷贝到服务器
然后按照一开始的测试步骤测试即可
程序通用说明
1.小总结
远程升级单片机程序其实就是使用模组以TCP方式连接Web服务器,
然后给TCP服务器发数据,数据格式是GET指令.
服务器接收到指令以后会下发文件给模组,模组通过串口把数据发给单片机,
单片机接收到数据以后写到flash,最后加载运行.
2.Flash分配
用户可以根据自己的需求调整stmflash.h文件Flash分配大小
注意:BootLoader程序和用户程序的stmflash.h文件要保证一样.
注意:如果使用的芯片的Flash容量是 256及其以上的型号
假设使用的是 256的
因为容量是256的,所以flash是以2K为一页.
首先FLASH_IAP_SIZE, FLASH_UPDATE_SIZE, FLASH_USERDATA_SIZE 保证是2的倍数
为保证程序运行区和程序备份区的地址是某一页的开始地址
所以 LASH_IAP_SIZE + FLASH_UPDATE_SIZE + FLASH_USERDATA_SIZE 的和需要是4的倍数
3.user.bin 和 user_crc_bin的区别
每隔128字节增加CRC校验位
改写size,把真实的文件大小填写到bin文件
用户程序详细说明
1.设置中断向量偏移
地址其实就是用户程序运行地址
2.软件设置程序运行位置和占用flash大小
注:在下载完BootLoader程序以后,串口日志会打印这些信息,根据日志打印的设置即可
3.解析下info.txt下载地址(服务器上记录固件信息的文件)
做这个程序是为省去用户解析的繁琐.
执行解析之后:
IAPStructValue.IP = mnif.cn;
IAPStructValue.Port = 80;
IAPStructValue.Path = /ota/hardware/STM32Air302BK/info.txt
4.处理更新(这个程序需要在认为用户程序没有问题的时候在用户程序里面执行一下)
如果更新成功,BootLoader里面会把更新状态置为 0xFF;用户程序需要调用一下这个函数清零这个状态.
如果用户程序不清零这个状态,重启以后BootLoader检查到0xFF会认为执行用户程序失败了.然后执行回滚.
5.控制模组获取服务器上记录固件信息的文件
6.解析info.txt文件内容
如果版本号不一样,提取和存储url和文件大小,然后设置升级标志,重启.
BootLoader程序详细说明
1.查看IAPInit函数
2.获取存储的固件文件大小,固件下载的url,并解析下url
3.如果有更新标志,则备份下用户程序
4.如果没有更新标志,则查看下更新状态
如果状态是更新有错误,则执行回滚,如果检测到没有备份的程序,就重新执行升级
5.如果更新状态是0x01,就设置更新状态为0xFF
7.控制模组连接TCP服务器(Web服务器)
8.发送get指令获取程序文件
8.在串口中断函数里面把固件数据写入缓存
提示:模组返回网络数据格式 +SKTRECV: {空格}{socked id},{数据个数}{冒号}{16进制表示的数据}{冒号}
假设返回"12"这个数据: +SKTRECV: {socked id},1"3132"
下面的NETRECV xxxxx 是为了做转换
注: IAPHttpHead是为了去掉http 头,找到数据的开始位置
9.主循环从缓存取数据,并写入flash
10.校验数据是把先前写入的提取出来校验,主要是为了保证更新的时候万无一失
11.判断接收完成
接收到相应的文件个数设置 IAPStructValue.ReadDataEndFlag = 1;//接收完成
则写入0x01状态,重启.
如果有错误,则尝试重新下载.
注:超过一段时间没有接收到数据,也会设置IAPStructValue.ReadDataEndFlag = 1;//接收完成
12,程序里面有下载超时和整体运行超时检测
下载超时:只有在确认开始写入程序文件的时候才运行,每次写入程序文件会清零.
主要解决接收一半程序便不再接收的问题
整体运行超时:该超时只要执行BootLoader程序便一直运行
客户可以在IAP.h修改默认的超时时间
12.重启以后如果检测到状态是0x01则写入0xFF,执行用户程序
如果检测状态是更新错误,则回滚程序,执行用户程序.
细节说明
1.如果编译用户程序出现下面的警告
其实是这个地方导致的
为了便于BootLoader程序提取用户程序bin文件里面的型号,把型号存储在了偏移1024字节的位置.
为了便于上位机把bin文件大小写到bin文件里面,还有便于BootLoader提取这个大小,也设置存储在了偏移1024字节的位置.
设置的这个字符串存储的位置影响到了芯片本身分配一些数组的位置.就会报上面的错误
用户可以把偏移个数增加,便可没有该警告
2.在前面的文章中说过一个事情:
凡是在BootLoader里面使用中断,跳转到用户程序以后同样有效
BootLoader里面使用了,滴答定时器中断; 串口1,2接收中断,空闲中断; 看门狗.
在加载用户程序之前清除了除了看门狗以外的所有中断.
如果用户在BootLoader里面使用了其它中断,也需要在此处清除!!
如果用户在BootLoader里面使用了其它中断,也需要在此处清除!!
如果用户在BootLoader里面使用了其它中断,也需要在此处清除!!
3.恢复出厂设置
为了预防超级意外的情况导致程序完全崩溃,在上电之前按下一个按钮,然后给板子上电.
用户按下时间超过5S,用户松开按钮以后
设置更新标志,清空flash里面记录的url地址,重启设备.
设备重启以后便会按照默认的地址下载程序
4.用户按照自己的项目修改BootLoader程序注意事项
1.在发送完获取程序文件指令以后,主循环不能带有执行超过5ms的延时函数
延时函数的存在会影响提取缓存数据写入flash的时间,从而导致缓存溢出,数据接收不完整.
2.如果用户想在BootLoader运行的时候显示更新状态或者进度
可以在IAPInit() ;IAPGetProgramFile(); IAPWriteData();函数里面相应的位置增加提示
注意:IAPWriteData()函数里面不能加延时!!!!
3.如果要展示更新进度
文件大小(字节): IAPStructValue.FileSizeSave
当前接收(字节): IAPStructValue.FileSizeNow
3.如果用户想只下载BootLoader之后让BootLoader自己立即升级程序