142 lines
5.0 KiB
Python
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 |