前面文章分析了OTA的实现架构、协议和存储问题,提到了一个细节,如果使用双程序更新模式,将Flash空间分成上下两部分,如下图所示,那么最后生成的BIN文件为了放在不同的位置,需要生成两份地址不同文件,然后根据芯片的实际使用情况,选择合适的文件进行烧写。
偶然看到一个信息,Nordic做双程升级时候,只需要一个二进制文件,不需要提供两个BIN文件进行选择。Nordic是怎么办到的呢?
内存布局
Nordic芯片的Flash布局图如下:
Flash地址从下向上增长,最底层的MBR(Master Boot Record)区域存放中断向量表的位置。芯片中的Bootloader、SoftDevice和Application都具有自己的向量表,MBR的寄存器UICR.NRFFW[1]指示系统该选择哪一个中断向量表。(参考)
SoftDevice区域存放协议栈。
Application区域存放用户固件程序。
APP Data区域存放用户希望永久保存的数据,比如设备地址等。这块区域在升级过程中也可以保持不被擦写。
DFU Bootloader区域存放Bootloader程序,用以执行升级过程。
更新方案
Nordic提供了三种更新方案,分别是:(参考)
- 双程DFU
- 单程DFU
- 更新BootLoader和SoftDevice
1. 双程DFU
双程DFU方案的操作流程如下:
从左侧图中可以看到Application区域空间分成了两部分:Blank 0和Blank 1。
假如当前的程序放在Blank 0区域,那么新的程序将被复制到Blank 1区域,如中间的图。
大多数芯片厂的DFU过程到这里就结束了,只要通过Bootloader引导MCU进入到新的程序地址即可。这样必然会产生本文开头提到的问题,在升级程序的时候,需要确定旧的程序放置位置。由于生成的BIN文件包含了起始地址信息,这意味着要新的程序要准备两份功能相同、地址不同的BIN文件,按照实际情况选择合适的文件烧写空白区域。
Nordic使用了一个小技巧,即将新的程序(Blank 1)复制到旧的程序空间(Blank 0),这样就是的程序基地址永远在Blank 0,从而解决了上述困难。
由于Flash赋值是一个耗时操作,DFU做起来一定会很慢。仔细观察,会发现双程DFU至少需要执行两次擦除和两次烧写,分别是:
- 烧写Blank 1
- 擦除Blank 0
- 烧写Blank 0
- 擦除Blank 1
疑问:如果在执行右侧图的Flash赋值过程中途,发生了断电,该怎么办?
我猜测应该先将Blank 1的内容复制到Blank 0,当复制完毕校验通过,再擦除Blank 1,结束DFU过程。这样即使在复制中途断电,Blank 1的内容仍然有效,重启后可以重新进行复制操作。读源码应该可以确认这一点。
2. 单程DFU
单程DFU的操作流程如下:
单程DFU就是现将Application区域清空,再将新的程序写入到Application空间的基地址。
这种做法好处是充分利用Application的空间,而且只需要擦除一次,烧写一次,操作时间相对于双程DFU一定会有大幅度降低。
单程DFU的缺点是不能在线更新,因为用户程序需要被擦除,所以一定需要断开连接和重启。
3. BootLoader和SoftDevice
升级BootLoader和SoftDevice的操作流程如下:
这个图乍一看比较复杂。
(1)擦除旧用户程序
(2)将新的Bootloader和SoftDevice写入Application区域
(3)将新的Bootloader和SoftDevice复制到Bootloader和SoftDevice区域
So easy? ——不是的!
并不是每个厂商的芯片都能实现这个功能,因为第(2)步到第(3)步之间,MCU要擦除Bootloader区域,有些BLE厂商的MCU,Bootloader程序是唯一的启动器,Bootloader程序自身是不可以被擦除的,否则MCU无法正常启动。Nordic的芯片存在MBR,利用MBR引导MCU跳转到Bootloader或其他地方。
程序在第(2)步结束时设置MBR的寄存器,让MCU下次启动时候不直接跳转到Bootloader区域,而是跳转到Application区域,执行一个复制操作,将新Bootloader程序和SoftDevice程序复制到各自区域,然后再设置MBR寄存器,让MCU下次重启时候直接跳转到Bootloader区域。
虽然仅仅增加了几行Flash来存放MBR信息,但是对MCU的更新提供了极大的灵活性。
(完)
ST的升级方式我也写过文档给内部人使用,但是在写的时候对于APP跳转这部分一直都没有很好的理解,写的非常好~
你说的是前面分析OTA的那个吧?
Very Good!
真棒写的
谢谢,多交流
博主,我想说,博客是很好,当时没有目录,找特定文章看,很累啊~~~~
多谢建议。我也有同感,有时候我自己找个以前的内容也觉得麻烦。我找找有没有好的模板,如果你有推荐欢迎留言。
BIN文件是不包含地址信息的,只有hex才包含地址信息
是的,烧写bin文件需要指定偏移地址,在某些对话场景下,二者表达意思都是烧录一个程序,没有误解即可。