HEX文件中可编辑的PIC序列号


8

目前,我的固件中有一个硬编码的序列号,用于正在使用的设计。固件可以读取并报告序列号。可以满足我的需求。麻烦在于,每个新的序列号都需要我更改代码并重新编译。当要建造许多单元时,这很麻烦,可能会引入错误,并且是全面的不良做法。序列号是给我的,硬件设计是一成不变的,因此我无法在硬件中添加任何功能来序列化这些单元(EEPROM /硅ID芯片/上拉)。我想做的是将序列号定位在固定地址,编译一次代码,然后在已编译的HEX文件中为每个新序列号编辑该地址。该数字在多个地方都有引用,因此理想情况下,我想一次定义和定位它,然后在我的代码的其他地方引用该“变量”。有谁知道如何使用C18编译器在我选择的特定可寻址存储器位置中定位常量数据?有没有人可以建议的更好的方法?


1
大约一半的PIC18内置了128字节至1K的EEPROM。我从您的问题假设您的PIC18是没有EEPROM的50%之一?
tcrosley

Answers:


4

特别是要解决使用C18编译器将变量绑定到PIC18上闪存中特定地址的问题,请在安装编译器的doc目录中的hlpC18ug.chm中参考“ Pragmas”一节。

为此,您需要在内存中定义一个新的“节”并将其绑定到起始地址,以便

#pragma romdata serial_no_section=0x1700

这将创建一个名为“ serial_no_section”的新节,该节从闪存(程序)存储器中的地址0x1700开始(因为我们在#pragma中定义了“ romdata”)。

在#pragma行之后,直接定义变量,因此:

#pragma romdata serial_no_section=0x1700
const rom int mySerialNumber = 0x1234;
#pragma romdata

现在,存储器中的地址0x1700处有0x12,地址0x1701处有0x34(因为PIC18使用little-endian模型)。“ const rom”确保编译器知道这是const变量类型,并且该变量位于“ rom”内存中,因此需要通过表读取指令进行访问。

最后#pragma romdata一条语句确保链接器认为合适时,将随后的所有变量声明链接到默认内存部分,而不要在“ serial_no_section”部分中继续进行。

现在,所有代码都可以简单地引用变量“ mySerialNumber”,并且您确切知道序列号可以在内存中找到的地址。

编辑十六进制代码可能会有些困难,因为您需要为所编辑的每一行计算校验和。我正在研究一个C ++类,以对Intel HEX文件进行解码和编码,这应该使此操作更容易,但尚未完成。解码文件有效,尚未进行再次编码。该项目(如果您有兴趣的话)在这里https://github.com/codinghead/Intel-HEX-Class

希望这可以帮助


4

我已经以类似于Joel所描述的方式完成了序列号(简称为s / n)。我正在使用PIC18F4620和CCS编译器。s / n在闪存中的位置被强制为最后4个字节。由于我仅使用80%的Flash,因此我的编译器和链接器不会在最后4个字节中写入可执行代码。

然后,我有2种将s / n实际写入单个单位的替代方法:

  • CCS在线调试器(ICD)具有允许在Flash内部任意位置进行操作的功能。这是一个有用的技巧。不幸的是,在以后的版本中,他们已将其删除。
  • PIC具有与PC的串行链接。序列号是通过它上传的。固件具有一个例程,该例程将接收序列号并将其存储在Flash中。

回复乔尔的评论

不了解C18,但是CCS编译器随附了库函数write_program_eeprom(...)read_program_eeprom(...)。这是他们组装时的样子。

.................... write_program_eeprom(i_ADDR,iWord);
EF84:BSF FD0.6
EF86:CLRF FF8
EF88:MOVLW 7F
EF8A:MOVWF FF7
EF8C:MOVLW F0
EF8E:MOVWF FF6
EF90:MOVLB 0
EF92:BRA EF24
EF94:MOVLW F0
EF96:MOVWF FF6
EF98:MOVFF 490,FF5
EF9C:TBLWT * +
EF9E:MOVFF 491,FF5
EFA2:TBLWT *
EFA4:BCF FA6.6
EFA6:BSF FA6.4
EFA8:RCALL EF3C
EFAA:RCALL EF3C
EFAC:CLRF FF8
EFAE:CLRF FF8
........... iWord = read_program_eeprom(i_ADDR); 
EF60:CLRF FF8
EF62:MOVLW 7F
EF64:MOVWF FF7
EF66:MOVLW F0
EF68:MOVWF FF6
EF6A:TBLRD * +
EF6C:MOVF FF5,W
EF6E:TBLRD *
EF70:MOVFF FF5,03
EF74:CLRF FF8
EF76:MOVLB 4
EF78:MOVWF x90
EF7A:MOVFF 03,491

1
是的,这正是我要的!您能描述一下您用来将S / N打包到闪存的最后几个字节中的哪些代码属性吗?
Joel B'2

“固件具有一个例程,该例程将接收该序列号并将其存储在Flash中” write_program_eeprom(...)read_program_eeprom(...)。EEPROM和闪存是两个不同的东西!
m.Alin 2012年

@ m.Alin这就是CCS ccompiler附带的“固定”功能的调用方式。他们实际上会写和读Flash。
尼克·阿列克谢夫

2

我已经做了几次。通常,我在程序存储器的固定位置定义一个固件信息区域,然后编写一个从模板HEX文件制作序列化HEX文件的程序。这些都是容易做的事情。

在生产环境中,所有测试通过后,您只需运行一次序列化程序。它使具有唯一序列号的临时HEX文件被编程到PIC中,然后删除该临时HEX文件。

我不会让该位置可重定位,然后必须找到它。随着链接器的移动,这可能会改变每个构建。对于像10F系列这样的很小的PIC,我已经做到了,这些常量是MOVLW指令的一部分。在这种情况下,我可以即时读取MAP文件以确定这些位置在哪里。为此,我在库中有MPLINK MAP文件解析代码。

要将某物放置在固定位置,请在固定地址处定义一个段。链接器将首先放置此类绝对段,然后在其周围放置可重定位的段。不要忘记在PIC 18上使用CODE_PACK而不是仅使用CODE,否则您将要处理整个指令字而不是单个字节。例如(仅输入,而不运行在assemlber后面):

.fwinfo code_pack h'1000';位于固定已知地址的固件信息区域
         db h'FFFFFFFF';序列号,由生产程序填写
         db fwtype;此固件的类型ID
         db fwver;版本号
         db fwseq;构建序列号

2

我建议将序列号存储在固定地址中。根据您的编译器/链接器和所讨论的部分,您可以采用几种方法:

  1. 定义一个可重定位的节,其中将包含序列号,在代码中使用#pragma指令将序列号强制进入该节,并在链接规范中强制该节的地址。
  2. 对于可以直接读取代码存储器的部分,请从允许链接器使用的区域中排除一个存储器区域(即告诉它该部分比实际小4个字节),然后使用某种方式读取代码中的序列号就像`(((unsigned long const *)0x3FFC)`
  3. 对于不能直接读取代码存储器的部件,您可以将“ RETLW”指令放在某个固定地址,然后使链接器确信有可调用函数在这些地址处返回“字节”。然后,人们会说“ out_hex(ser_byte0()); out_hex(ser_byte1()); out_hex(ser_byte2());以输出序列号的字节。

所有PIC 18F都可以通过表读取机制读取程序存储器。
Olin Lathrop'2

那是真实的。14位部分中的一些也可以读取程序存储器。但是,即使在可以读取程序存储器的PIC上,该retlw方法也通常要快得多(在18位PIC上,从a call到a retlw将总共​​花费四个周期;使用一个clrf TBLPTRU/movlw xx/movwf TBLPTRH/movlw xx/movwf TBLPTRL/tblrd *+/movf TABLAT,w将花费八个周期)。
supercat '02

1

我会做相反的事情:编译并链接代码,然后从链接器文件中找出值的存储位置。您可能需要在映射到Flash的段中显式定位变量。

不需要这样,但是我为Wisp648程序员提供的PC软件具有读取.hex文件,修改特定位置以及将.hex文件写回(到相同或另一个文件)的能力。无需我的程序员在场。源代码可用(在Python中),许可证允许所有使用:www.voti.nl/xwisp一旦解决了主要问题,可能会很方便。


感谢@Wouter van Ooijen!我试图避免使用“查找值存储在哪里”的方法,因为这很可能意味着将值重新放置在连续的编译中,并要求我(或一些在我身后的可悲的家伙)找出该值在哪里再次位于,肯定会带来问题。
Joel
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.