本帖最后由 宫影空明人不往 于 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文件的传输仅进行简单的处理,实际开发中还需要加上校验的确认,错误处理等等。
|