本帖最后由 宫影空明人不往 于 2024-7-30 15:35 编辑
#申请原创# 前言 HEX文件和BIN文件是常用来进行IAP升级的文件格式。BIN文件就是简单的数据文件,可以直接将其内容烧录到芯片FLASH相应的地方,而HEX文件则会带有一些其他属性相关信息。本篇帖子将讲解下如何提取HEX文件的信息并将内容烧录到FLASH中。
HEX文件介绍 Hex文件是一种十六进制文本格式,通常用于描述固件或程序的二进制数据。它是一种常见的用于烧录程序到嵌入式系统中的文件格式。下面是Hex文件的基本结构和一些重要的信息: Hex文件可由五部分组成,分别如下: - 起始符号:记录以一个冒号(:)开头,表示记录的起始。
- 字节数:表示接下来的数据字节数目,以两位十六进制数表示。最多可以传输255字节的数据。
- 地址:描述数据的起始地址,通常为目标设备的存储器地址。地址字段的长度取决于Hex文件类型(16位地址或32位地址)。
- 记录类型:指定记录的类型,包括数据记录、结束记录等。
- 00:数据记录(Data Record),描述要写入目标设备的数据。
- 01:结束记录(End Of File Record),表示文件结束。
- 04:扩展地址,也可以理解为基地址。
- 05:程序的入口地址。
- 等等
- 数据(Data):实际的数据以十六进制形式出现,长度由字节数字段决定。
- 校验和(Checksum):用于检测数据在传输过程中的错误。校验和是记录中所有字节的和(不包括起始符号)的二进制补码的低字节(即取低8位的结果),并且其值应为0。
根据上面HEX的结构,下面对Hex文件进行分析,使用的例子为IAP的APP1升级程序的HEX文件。 :020000040800F2
:1040000010040020B14100080B4C0008074C0008C8
:10401000094C0008BD420008954C00080000000053
我们可以看到,一开始字段的数据长度为0x02,地址为0x0000,类型为0x04,数据为0x0800,校验值为0XF2. 紧接着就是长度为0x10,地址为0x4000,类型为0x00,数据为…,以及校验值为0Xc8。 从上面两段可以看出该第二段的数据需要烧录的地址为0x0800 << 16| 0x4000。第三段则为0x0800 << 16 | 0x4010。后续数据一次类推。 :040000050800419915
:00000001FF
结束的两个字段就表示程序的入口地址为0x08004199,以及该HEX文件传输完毕。
代码编写 这里借用APM32F4xx_SDK_V1.4版本的SDK进行开发,使用的是串口轮询例程。
1.数据收集 在收到':'数据时判断是HEX文件传下来,进行原始数据接收,当接收到的数据长度符合预期时,进行数据处理并退出相应循环。具体如下: while(1)
{
/* Wait until end of reception */
while(USART_ReadStatusFlag(F4COM1, USART_FLAG_RXBNE) == RESET);
temp = USART_RxData(F4COM1);
//检测到‘:’
if(temp == (uint8_t)':')
{
//重置状态
state = 0;
count = 0;
while(state == 0)
{
while(USART_ReadStatusFlag(F4COM1, USART_FLAG_RXBNE) == RESET);
temp = USART_RxData(F4COM1);
hex_buf[count] = temp;
count++;
if(count == HEXtoASCII(hex_buf[0], hex_buf[1])*2+10)
{
//单字段完成
state = 1;
}
}
//数据处理
DataProcess();
}
}
2.数据转换 我们看到的HEX16进制数据使用ASCII表示的,比如说数据长度进行0x02,传输的是0x30,0x32,因此需要对其进行数据处理。 具体处理代码如下: #define ASCIItoHEX(x) (x>0x39?(x-0x40+9):(x-0x30))
#define HEXtoASCII(x,y) (ASCIItoHEX(x)*16 + ASCIItoHEX(y))
首先对单个ASCII转换个16进制的值,然后将两个8位数据合并成16位数据储存,方便后续处理。
3.数据处理 对转换后的16进制数据进行处理,主要是将一些信息提取出来,比如说扩展地址,当前地址,数据等等,然后针对不同的数据类型进行不同的操作,主要如下: void DataProcess(void)
{
uint8_t i = 0;
uint8_t len = 0;
//获取16位数据数量
process_buf[0] = HEXtoASCII(hex_buf[0], hex_buf[1]);
//加上其他数据
len = process_buf[0] + 5;
//数据转换
for(i = 1; i <len ;i++)
{
process_buf[i] = HEXtoASCII(hex_buf[2*i], hex_buf[2*i+1]);
}
//提取信息
DATANUM = process_buf[0];
ODDESTADDR = process_buf[1]<<8 | process_buf[2];
DATATYPE = process_buf[3];
CHECKNUM = process_buf[len-1];
//数据处理
switch(DATATYPE)
{
case 0X00://数据段
for(i = 0; i < DATANUM/4; i++)
{
DATABUF[i] = process_buf[4+4*i]| process_buf[5+4*i]<<8 | process_buf[6+4*i]<<16 | process_buf[7+4*i]<<24;
}
Flash_Program();
break;
case 0X04://扩展地址
BASEADDR = process_buf[4]<<8 | process_buf[5];
break;
case 0X01://结束段
Jump_to_APP1();
break;
default:
break;
}
}
功能检验使用串口助手工具将APP程序传给单片机,单片机正常运行跳转程序。
本次对HEX文件的传输仅进行简单的处理,实际开发中还需要加上校验的确认,错误处理等等。
|
一个简单的HEX文件进行IAP升级演示,通过数据收集-数据转换-数据处理逐步完整整个操作
感谢大佬的文章分享~后续申请原创请@21小跑堂,以便跑堂及时安排审核~~~