From 7bbe0a08efe38acc321af1cd5632a02a02999ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=20=E6=B3=BD=E9=9A=86?= Date: Thu, 29 Aug 2024 16:53:28 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=84=9A=E6=9C=AC=E7=BB=93?= =?UTF-8?q?=E6=9E=84,=20=E6=B8=85=E7=90=86=E5=86=97=E4=BD=99=E4=BB=A3?= =?UTF-8?q?=E7=A0=81;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/dev_EnergyRouter.py | 2 +- source/dev_LaminaAdapter.py | 26 +- source/dev_LaminaController.py | 73 +++- source/func_frame.py | 2 +- source/{utl_upgrade.py => func_upgrade.py} | 483 ++++++++++----------- source/{utl.py => tools/ByteConv.py} | 7 +- source/tools/IntelHex.py | 142 ++++++ source/tools/__init__.py | 0 8 files changed, 468 insertions(+), 267 deletions(-) rename source/{utl_upgrade.py => func_upgrade.py} (59%) rename source/{utl.py => tools/ByteConv.py} (95%) create mode 100644 source/tools/IntelHex.py create mode 100644 source/tools/__init__.py diff --git a/source/dev_EnergyRouter.py b/source/dev_EnergyRouter.py index ae7bfcc..8d94301 100644 --- a/source/dev_EnergyRouter.py +++ b/source/dev_EnergyRouter.py @@ -2,7 +2,7 @@ import time import socket import random from pathlib import Path -from utl import trans_list_to_str +from tools.ByteConv import trans_list_to_str from func_frame import make_frame_modbus, check_frame_modbus modbus_map = { diff --git a/source/dev_LaminaAdapter.py b/source/dev_LaminaAdapter.py index 5572876..a93400f 100644 --- a/source/dev_LaminaAdapter.py +++ b/source/dev_LaminaAdapter.py @@ -1,7 +1,7 @@ import time from pathlib import Path from serial import Serial -from utl import trans_list_to_str +from tools.ByteConv import trans_list_to_str from func_frame import make_frame_dlt645, check_frame_dlt645 modbus_map = { @@ -92,7 +92,7 @@ modbus_map = { 0xA6: ["抖动频率下限", 2], 0xA7: ["电池电压判断限值", 2], 0xA8: ["MPPT追踪模式", 1], - 0xA9: ["ADC参考电压", 1], + 0xA9: ["ADC参考电压", 2], 0xAA: ["保留", 1], 0xAB: ["保留", 1], 0xAC: ["保留", 1], @@ -346,11 +346,11 @@ if __name__=='__main__': "Log": {'com_name': None, # 'addr_645': [0x01, 0x00, 0x00, 0x00, 0x00, 0x40], }, - "Debug": {'com_name': 'COM8', 'baudrate': 115200, 'parity': 'N', 'bytesize': 8, 'stopbits': 1, + "Debug": {'com_name': 'COM11', 'baudrate': 115200, 'parity': 'N', 'bytesize': 8, 'stopbits': 1, # 'addr_645': [0x01, 0x02, 0x03, 0x04, 0x05, 0x06], 'frame_print': True, 'time_out': 0.1, 'retry': 1, 'retry_sub': 10}, - "HPLC": {'com_name': 'COM4', 'baudrate': 9600, 'parity': 'E', 'bytesize': 8, 'stopbits': 1, + "HPLC": {'com_name': 'COM10', 'baudrate': 9600, 'parity': 'E', 'bytesize': 8, 'stopbits': 1, # 'addr_645': [0x01, 0x02, 0x03, 0x04, 0x05, 0x06], 'frame_print': True, 'time_out': 0.5, 'retry': 3, 'retry_sub': 10}, @@ -361,6 +361,22 @@ if __name__=='__main__': dev_lamina.frame_read(0x0100, 0x20) + if 0: + dev_lamina.frame_read(0xA9, 1) # 读ADC参考电压 + dev_lamina.frame_write_one(0xA9, 2000) # 写ADC参考电压:2.0V + dev_lamina.frame_write_one(0xA9, 3300) # 写ADC参考电压:3.3V + dev_lamina.frame_read(0x13, 1) # 读输入电压 + dev_lamina.frame_read(0x16, 1) # 读输出电压 + dev_lamina.frame_read(0x97, 4) # 读校准参数: Vin_a, Vin_b, Vout_a, Vout_b + dev_lamina.frame_write_one(0x97, 1000) # 写校准参数Vin_a: 1.000 + dev_lamina.frame_write_one(0x97, 1500) # 写校准参数Vin_a: 1.500 + dev_lamina.frame_write_one(0x98, 100) # 写校准参数Vin_b: 1.00 + dev_lamina.frame_write_one(0x98, 150) # 写校准参数Vin_b: 1.50 + dev_lamina.frame_write_one(0x99, 1000) # 写校准参数Vout_a: 1.000 + dev_lamina.frame_write_one(0x99, 1500) # 写校准参数Vout_a: 1.500 + dev_lamina.frame_write_one(0x9A, 1000) # 写校准参数Vout_a: 1.00 + dev_lamina.frame_write_one(0x9A, 1500) # 写校准参数Vout_a: 1.50 + if 0: dev_lamina.frame_write_str(0x82, [0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA]) dev_lamina.frame_write_str(0x82, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) @@ -434,7 +450,7 @@ if __name__=='__main__': dev_lamina.frame_read(0x0170, 0x30) if not hasattr(__builtins__,"__IPYTHON__"): - path_bin = Path(r"D:\WorkingProject\LightStackAdapter\software\lamina_adapter\tools\upgrade\SLCP001_240604_1200_V1.01a.bin") + path_bin = Path(r"D:\WorkSpace\UserTool\SelfTool\FrameParser\test\p460\result\lamina_adapter_t1.dat") # path_bin = Path(r"D:\WorkingProject\LightStackAdapter\software\lamina_adapter\tools\upgrade\SLCP001_240520_0000_T1.11.bin") # 生产镜像版本 # path_bin = Path(r"D:\WorkingProject\LightStackAdapter\software\lamina_adapter\tools\upgrade\SLCP001_240525_1800_V1.12.bin") diff --git a/source/dev_LaminaController.py b/source/dev_LaminaController.py index 3cb4b9f..174f976 100644 --- a/source/dev_LaminaController.py +++ b/source/dev_LaminaController.py @@ -1,8 +1,10 @@ import time from pathlib import Path from serial import Serial -from utl import trans_list_to_str +from tools.ByteConv import trans_list_to_str +from tools.IntelHex import file_Bin_to_IntelHex from func_frame import make_frame_modbus, check_frame_modbus +from func_upgrade import GenerateImage_DLSP001_p280039, GeneratePackage_DLSP001_p280039 modbus_map = { # 1 - Hex @@ -329,15 +331,73 @@ def test_communication(time_out=2): print(f"Success Rate: {log_success / (log_success + log_failed) * 100}%") dev_lamina.flag_print = saveconfig_print + +def make_Image(): + """ 叠光控制器DSP镜像与升级包生成流程 """ + root = Path(r"test\p280039") + result = Path(r"test\p280039\result") + + # 正常启动镜像 + hex_boot = root / r"DLSP001_240828_0900_BL1.01.hex" + hex_main = root / r"DLSP001_240828_0900_V1.01.hex" + hex_back = root / r"DLSP001_240828_0900_B1.01.hex" + hex_update = root / r"DLSP001_240828_0900_T1.01.hex" + + file_image = result / f'{hex_main.stem}_ROM.hex' + file_main_header = result / 'header_main.bin' + file_back_header = result / 'header_back.bin' + file_package = result / f'{hex_update.stem}.dat' + file_update_bin = result / f'{hex_update.stem}.bin' + file_package_buffer = result / f'{hex_update.stem}.datbuffer' + + data_bins = GenerateImage_DLSP001_p280039(hex_boot, hex_main, hex_back) + data_package, data_update_bin = GeneratePackage_DLSP001_p280039(hex_update) + + data_buffer = bytearray(2 * len(data_package)) + for i in range(len(data_package)): + data_buffer[2*i] = data_package[i] + + file_package.write_bytes(data_package) + file_main_header.write_bytes(data_bins[1]) + file_back_header.write_bytes(data_bins[2]) + file_update_bin.write_bytes(data_update_bin) + file_package_buffer.write_bytes(data_buffer) + + data_hex = file_Bin_to_IntelHex(data_bins[0], 0x80000, memory_width=2) + file_image.write_text(data_hex) + + # 异常镜像-主分区md5错误 + file_image1 = result / f'{file_image.stem}_b1.hex' + data_image = data_bins[0].copy() + data_image[2 * 0x006018: 2 * 0x00601A] = [0x00, 0x01, 0x00, 0x02] + data_hex = file_Bin_to_IntelHex(data_image, 0x80000, memory_width=2) + file_image1.write_text(data_hex) + + # 异常镜像-备份分区md5错误 + file_image2 = result / f'{file_image.stem}_b2.hex' + data_image = data_bins[0].copy() + data_image[2 * 0x007018: 2 * 0x00701A] = [0x00, 0x01, 0x00, 0x02] + data_hex = file_Bin_to_IntelHex(data_image, 0x80000, memory_width=2) + file_image2.write_text(data_hex) + + # 异常镜像-双分区md5错误 + file_image3 = result / f'{file_image.stem}_b3.hex' + data_image = data_bins[0].copy() + data_image[2 * 0x006018: 2 * 0x00601A] = [0x00, 0x01, 0x00, 0x02] + data_image[2 * 0x007018: 2 * 0x00701A] = [0x00, 0x01, 0x00, 0x02] + data_hex = file_Bin_to_IntelHex(data_image, 0x80000, memory_width=2) + file_image3.write_text(data_hex) + + if __name__=='__main__': mode_config = { "Log": {'com_name': None, # 'addr_645': [0x01, 0x00, 0x00, 0x00, 0x00, 0x40], }, - "Debug": {'com_name': 'COM8', 'baudrate': 250000, 'parity': 'E', 'bytesize': 8, 'stopbits': 1, - 'addr_645': [0x01, 0x02, 0x03, 0x04, 0x05, 0x06], + "Debug": {'com_name': 'COM8', 'baudrate': 115200, 'parity': 'N', 'bytesize': 8, 'stopbits': 1, + # 'addr_645': [0x01, 0x02, 0x03, 0x04, 0x05, 0x06], 'frame_print': True, - 'time_out': 0.2, 'retry': 1, 'retry_sub': 10}, + 'time_out': 0.2, 'retry': 3, 'retry_sub': 10}, } @@ -418,7 +478,10 @@ if __name__=='__main__': dev_lamina.frame_read(0x0170, 0x30) if not hasattr(__builtins__,"__IPYTHON__"): - path_bin = Path(r"D:\WorkingProject\LightStackAdapter\software\lamina_adapter\tools\upgrade\SLCP001_240625_2030_V1.04.bin") + + make_Image() + + path_bin = Path(r"D:\WorkSpace\UserTool\SelfTool\FrameParser\test\p280039\result\DLSP001_240828_0900_T1.01.dat") # path_bin = Path(r"D:\WorkingProject\LightStackAdapter\software\lamina_adapter\tools\upgrade\SLCP001_240520_0000_T1.11.bin") # 生产镜像版本 # path_bin = Path(r"D:\WorkingProject\LightStackAdapter\software\lamina_adapter\tools\upgrade\SLCP001_240525_1800_V1.12.bin") diff --git a/source/func_frame.py b/source/func_frame.py index 13aa2d5..7a04932 100644 --- a/source/func_frame.py +++ b/source/func_frame.py @@ -1,6 +1,6 @@ import struct from crc import Calculator, Crc16 -from utl import display_hex, trans_list_to_str +from tools.ByteConv import trans_list_to_str, display_hex modbus_map = { # 1 - Hex diff --git a/source/utl_upgrade.py b/source/func_upgrade.py similarity index 59% rename from source/utl_upgrade.py rename to source/func_upgrade.py index 01bd98e..fe110be 100644 --- a/source/utl_upgrade.py +++ b/source/func_upgrade.py @@ -4,7 +4,9 @@ from pathlib import Path from datetime import datetime from crc import Calculator, Crc16 -from utl import conv_int_to_array, trans_list_to_str +from tools.ByteConv import trans_list_to_str, conv_int_to_array +from tools.IntelHex import file_IntelHex_to_Bin, file_Bin_to_IntelHex + Header_Tag = { 'file_type': [0x00, 2], # 0 - 文件类型; 2byte @@ -22,68 +24,6 @@ Header_Tag = { 'hex_name': [0xFF, -1, 80], # 255 - Hex文件名; less than 80byte } -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) * 16 - offset_begin = 16 - elif file_data[8] == '4': - base_address = int(file_data[9: 13], 16) * 2**16 - 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_encryption(buffer): """ 文件加密算法 """ @@ -104,6 +44,7 @@ def file_encryption(buffer): def build_header(config: dict, len_max=512): """ 基于配置参数, 生成文件信息头; + V1版本, 依据字典生成tag标签组; """ # 定义文件头 m_file_header = bytearray(len_max) @@ -112,7 +53,10 @@ def build_header(config: dict, len_max=512): tag_num = 0 for tag, value in config.items(): if tag in Header_Tag.keys(): - if Header_Tag[tag][1] == -1: + if tag == 'hex_name' and len_max < 256: + """ 当文件头长度不足时, 跳过文件名标签 """ + continue + elif Header_Tag[tag][1] == -1: tag_len = min(len(value), Header_Tag[tag][2]) else: tag_len = Header_Tag[tag][1] @@ -132,9 +76,11 @@ def build_header(config: dict, len_max=512): else: return m_file_header + def build_header_lite(config: dict): """ 基于配置参数, 生成文件信息头; + V2版本, 仅提供必要信息; """ # 定义文件头 m_file_header = bytearray(64) @@ -144,9 +90,11 @@ def build_header_lite(config: dict): return m_file_header + def build_header_new(config: dict): """ 基于配置参数, 生成新版文件信息头; + V3版本, 依据新版格式填充数据; """ # 定义文件头 m_file_header = [0xFF] * 184 @@ -207,7 +155,7 @@ def build_header_new(config: dict): m_file_header[158: 160] = config['upgrade_type'] m_file_header[160: 182] = [0x00] * 22 else: - m_file_header[158: 182] = [0x00] * 24 + m_file_header[158: 182] = [0x00] * 24 m_file_header = bytearray(m_file_header) @@ -217,89 +165,25 @@ def build_header_new(config: dict): return m_file_header -def make_datafile(file_path: str, config: dict, header_len=512): - """ 升级文件生成函数; 完整文件头, TI-hex转换 """ - file_path = Path(file_path) - file_data = file_path.read_text() - data_bin = file_IntelHex_to_Bin(file_data, config['flash_addr'], len_max=config['flash_size'] * 2) - md5_ctx = hashlib.md5() - md5_ctx.update(data_bin) - config['file_length'] = conv_int_to_array(len(data_bin)) - config["md5"] = list(md5_ctx.digest()) - if header_len > 256: - config['hex_name'] = list(file_path.name.encode())[:80] - data_header = build_header(config, header_len) - if data_header is None: - raise ("header tag oversize! ") - data_encrypt = file_encryption(data_bin) - return data_header, data_bin, data_encrypt - -def make_datafile1(file_path: str, config: dict, header_len=512): - """ 升级文件生成函数; 简易文件头, TI-Hex转换 """ - file_path = Path(file_path) - file_data = file_path.read_text() - data_bin = file_IntelHex_to_Bin(file_data, config['flash_addr'], len_max=config['flash_size'] * 2) - md5_ctx = hashlib.md5() - md5_ctx.update(data_bin) - - config['file_length'] = conv_int_to_array(len(data_bin), True) - config["md5"] = list(md5_ctx.digest()) - if header_len > 256: - config['hex_name'] = list(file_path.name.encode())[:80] - - data_header = build_header_lite(config) - data_encrypt = file_encryption(data_bin) - return data_header, data_bin, data_encrypt - -def make_datafile2(file_path: str, config: dict, header_len=512): - """ 升级文件生成函数; 完整文件头 """ - file_path = Path(file_path) - data_bin = file_path.read_bytes() - md5_ctx = hashlib.md5() - md5_ctx.update(data_bin) - config['file_length'] = conv_int_to_array(len(data_bin)) - config["md5"] = list(md5_ctx.digest()) - if header_len > 256: - config['hex_name'] = list(file_path.name.encode())[:80] - - data_header = build_header(config, header_len) - if data_header is None: - raise Exception("Header tag oversize. ") - data_encrypt = file_encryption(data_bin) - return data_header, data_bin, data_encrypt - -def make_datafile3(file_path: str, config: dict, header_len=184): - """ 升级文件生成函数; 完整文件头 """ - file_path = Path(file_path) - file_data = file_path.read_text() - data_bin = file_IntelHex_to_Bin(file_data) - md5_ctx = hashlib.md5() - md5_ctx.update(data_bin) - config['file_length'] = conv_int_to_array(len(data_bin)) - config["md5"] = list(md5_ctx.digest()) - config['hex_name'] = list(file_path.name.encode())[:64] - config['hex_name'] += [0] * (64 - len(config['hex_name'])) - - data_header = build_header_new(config) - if data_header is None: - raise Exception("Header tag oversize. ") - data_encrypt = file_encryption(data_bin) - return data_header, data_bin, data_encrypt - - -def test1(fp): +def test1(fp: Path): """ bin文件生成测试 """ file1 = Path(fp) path1 = file1.parent / (file1.stem + ".bin") data1 = file1.read_text() data2 = file_IntelHex_to_Bin(data1, 0x3F0100) path1.write_bytes(data2) - pass + + # 测试Bin到IntelHex + bin = Path(fp).read_bytes() + result = file_Bin_to_IntelHex(bin, 0x80000, memory_width=2) + (fp.parent / (fp.stem + ".hex")).write_text(result) + def test2(): - """ md5校验, 加密测试 """ - bin_offcial = Path(r"D:\WorkingProject\LightStackAdapter\software\lamina_adapter\tools\uart_tool\江苏发货版本\SLCP001_240517_1800_V1.11.bin") + """ 校验, 加密测试 """ + # Header - Crc16 + bin_offcial = Path(r"D:\WorkSpace\UserTool\SelfTool\FrameParser\test\p460\result\lamina_adapter_t1.dat") data_offcial = bin_offcial.read_bytes() byte_data = data_offcial[:182] crc = data_offcial[182:184] @@ -310,17 +194,32 @@ def test2(): code_crc16 = calculator.checksum(bytearray(byte_data)) print(f"Result = {hex(code_crc16)}, Offcial Result = {crc}") + # File - md5 data_bin = '123456 123456 '.encode() md5_ctx = hashlib.md5() md5_ctx.update(data_bin) hash = md5_ctx.hexdigest() + # File - encrypt buffer1 = data_bin[:] buffer1_en = file_encryption(buffer1) buffer2 = buffer1_en[:6] + buffer1[6:] - buffer2_en = file_encryption(buffer2) + buffer2_de = file_encryption(buffer2) pass -def test3(path_bin): + +def task5(): + """ 文件缓冲区对比测试 """ + file_dat = Path(r"test\p280039\result\lamina_controller_dsp_t1.dat") + file_dat_buffer = Path(r"test\p280039\result\lamina_controller_dsp_buffer.bin") + file_dat_buffer.exists(), file_dat.exists() + data_dat = file_dat.read_bytes() + data_dat_buffer = file_dat_buffer.read_bytes() + for i in range(len(data_dat)): + if data_dat[i] != data_dat_buffer[2*i]: + print(f"Diff in {hex(i)}, Data: {data_dat[i]}!={data_dat_buffer[2*i]}") + + +def GeneratePackage_Demo_Xilinx(path_bin: Path): """ 完整升级包生成测试 """ config = { 'file_type': [0x10, 0x01], # Xilinx-Demo 自机升级文件 @@ -342,19 +241,31 @@ def test3(path_bin): # 'flash_size': 0x005FC0, # 程序空间大小 } - header, data_b, _ = make_datafile2(path_bin, config, header_len=128) - header_512, data_b_512, _ = make_datafile2(path_bin, config, header_len=512) + data_bin = path_bin.read_bytes() + md5_ctx = hashlib.md5() + md5_ctx.update(data_bin) + config["md5"] = list(md5_ctx.digest()) + config['file_length'] = conv_int_to_array(len(data_bin)) + config['hex_name'] = list(path_bin.name.encode())[:80] + + if (header:= build_header(config, 128)) is None: + raise Exception("Header tag oversize. ") + if (header_512:= build_header(config, 512)) is None: + raise Exception("Header tag oversize. ") + + data_encrypt = file_encryption(data_bin) print("Upgrade file generated successfully.") - print(f"\t header_length={len(header)}, bin_length={len(data_b)}[{hex(len(data_b))}]") + print(f"\t header_length={len(header)}, bin_length={len(data_bin)}[{hex(len(data_bin))}]") print(f"\t file md5: {trans_list_to_str(config['md5'])}") file1 = path_bin.parent / (path_bin.stem + '.dat') - file1.write_bytes(header + data_b) + file1.write_bytes(header + data_bin) file2 = path_bin.parent / (path_bin.stem + '_h512.dat') - file2.write_bytes(header_512 + data_b) + file2.write_bytes(header_512 + data_bin) -def test4(path_boot, path_main, path_back): - """ 叠光适配器新版升级方案测试 """ + +def GenerateImage_SLCP001_p4a0(path_boot: Path, path_main: Path, path_back: Path): + """ 叠光适配器-4A0平台版本 镜像生成 """ config = { 'prod_type': [0x45, 0x00], # 产品类型 'method_compress': False, # 文件压缩 @@ -362,81 +273,108 @@ def test4(path_boot, path_main, path_back): 'prog_type': 'app', # 程序类型 'area_code': [0x00, 0x00], # 地区 } - file_path = Path(path_boot) - file_data = file_path.read_text() - boot_bin = file_IntelHex_to_Bin(file_data, len_max=0x010000) - main_header, main_data_b, main_data_e = make_datafile3(path_main, config) - back_header, back_data_b, back_data_e = make_datafile3(path_back, config) + bin_boot = file_IntelHex_to_Bin(path_boot.read_text(), len_max=0x010000) + bin_main = file_IntelHex_to_Bin(path_main.read_text(), len_max=0x0CC000) + bin_back = file_IntelHex_to_Bin(path_back.read_text(), len_max=0x040000) + encrypt_main = file_encryption(bin_main) + encrypt_back = file_encryption(bin_back) + + md5_ctx = hashlib.md5() + md5_ctx.update(bin_main) + config["md5"] = list(md5_ctx.digest()) + config['file_length'] = conv_int_to_array(len(bin_main)) + config['hex_name'] = list(path_main.name.encode())[:64] + config['hex_name'] += [0] * (64 - len(config['hex_name'])) + if (main_header:=build_header_new(config)) is None: + raise Exception("Header tag oversize. ") + + md5_ctx = hashlib.md5() + md5_ctx.update(bin_back) + config["md5"] = list(md5_ctx.digest()) + config['file_length'] = conv_int_to_array(len(bin_back)) + config['hex_name'] = list(path_back.name.encode())[:64] + config['hex_name'] += [0] * (64 - len(config['hex_name'])) + if (back_header:=build_header_new(config)) is None: + raise Exception("Header tag oversize. ") print("Merge Image generated successfully.") print(f"Main File:") - print(f"\t header_length={len(main_header)}, bin_length={len(main_data_b)}[{hex(len(main_data_b))}]") + print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") print(f"Back File:") - print(f"\t header_length={len(back_header)}, bin_length={len(back_data_b)}[{hex(len(back_data_b))}]") + print(f"\t header_length={len(back_header)}, bin_length={len(bin_back)}[{hex(len(bin_back))}]") # 组装镜像 Image = [0xFF] * 0x100000 offset_image = 0 - Image[offset_image: offset_image + len(boot_bin)] = boot_bin + Image[offset_image: offset_image + len(bin_boot)] = bin_boot offset_image = 0x010000 - Image[offset_image: offset_image + len(main_data_b)] = main_data_b + Image[offset_image: offset_image + len(bin_main)] = bin_main offset_image = 0x0BC000 - Image[offset_image: offset_image + len(back_data_b)] = back_data_b + Image[offset_image: offset_image + len(bin_back)] = bin_back offset_image = 0x0FC000 Image[offset_image: offset_image + len(main_header)] = main_header offset_image = 0x0FE000 Image[offset_image: offset_image + len(back_header)] = back_header - return bytearray(Image), main_header, main_data_b, main_data_e, back_header, back_data_b, back_data_e + return bytearray(Image), main_header, back_header -def task5(): - """ 文件缓冲区对比测试 """ - file_dat = Path(r"test\p280039\result\lamina_controller_dsp_t1.dat") - file_dat_buffer = Path(r"test\p280039\result\lamina_controller_dsp_buffer.bin") - file_dat_buffer.exists(), file_dat.exists() - data_dat = file_dat.read_bytes() - data_dat_buffer = file_dat_buffer.read_bytes() - for i in range(len(data_dat)): - if data_dat[i] != data_dat_buffer[2*i]: - print(f"Diff in {hex(i)}, Data: {data_dat[i]}!={data_dat_buffer[2*i]}") -def GenerateImage_SLCP001_p460(path_boot, path_main, path_back): +def GenerateImage_SLCP001_p460(path_boot: Path, path_main: Path, path_back: Path): """ 叠光适配器-460平台版本 镜像生成 """ config = { 'prod_type': [0x45, 0x00], # 产品类型 'method_compress': False, # 文件压缩 - 'prog_id': list(b"SLCP001"), # 程序识别号 + 'prog_id': list(b"SLCP101"), # 程序识别号 'prog_type': 'app', # 程序类型 'area_code': [0x00, 0x00], # 地区 } - file_path = Path(path_boot) - file_data = file_path.read_text() - boot_bin = file_IntelHex_to_Bin(file_data, len_max=0x00C000) - main_header, main_data_b, main_data_e = make_datafile3(path_main, config) - back_header, back_data_b, back_data_e = make_datafile3(path_back, config) + bin_boot = file_IntelHex_to_Bin(path_boot.read_text(), len_max=0x00C000) + bin_main = file_IntelHex_to_Bin(path_main.read_text(), len_max=0x024000) + bin_back = file_IntelHex_to_Bin(path_back.read_text(), len_max=0x024000) + encrypt_main = file_encryption(bin_main) + encrypt_back = file_encryption(bin_back) + + md5_ctx = hashlib.md5() + md5_ctx.update(bin_main) + config["md5"] = list(md5_ctx.digest()) + config['file_length'] = conv_int_to_array(len(bin_main)) + config['hex_name'] = list(path_main.name.encode())[:64] + config['hex_name'] += [0] * (64 - len(config['hex_name'])) + if (main_header:=build_header_new(config)) is None: + raise Exception("Header tag oversize. ") + + md5_ctx = hashlib.md5() + md5_ctx.update(bin_back) + config["md5"] = list(md5_ctx.digest()) + config['file_length'] = conv_int_to_array(len(bin_back)) + config['hex_name'] = list(path_back.name.encode())[:64] + config['hex_name'] += [0] * (64 - len(config['hex_name'])) + if (back_header:=build_header_new(config)) is None: + raise Exception("Header tag oversize. ") print("Merge Image generated successfully.") print(f"Main File:") - print(f"\t header_length={len(main_header)}, bin_length={len(main_data_b)}[{hex(len(main_data_b))}]") + print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") print(f"Back File:") - print(f"\t header_length={len(back_header)}, bin_length={len(back_data_b)}[{hex(len(back_data_b))}]") + print(f"\t header_length={len(back_header)}, bin_length={len(bin_back)}[{hex(len(bin_back))}]") # 组装镜像 Image = [0xFF] * 0x058000 offset_image = 0 - Image[offset_image: offset_image + len(boot_bin)] = boot_bin + Image[offset_image: offset_image + len(bin_boot)] = bin_boot offset_image = 0x00C000 - Image[offset_image: offset_image + len(main_data_b)] = main_data_b + Image[offset_image: offset_image + len(bin_main)] = bin_main offset_image = 0x030000 - Image[offset_image: offset_image + len(back_data_b)] = back_data_b + Image[offset_image: offset_image + len(bin_back)] = bin_back offset_image = 0x054000 Image[offset_image: offset_image + len(main_header)] = main_header offset_image = 0x056000 Image[offset_image: offset_image + len(back_header)] = back_header - return bytearray(Image), main_header, main_data_b, main_data_e, back_header, back_data_b, back_data_e + return bytearray(Image), main_header, back_header -def GeneratePackage_SLCP001_p460(path_hex): + +def GeneratePackage_SLCP001_p460(path_hex: Path): """ 叠光适配器-460平台版本 生成升级包 """ config = { 'prod_type': [0x45, 0x00], # 产品类型 @@ -445,61 +383,136 @@ def GeneratePackage_SLCP001_p460(path_hex): 'prog_type': 'app', # 程序类型 'area_code': [0x00, 0x00], # 地区 } - main_header, main_data_b, main_data_e = make_datafile3(path_hex, config) + bin_main = file_IntelHex_to_Bin(path_hex.read_text(), len_max=0x024000) + encrypt_main = file_encryption(bin_main) - print("Merge Image generated successfully.") + md5_ctx = hashlib.md5() + md5_ctx.update(bin_main) + config["md5"] = list(md5_ctx.digest()) + config['file_length'] = conv_int_to_array(len(bin_main)) + config['hex_name'] = list(path_hex.name.encode())[:64] + config['hex_name'] += [0] * (64 - len(config['hex_name'])) + if (main_header:=build_header_new(config)) is None: + raise Exception("Header tag oversize. ") + + print("Package generated successfully.") + print(f"File name: {path_hex.name}") print(f"File Info:") - print(f"\t header_length={len(main_header)}, bin_length={len(main_data_b)}[{hex(len(main_data_b))}]") + print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") # 组装镜像 - Image = [0xFF] * (len(main_header) + len(main_data_e)) + Image = [0xFF] * (len(main_header) + len(encrypt_main)) offset_image = 0 Image[offset_image: offset_image + len(main_header)] = main_header offset_image += len(main_header) - Image[offset_image: offset_image + len(main_data_e)] = main_data_e + Image[offset_image: offset_image + len(encrypt_main)] = encrypt_main - return bytearray(Image), main_data_b + return bytearray(Image), bin_main -def GeneratePackage_XXX001_p280039(path_hex): - """ 叠光控制器DSP-280039平台版本 生成升级包 """ + +def GenerateImage_DLSP001_p280039(path_boot: Path, path_main: Path, path_back: Path): + """ 叠光适配器-460平台版本 镜像生成 """ config = { 'prod_type': [0x46, 0x00], # 产品类型 'method_compress': False, # 文件压缩 - 'prog_id': list(b"SLCP001"), # 程序识别号 + 'prog_id': list(b"DLSP001"), # 程序识别号 'prog_type': 'app', # 程序类型 'area_code': [0x00, 0x00], # 地区 'upgrade_type': [0x00, 0x00], # 升级方式(0-片外缓冲, 1-片内缓冲, 2-升级备份) } - path_hex = Path(path_hex) - file_data = path_hex.read_text() - data_bin = file_IntelHex_to_Bin(file_data, conv_end = False) + bin_boot = file_IntelHex_to_Bin(path_boot.read_text(), len_max=2 * 0x004000, conv_end=False) + bin_main = file_IntelHex_to_Bin(path_main.read_text(), len_max=2 * 0x014000, conv_end=False) + bin_back = file_IntelHex_to_Bin(path_back.read_text(), len_max=2 * 0x014000, conv_end=False) + md5_ctx = hashlib.md5() - md5_ctx.update(data_bin) - config['file_length'] = conv_int_to_array(len(data_bin)) + md5_ctx.update(bin_main) config["md5"] = list(md5_ctx.digest()) - config['hex_name'] = list(path_hex.name.encode())[:64] + config['upgrade_type'] = [0x00, 0x00] # 主程序-片外缓冲 + config['file_length'] = conv_int_to_array(len(bin_main)) + config['hex_name'] = list(path_main.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) - - data_header = build_header_new(config) - if data_header is None: + if (main_header:=build_header_new(config)) is None: raise Exception("Header tag oversize. ") - data_encrypt = file_encryption(data_bin) - main_header, main_data_b, main_data_e = data_header, data_bin, data_encrypt + md5_ctx = hashlib.md5() + md5_ctx.update(bin_back) + config["md5"] = list(md5_ctx.digest()) + config['upgrade_type'] = [0x02, 0x00] # 备份程序 + config['file_length'] = conv_int_to_array(len(bin_back)) + config['hex_name'] = list(path_back.name.encode())[:64] + config['hex_name'] += [0] * (64 - len(config['hex_name'])) + if (back_header:=build_header_new(config)) is None: + raise Exception("Header tag oversize. ") + + main_header_buffer = bytearray() + for byte_org in main_header: + main_header_buffer.extend(bytearray([0x00, byte_org])) + back_header_buffer = bytearray() + for byte_org in back_header: + back_header_buffer.extend(bytearray([0x00, byte_org])) + main_encrypt = file_encryption(bin_main) + back_encrypt = file_encryption(bin_back) print("Merge Image generated successfully.") - print(f"File Info:") - print(f"\t header_length={len(main_header)}, bin_length={len(main_data_b)}[{hex(len(main_data_b))}]") + print(f"Main File:") + print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") + print(f"Back File:") + print(f"\t header_length={len(back_header)}, bin_length={len(bin_back)}[{hex(len(bin_back))}]") # 组装镜像 - Image = [0xFF] * (len(main_header) + len(main_data_e)) + Image = [0xFF] * 2 * 0x030000 + offset_image = 0 + Image[offset_image: offset_image + len(bin_boot)] = bin_boot + offset_image = 2 * 0x006000 + Image[offset_image: offset_image + len(main_header_buffer)] = main_header_buffer + offset_image = 2 * 0x007000 + Image[offset_image: offset_image + len(back_header_buffer)] = back_header_buffer + offset_image = 2 * 0x008000 + Image[offset_image: offset_image + len(bin_main)] = bin_main + offset_image = 2 * 0x01C000 + Image[offset_image: offset_image + len(bin_back)] = bin_back + + return bytearray(Image), main_header, back_header + + +def GeneratePackage_DLSP001_p280039(path_hex: Path): + """ 叠光控制器DSP-280039平台版本 生成升级包 """ + config = { + 'prod_type': [0x46, 0x00], # 产品类型 + 'method_compress': False, # 文件压缩 + 'prog_id': list(b"DLSP001"), # 程序识别号 + 'prog_type': 'app', # 程序类型 + 'area_code': [0x00, 0x00], # 地区 + 'upgrade_type': [0x00, 0x00], # 升级方式(0-片外缓冲, 1-片内缓冲, 2-升级备份) + } + + bin_main = file_IntelHex_to_Bin(path_hex.read_text(), len_max=2 * 0x014000, conv_end=False) + encrypt_main = file_encryption(bin_main) + + md5_ctx = hashlib.md5() + md5_ctx.update(bin_main) + config["md5"] = list(md5_ctx.digest()) + config['file_length'] = conv_int_to_array(len(bin_main)) + config['hex_name'] = list(path_hex.name.encode())[:64] + config['hex_name'] += [0] * (64 - len(config['hex_name'])) + if (main_header:=build_header_new(config)) is None: + raise Exception("Header tag oversize. ") + + print("Package generated successfully.") + print(f"File name: {path_hex.name}") + print(f"File Info:") + print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") + + # 组装镜像 + Image = [0xFF] * (len(main_header) + len(encrypt_main)) offset_image = 0 Image[offset_image: offset_image + len(main_header)] = main_header offset_image += len(main_header) - Image[offset_image: offset_image + len(main_data_e)] = main_data_e + Image[offset_image: offset_image + len(encrypt_main)] = encrypt_main + + return bytearray(Image), bin_main - return bytearray(Image), main_data_b def Process1(): """ 镜像生成流程 """ @@ -509,15 +522,22 @@ def Process1(): hex_boot = root / r"bootloader.hex" hex_main = root / r"lamina_adapter.hex" hex_back = root / r"lamina_adapter_back.hex" + hex_update = root / r"lamina_adapter_t1.hex" file_image = result / f'{hex_main.stem[:-6]}_ROM.bin' file_main_header = result / 'SLCP001_header_main.bin' file_back_header = result / 'SLCP001_header_back.bin' + file_package = result / f'{hex_update.stem}.dat' + file_bin = result / f'{hex_update.stem}.bin' data_bins = GenerateImage_SLCP001_p460(hex_boot, hex_main, hex_back) + data_package, data_bins = GeneratePackage_SLCP001_p460(hex_update) + file_image.write_bytes(data_bins[0].copy()) file_main_header.write_bytes(data_bins[1].copy()) - file_back_header.write_bytes(data_bins[4].copy()) + file_back_header.write_bytes(data_bins[2].copy()) + file_package.write_bytes(data_package) + file_bin.write_bytes(data_bins) # 异常镜像-主分区md5错误 file_image1 = result / f'{file_image.stem}_b1.bin' @@ -538,51 +558,10 @@ def Process1(): data_image[0x056018: 0x05601A] = [0x00, 0x01] file_image3.write_bytes(data_image) -def Process2(): - """ 升级包生成流程 """ - root = Path(r"test\p460") - result = Path(r"test\p460\result") - - hex_main = root / r"lamina_adapter_t1.hex" - file_package = result / f'{hex_main.stem}.dat' - file_bin = result / f'{hex_main.stem}.bin' - - data_package, data_bins = GeneratePackage_SLCP001_p460(hex_main) - file_package.write_bytes(data_package) - file_bin.write_bytes(data_bins) - -def Process3(): - """ 叠光控制器DSP升级包生成流程 """ - root = Path(r"test\p280039") - result = Path(r"test\p280039\result") - - hex_main = root / r"lamina_controller_dsp_t1.hex" - file_package = result / f'{hex_main.stem}.dat' - file_bin = result / f'{hex_main.stem}.bin' - file_package_buffer = result / f'{hex_main.stem}.datbuffer' - - data_package, data_bins = GeneratePackage_XXX001_p280039(hex_main) - file_package.write_bytes(data_package) - file_bin.write_bytes(data_bins) - - data_buff = bytearray(2 * len(data_package)) - for i in range(len(data_package)): - data_buff[2*i] = data_package[i] - file_package_buffer.write_bytes(data_buff) - if __name__ == "__main__": # path_bin = Path("F:\\Work\\FPGA\\Test\\Vivado\\test_update\\test_update.vitis\\upgrade_system\\Debug\\sd_card\\BOOT.BIN") - # test3(path_bin) + # GeneratePackage_Demo_Xilinx(path_bin) # test2() - - if 0: - bin_back = Path(r"D:\WorkingProject\LightStackAdapter\software\lamina_adapter\tools\upgrade\lamina_adapter_back.bin") - bin_main = Path(r"D:\WorkingProject\LightStackAdapter\software\lamina_adapter\tools\upgrade\lamina_adapter_main.bin") - main_header1 = bin_main.read_bytes()[:184] - main_data_e1 = bin_main.read_bytes()[184:] - back_header1 = bin_back.read_bytes()[:184] - back_data_e1 = bin_back.read_bytes()[184:] - - Process1() + pass diff --git a/source/utl.py b/source/tools/ByteConv.py similarity index 95% rename from source/utl.py rename to source/tools/ByteConv.py index cd2386c..e2c6293 100644 --- a/source/utl.py +++ b/source/tools/ByteConv.py @@ -1,14 +1,15 @@ - def trans_list_to_str(data: list) -> str: """ 标准串口字符串表示 """ func_trans = lambda x: ('00' + hex(x % 256)[2:])[-2:].upper() return " ".join(map(func_trans, data)) + def trans_str_to_list(data: str) -> list: """ 标准串口字符串转换列表 """ func_trans = lambda x: int(x, 16) return list(map(func_trans, data.strip().split(" "))) + def conv_int_to_array(num: int, big_end=False): """ 数值转字节数组 """ result = [0, 0, 0, 0] @@ -22,9 +23,9 @@ def conv_int_to_array(num: int, big_end=False): num //= 0x100 return result + def display_hex(data, len) -> str: """ Hex字符表示 """ data %= 2 ** (4 * len) result = "0" * len + hex(data)[2:] - return "0x" + result[-len:].upper() - + return "0x" + result[-len:].upper() \ No newline at end of file diff --git a/source/tools/IntelHex.py b/source/tools/IntelHex.py new file mode 100644 index 0000000..91f989a --- /dev/null +++ b/source/tools/IntelHex.py @@ -0,0 +1,142 @@ +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 \ No newline at end of file diff --git a/source/tools/__init__.py b/source/tools/__init__.py new file mode 100644 index 0000000..e69de29