热度 1||
一、什么是bootlloader?
在嵌入式操作系统中,BootLoader是在操作系统内核运行之前运行。可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。因此整个系统的加载启动任务就完全由BootLoader来完成。
以上是百度百科上对bootloader的描述,但是我们这里所说的bootloader是为了实现单片机IAP功能,所编写的一段引导程序,从而实现我们APP的程序数据能够通过串口等通信方式写进Flash程序空间最终实现自编程和程序更新的目的,这就是我们这里说的bootloader。
二、程序架构
具有bootloader的一个完整的应用系统程序分为两大部分:1、APP程序:应用系统功能实现层(通俗的讲就是我们自己要写的程序);2、bootloader引导程序:就是系统启动或复位时的入口程序,主要的功能包括时钟初始化、Uart通信初始化、判断是执行boot串口升级程序还是跳转执行APP程序。Bootloader的程序架构如下图所示:
三、bootloader串口升级协议
主机发送数据格式:头码(80H)+长度码+负载消息+校验和(CRC8),其中:
头码固定为80H,用于界定数据帧开始;
长度码:值为负载消息的总字节数;
负载消息的格式为:CMD+ADDR_L+ADDR_H+data;其中,CMD为一个字节的主机命令码;ADDR_L和ADDR_H为data写入目标机Flash地址的高低字节值;data为需要写入Flash程序空间的数据;检验和为所有负载消息按发送顺序先后对其CRC8(x8+x2+x+1)计算所得的校验值。
表1:主机命令表
命令描述 |
命令码 |
Byte-1 |
Byte-2 |
Byte-3 |
…… |
Byte-n |
擦除段 |
12H |
ADDR_L |
ADDR_H |
X |
X |
X |
擦除APP |
15H |
X |
X |
X |
X |
X |
接收编程数据块 |
10H |
ADDR_L |
ADDR_H |
Data-0 |
…… |
Data-n |
读取版本号 |
19H |
X |
X |
X |
X |
X |
跳转至APP |
1CH |
X |
X |
X |
X |
X |
注:X表示没有该字段数据;……表示连续的数据。
1、 擦除段:由指定的地址开始擦除目标机Flash连续的512字节的程序空间。
2、 擦除APP:擦除目标机的APP程序空间
3、 接收编程数据块:将接收到的数据写入目标机指定地址的程序空间
4、 读取版本号:读取目标机当前的bootloader的版本号
5、 跳转至APP:一般用于APP程序更新完成后,指示目标机跳转到APP程序运行
目标机(从机)回应为单字节回应码,具体含义如下:
表2:目标机回应码
回应名称 |
回应码 |
具体描述 |
OK |
0x01 |
命令执行成功 |
头码错误 |
0x51 |
数据帧头码错误 |
校验错误 |
0x52 |
数据帧校验错误 |
数据帧长度为0 |
0x53 |
数据长度码为0 |
负载消息长度超限 |
0x54 |
数据帧消息长度超过所允许的最大长度值 |
未知错误 |
0x55 |
协议未知错误 |
参数错误 |
0x5C |
命令参数错误 |
命令错误 |
0x6C |
根据协议无法解析该命令 |
Bootloader版本号 |
0至255 |
版本号,不建议存在与以上回应码相重叠的版本号 |
四、Bootloader程序内存空间分布
为实现单片机的IAP功能和合理的使用单片机的存储空间,我们需要对单片机的内存(这里的内存指的是单片机上所有可利用的存储资源,包括RAM、Flash)资源进行的合理的规划。以MSP430G2553为例,该Bootloader对其内存空间规划分布大致分为三个部分:RAM空间、Flash中的APP程序空间、Flash中的Bootloader程序空间。
RAM空间主要贮存着单片外设模块的寄存器(不可改变)、程序运行空间;
Flash中的APP程序空间存储着APP的代码数据和APP程序中的常量数据、APP层中断服务程序向量表、APP程序校验值等
Flash中的Bootloader程序空间存储着Bootloader程序代码数据和Boot层中断向量表等
具体内存空间分配如下表所示:
表3:内存分配空间
内存标签 |
地址 |
描述 |
|
|
0x0000 |
外围模块贮存位置 |
|
__RAM_Start |
0x01FF 0x0200 |
||
Boot层预先定义的变量指定的内存空间 |
|||
__NonReserve_RAM_Start(Boot) |
0x0205 0x0206 |
||
Boot层内存空间 |
|||
__NonReserve_RAM_Start(App) |
0x021F 0x0220 |
||
APP层内存空间 |
|||
__RAM_End |
0x03FF |
|
|
| | | |
| | | |
| | | |
|
INFOBOOT(Start) |
0x1000 |
时钟模块寄存器校准值、Bootloader的程序代码数据空间 |
|
INFOBOOT(End) |
0x10C0 |
|
|
| | | |
| | | |
| | | |
|
__Flash_Start(_AppChecksum) |
0xC000 |
APP程序代码数据检验和存储空间 |
|
_App_Start |
0xC002 0xC003 |
||
APP程序代码数据存储空间 |
|||
_App_End |
0xFBFF |
|
|
__Boot_Start |
0xFC00 |
Bootloader程序代码数据空间 |
|
__Boot_VectorTable |
0xFFDF 0xFFE0 |
||
单片机中断向量表 程序复位向量 |
|||
__Boot_Reset |
0xFFFE |
|
|
__Flash_End |
0xFFFF |
|
五、单片机IAP升级实例
现在假定单片机正在跑Bootloader升级引导程序,主机通过串口更新APP程序的基本流程如下:
读取Bootloader版本号 擦除APP程序空间 发送APP程序代码数据1
发送APP程序代码数据2(中断向量映射表代码) APP程序代码数据CRC校验值
APP程序更新完成发送跳转至APP命令
现假定APP程序编译完成后的16进制代码数据如下:
@C000
92 DD
@c004
A2 D2 60 01 F2 F0 EF 00 29 00 0D 12 0E 12 3D 40
3C 82 3E 40 0E 00 1D 83 0E 73 FD 23 0D 93 FB 23
3E 41 3D 41 00 3C 0D 12 0E 12 3D 40 3C 82 3E 40
0E 00 1D 83 0E 73 FD 23 0D 93 FB 23 3E 41 3D 41
00 3C F2 D0 10 00 29 00 0D 12 0E 12 3D 40 3C 82
3E 40 0E 00 1D 83 0E 73 FD 23 0D 93 FB 23 3E 41
3D 41 00 3C 0D 12 0E 12 3D 40 3C 82 3E 40 0E 00
1D 83 0E 73 FD 23 0D 93 FB 23 3E 41 3D 41 00 3C
00 13 A2 D2 60 01 F2 D0 20 00 29 00 F2 E0 10 00
29 00 D2 E3 20 02 0D 12 0E 12 3D 40 3C 82 3E 40
0E 00 1D 83 0E 73 FD 23 0D 93 FB 23 3E 41 3D 41
00 3C 92 C3 62 01 00 13 0F 12 0E 12 0D 12 0C 12
0B 12 B1 C0 10 00 0A 00 C2 43 2B 00 B0 12 E0 C0
3B 41 3C 41 3D 41 3E 41 3F 41 00 13 B2 40 DE C0
00 02 D2 D3 02 02 32 C2 03 43 B2 40 0B 5A 20 01
FF 3F D2 B3 03 00 07 24 D2 C3 03 00 D2 42 66 00
21 02 D2 43 22 02 00 13 1F 4C 01 00 0F 93 05 24
1D 53 CD 43 FF FF 1F 83 FB 23 30 41 F2 F0 DF 00
29 00 00 13 00 00 03 00 0C C1 28 C1 20 02
@fbce
30 40 26 C1 30 40 BC C0 30 40 04 C0 30 40 04 C0
30 40 F6 C0 30 40 04 C0 30 40 86 C0 30 40 04 C0
30 40 04 C0 30 40 04 C0 30 40 04 C0 30 40 04 C0
20 C1
q
该段数据分为三个部分:校验值、程序数据代码、中断向量映射表
校验值的地址位置为:0xC000,值为:92DD(LSB,92为地址空间中的低字节,DD为地址空间高字节)
同样依次将程序代码数据从地址0xC004开始写目标机对应的地址空间,中断向量表程序数据从0xFBCE开始写入目标机对应的程序空间。写入成功后发送APP跳转命令,程序跳转至APP层执行,此时APP更新成功。
通信举例:
1、 读取目标机版本号
主机发送:8001194F
目标机回复:A1(版本号)
2、 擦除APP程序空间
主机发送:8001156B
目标机回复:01(OK)
3、 发送程序代码数据
主机发送:801310DEFB3040F6C0304004C0304086C0304004C029
目标机回复:10(写入Flash的字节数);55(写入失败)
4、 发送程序跳转命令
主机发送:80011C54
目标机回复:01(OK)