工作经验总结:S19(SRecord)文件解析

一、SRecord文件简介

        SRecord文件是由Motorola公司定义的一种ASCII文本文件,文件扩展名包括:.s19、.s28、.s37、.s、.s1、.s2、.s3、.sx、.srec、.exo、.mot、.mxt,都是同一种格式,文件内容没有差异,主要用于记录微控制器、EPROM和其他类型的可编程设备的程序记录。

 

二、SRecord解析格式

SRecord文件一般格式如下:

typecountaddressdatachecksum
2 Byte2 Byte4 or 6 or 8 Byte0~64 Byte2 Byte
  • type:表示该行的数据记录类型
类型字段(type)记录内容地址字段数据字段记录描述
S0标题信息0x0000

1. mname is char[20] and is the module name.

2. ver is char[2] and is the version number.

3. rev is char[2] and is the revision number.

4. description is char[0-36] and is a text comment.

S1数据16位地址该记录包含从 16 位地址字段开始的数据。该记录通常用于 8 位微控制器
S2数据24位地址该记录包含从 24 位地址开始的数据
S3数据32位地址该记录包含从 32 位地址开始的数据。该记录通常用于 32 位微控制器
S4ResverdResverd×
S5计数16 位计数×此可选记录包含S1 / S2 / S3记录的 16 位计数。如果记录计数小于或等于 65,535 (0xFFFF),则使用此记录,否则将使用S6记录
S6计数24 位计数×此可选记录包含S1 / S2 / S3记录的 24 位计数。如果记录计数小于或等于 16,777,215 (0xFFFFFF),则使用此记录。如果小于 65,536 (0x010000),则将使用S5记录
S7记录起始地址,并且终止S3记录32位地址×该记录包含 32 位地址的起始执行位置。这用于终止一系列 S3 记录
S8记录起始地址,并且终止S2记录24位地址×该记录包含 24 位地址的起始执行位置。这用于终止一系列 S2 记录
S9记录起始地址,并且终止S1记录16位地址×该记录包含 16 位地址的起始执行位置。这用于终止一系列 S1 记录
  • count:(address + data + checksum)区域的字节总数
  • address:对应记录数据的起始地址信息
  • data:数据内容或者描述信息
  • checksum:(cout + address + data)区域的字节累加和S,保留最低有效字节,计算有效字节的补码checksum = ~(S & 0xFF) & 0xFF

(1)SRecord  S0/S3/S7解析示例

S01200004B4C5F333030395F4150502E733139E0
S30B100693F00000000000005B
S30910080000FECACEFA4E
S7051006818DD6
  • S0 12 0000 4B4C5F333030395F4150502E733139 E0

S0 表示记录标题信息

12 表示 addr + data + checksum 区域的字节数为12个字节

0000 固定为0000

4B4C5F333030395F4150502E733139 记录相关信息

E0 表示count + addr + data 区域的校验和为E0

  • S3 09 10080000 FECACEFA 4E 表示0x10080000地址起始的数据为FECACEFA
0x100800000xFE
0x100800010xCA
0x100800020xCE
0x100800030xFA

 

  • S7 05 1006818D D6 表示main函数的入口地址为0x1006818D,并且结束S3的记录(类似文件末尾)

(2)SRecord  S0/S1/S5/S9解析

S00600004844521B
S1130000285F245F2212226A000424290008237C2A
S11300100002000800082629001853812341001813
S113002041E900084E42234300182342000824A952
S107003000144ED492
S5030004F8
S9030000FC
  • S1 13 0000 285F245F2212226A000424290008237C 2A 表示0x0000起始地址的数据为285F245F2212226A000424290008237C

  • S5 03 0004 F8

S5 表示记录S1/S2/S3的计数

03 表示 addr + data + checksum 区域的字节数为3个字节

0004 表示前面S1记录的数量为4个

F8 表示count + addr + data 区域的校验和为F8

累加和 S = (03 + 00 + 00 + 04)= 0x07

校验和 checksum = ~(S & 0xFF)& 0xFF = 0xF8

  • S9 03 0000 FC 表示main函数的入口地址为0x0000,并且结束S1的记录(类似文件末尾)

​​​​​​​

三、SRecord解析Python代码示例

s19(SRecord)​​​​​​​文件的内容行解析python代码示例:

 def _line_analyse(self, line:str):
        # string fliter
        line = line.strip()  # 去除开头与结尾的空格或换行符
        
        # S19 file format
        type        = line[0:2]
        count       = int(line[2:4], 16)    # addr + data + checksum
        checksum    = int(line[-2:], 16)
        
        # S19 file info string dispose
        # 标题类型
        if (type == "S0"):
            pass
        
        # 数据类型
        # ( S1: 地址段 2个字节; S2: 地址段 3个字节; S3: 地址段 4个字节)
        elif (type == "S1" or\
              type == "S2" or\
              type == "S3"):
            
            # 地址索引和数据索引
            ADDRESS_LINE_INDEX = 4
            ADDRESS_LEN = DATA_TYPE_ADDR_LEN_ENUM.get(type)
            DATA_LINE_INDEX = ADDRESS_LINE_INDEX + ADDRESS_LEN
            DATA_LEN = (count * 2) - ADDRESS_LEN - 2    # data = cout - addr - checksum
            
            # 地址数据
            address = int(line[ADDRESS_LINE_INDEX : ADDRESS_LINE_INDEX + ADDRESS_LEN], 16)
            
            # 地址对应的data数据
            data_hex_list = []
            for i in range(DATA_LINE_INDEX, DATA_LINE_INDEX + DATA_LEN, 2):
                data_hex = int(line[i : i+2], 16)
                data_hex_list.append(data_hex)
            
            # checksum 校验
            # 该行所有16进制累加和S,保留最低有效字节,计算有效字节补码
            checksum_temp = 0
            for i in range(2, len(line) - 2, 2):
                checksum_temp += int(line[i:i+2], 16)
            checksum_temp = ~(checksum_temp & 0xFF) & 0xFF
            
            # 检验checksum
            if checksum_temp == checksum:
                self.data_dict[address] = data_hex_list
            else:
                print("checksum_temp:0x{:2x}, checksum:0x{:2x}, line:{:s}".format(checksum_temp, checksum, line))
        
        # Resverd
        elif (type == "S4"):
            pass
        
        # 数据计数类型(包含S1/S2/S3的计数)
        elif (type == "S5" or\
              type == "S6"):
            pass
        
        # 起始地址类型
        # ( S9: 终止S1记录; S8: 终止S2记录; S7: 终止S3记录)
        elif (type == "S7" or\
              type == "S8" or\
              type == "S9"):
            self.is_finished_analyse = True
            
            # 起始地址索引与长度
            MAIN_ADDRESS_INDEX = 4
            MAIN_ADDRESS_ADDRESS_LEN = (count * 2) - 2   # 减去checksum长度
            
            self.main_address = int(line[MAIN_ADDRESS_INDEX: MAIN_ADDRESS_INDEX + MAIN_ADDRESS_ADDRESS_LEN], 16) 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃鱼的猫丿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值