datasheet

EEWorld 电子工程世界

文章数:4152 被阅读:1884383

账号入驻

干货 | 小谈 bootloader 和 APP 两重升级

2019-01-03
    阅读数:

EEWorld

电子资讯 犀利解读 

技术干货 每日更新

     

 



一般设计来说,bootloader作为引导程序和升级APP,改动并不大而且也相对稳定。但是如果项目中遇到非得更新bootloader的,比如协议的更新替换,这时候就有设计此方案的必要性了。
     

不多说,直接进入正题。

flash分区图和程序图如下,接下来的描述都是基于这图来进行分析
大概说下思路:简单的说就是设计三段程序,bootloader0、bootloader1、APP。
      

这里假设使用的是ST的STM32F103C8T6,该款单片机有64K flash,每个扇区为1K,一共64个扇区。在这些扇区的分配中,bootloader0占用1K,也就是一个扇区空间(0x8000000~0x80003FFF);bootloader1占用22K,也就是22个扇区空间(0x8000400~0x80005BFF);标志区占用1K,也同样为一个扇区空间(0x80005C00~0x80006000);APP部分包括APP和DATA,还有40K空间可利用。这个就flash的分区思路。
      

此次再来说下1K标志区的存储,在这里我只用了10个字节存储,当然如果有一些必要的标志数据啥的,也可以存储在此空间,在这里我用结构体表示这些变量成员,并把标志区的flash地址转换成此结构体指针。



次再来说明程序流程图。正常模式下,系统开始运行是从bootloader0开始的,然后跳转到bootloader1,再者跳转到APP,这就是一个流程。


bootloader0的程序也很简单,无非就是判断标志区的标志变量是否改变,从而选择跳转到Bootloader1或者APP区域。bootloader0的main函数如下,按照上述的流程图可以明白,只要是标志区的跳转标记是正常模式或者bootloader_flag未被置位,说明是没有升级过bootloader1或者已经升级成功的,进而就跳转到bootloader1。否则都直接进入APP,这样可以防止APP里面升级bootloader失败了而且不小心断电了,不用经过Bootloader1进入APP再次升级bootloader1。



当然在启动文件里面,不需要进入系统时钟初始化直接进去main,所以我们同样也要修改下启动文件。



最后生成的bootloader0空间比较小,如果觉得这1K扇区用的比较浪费,也同样可以存储一些你觉得必要的数据。


 

那么接下来先说明下16个字节升级参数,这16个字节是每次制作升级bin包的时候插入到此Bin包的头16个字节。说明如下:


bin包的发送上,我的上位机是这样处理的,先每次间隔两秒发送16个字节参数,后续的bin包拆分512个字节依次200ms发送。(下面会简单介绍下上位机的思路。)
     

接下来再看Bootloader1,此段代码作为引导进入APP以及升级APP的代码,其作用也不言而喻。回到原来那个流程图,当APP收到APP升级的16个字节升级参数(下面会说明)的时候,APP会把标志区的跳转标志设置为升级模式并且把bootloader1置位并且复位,这时候程序重新运行的时候就一直在bootloader1中运行,一直等待升级APP,当再次收到16个字节升级参数的时候,记录升级参数的CRC,bin包的总长度、根据升级包的总数量擦出APP区域的对应空间。后续在接受512个字节的时候依次写入flash,到最后一包的时候,check下CRC是否对应上,对的上就更新标志区的标志变量并且复位,check不对就上报信息给上位机并且重发。截图中的是明文协议。因为之前用的是明文协议(方便但是弊端比较多,所以才会要更新为暗文协议。)
     
 
再者说明APP部分,APP部分主要是一者升级APP,设置标志区的标志变量并且复位跳转至Bootloader1进行APP升;二者是升级Bootloader1。区分是升级APP还是Bootloader主要在于区分16个字节升级参数,16个字节升级参数里面带有一个字节判断APP还是bootloader,以此来决定哪个类型升级。


 

底层上已经大概说明完毕,不管是用xyzmodemx协议、modbus协议、自定义协议也好,只要能考虑好升级的安全性和全面性,还有代码逻辑思路清晰,其实都可以。
     

接下来说下上位机。我用的是QT,升级使用定时器来做非阻塞式单线程,当然使用多线程升级更加方便。一部分截图如下。对于生产员工来说,只需要点击两个空间,等待进度条100%即可。


 

      

在控件逻辑上,打开升级文件,使用QFileDialog类并把bin包信息通过全局变量记录下来。


 
再点击发送升级文件控件,逻辑上是开启两个定时器,一个2s定时,一个200ms定时,当然两个定时都可以根据情况修改;这两个定时的作用是,2s定时的是发送两次16个升级参数,后面的200ms定时是依次发送512包的bin包数据。


 
在2s定时的槽函数里面进行发送16个升级参数,发送完关闭2s定时并且开始200ms定时。


 
发送bin包里面的头16个字节,可以带参多次发送。(这个是对应2S定时槽函数。)


 
在发送bin包的每次512个字节的时候,先记录总的512个字节总段数,每次发送完一包,依次使用seek函数来设置当前文件的位置,并且使用read设置要读的字节长度,直到发送至总段数到了。(这个是对应200ms定时槽函数)代码如下:


 
至此,对于两重升级就结束了。



聚焦行业热点, 了解最新前沿

敬请关注EEWorld电子头条

http://www.eeworld.com.cn/mp/wap

复制此链接至浏览器或长按下方二维码浏览

以下微信公众号均属于

 EEWorld(www.eeworld.com.cn)

欢迎长按二维码关注!


EEWorld订阅号:电子工程世界

EEWorld服务号:电子工程世界福利社

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: TI培训

北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2018 EEWORLD.com.cn, Inc. All rights reserved