前言
最近研究Bootloader,通过串口实现STM32程序的更新。需要学习了解STM32的Hex文件格式。在这进行一下总结。
HEX文件格式
我们通过文本形式打开hex文件,可以看到:
这一行就是一条指令数据,这里对数据帧格式进行说明:
报头 | 本行数据长度 | 数据起始地址 | 数据类型 | 数据 | 校验码 |
:(冒号) | 1 byte | 2 byte | 1 byte | n byte | 1 byte |
结合这个格式可以发现,它将数值1byte变成了字符串形式的2个字符来表示。
用第一行数据 :020000040800F2 作为示例:
":" 表示 指令头
"02" 表示 数据部分有两字节(即四个字符)
"0000" 表示 数据的16位起始存储器地址偏移量,是0x0000。数据的物理地址是通过将此偏移量添加到先前建立的基地址来计算的。
"04" 表示 数据类型。基地址
"0800" 表示 数据内容,为 0x08 和 0x00
"F2" 是检验码。LRC校验(纵向冗余校验):在线LRC校验(纵向冗余校验)计算器 (lddgo.net)
该条语句功能即说明 基地址为0x0800<<16为0x08000000.
后面的数据语句的地址则是在该条语句基地址基础上的偏移量。
第四字节表示数据类型,数据类型有:0x00、0x01、0x02、0x03、0x04、0x05。
数据类型 | 功能 | 描述 | 示例 |
00 | 数据 | 包含数据和该数据的16位起始地址。字节计数指定记录中的数据字节数。右侧显示的示例为0B (十一)个数据字节(61, 64, 64, 72, 65, 73, 73, 20, 67, 61, 70)位于以地址开头的连续地址 0010。 | :0B0010006164647265737320676170A7 |
01 | 文件结束 | 每个文件在文件的最后一行必须恰好发生一次。数据字段为空(因此字节数为00),并且地址字段通常为 0000。 | :00000001FF |
02 | 扩展段地址 | 数据字段包含一个16位的段基址(因此字节数始终为02)与80x86实模式寻址兼容。地址字段(通常为0000)被忽略。最近的段地址02记录乘以16,然后加到每个后续数据记录地址,以形成数据的物理起始地址。这允许寻址多达1 MB的地址空间。 | :020000021200EA |
03 | 起始段地址 | 对于80x86处理器,请指定CS:IP寄存器的初始内容(即起始执行地址)。地址字段是0000,字节数始终为04,前两个数据字节是CS值,后两个是IP值。 | :0400000300003800C1 |
04 | 扩展线性地址 | 允许32位寻址(最大4GiB)。记录的地址字段将被忽略(通常是0000),其字节数始终为02。两个数据字节(大字节序)为所有后续类型指定32位绝对地址的高16位00记录; 这些高位地址位适用于下一个04记录。类型的绝对地址00 通过组合最近的高16位地址位形成记录 04 用低16位的地址记录 00记录。如果是类型00 记录之前没有任何类型 04 记录,然后其高16位地址位默认为0000。 | :02000004FFFFFC |
05 | 起始线性地址 | 地址字段是 0000(未使用),字节数始终为04。四个数据字节代表一个32位地址值(big-endian)。对于80386和更高版本的CPU,此地址将加载到EIP寄存器中。 | :0400000508000135B9 |
总结
了解了这个东西,似乎自己也能做一个stm32版本的类似arduino的bootloader了。