Files
DebugTool/source/tools/IntelHex.py
2024-08-29 16:53:28 +08:00

142 lines
5.0 KiB
Python

def calculate_checksum(data):
""" 计算校验域 """
checksum = 0
for i in range(0, len(data), 2):
checksum += int(data[i: i+2], 16)
return (0x100 - checksum) & 0xFF
def file_IntelHex_to_Bin(file_data, base_address=0, len_max=1, **kwargs):
"""
将Intel Hex格式文件转换为Bin格式;
"""
if base_address == 0:
if file_data[8] == '2':
base_address = int(file_data[9: 13], 16) * 0x100
offset_begin = 16
elif file_data[8] == '4':
base_address = int(file_data[9: 13], 16) * 0x10000
offset_begin = 16
else:
base_address = 0
offset_begin = 0
base_address += int(file_data[offset_begin + 3: offset_begin + 7], 16)
base_address &= ~0x0FFF
len_space = len_max
result = bytearray(len_space).replace(b'\x00', b'\xff')
lines = file_data.split('\n')
offset = 0
max_address = 0
for line in lines:
if line[0] == ':':
checksum = sum([int(x, 16) * (15 * (~i & 0x01) + 1) for i, x in enumerate(line[1:])])
if (checksum & 0x00FF) != 0:
raise Exception('Hex file checksum error!')
if line[7:9] == '00':
len_line = int(line[1:3], 16)
address = offset + int(line[3:7], 16) - base_address
data = bytearray.fromhex(line[9:-2])
if 'conv_end' in kwargs.keys():
address *= 2
if kwargs['conv_end']:
for i in range(0, len_line, 2):
t = data[i]
data[i] = data[i+1]
data[i+1] = t
if (address + len_line) > max_address:
max_address = address + len_line
if max_address >= len_space:
if len_max == 1:
result += bytearray(max_address - len_space).replace(b'\x00', b'\xff')
len_space += max_address - len_space
else:
raise Exception("Bin file Oversize.")
result[address:address+len_line] = data
elif line[7:9] == '01':
break
elif line[7:9] == '02':
offset = int(line[9:-2], 16) * 16
elif line[7:9] == '03':
pass
elif line[7:9] == '04': # 拓展地址偏移
offset = int(line[9:-2], 16) * 2**16
elif line[7:9] == '05':
pass
return result[:max_address]
def file_Bin_to_IntelHex(file_data: bytearray, base_address=0, **kwargs):
"""
将Bin格式文件转换为Intel Hex格式;
"""
chunk_size = 32
rom_width = 8
memory_width = 8
if 'chunk_size' in kwargs.keys():
""" 数据分块大小 """
chunk_size = kwargs['chunk_size']
if 'memory_width' in kwargs.keys():
""" 地址数据位宽 """
memory_width = kwargs['memory_width'] * 8
if 'rom_width' in kwargs.keys():
""" rom数据位宽 """
rom_width = kwargs['rom_width'] * 8
def record_extern_address(address, record_type):
""" 添加地址记录 """
if record_type == 4:
record_data = (address & 0xFFFF0000) >> 16
elif record_type == 2:
record_data = (address & 0xFFFF0) >> 4
else:
raise Exception("Unknow record tye.")
hex_record = f':020000{record_type:02X}{record_data:04X}'
hex_record += f'{calculate_checksum(hex_record[1:]):02X}\n'
return hex_record
result = str()
# 添加开始记录
extern_address = 0
if base_address >= 2 ** 32:
""" 超过最大可表示范围, 抛出异常 """
raise Exception("base_address oversize")
elif base_address >= 2 ** 16:
result += record_extern_address(base_address, 4)
extern_address = base_address & 0xFFFF0000
elif base_address >= 2 ** 4:
result += record_extern_address(base_address, 2)
extern_address = base_address & 0xFFFF0
record_type = 0
binary_offset = 0
while binary_offset < len(file_data):
""" 循环分块处理数据 """
data_chunk = file_data[binary_offset: binary_offset + chunk_size]
record_len = len(data_chunk)
record_data = data_chunk
record_addr = (base_address - extern_address + (binary_offset // (memory_width // 8)))
if record_addr >= 0x10000:
result += record_extern_address((base_address + (binary_offset // (memory_width // 8))), 4)
extern_address = (base_address + (binary_offset // (memory_width // 8))) & 0xFFFF0000
continue
# 构造记录
hex_record = f':{record_len:02X}{record_addr:04X}{record_type:02X}'
hex_record += ''.join(f'{byte:02X}' for byte in record_data)
hex_record += f'{calculate_checksum(hex_record[1:]):02X}\n'
result += hex_record
binary_offset += chunk_size
# 添加结束记录
hex_record = f':00000001FF\n'
result += hex_record
return result