对于一个复杂的单片机项目来说,有一个 BootLoader(以下简称BL)是非常重要的。它可以使得你的应用程序代码维护和升级更加便捷。 本篇文章,带你了解为什么要设计 Bootloader,以及如何设计 Bootloader。争取做到知其然、知其所以然。 通过对 BL 进行详细的讲解,希望让大家可以体会到它的重要性。 1、烧录方式的更新迭代更方便的ISP烧录方式1、依赖于专门的上位机或下载器硬件,不能作到统型; 1、通信方式统一(比如一律都用串口)); 2、提供一个友好的操作界面(比如命令行方式); 3、高效快速,没有附加操作,最好一键自动化烧录; 4、另外再增加一些嵌入式固件管理的功能(比如固件版本管理)。 关于BootloaderBootloader的基本形态可以看到BL就是一段存储在ROM中的程序,它主要实现4个功能: 1、通过某种途径获取要烧录的固件数据; 2、将固件数据写入到ROM的APP区中; 3、跳转到APP区运行,将烧录进去的用户程序引导起来; Bootloader的两个设计实例基本的操作逻辑如下: 1、通过超级终端、SecureCRT 或 Xshell 之类的串口终端输入命令 program; 2、BL 接收到命令后,开始等待接收固件文件数据; 3、串口终端通过某种文件数据传输协议(例如 X/Y/Zmodem协议)将固件数据传给BL; 4、BL 将固件数据写入到 ROM 的 APP 区中; 基本的操作逻辑如下: 1、将待烧录的固件拷贝到SD卡中; 2、将SD卡插入到卡槽中; 3、BL 检测到 SD 卡插入,搜索卡中 BIN 文件; 4、将 BIN 文件数据读出写入到 ROM 的 APP 区中; BL实现的要点#define VECT_TAB_OFFSET 0x4000
把Bootloader玩出花上面我所讲的都是BL最基础的一些内容,是我们实现BL所必须了解的。BL真正的亮点在于多种多样的固件数据获取方式。 BL的实现与延伸(串口传输固件) 前面我讲到过两个BL应用的实例,一个是串口传输固件文件,一个是SD卡拷贝固件文件。它们是在实际工程中经常被用到的两种BL形式。 这里着重对前一个实例的实现细节进行讲解剖析,因为它非常具有典型意义,如图
第一个问题,串口通信协议以及文件传输实现的相关内容略显繁杂,在以后的文章会专门进行讲解。 第二个问题:经过串口传输最终由单片机接收到的固件数据是可能出现差错的,而有错误的固件冒然直接写入到APP区,是一定运行不起来的。所以,我们要对数据各帧进行暂存,等全部传输完成后,对其进行整体校验,以保证固件数据的绝对正确。 针对第三个问题,我们要着重探讨一下。 一个文件从发送方传输到接收方,如何确定它是否存在错误? 通常的做法在文件中加入校验码,接收方对数据按照相同的校验码计算方法计算得到校验码,将之与文件中的校验码进行对比,一致则说明传输无误,如图。 上图是对固件文件的补齐以及追加校验码的示意。 为什么要对文件补齐?嵌入式程序经过交叉编译生成的可烧录文件,比如 BIN,多数情况下都不是128、256、512或1024的整数倍。这就会导致在传输的时候,最后一帧数据的长度不足整帧,就会产生一个数据尾巴。 取整补齐是解决数据尾巴最直接的方法。这一操作是在上位机上完成的,通常是编写一个小软件来实现。这个小软件同时会将校验码追加到固件文件末尾。这个校验码可以使用校验和(Checksum)或者 CRC,一般是 16 位或 32 位,如图,通过一个小软件实现对固件文件补齐和添加校验码。 又有人会问:“要把整个固件暂存下来,再作校验,那得需要额外的存储空间吧,外扩ROM(FlashROM或EEPROM)?” 是的。如果想节省成本,我们也可以不暂存,传输时直接烧写到APP区。这是有风险的,但是一般来说问题不大(STC和STM32的串口ISP其实也都是实时烧写,并不暂存)。 因为在传输的过程中,传输协议对数据的正确性是有一定保障的,它会对每一帧数据进行校验,失败的话会有重传,连续失败可能会直接终止传输。所以说,一般只要传输能够完成,基本上数据正确性不会有问题。 但是,仍然建议对固件进行整体校验,在成本允许的情况下适当扩大ROM容量。同时,固件暂存还有一个另外的好处,在APP区中的固件受到损坏的时候,比如固件意外丢失或IAP时不小心擦除了APP区,此时我们还可以从暂存固件恢复回来(完备的BL会包含固件恢复的功能)。 其实也不必非要外扩ROM,如果固件体积比较小的话,我们可以把单片机的片上ROM砍成两半来用,用后一半来作固件暂存。将片上ROM划分为3部分: 我们将片上ROM划分为3部分,分别用于存储 BL、APP 固件以及暂存固件。比如我们使用 STM32F103RBT6,它一共有128KB 的 ROM,可以划分为 16K/56K/56K。 有些产品对成本极为敏感。我就有过这样的开发经历,当时使用的单片机是 STM32F103C8T6,片上ROM总容量为64K,固件大小为48K,BL为12K。在通过BL进行固件烧写时根本没有多余的ROM进行固件暂存。我使用了一招“狗尾续貂”,如图 我无意中了解到 STM32F103C8T6 与 RBT6 的晶元是同一个。只是因为有些芯片后 64KB 的ROM性能不佳或有瑕疵,而被限制使用了。我实际测试了一下,确实如此。 但是后 64K ROM 的使用是有前提的,也就是需要事先对其好坏进行验证。如果是好的,则暂存校验,再写入APP区;而如果是坏的,那么就直接在固件传输时实时写入APP区(这个办法我屡试不爽,还没有发现后64K有坏的)。 以上振南所介绍的是一种“骚操作”,根本上还是有一定的风险的,ST 官方有声明过,对后 64K ROM 的质量不作保证,所以还是要慎用。 10米之内隔空烧录 这个“隔空烧录”源于我的一个 IoT 项目,它是对空调的外机进行工况监测。大家知道,空调外机的安装那可不是一般人能干的,它要不就在楼顶,要不就在悬窗上。这给硬件升级嵌入式程序带来很大的困难。 所以,我实现了“隔空烧录”的功能,其实它就是串口BL应用的一个延伸,如图所示,通过蓝牙串口模块实现“隔空烧录”。 “隔空烧录确实牛,但是总要抱着一个电脑,这不太方便吧。”确实是!还记得前面我提过的AVRUBD通信协议吗?它的上位机软件是有手机版的。这样我们只要有手机,就能“隔空烧录”了,如图,手机连接蓝牙串口模块实现“手机隔空烧录”。 “哪个APP?快告诉我名字”,别急,蓝牙串口助手安卓版,下图是正在传输固件的界面。 AVRUBD其实是对 Xmodem 协议的改进,这个我们放在专门的文章进行详细讲解。 BL的分散烧录 我们知道BL的核心功能其实就是程序烧录。那你有没有遇到过比较复杂的情况,如图所示,一个系统(产品)中有多个部件需要烧录固件。 这种情况是有可能遇到的。主 MCU+CPLD+通信协处理器+采集协处理器就是典型的复杂系统架构。这种产品在批量生产阶段,烧录程序是非常繁琐的。首先需要维护多个固件,再就是需要一个个给每一个部件进行烧写,烧写方式可能还不尽相同。所以我引入了一个机制,叫“BL的分散烧录”。 首先,我们将所有的固件拼装成一个大固件(依次数据拼接),并将这个大固件预先批量烧录到外扩 ROM 中,比如spiFlash;再将主MCU预先烧录好BL;然后进行SMT焊接。 PCBA生产出来之后,只要一上测试工装(首次上电),BL会去外扩ROM中读取大固件,并从中分离出各个小固件,分别以相应的接口烧录到各个部件中去。配合工装的测试命令,直接进行自检。 这样做,批量化生产是非常高效的。当然,这个 BL 开发起来也会有一定难度,最大问题可能还是各个部件烧录接口的实现(有些部件的烧录协议是比较复杂的,比如 STM32 的 SWD 或者 ESP8266 的 SLIP)。 BL没有最好的,只有最适合自己的。通常来说,我们并不会把BL设计得非常复杂,原则上它应该尽量短小精炼,以便为APP区节省出更多的ROM空间。毕竟不能喧宾夺主,APP才是产品的主角。 不走寻常路的BLBootpatcher 我来问大家一个问题:“Bootloader在 ROM 中的位置一定是在 APP 区前面吗?”很显然不是,AVR 就是最好的例子。那如果我们限定是 STM32 呢?似乎是的。上电复位一定是从0X08000000位置开始运行的,而且BL一定是先于APP运行的。 在某些特殊的情况下,如果 APP 必须要放在0X08000000位置上的话,请问还有办法实现BL串口烧录吗?要知道APP在运行的时候,是不能 IAP 自己的程序存储器的(就是自己能自己擦出重新烧录新固件)。请看图,BL位于APP之后称之为Bootpatcher。 APP运行时,想要重新烧录自身,它可以直接跳转到后面的BL上,BL运行起来之后开始接收固件文件,暂存校验OK之后,将固件写入到前面的APP区。然后跳转到 0X08000000,或者直接重启。这样新的APP就运行起来了。 这个位于 APP 后面的 BL,我们称之为 Bootpatcher(意为启动补丁)。但是这种作法是有风险的,一旦 APP 区烧录失败,那产品就变砖了。所以这种方法一般不用。 APP反烧BL 前面我们都是在讲BL烧录APP,那如果BL需要升级怎么办呢?用 JLINK。不错,不过有更直接的方法,如图,APP烧录BL区。 这是一种逆向思维,我们在 APP 程序中也实现接收固件文件,暂存校验,然后将其烧录到 BL 区。这种作法与Bootpatcher 同理,也是有一定风险的,但一般都没有问题。 最后OK,本系列文章对BL进行了详尽的剖析讲解,应该做到了深入浅出,包含基本的原理,以及实例的实现,还有一些知识的扩展。希望能够对大家产生启发,在实际的工作中将这些知识付诸实践。 作者/来源:一起学嵌入式 |
|
来自: 新用户62592529 > 《MCU行业》