什么是BootLoader
在嵌入式操作系统中,BootLoader是在操作系统内核运行之前运行。可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。在嵌入式系统中,通常并没有像BIOS那样的固件程序(注,有的嵌入式CPU也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。在一个基于ARM7TDMI core的嵌入式系统中,系统在上电或复位时通常都从地址0x00000000处开始执行,而在这个地址处安排的通常就是系统的BootLoader程序
以上来自百度百科,那么汽车电子中,某些ECU要满足OTA的需求,也需要具备BootLoader的功能。
简单概括一下汽车电子中的BootLoader,即Boot:对App的引导,使PC指针跳转到App的Main函数。Loader:通过某种协议将新的App程序下载到Flash中。
相关法规或者是客户要求,在Boot或者是Loader的过程中,需要对App进行验证
这个有点类似于Android的“线刷”
Boot的实现
1. 设置地址
BootLoader程序设置为0x00000000;App程序根据芯片手册自己去定义一个,我这里以0x00010000为例。
每个编译器设置的方法不同,同一个编译器也可能有不同方法,这个请自行搜索。
2. 判断是否可以跳转到App
正常上电,代码会跑到BootLoader的main函数,在这个函数中我们需要做硬件初始化(Can、定时器等),协议栈的初始化等等,然后就是要判断当前是否要跳转到App还是驻留在BootLoader中等待App的下载。
最基本的判断条件就是当前的Falsh中有没有App或着App是否有效,比如你在每一次通过BootLoader下载App成功之后都向某一片固定的Flash写一串数据,然后在每一次启动BootLoader都会判断这一片Flash中有没有这个数据即可,前提是每一次下载之前都会清空Flash,一般不清空写不进去。具体方法有很多,更为安全一点的比如每次启动Boot都对App程序进行一次CRC校验,麻烦一点 稍微有点耗时
除此之外要判断是不是外部有下载请求(来自诊断仪或其他上位机)
这里又要分两个,当App运行正常时,判断是不是用户在App中进入了编程会话,并且发送了重启指令,怎么实现 和上述方法一致(在APP程序重启之前,判断当前是否是编程会话,如果是则向Flash中存标志位)
当App不正常时,比如我们的App一运行就跑飞了,我们可以在BootLoader中设置一个强刷指令,当BootLoader跳转的App之前收到了这一帧指令(我这里是通过can)就驻留在Boot里面等待新的App程序刷入,当然时间要把控好,不可以太长,等待100ms足够了
3. 跳转
Easy
(*(void (*)(void))(APP_StartAddr))();
当然在此之前你要做点事情,例如关闭所有中断
Loader的实现
1. 前提
前提是你已经驻留在BootLoader里面。一般有三种情况没有App、从App跳转过来下载新的App、App无效通过强刷指令驻留在BootLoader。
2. 请求下载
UDSONCAN的0x34服务,具体详见ISO-14229
3. 下载
UDSONCAN的0x36服务,具体详见ISO-14229
4. 请求退出下载
UDSONCAN的0x37服务,具体详见ISO-14229
5. 校验
UDSONCAN的0x31服务,具体详见ISO-14229
这个0x31服务在UDS中定义的比较广泛,他就类似于让ECU执行一段特殊的代码,它可以是一个测试用例,比如通过0x31服务让ECU某一个灯亮一下,也可以用来校验CRC,只要通讯双方的格式对的上就可以。
除了程序CRC校验(程序完整性检查)之外,还可以有程序依赖性检查(例如检查常电电压等)
6. 重启
拓展
-
Flash驱动独立下载
正常通过BootLoader烧录App的时候,只需要拿到App的hex文件即可,但是市场上有很多ECU是将Flash驱动和Bootloader分开。
当需要下载App的时候,要先下载Flash驱动,下载到RAM里,再通过这个Flash驱动把App下载到Flash里,这么做的目的是对Falsh的保护。也就是说一次成功的下载需要两份Hex文件。
-
两级Boot
在BootLoader中可以更新BootLoader,暂时还没有实现过,有待尝试
以上是我对BootLoader的理解,望指正