遇见往事 / 编程器与Intel HEX文件格式
life·@oflyhigh·
0.000 HBD遇见往事 / 编程器与Intel HEX文件格式
今天早晨查找资料的时候,无意中发现一篇自己16年前翻译的文章,不胜感慨。  (图源 :[pixabay](https://pixabay.com)) # 欲做编程器 那时候和朋友一起创业做一些单片机相关的硬件开发,单片机开发一个重要的步骤就是将我们编写出来的程序烧写到单片机内部让其工作,而完成这个步骤需要用到一个设备叫做编程器(现在也有叫下载器的),为此我们特意花2000多大洋购入这个设备,对于当时的我们而言,这是比较巨大的一笔开销了。 尽管用我们购买的编程器可以完成程序的烧写的烧写工作,但是需要将待烧写的芯片插到编程器的芯片座上,再启动编程器软件,从一堆列表中选取芯片厂商、芯片型号,再从文件选择框中选择我们要烧写的目标文件,然后去执行烧写校验等诸多步骤,完成后再把芯片从芯片座上拔下来,插入到我们硬件电路对应的芯片座中。 这个过程很繁琐,并且有一些弊端,比如对于我们将芯片直接焊接到电路板上的情况,再想更新芯片程序基本上是没有可能了。所以为了解决这个问题,我们计划开发一款自己的编程器,一方面简化操作流程,另外一方面可以直接对已经焊接到电路板上的芯片进行操作(电路板上预留接口)。 # HEX文件格式的挑战 开发自己的编程器主要可以分成两个方面的工作:一是硬件部分,负责将数据写入到对应芯片中(ICSP);一个是桌面软件,负责读取目标文件中的数据,并发送给硬件部分。桌面软件和硬件之间的按照我们自己约定的通信协议通信。 当时我们使用单片机开发软件(Keil C)主要生成两种格式的文件: ***`bin格式`***以及***`hex格式`***,***`bin格式`***就相当于一个二进制文件,对于桌面软件来讲,把读到的所有数据都发出去,就完工了,而***`hex格式`***则是很复杂的一个文本文件。 当时一些很多小伙伴的做法是使用两款软件,***`bin2hex`***以及***`hex2bin`***在两种格式间进行转换,也就是说,如果我们的编程器想处理***`hex文件`***,可以先调用***`hex2bin`***再处理***`bin文件`***即可。但是这样做有一个弊端,如果我想写入指定的地址区间,忽略掉其它区域(比如写eeprom的指定区域),从bin文件上,没法判断全零的区域是要擦除还是要保留的,而hex文件则没有这个问题。 因此,我们计划在桌面软件中增加hex格式的支持,对于硬件部分无需任何修改,因为它接收到是地址和数据,所有解析处理都是在软件部分完成的。这对软件部分是一个挑战,我们需要能理解和处理hex格式。 # 达成目标 当时能找到的资料有限,中文资料更是没有,当时最权威的一篇资料就是Keil网站上的这篇文章了:[GENERAL: INTEL HEX FILE FORMAT](http://www.keil.com/support/docs/1584/),为了吃透Intel Hex File Format,我仔细读了N遍,并最终将其翻译成为中文。最后,基于我对Intel Hex文件格式的深刻理解,在软件中实现了Hex文件的解析和处理。在工作中使用我们自己的编程器后,大幅提升了我们的工作效率。 再后来我们创业失败散伙,几个小伙伴各奔东西,其中一个小伙伴接手了当时我们所有的设备、技术以及电子元件等,继续搞硬件开发,现在混得风生水起。前段时间我们闲聊时偶然提起那时候做的一些工具,他说我们实现的编程器现在依然是他团队成员常用的工具之一,当然了,做了一些改版,外观啥的漂亮多了,功能也愈加强大,但是核心的东西还是没有啥变化。 16年前开发的东西,现在还在发挥光和热,这真是让我很欣慰也很感概。恰巧今天翻到自己翻译的文章,那么就把它也贴区块链上吧,尽管现在看起来,翻译的不是那么完美,但是还是要比网上不少类似的介绍文章要强得多,毕竟当时倾注了我不少心血呢。 ----- # 附原文及翻译内容 英文原文: [GENERAL: INTEL HEX FILE FORMAT](http://www.keil.com/support/docs/1584/) 以下为翻译内容: ***<sub>部分代码串行了,将就看吧</sub>***😀 ``` 问题: 什么是Intel HEX文件格式? 回答: Intel HEX文件是由一行行符合Intel HEX文件格式的文本所构成的ASCII文本文件。在Intel HEX文件中,每一行包含一个HEX记录。这些记录由对应机器语言码和/或常量数据的十六进制编码数字组成。Intel HEX文件通常用于传输将被存于ROM或者EPROM中的程序和数据。大多数EPROM编程器或模拟器使用Intel HEX文件。 记录格式 Intel HEX由任意数量的十六进制记录组成。每个记录包含5个域,它们按以下格式排列: :llaaaatt[dd...]cc 每一组字母对应一个不同的域,每一个字母对应一个十六进制编码的数字。每一个域由至少两个十六进制编码数字组成,它们构成一个字节,就像以下描述的那样: : 每个Intel HEX记录都由冒号开头. ll 是数据长度域,它代表记录当中数据字节(dd)的数量. aaaa 是地址域,它代表记录当中数据的起始地址. tt 是代表HEX记录类型的域,它可能是以下数据当中的一个: 00 – 数据记录 01 – 文件结束记录 02 – 扩展段地址记录 04 – 扩展线性地址记录 dd 是数据域,它代表一个字节的数据.一个记录可以有许多数据字节.记录当中数据字节的数量必须和数据长度域(ll)中指定的数字相符. cc 是校验和域,它表示这个记录的校验和.校验和的计算是通过将记录当中所有十六进制编码数字对的值相加,以256为模进行以下补足. 数据记录 Intel HEX文件由任意数量以回车换行符结束的数据记录组成.数据记录外观如下: :10246200464C5549442050524F46494C4500464C33 其中: 10 是这个记录当中数据字节的数量. 2462 是数据将被下载到存储器当中的地址. 00 是记录类型(数据记录) 464C…464C是数据. 33 是这个记录的校验和. 扩展线性地址记录(HEX386) 扩展线性地址记录也叫作32位地址记录或HEX386记录.这些记录包含数据地址的高16位.扩展线性地址记录总是有两个数据字节,外观如下: :02000004FFFFFC 其中: 02 是这个记录当中数据字节的数量. 0000 是地址域,对于扩展线性地址记录,这个域总是0000. 04 是记录类型 04(扩展线性地址记录) FFFF 是地址的高16位. FC 是这个记录的校验和,计算方法如下: 01h + NOT(02h + 00h + 00h + 04h + FFh + FFh). 当一个扩展线性地址记录被读取,存储于数据域的扩展线性地址被保存,它被应用于从Intel HEX文件读取来的随后的记录.线性地址保持有效,直到它被另外一个扩展地址记录所改变. 通过把记录当中的地址域与被移位的来自扩展线性地址记录的地址数据相加获得数据记录的绝对存储器地址. 以下的例子演示了这个过程.. 来自数据记录地址域的地址 2462 扩展线性地址记录的数据域 + FFFF ------------ 绝对存储器地址 FFFF2462 扩展段地址记录(HEX86) 扩展段地址记录也叫HEX86记录,它包括4-19位数据地址段.扩展段地址记录总是有两个数据字节,外观如下: :020000021200EA 其中: 02 是记录当中数据字节的数量. 0000 是地址域.对于扩展段地址记录,这个域总是0000. 02 是记录类型 02(扩展段地址记录) 1200 是地址段. EA 是这个记录的校验和,计算方法如下: 01h + NOT(02h + 00h + 00h + 02h + 12h + 00h). 当一个扩展段地址记录被读取,存储于数据域的扩展段地址被保存,它被应用于从Intel HEX文件读取来的随后的记录.段地址保持有效,直到它被另外一个扩展地址记录所改变. 通过把记录当中的地址域与被移位的来自扩展段地址记录的地址数据相加获得数据记录的绝对存储器地址. 以下的例子演示了这个过程.. 来自数据记录地址域的地址 2462 扩展段地址记录数据域 + 1200 --------- 绝对存储器地址 00014462 文件结束(EOF)记录 Intel HEX文件必须以文件结束(EOF)记录结束.这个记录的记录类型域的值必须是01.EOF记录外观总是如下: :00000001FF 其中: 00 是记录当中数据字节的数量. 0000 是数据被下载到存储器当中的地址.在文件结束记录当中地址是没有意义被忽略的.0000h是典型的地址. 01 是记录类型 01(文件结束记录) FF 是这个记录的校验和,计算方法如下: 01h + NOT(00h + 00h + 00h + 01h). Intel HEX文件例子: 下面是一个完整的Intel HEX文件的例子: :10001300AC12AD13AE10AF1112002F8E0E8F0F2244 :10000300E50B250DF509E50A350CF5081200132259 :03000000020023D8 :0C002300787FE4F6D8FD7581130200031D :10002F00EFF88DF0A4FFEDC5F0CEA42EFEEC88F016 :04003F00A42EFE22CB :00000001FF ```
👍 oflyhigh, eval, michelnilles, ffcrossculture, cqf, ainiaziz, htliao, linuslee0216, hannahwu, ytienchu, exec, xiaoshancun, somebody, mamoru, yyyy, mark-waser, digital-wisdom, jwaser, herpetologyguy, morgan.waser, bwaser, yulan, ellepdub, ethical-ai, strong-ai, davidjkelley, technoprogressiv, handyman, monkeyplayfire, devilwsy, feelapi, lingfei, duane.dos, deanliu, travelgirl, xiaokongcom, leonellaforever, skenan, cnbuddy, tensaix2j, archiles, ericsim, ericsim1991, ericsim1989, dylanhobalart, livingfree, alexis555, susanlo, redes, arcange, raphaelle, avika, lohithacharya, lengxiaohua, littlevoice, blackbunny, lalala, ethansteem, laoyao, xiaohui, helene, chinadaily, idx, abit, dennisphillips, brendashockley, praz735u5, wuyueling, bagleyy, how2rockstar, ozphil, cchampion, chaofanjun, yuanyi, raffyspyder, zahansafallwa, langyue, dgorbunov, arx27, cossel-log, yxp520lmx, kbrdek, jjirong, feng1925, teukufariz, ygern, rizwanmirza, cyprussports, powerfj, lenov, jimjin, heer, cryptosmile, kayros, comrade, hadimemories, spiritpower, tigerfish, danibehram, matthewguo, nostalgic1212, znx, mod-tamichh, ace108, ninedragons, magicmonk, susanli3769, jjohnson78, liflorence, weiwang01, networker5, aistis, rea, cliodhna, liwen12345, lydiachan, blackfox86, mohammedab, englishtchrivy, pharesim, blishs, leewang,