.Hex文件直接解析的实现_PIC芯片

news2024/11/27 12:28:42

1.问题

        bootloader写成后,需要处理传送过来的.Hex,或者等价的文件的烧录。MicroChip官方并未给出一个.Hex转为.Bin的处理策略。在它的Bootloader代码中,我们可以大致看到它的实现机制,它定义了一组命令。上位机在处理升级时,与Bootloader要通过这组指令进行信息传递。这是一个交互式的协议。如果我们抛开这个交互协议,希望自己处理升级过程,那么,需要对.Hex文件本身进行处理。然后才能让bootloader解析。

2.分析

2.1     Hex文件格式

Microchip给出了这个定义,参见:

MPLAB® IPE Intel HEX File Format | Microchip TechnologyLearn what records are contained within a hex file and where the records are within the file. icon-default.png?t=N5K3https://www.microchip.com/en-us/education/developer-help/learn-tools-software/mcu-mpu/mplab-ipe/sqtp-file-format-specification/intel-hex

重点如下:

  • Hex文件被拆分为一条条记录。
  • 每条记录头部固定,分别是
    • Byte0: ":"
    • Byte1: 数据字段长度
    • Byte2-3:数据要放置到的内存区域地址:两字节,这是英特尔固有的格式MSB,高位前,注意。
    • Byte4:这是类型,对PIC而言,只有3种类型:0,1,4
    • Byte5开始,是有效载荷。总长度= Byte1
    • 最后一个字段是校验和,校验和从Byte1开始,至有效载荷结束。校验和要保证,从Byte1到它自身的值=0.

2.2     字节流分帧解析

//与Hex分帧相关的数据结构
#define FLASH_WRITE_BLOCK 64
#define HEX_MAX_RECORD 16
#define HEX_RECORD_STR_MAX (1+5*2+0x10*2)
struct _HexRecorderFilterObj
{
    uint16_t targetAddr;
    uint8_t write_block[FLASH_WRITE_BLOCK]; //注意類型
    uint8_t write_block_offset;
    uint8_t frame_cache[HEX_RECORD_STR_MAX+1];
    uint8_t frame_cache_offset;
    uint16_t debugCnt[4]; /*line, 0cnt, 1cnt, 4cnt*/
    uint32_t file_len;
}hexRecorderFilterObj;

//Hex分帧数据结构初始化
void HexRecordFilter_Init(void)
{
    //hexRecorderFilterObj.write_block_offset = 0;
    //hexRecorderFilterObj.frame_cache_offset = 0;
    memset(&hexRecorderFilterObj, 0, sizeof(hexRecorderFilterObj));
}

//辅助函数,将缓冲区中相邻的一个Hex字节读出来
//未考虑小写字符,未考虑容错
uint8_t Hex2Byte(uint8_t *buf)
{
    uint8_t ret;
    if((*buf>='0')&& (*buf<='9')) ret = (*buf - '0');
    else ret = (*buf - 'A') + 10;
    buf++;
    ret<<=4;
    if((*buf>='0')&& (*buf<='9')) ret |= (*buf - '0');
    else ret |= (*buf - 'A')+ 10;
    return ret;
}

//这里传入是已经是.hex的一个完整的帧
bool Decode_a_hex_frame(uint8_t *frame, uint32_t len)
{
//:1057E000FFFFFF00FFFFFF00FFFFFF00FFFFFF00C5
    if(Hex2Byte(frame+1)*2+5*2+1 != len) return false;
    hexRecorderFilterObj.file_len += len;
    hexRecorderFilterObj.debugCnt[0]++;
    switch(Hex2Byte(frame+7))
    {
        case 0x01: hexRecorderFilterObj.debugCnt[2]++; break;
        case 0x04: hexRecorderFilterObj.debugCnt[3]++; break;
        case 0x00: hexRecorderFilterObj.debugCnt[1]++; break;
        default: 
            return false;
    }
    return true;
}

//一个统计函数
void PrintHexFileFilterDesc(void)
{
    xlog("total rec:%d, f0:%d,f1:%d,f4:%d; filelen=%d\r\n", 
            hexRecorderFilterObj.debugCnt[0],
            hexRecorderFilterObj.debugCnt[1],
            hexRecorderFilterObj.debugCnt[2],
            hexRecorderFilterObj.debugCnt[3],
            hexRecorderFilterObj.file_len);
}

//顶层函数,传入Hex的分段读入的信息
//已适当考虑容错
HAL_StatusTypeDef HexRecordFilter(uint8_t *buf, uint32_t len)
{
//:1057F00000000000FFFF0000EE2300007F3E0000DD
    do
    {
        if(hexRecorderFilterObj.frame_cache_offset>0)
        {
            if(hexRecorderFilterObj.frame_cache_offset>HEX_RECORD_STR_MAX)
            {
                hexRecorderFilterObj.file_len+=hexRecorderFilterObj.frame_cache_offset;
                hexRecorderFilterObj.frame_cache_offset = 0;
            }
            else if((*buf=='\r') || (*buf == '\n'))
            {
                hexRecorderFilterObj.frame_cache[hexRecorderFilterObj.frame_cache_offset] = 0;
                if(!Decode_a_hex_frame(hexRecorderFilterObj.frame_cache, hexRecorderFilterObj.frame_cache_offset))
                {
                    //return HAL_ERROR;
                }
                hexRecorderFilterObj.file_len++;
                hexRecorderFilterObj.frame_cache_offset = 0;
            }
            else hexRecorderFilterObj.frame_cache[hexRecorderFilterObj.frame_cache_offset++] = *buf;
        }
        else if(*buf == ':')
        {
            hexRecorderFilterObj.frame_cache[0] = *buf;
            hexRecorderFilterObj.frame_cache_offset = 1;
        }
        else
        {
            hexRecorderFilterObj.file_len++;
        }
        buf++;
        len--;
    }while(len>0);
    return HAL_OK;
}

3.实现结果

total rec:292, f0:289,f1:1,f4:2; filelen=13056

实际的文件: filelen:12956字节。记录292行。无误。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/723907.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于FreeRTOS的嵌入式设备管理关键技术研究及实现(学习六重要)

差分升级算法研究及改进 文件差分算法通过对不同文件的片段进行对比查找差异&#xff0c;将差异描述输出为差分文件。 差分算法是差分升级的关键技术&#xff0c;因此&#xff0c;差分算法的性能决定着整个升级系统的性能。 差分算法研究 差分更新又称为增量编码&#xff0…

yarn介绍与说明

1.介绍 说明&#xff1a;Yarn 是一个由 Facebook、Google、Exponent 和 Tilde 公司联合推出的新一代 JavaScript 包管理工具&#xff0c;用于取代 npm。与 npm 相比&#xff0c;Yarn 可以更快地下载依赖&#xff0c;更好地管理依赖版本&#xff0c;更稳定地构建依赖关系。 2.…

AWVS扫描工具使用教程

AWVS是一款Web漏洞扫描工具&#xff0c;通过网络爬虫测试网站安全&#xff0c;检测流行的Web应用攻击&#xff0c;如跨站脚本、sql 注入等。据统计&#xff0c;75% 的互联网攻击目标是基于Web的应用程序。 AWVS的主要功能模块 Blind SQL Injector&#xff1a;盲注工具 HTTP E…

单元测试报错 No tests found for given includes: [StudyApplicationTests.contextLoads]

当你运行单元测试报错No tests found for given includes: [StudyApplicationTests.contextLoads] 如下&#xff1a; 可能是因为你的gradle测试默认使用的是以gradle启动,改成以IDEA启动即可

力扣 64. 最小路径和

文章目录 题目描述解题思路 题目描述 https://leetcode.cn/problems/minimum-path-sum/ 解题思路 问题类型&#xff1a;动态规划 private int MinPathSum(int[][] grid) {for (int i 0; i < grid.Length; i) {for (int j 0; j < grid[i].Length; j) {if (i 0 &am…

Vue3 Diff 算法简易版

背景 学习一下Vue3中的diff算法~ 逻辑概述 这个算法的过程不算太复杂&#xff1a; 同时从新旧列表的头部遍历&#xff0c;找出相同的节点&#xff0c;则patch&#xff0c;否则就停止遍历&#xff1b;同时从新旧列表的尾部遍历&#xff0c;找出相同的节点&#xff0c;则patc…

使用Jetpack Compose中的LazyHorizontalGrid构建灵活的水平网格布局

在这篇博客中&#xff0c;我们将探讨如何使用Jetpack Compose中的LazyHorizontalGrid构建灵活的水平网格布局。 什么是LazyHorizontalGrid&#xff1f; LazyHorizontalGrid是Jetpack Compose中的一个组件&#xff0c;它可以用来创建一个灵活的、可滚动的水平网格布局。这个组件…

django 自定义分页类和使用总结

一、关于为何要分页 当处理大量数据时&#xff0c;如果一次将这些数据查询出来进行响应&#xff0c;必然对服务器内存、负载有所影响&#xff0c;影响低接口响应&#xff0c;进而影响用户体验。 常见的方式是将数据分段展示给用户&#xff0c;如果当前分段中没有需要的数据&am…

Leetcode:84. 柱状图中最大的矩形(单调栈C++)

目录 84. 柱状图中最大的矩形 问题描述&#xff1a; 实现代码与解析&#xff1a; 单调栈 原理思路&#xff1a; 84. 柱状图中最大的矩形 问题描述&#xff1a; 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。…

Redis 7 十大数据类型

10大数据结构图示 10大数据类型&#xff1a; redis字符串(String)redis列表(ist)redis哈希表(Hash)redis集合(Set)redis有序集合(ZSet)redis地理空间(GEO)redis基数统计(HyperLogLog)redis位图(bitmap)redis位域(bitfield)redis流(Stream) Redis键(key) 命令不区分大小写&am…

数据结构-堆的创建(详解)

目录 堆的概念及结构 堆的实现 堆的向上调整算法 代码实现&#xff1a; 思路详解&#xff1a; 堆的向下调整算法 代码实现&#xff1a; 思路详解&#xff1a; 堆的创建&#xff1a; 堆结构的定义及相关函数的声明&#xff1a; 堆的初始化&#xff1a; 堆的销毁&#x…

如何减少图片大小内存?压缩图片内存大小的方法介绍

什么时候需要压缩图片内存大小 随着移动设备的普及和社交媒体的盛行&#xff0c;我们经常需要通过分享图片来传达信息和与他人互动。然而&#xff0c;有时候图片的文件大小过大&#xff0c;可能会导致上传、下载或发送过程中遇到问题。以下是一些常见情况下需要压缩图片内存大…

插值应用案例2

案例1 高点和高程 在一丘陵地带测量高程&#xff0c;x和y方向每隔100m测一个点&#xff0c;得到高程如下表所列&#xff0c;试插值一曲面&#xff0c;确定合适的模型&#xff0c;并由此测到最高点和相应的高程。 x0/z0\y0 100 200 300 400 500 100 636 697 624 478 …

Android GlSurfaceView 入门教程 : 绘制一个三角形

1. GlSurfaceView是什么 GlSurfaceView是Android中的一个类&#xff0c;继承自SurfaceView&#xff0c;用于显示OpenGL ES图形渲染的一个视图。 OpenGL ES是一种跨平台的图形API&#xff0c;用于渲染2D和3D图形&#xff0c;也可以将相机的画面显示到GlSurfaceView上&#xff0…

Spring Boot 中的 SQL 注入攻击是什么,原理,如何预防

Spring Boot 中的 SQL 注入攻击是什么&#xff0c;原理&#xff0c;如何预防 随着互联网的发展&#xff0c;Web 应用程序的数量不断增加&#xff0c;而 SQL 注入攻击也成为了常见的网络安全问题之一。SQL 注入攻击是通过在 Web 应用程序中注入恶意的 SQL 代码&#xff0c;从而…

@RestController 和 @Controller的区别?

Controller 返回一个页面单独使用 Controller 不加 ResponseBody的话一般使用在要返回一个视图的情况&#xff0c;这种情况属于比较传统的Spring MVC 的应用&#xff0c;对应于前后端不分离的情况 RestController 返回JSON 或 XML 形式数据 但RestController只返回对象&#…

FPGA综合设计实验:基于PWM脉宽调制的呼吸流水灯设计

目录 一、引言 二、项目准备 1.项目预期目标 2.项目原理及总体实现思路 三、项目模块设计 1.顶层模块 2.按键控制模块 3.呼吸灯模块 4.数码管显示模块 5.二进制转BCD码模块 四、项目测试 1.仿真测试 2.实物测试 五、项目总结 1.选题思考与过程反思 2.设计的具体…

MySQL之常见的CRUD面试题【上】

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于MySQL数据库的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 导读&#xff1a; 一.数据库的连表…

如何获得免费英文文献翻译呢?

我偶然之间发现的一个小技巧分享给大家&#xff01; 这个方法很简单&#xff0c;巧妙地运用了某外国浏览器自带的翻译功能&#xff0c;所以我们需要的是某外国浏览器 1.将需要翻译的pdf文档保存 2.进入http://pdfdo.com/pdf-to-html.aspx将PDF转为网页 3. 上传文件后耐心等待转…