From 910259cdf58aa0037a0121376fdeeebed78ead80 Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Wed, 26 Jan 2022 20:43:38 +0200 Subject: [PATCH 01/21] Reworked most, first commit. --- ch55xtool/ch55xtool.py | 803 +++++++++++++++++++++-------------------- 1 file changed, 406 insertions(+), 397 deletions(-) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index 83b0710..8436b72 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -4,426 +4,435 @@ import sys import os import time -import array -import math import argparse +import random import usb.core import usb.util - # ======= Some C-like static constants ======= -DFU_ID_VENDOR = 0x4348 -DFU_ID_PRODUCT = 0x55e0 +DFU_ID_VENDOR = 0x4348 +DFU_ID_PRODUCT = 0x55e0 -EP_OUT_ADDR = 0x02 -EP_IN_ADDR = 0x82 +EP_OUT_ADDR = 0x02 +EP_IN_ADDR = 0x82 USB_MAX_TIMEOUT = 2000 -DETECT_CHIP_CMD_V2 = [ - 0xa1, - 0x12, - 0x00, - 0x52, - 0x11, - 0x4d, - 0x43, - 0x55, - 0x20, - 0x49, - 0x53, - 0x50, - 0x20, - 0x26, - 0x20, - 0x57, - 0x43, - 0x48, - 0x2e, - 0x43, - 0x4e] -END_FLASH_CMD_V2 = [0xa2, 0x01, 0x00, 0x00] -RESET_RUN_CMD_V2 = [0xa2, 0x01, 0x00, 0x01] -SEND_KEY_CMD_V20 = [0xa3, 0x30, 0x00] -SEND_KEY_CMD_V23 = [0xa3, 0x38, 0x00] + [0x00] * (0x38) -ERASE_CHIP_CMD_V2 = [0xa4, 0x01, 0x00, 0x08] -WRITE_CMD_V2 = [0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] -VERIFY_CMD_V2 = [0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] -READ_CFG_CMD_V2 = [0xa7, 0x02, 0x00, 0x1f, 0x00] - CH55X_IC_REF = {} CH55X_IC_REF[0x51] = { - 'device_name': 'CH551', - 'device_flash_size': 10240, - 'device_dataflash_size': 128, - 'chip_id': 0x51} + 'device_name': 'CH551', + 'device_flash_size': 10240, + 'device_dataflash_size': 128, + 'chip_id': 0x51} CH55X_IC_REF[0x52] = { - 'device_name': 'CH552', - 'device_flash_size': 16384, - 'device_dataflash_size': 128, - 'chip_id': 0x52} + 'device_name': 'CH552', + 'device_flash_size': 16384, + 'device_dataflash_size': 128, + 'chip_id': 0x52} CH55X_IC_REF[0x53] = { - 'device_name': 'CH553', - 'device_flash_size': 10240, - 'device_dataflash_size': 128, - 'chip_id': 0x53} + 'device_name': 'CH553', + 'device_flash_size': 10240, + 'device_dataflash_size': 128, + 'chip_id': 0x53} CH55X_IC_REF[0x54] = { - 'device_name': 'CH554', - 'device_flash_size': 14336, - 'device_dataflash_size': 128, - 'chip_id': 0x54} + 'device_name': 'CH554', + 'device_flash_size': 14336, + 'device_dataflash_size': 128, + 'chip_id': 0x54} CH55X_IC_REF[0x59] = { - 'device_name': 'CH559', - 'device_flash_size': 61440, - 'device_dataflash_size': 128, - 'chip_id': 0x59} + 'device_name': 'CH559', + 'device_flash_size': 61440, + 'device_dataflash_size': 128, + 'chip_id': 0x59} +CH55X_IC_REF[0x68] = { + 'device_name': 'CH568', + 'device_flash_size': (128+64)*1024, + 'device_dataflash_size': 32*1024, + 'chip_id': 0x68} # ============================================= +WCH_CMDS = { "Detect": b'\xA1', + "End": b'\xA2', + "SetKey": b'\xA3', + "FlashErase": b'\xA4', + "FlashWrite": b'\xA5', + "FlashVerify": b'\xA6', + "ReadConfig": b'\xA7', + "WriteConfig": b'\xA8', + "DataErase": b'\xA9', + "DataWrite": b'\xAA', + "DataRead": b'\xAB', + } + +END_FLASH_CMD_V2 = [0xa2, 0x01, 0x00] + [0x00] +RESET_RUN_CMD_V2 = [0xa2, 0x01, 0x00] + [0x01] + +# Meaning of those two values not yet clear :( +DETECT_PL_START = b'\x42\x10' +#DETECT_PL_START = b'\x52\x11' +DETECT_APP_ID_B = b'MCU ISP & WCH.CN' + +# Unknown bits work only all together like 0x07 !! +CFG_FLAG_UNKN1 = 0x01 +CFG_FLAG_UNKN2 = 0x02 +CFG_FLAG_UNKN3 = 0x04 +CFG_FLAG_UNKNs = CFG_FLAG_UNKN1 | CFG_FLAG_UNKN2 | CFG_FLAG_UNKN3 +# Those bits work individualy +CFG_FLAG_BOOTVER = 0x08 +CFG_FLAG_UID = 0x10 +# ============================================= -def __get_dfu_device(idVendor=DFU_ID_VENDOR, idProduct=DFU_ID_PRODUCT): - dev = usb.core.find(idVendor=idVendor, idProduct=idProduct) - if dev is None: - return (None, 'NO_DEV_FOUND') - try: - if dev.is_kernel_driver_active(0): - try: - dev.detach_kernel_driver(0) - except usb.core.USBError: - return (None, 'USB_ERROR_CANNOT_DETACH_KERNEL_DRIVER') - except BaseException: - pass # Windows dont need detach - - try: - dev.set_configuration() - except usb.core.USBError: - return (None, 'USB_ERROR_CANNOT_SET_CONFIG') - - try: - usb.util.claim_interface(dev, 0) - except usb.core.USBError: - return (None, 'USB_ERROR_CANNOT_CLAIM_INTERFACE') - - return (dev, '') - - -def __detect_ch55x_v2(dev): - dev.write(EP_OUT_ADDR, DETECT_CHIP_CMD_V2) - ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) - try: - return CH55X_IC_REF[ret[4]] - except KeyError: - return None - - -def __read_cfg_ch55x_v2(dev): - dev.write(EP_OUT_ADDR, READ_CFG_CMD_V2) - ret = dev.read(EP_IN_ADDR, 30, USB_MAX_TIMEOUT) - - ver_str = 'V%d.%d%d' % (ret[19], ret[20], ret[21]) - chk_sum = (ret[22] + ret[23] + ret[24] + ret[25]) % 256 - - return (ver_str, chk_sum) - - -def __write_key_ch55x_v20(dev, chk_sum): - SEND_KEY_CMD_V20 = SEND_KEY_CMD_V20 + [chk_sum] * 0x30 - - dev.write(EP_OUT_ADDR, SEND_KEY_CMD_V20) - ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) - if ret[3] == 0: - return True - else: - return None - - -def __write_key_ch55x_v23(dev): - dev.write(EP_OUT_ADDR, SEND_KEY_CMD_V23) - ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) - if ret[3] == 0: - return True - else: - return None - - -def __erase_chip_ch55x_v2(dev): - dev.write(EP_OUT_ADDR, ERASE_CHIP_CMD_V2) - ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) - if ret[3] == 0: - return True - else: - return None - - -def __write_flash_ch55x_v20(dev, chk_sum, chip_id, payload): - # Payload needs to be padded, 56 is a good number - payload = payload + [0] * \ - ((math.ceil(len(payload) / 56) * 56) - len(payload)) - file_length = len(payload) - - for index in range(file_length): - if index % 8 == 7: - payload[index] = ( - payload[index] ^ ( - (chk_sum + chip_id) % 256)) % 256 - - left_len = file_length - curr_addr = 0 - - while curr_addr < file_length: - - if left_len >= 56: - pkt_length = 56 - else: - pkt_length = left_len - - __WRITE_CMD_V2 = WRITE_CMD_V2 - __WRITE_CMD_V2[1] = pkt_length + 5 - __WRITE_CMD_V2[3] = curr_addr % 256 - __WRITE_CMD_V2[4] = (curr_addr >> 8) % 256 - __WRITE_CMD_V2[7] = left_len % 256 - __WRITE_CMD_V2 = __WRITE_CMD_V2 + \ - payload[curr_addr:curr_addr + pkt_length] - - dev.write(EP_OUT_ADDR, __WRITE_CMD_V2) - ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) - - curr_addr = curr_addr + pkt_length - left_len = left_len - pkt_length - - if ret[4] != 0x00: - return None - - return file_length - - -def __write_flash_ch55x_v23(dev, chk_sum, chip_id, payload): - # Payload needs to be padded, 56 is a good number - payload = payload + [0] * \ - ((math.ceil(len(payload) / 56) * 56) - len(payload)) - file_length = len(payload) - - for index in range(file_length): - if index % 8 == 7: - payload[index] = ( - payload[index] ^ ( - (chk_sum + chip_id) % 256)) % 256 - else: - payload[index] = (payload[index] ^ chk_sum) % 256 - - left_len = file_length - curr_addr = 0 - - while curr_addr < file_length: - - if left_len >= 56: - pkt_length = 56 - else: - pkt_length = left_len - - __WRITE_CMD_V2 = WRITE_CMD_V2 - __WRITE_CMD_V2[1] = pkt_length + 5 - __WRITE_CMD_V2[3] = curr_addr % 256 - __WRITE_CMD_V2[4] = (curr_addr >> 8) % 256 - __WRITE_CMD_V2[7] = left_len % 256 - __WRITE_CMD_V2 = __WRITE_CMD_V2 + \ - payload[curr_addr:curr_addr + pkt_length] - - dev.write(EP_OUT_ADDR, __WRITE_CMD_V2) - ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) - - curr_addr = curr_addr + pkt_length - left_len = left_len - pkt_length - - if ret[4] != 0x00: - return None - - return file_length - - -def __verify_flash_ch55x_v20(dev, chk_sum, chip_id, payload): - # Payload needs to be padded, 56 is a good number - payload = payload + [0] * \ - ((math.ceil(len(payload) / 56) * 56) - len(payload)) - file_length = len(payload) - - for index in range(file_length): - if index % 8 == 7: - payload[index] = ( - payload[index] ^ ( - (chk_sum + chip_id) % 256)) % 256 - - left_len = file_length - curr_addr = 0 - - while curr_addr < file_length: - - if left_len >= 56: - pkt_length = 56 - else: - pkt_length = left_len - - __VERIFY_CMD_V2 = VERIFY_CMD_V2 - __VERIFY_CMD_V2[1] = pkt_length + 5 - __VERIFY_CMD_V2[3] = curr_addr % 256 - __VERIFY_CMD_V2[4] = (curr_addr >> 8) % 256 - __VERIFY_CMD_V2[7] = left_len % 256 - __VERIFY_CMD_V2 = __VERIFY_CMD_V2 + \ - payload[curr_addr:curr_addr + pkt_length] - - dev.write(EP_OUT_ADDR, __VERIFY_CMD_V2) - ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) - - curr_addr = curr_addr + pkt_length - left_len = left_len - pkt_length - - if ret[4] != 0x00: - return None - - return file_length - - -def __verify_flash_ch55x_v23(dev, chk_sum, chip_id, payload): - # Payload needs to be padded, 56 is a good number - payload = payload + [0] * \ - ((math.ceil(len(payload) / 56) * 56) - len(payload)) - file_length = len(payload) - - for index in range(file_length): - if index % 8 == 7: - payload[index] = ( - payload[index] ^ ( - (chk_sum + chip_id) % 256)) % 256 - else: - payload[index] = (payload[index] ^ chk_sum) % 256 - - left_len = file_length - curr_addr = 0 - - while curr_addr < file_length: - - if left_len >= 56: - pkt_length = 56 - else: - pkt_length = left_len - - __VERIFY_CMD_V2 = VERIFY_CMD_V2 - __VERIFY_CMD_V2[1] = pkt_length + 5 - __VERIFY_CMD_V2[3] = curr_addr % 256 - __VERIFY_CMD_V2[4] = (curr_addr >> 8) % 256 - __VERIFY_CMD_V2[7] = left_len % 256 - __VERIFY_CMD_V2 = __VERIFY_CMD_V2 + \ - payload[curr_addr:curr_addr + pkt_length] - - dev.write(EP_OUT_ADDR, __VERIFY_CMD_V2) - ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) - - curr_addr = curr_addr + pkt_length - left_len = left_len - pkt_length - - if ret[4] != 0x00: - return None - - return file_length +def cmd_send(dev, cmd_bin, payload): + pl_len = len(payload) + packet = cmd_bin + pl_len.to_bytes(2,'little') + payload + dev.write(EP_OUT_ADDR,packet) + +def cmd_reply_receive(dev, cmd_bin): + reply = dev.read(EP_IN_ADDR, dev.bMaxPacketSize0, USB_MAX_TIMEOUT) + #reply = dev.read(EP_IN_ADDR, 4, USB_MAX_TIMEOUT) + if((reply != None) and (reply[0] == cmd_bin[0])): + reply_val = reply[1] + reply_payload_len = int.from_bytes(reply[2:4],'little') + if(reply_payload_len > 0): + #reply_payload = dev.read(EP_IN_ADDR, reply_payload_len, USB_MAX_TIMEOUT) + reply_payload = reply[4:4+reply_payload_len] + else: + reply_payload = None + else: + reply_val = None + reply_payload = None + + return reply_val, reply_payload + +def cmd_exec(dev, cmd, payload): + cmd_bin = WCH_CMDS.get(cmd) + if(cmd_bin != None): + cmd_send(dev, cmd_bin, payload) + return cmd_reply_receive(dev, cmd_bin) + else: + return None,None +def __get_dfu_device(idVendor=DFU_ID_VENDOR, idProduct=DFU_ID_PRODUCT): + dev = usb.core.find(idVendor=idVendor, idProduct=idProduct) + if dev is None: + return (None, 'NO_DEV_FOUND') + try: + if dev.is_kernel_driver_active(0): + try: + dev.detach_kernel_driver(0) + except usb.core.USBError: + return (None, 'USB_ERROR_CANNOT_DETACH_KERNEL_DRIVER') + except BaseException: + pass # Windows dont need detach + + try: + dev.set_configuration() + except usb.core.USBError: + return (None, 'USB_ERROR_CANNOT_SET_CONFIG') + + try: + usb.util.claim_interface(dev, 0) + except usb.core.USBError: + return (None, 'USB_ERROR_CANNOT_CLAIM_INTERFACE') + + return (dev, '') + +def __detect_ch5xx(dev): + cmd_pl = DETECT_PL_START + DETECT_APP_ID_B + ret, ret_pl = cmd_exec(dev, 'Detect', cmd_pl) + if(ret != None and len(ret_pl) == 2): + chip_id = ret_pl[0] + chip_subid = ret_pl[1] + else: + chip_id = 0 + chip_subid = 0 + return ret, chip_id, chip_subid + +def __read_cfg_ch5xx(dev, req_fields, chip_id, chip_subid): + predict_ret_pl_len = 2 # 2 byte for fields + if(req_fields & CFG_FLAG_UNKN1): predict_ret_pl_len += 4 + if(req_fields & CFG_FLAG_UNKN2): predict_ret_pl_len += 4 + if(req_fields & CFG_FLAG_UNKN3): predict_ret_pl_len += 4 + if(req_fields & CFG_FLAG_BOOTVER): predict_ret_pl_len += 4 + if(req_fields & CFG_FLAG_UID): predict_ret_pl_len += 8 + + cmd_pl = req_fields.to_bytes(2,'little') + ret, ret_pl = cmd_exec(dev, 'ReadConfig', cmd_pl) + + cfg_dict = {} + if(ret is None): + print("Get config failure!") + return ret, cfg_dict + + reply_prc_bytes = 0 + reply_fields = int.from_bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+2],'little') + reply_prc_bytes += 2 + + if(len(ret_pl) != predict_ret_pl_len or reply_fields != req_fields): + print("Reply fields do not match requested!") + + cfg_dict["Fields"] = reply_fields + if(reply_fields & CFG_FLAG_UNKN1): + cfg_dict[CFG_FLAG_UNKN1] = ret_pl[reply_prc_bytes:reply_prc_bytes+4] + reply_prc_bytes += 4 + + if(reply_fields & CFG_FLAG_UNKN2): + cfg_dict[CFG_FLAG_UNKN2] = ret_pl[reply_prc_bytes:reply_prc_bytes+4] + reply_prc_bytes += 4 + + if(reply_fields & CFG_FLAG_UNKN3): + cfg_dict[CFG_FLAG_UNKN3] = ret_pl[reply_prc_bytes:reply_prc_bytes+4] + reply_prc_bytes += 4 + + if(reply_fields & CFG_FLAG_BOOTVER): + cfg_dict[CFG_FLAG_BOOTVER] = ret_pl[reply_prc_bytes:reply_prc_bytes+4] + reply_prc_bytes += 4 + + if(reply_fields & CFG_FLAG_UID): + if((chip_subid == 0x11) and (chip_id not in [0x55, 0x56, 0x57])): + cfg_dict[CFG_FLAG_UID] = ret_pl[reply_prc_bytes:reply_prc_bytes+4] + b'\x00'*4 + else: + cfg_dict[CFG_FLAG_UID] = ret_pl[reply_prc_bytes:reply_prc_bytes+8] + reply_prc_bytes += 8 + + return ret, cfg_dict + +def __write_cfg_ch5xx(dev, cfg_dict): + cfg_fileds = cfg_dict.get("Fields") + if(cfg_fileds is None): + print("Not defined fields to set configuration.") + return None, None + set_fields = 0 + cmd_pl = b'' + if(cfg_fields & CFG_FLAG_UNKN1): + field_val = cfg_dict.get(CFG_FLAG_UNKN1) + if(field_val != None and len(field_val) == 4): + set_fields |= CFG_FLAG_UNKN1 + cmd_pl += field_val + else: + print("Incorrect or no value for cfg field 0x%02X"%(CFG_FLAG_UNKN1)) + + if(cfg_fields & CFG_FLAG_UNKN2): + field_val = cfg_dict.get(CFG_FLAG_UNKN2) + if(field_val != None and len(field_val) == 4): + set_fields |= CFG_FLAG_UNKN2 + cmd_pl += field_val + else: + print("Incorrect or no value for cfg field 0x%02X"%(CFG_FLAG_UNKN2)) + + if(cfg_fields & CFG_FLAG_UNKN3): + field_val = cfg_dict.get(CFG_FLAG_UNKN3) + if(field_val != None and len(field_val) == 4): + set_fields |= CFG_FLAG_UNKN3 + cmd_pl += field_val + else: + print("Incorrect or no value for cfg field 0x%02X"%(CFG_FLAG_UNKN3)) + + if(set_fields > 0): + cmd_pl = set_fields.to_bytes(2,'little') + cmd_pl + ret, ret_pl = cmd_exec(dev, 'WriteConfig', cmd_pl) + return ret, cfg_dict + else: + print("No setable chip fields in given config.") + return None, None + +def __chip_uid_chk_sum(chip_subid, chip_uid): + if(chip_subid == 0x11): + return sum(chip_uid[:4]) & 0xFF + else: + return sum(chip_uid) & 0xFF + +def __gen_key_values(chip_id, chip_uid_chksum): + # In original soft KeyBase length = 30 + (random int)%31 + key_base_len = random.randint(30,61) + key_base = bytearray(key_base_len) + for i in range(key_base_len): + key_base[i] = random.randint(0,255) + key = bytearray(8) + key[0] = chip_uid_chksum ^ key_base[ 4 * (key_base_len // 7)] + key[1] = chip_uid_chksum ^ key_base[ key_base_len // 5 ] + key[2] = chip_uid_chksum ^ key_base[ key_base_len // 7 ] + key[3] = chip_uid_chksum ^ key_base[ 6 * (key_base_len // 7)] + key[4] = chip_uid_chksum ^ key_base[ 3 * (key_base_len // 7)] + key[5] = chip_uid_chksum ^ key_base[ 3 * (key_base_len // 5)] + key[6] = chip_uid_chksum ^ key_base[ 5 * (key_base_len // 7)] + key[7] = (chip_id + key[0]) & 0xff + return key, key_base + +def __send_key_base(dev, key_base): + ret, ret_pl = cmd_exec(dev, 'SetKey', key_base) + if (ret != None and len(ret_pl)>0): + return ret_pl[0] == 0 + else: + return None + +def __flash_ops_write_verify(dev, key_xor_chksum, data, func="Write",max_packet_size=64): + if(func not in [ 'Write' , 'Verify'] ): + return None + data_length = len(data) + curr_addr = 0 + max_data_len_perpack = max_packet_size - 3 - 5 + data_buff = bytearray(max_data_len_perpack) + while curr_addr < data_length: + left_len = data_length - curr_addr + if (left_len) > max_data_len_perpack: + pkt_length = max_data_len_perpack + data_buff[:pkt_length] = data[curr_addr:curr_addr+pkt_length] + else: + pkt_length = left_len + data_buff[:pkt_length] = data[curr_addr:curr_addr+pkt_length] + tmp = left_len & 0x07 + if( tmp != 0): + pad_len = 8 - tmp + pkt_length += pad_len + data_buff[left_len:pkt_length] = b'\x00'* pad_len + + for index in range(pkt_length): + data_buff[index] ^= key_xor_chksum[index & 0x07] + + cmd_pl = curr_addr.to_bytes(4,'little') + bytes([random.randint(0,255)]) + data_buff[:pkt_length] + + ret, ret_pl = cmd_exec(dev, 'Flash'+func, cmd_pl) + if( ret == None or ret_pl[0] != 0x00): + return None + curr_addr = curr_addr + pkt_length + if(curr_addr > data_length): + return data_length + else: + return curr_addr + +def __erase_chip_ch5xx(dev, chip_ref): + # We assume pages size is 1kb + erase_page_cnt = chip_ref['device_flash_size']>>10 + cmd_pl = erase_page_cnt.to_bytes(4,'little') + ret, ret_pl = cmd_exec(dev,'FlashErase', cmd_pl) + if ret_pl[0] == 0: + return True + else: + return None def __end_flash_ch55x_v2(dev): - dev.write(EP_OUT_ADDR, END_FLASH_CMD_V2) - ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) - if ret[4] != 0x00: - return None - else: - return True - + dev.write(EP_OUT_ADDR, END_FLASH_CMD_V2) + ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) + if ret[4] != 0x00: + return None + else: + return True def __restart_run_ch55x_v2(dev): - dev.write(EP_OUT_ADDR, RESET_RUN_CMD_V2) - + dev.write(EP_OUT_ADDR, RESET_RUN_CMD_V2) def main(): - parser = argparse.ArgumentParser( - description="USBISP Tool For WinChipHead CH55x.") - parser.add_argument( - '-f', - '--file', - type=str, - default='', - help="The target file to be flashed. This must be a binary file (hex files are not supported).") - parser.add_argument( - '-r', - '--reset_after_flash', - action='store_true', - default=False, - help="Reset after finsh flash.") - args = parser.parse_args() - - ret = __get_dfu_device() - if ret[0] is None: - print('Failed to get device, please check your libusb installation.') - sys.exit(-1) - - dev = ret[0] - - ret = __detect_ch55x_v2(dev) - if ret is None: - print('Unable to detect CH55x.') - print('Welcome to report this issue with a screen shot from the official CH55x tool.') - sys.exit(-1) - - print('Found %s.' % ret['device_name']) - chip_id = ret['chip_id'] - - ret = __read_cfg_ch55x_v2(dev) - chk_sum = ret[1] - - print('BTVER: %s.' % ret[0]) - - if args.file != '': - payload = list(open(args.file, 'rb').read()) - if args.file.endswith('.hex') or args.file.endswith('.ihx') or payload[0]==58: - print("WARNING: This looks like a hex file. This tool only supports binary files.") - if ret[0] in ['V2.30']: - ret = __write_key_ch55x_v20(dev, chk_sum) - if ret is None: - sys.exit('Failed to write key to CH55x.') - - ret = __erase_chip_ch55x_v2(dev) - if ret is None: - sys.exit('Failed to erase CH55x.') - - ret = __write_flash_ch55x_v20(dev, chk_sum, chip_id, payload) - if ret is None: - sys.exit('Failed to flash firmware of CH55x.') - - ret = __verify_flash_ch55x_v20(dev, chk_sum, chip_id, payload) - if ret is None: - sys.exit('Failed to verify firmware of CH55x.') - else: - if ret[0] in ['V2.31', 'V2.40']: - ret = __write_key_ch55x_v23(dev) - if ret is None: - sys.exit('Failed to write key to CH55x.') - - ret = __erase_chip_ch55x_v2(dev) - if ret is None: - sys.exit('Failed to erase CH55x.') - - ret = __write_flash_ch55x_v23(dev, chk_sum, chip_id, payload) - if ret is None: - sys.exit('Failed to flash firmware of CH55x.') - - ret = __verify_flash_ch55x_v23(dev, chk_sum, chip_id, payload) - if ret is None: - sys.exit('Failed to verify firmware of CH55x.') - else: - sys.exit('Bootloader version not supported.') - - ret = __end_flash_ch55x_v2(dev) - if ret is None: - sys.exit('Failed to end flash process.') - - print('Flash done.') - - if args.reset_after_flash: - __restart_run_ch55x_v2(dev) - print('Restart and run.') + parser = argparse.ArgumentParser( + description="USBISP Tool For WinChipHead CH55x/CH56x .") + parser.add_argument( + '-f', '--flash', type=str, default='', + help="The target file to be flashed. This must be a binary file (hex files are not supported).") + parser.add_argument( + '-e', '--erase', action='store_true', default=False, + help="Erase chip program flash.") + parser.add_argument( + '-c', '--clean', action='store_true', default=False, + help="Clean chip data eeprom.") + + parser.add_argument( + '-r', '--reset_at_end', action='store_true', default=False, + help="Reset as the end of operations.") + parser.add_argument( + '-l', '--list', action='store_true', default=False, + help="List connected devices.") + parser.add_argument( + '-v', '--verbose', action='store_true', default=False, + help="Verbose program process output.") + + args = parser.parse_args() + + + ret = __get_dfu_device() + if ret[0] is None: + print('Failed to get device, please check your libusb installation.') + sys.exit(-1) + + dev = ret[0] + + #print("Device max_pack_size: %s" % (dev.bMaxPacketSize0)) + + ret, chip_id, chip_subid = __detect_ch5xx(dev) + if ret is None: + print('Unable to detect CH5xx.') + print('Welcome to report this issue with a screen shot from the official CH5xx tool.') + sys.exit(-1) + + chip_ref = CH55X_IC_REF.get(chip_id) + if chip_ref is None: + print('Chip ID: %x is not known = not supported' % chip_id) + print('Welcome to report this issue with a screen shot from the official CH5xx tool.') + sys.exit(-1) + + print('Found %s with SubId:%d' % (chip_ref['device_name'], chip_subid)) + + ret, chip_cfg = __read_cfg_ch5xx(dev, CFG_FLAG_BOOTVER | CFG_FLAG_UID | CFG_FLAG_UNKNs, chip_id, chip_subid) + if ret is None: + print('Cannot read chip configuration!') + sys.exit(-1) + else: + bootver = chip_cfg.get(CFG_FLAG_BOOTVER) + uid = chip_cfg.get(CFG_FLAG_UID) + if( bootver is None or uid is None): + print('Cannot read chip bootloader version or uniqe ID.') + sys.exit(-1) + + ver_str = '%d%d.%d%d' % (bootver[0], bootver[1], bootver[2], bootver[3]) + print('BTVER:%s' % ver_str) + + uid_str = '%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X' % (uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]) + print('UID:%s' % uid_str) + + verb = True + + flash_file = args.flash + + if flash_file != '': + file_data = list(open(flash_file, 'rb').read()) + if flash_file.endswith('.hex') or flash_file.endswith('.ihx') or file_data[0]==58: + print("WARNING: This looks like a hex file. This tool only supports binary files.") + if ver_str in ['02.30', '02.31', '02.40']: + chk_sum = __chip_uid_chk_sum(chip_subid, uid) + + enc_key, key_b = __gen_key_values(chip_id, chk_sum) + ret = __send_key_base(dev,key_b) + if ret is None: + sys.exit('Failed to write key for flash write to CH5xx.') + + ret = __erase_chip_ch5xx(dev,chip_ref) + if ret is None: + sys.exit('Failed to erase CH55x.') + + ret = __flash_ops_write_verify(dev, enc_key, file_data, func="Write") + if ret is None: + sys.exit('Failed to flash firmware of CH55x.') + + enc_key, key_b = __gen_key_values(chip_id, chk_sum) + ret = __send_key_base(dev,key_b) + if ret is None: + sys.exit('Failed to write key for flash verify to CH5xx.') + + ret = __flash_ops_write_verify(dev, enc_key, file_data, func="Verify") + if ret is None: + sys.exit('Failed to verify firmware of CH55x.') + else: + sys.exit('Bootloader version not supported.') + + ret = __end_flash_ch55x_v2(dev) + if ret is None: + sys.exit('Failed to end flash process.') + + print('Flash done.') + + if args.reset_at_end: + __restart_run_ch55x_v2(dev) + print('Restart and run.') + +if __name__ == '__main__': + sys.exit(main()) From bd092a485ac708b2e130a8fc257092bcdf88bdef Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Mon, 21 Mar 2022 15:25:12 +0200 Subject: [PATCH 02/21] Bug fix of receiving size depend on endpoint. UID/BOOTLOADERVER/CFGs frocessing fix. Removed printout of wrong maximal packet size. --- ch55xtool/ch55xtool.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index 8436b72..91db050 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -89,13 +89,14 @@ def cmd_send(dev, cmd_bin, payload): dev.write(EP_OUT_ADDR,packet) def cmd_reply_receive(dev, cmd_bin): - reply = dev.read(EP_IN_ADDR, dev.bMaxPacketSize0, USB_MAX_TIMEOUT) - #reply = dev.read(EP_IN_ADDR, 4, USB_MAX_TIMEOUT) + cfg = dev.get_active_configuration() + intf = cfg[(0,0)] + ep_in = usb.util.find_descriptor(intf, bEndpointAddress=EP_IN_ADDR) + reply = ep_in.read(ep_in.wMaxPacketSize, USB_MAX_TIMEOUT) if((reply != None) and (reply[0] == cmd_bin[0])): reply_val = reply[1] reply_payload_len = int.from_bytes(reply[2:4],'little') if(reply_payload_len > 0): - #reply_payload = dev.read(EP_IN_ADDR, reply_payload_len, USB_MAX_TIMEOUT) reply_payload = reply[4:4+reply_payload_len] else: reply_payload = None @@ -174,26 +175,26 @@ def __read_cfg_ch5xx(dev, req_fields, chip_id, chip_subid): cfg_dict["Fields"] = reply_fields if(reply_fields & CFG_FLAG_UNKN1): - cfg_dict[CFG_FLAG_UNKN1] = ret_pl[reply_prc_bytes:reply_prc_bytes+4] + cfg_dict[CFG_FLAG_UNKN1] = int.from_bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4],'little') reply_prc_bytes += 4 if(reply_fields & CFG_FLAG_UNKN2): - cfg_dict[CFG_FLAG_UNKN2] = ret_pl[reply_prc_bytes:reply_prc_bytes+4] + cfg_dict[CFG_FLAG_UNKN2] = int.from_bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4],'little') reply_prc_bytes += 4 if(reply_fields & CFG_FLAG_UNKN3): - cfg_dict[CFG_FLAG_UNKN3] = ret_pl[reply_prc_bytes:reply_prc_bytes+4] + cfg_dict[CFG_FLAG_UNKN3] = int.from_bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4],'little') reply_prc_bytes += 4 if(reply_fields & CFG_FLAG_BOOTVER): - cfg_dict[CFG_FLAG_BOOTVER] = ret_pl[reply_prc_bytes:reply_prc_bytes+4] + cfg_dict[CFG_FLAG_BOOTVER] = bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4]) reply_prc_bytes += 4 if(reply_fields & CFG_FLAG_UID): if((chip_subid == 0x11) and (chip_id not in [0x55, 0x56, 0x57])): - cfg_dict[CFG_FLAG_UID] = ret_pl[reply_prc_bytes:reply_prc_bytes+4] + b'\x00'*4 + cfg_dict[CFG_FLAG_UID] = bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4]) + b'\x00'*4 else: - cfg_dict[CFG_FLAG_UID] = ret_pl[reply_prc_bytes:reply_prc_bytes+8] + cfg_dict[CFG_FLAG_UID] = bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+8]) reply_prc_bytes += 8 return ret, cfg_dict @@ -209,7 +210,7 @@ def __write_cfg_ch5xx(dev, cfg_dict): field_val = cfg_dict.get(CFG_FLAG_UNKN1) if(field_val != None and len(field_val) == 4): set_fields |= CFG_FLAG_UNKN1 - cmd_pl += field_val + cmd_pl += field_val.to_bytes(4,'little') else: print("Incorrect or no value for cfg field 0x%02X"%(CFG_FLAG_UNKN1)) @@ -217,7 +218,7 @@ def __write_cfg_ch5xx(dev, cfg_dict): field_val = cfg_dict.get(CFG_FLAG_UNKN2) if(field_val != None and len(field_val) == 4): set_fields |= CFG_FLAG_UNKN2 - cmd_pl += field_val + cmd_pl += field_val.to_bytes(4,'little') else: print("Incorrect or no value for cfg field 0x%02X"%(CFG_FLAG_UNKN2)) @@ -225,7 +226,7 @@ def __write_cfg_ch5xx(dev, cfg_dict): field_val = cfg_dict.get(CFG_FLAG_UNKN3) if(field_val != None and len(field_val) == 4): set_fields |= CFG_FLAG_UNKN3 - cmd_pl += field_val + cmd_pl += field_val.to_bytes(4,'little') else: print("Incorrect or no value for cfg field 0x%02X"%(CFG_FLAG_UNKN3)) @@ -356,8 +357,6 @@ def main(): dev = ret[0] - #print("Device max_pack_size: %s" % (dev.bMaxPacketSize0)) - ret, chip_id, chip_subid = __detect_ch5xx(dev) if ret is None: print('Unable to detect CH5xx.') From e7c9d643f0078660572125cbec6d92ba3d389052 Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Mon, 21 Mar 2022 15:29:21 +0200 Subject: [PATCH 03/21] Added file data size check to fit in flash. Error reporting sizes in human readable format. --- ch55xtool/ch55xtool.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index 91db050..7496a7a 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -396,6 +396,10 @@ def main(): file_data = list(open(flash_file, 'rb').read()) if flash_file.endswith('.hex') or flash_file.endswith('.ihx') or file_data[0]==58: print("WARNING: This looks like a hex file. This tool only supports binary files.") + if len(file_data) > chip_ref['device_flash_size']: + print('The binary is too large for the device.') + print('Binary size: %d, Flash size: %d' % (len(file_data),chip_ref['device_flash_size'])) + sys.exit(-1) if ver_str in ['02.30', '02.31', '02.40']: chk_sum = __chip_uid_chk_sum(chip_subid, uid) From 4917e9778b24ed1f8b27d1e77c3c841c0422fa3f Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Mon, 21 Mar 2022 16:29:20 +0200 Subject: [PATCH 04/21] Reworked process "End" to single functions because it is single comand with parameter to restart or not. --- ch55xtool/ch55xtool.py | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index 7496a7a..7504b85 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -64,9 +64,6 @@ "DataRead": b'\xAB', } -END_FLASH_CMD_V2 = [0xa2, 0x01, 0x00] + [0x00] -RESET_RUN_CMD_V2 = [0xa2, 0x01, 0x00] + [0x01] - # Meaning of those two values not yet clear :( DETECT_PL_START = b'\x42\x10' #DETECT_PL_START = b'\x52\x11' @@ -313,16 +310,14 @@ def __erase_chip_ch5xx(dev, chip_ref): else: return None -def __end_flash_ch55x_v2(dev): - dev.write(EP_OUT_ADDR, END_FLASH_CMD_V2) - ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) - if ret[4] != 0x00: - return None +def __end_flash_ch5xx(dev, restart_after = False): + cmd_pl = bytes([restart_after]) + if(restart_after): + cmd_bin = WCH_CMDS.get("End") + cmd_send(dev, cmd_bin, cmd_pl) + return True,None else: - return True - -def __restart_run_ch55x_v2(dev): - dev.write(EP_OUT_ADDR, RESET_RUN_CMD_V2) + return cmd_exec(dev, "End", cmd_pl) def main(): parser = argparse.ArgumentParser( @@ -349,7 +344,6 @@ def main(): args = parser.parse_args() - ret = __get_dfu_device() if ret[0] is None: print('Failed to get device, please check your libusb installation.') @@ -427,15 +421,19 @@ def main(): else: sys.exit('Bootloader version not supported.') - ret = __end_flash_ch55x_v2(dev) - if ret is None: - sys.exit('Failed to end flash process.') - - print('Flash done.') - - if args.reset_at_end: - __restart_run_ch55x_v2(dev) - print('Restart and run.') + ret, ret_pl = __end_flash_ch5xx(dev, restart_after = args.reset_at_end) + if(ret is True): + print('Flash done.',end="") + print(' Restart and run.') + elif(ret is None): + sys.exit('Failed to end flash process. No response.') + else: + if(ret_pl != None): + if ret_pl[0] != 0x00: + resp_str = ' Response: %02x' % (ret_pl[0]) + sys.exit('Failed to end flash process.'+ resp_str) + else: + print('Flash done.') if __name__ == '__main__': sys.exit(main()) From 1ff1982769791f8b151693e64812162c68d7205c Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Mon, 21 Mar 2022 16:59:24 +0200 Subject: [PATCH 05/21] Bootloader version check now reworked so value represented as float and need be >= 2.3 --- ch55xtool/ch55xtool.py | 51 +++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index 7504b85..2b99468 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -394,33 +394,34 @@ def main(): print('The binary is too large for the device.') print('Binary size: %d, Flash size: %d' % (len(file_data),chip_ref['device_flash_size'])) sys.exit(-1) - if ver_str in ['02.30', '02.31', '02.40']: - chk_sum = __chip_uid_chk_sum(chip_subid, uid) - - enc_key, key_b = __gen_key_values(chip_id, chk_sum) - ret = __send_key_base(dev,key_b) - if ret is None: - sys.exit('Failed to write key for flash write to CH5xx.') - - ret = __erase_chip_ch5xx(dev,chip_ref) - if ret is None: - sys.exit('Failed to erase CH55x.') - - ret = __flash_ops_write_verify(dev, enc_key, file_data, func="Write") - if ret is None: - sys.exit('Failed to flash firmware of CH55x.') - - enc_key, key_b = __gen_key_values(chip_id, chk_sum) - ret = __send_key_base(dev,key_b) - if ret is None: - sys.exit('Failed to write key for flash verify to CH5xx.') - - ret = __flash_ops_write_verify(dev, enc_key, file_data, func="Verify") - if ret is None: - sys.exit('Failed to verify firmware of CH55x.') - else: + + if(float(ver_str)<2.3): sys.exit('Bootloader version not supported.') + chk_sum = __chip_uid_chk_sum(chip_subid, uid) + + enc_key, key_b = __gen_key_values(chip_id, chk_sum) + ret = __send_key_base(dev,key_b) + if ret is None: + sys.exit('Failed to write key for flash write to CH5xx.') + + ret = __erase_chip_ch5xx(dev,chip_ref) + if ret is None: + sys.exit('Failed to erase CH55x.') + + ret = __flash_ops_write_verify(dev, enc_key, file_data, func="Write") + if ret is None: + sys.exit('Failed to flash firmware of CH55x.') + + enc_key, key_b = __gen_key_values(chip_id, chk_sum) + ret = __send_key_base(dev,key_b) + if ret is None: + sys.exit('Failed to write key for flash verify to CH5xx.') + + ret = __flash_ops_write_verify(dev, enc_key, file_data, func="Verify") + if ret is None: + sys.exit('Failed to verify firmware of CH55x.') + ret, ret_pl = __end_flash_ch5xx(dev, restart_after = args.reset_at_end) if(ret is True): print('Flash done.',end="") From f55de584987d1d81eeb1cf2e7db222c6c07314f7 Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Mon, 21 Mar 2022 17:11:03 +0200 Subject: [PATCH 06/21] Make chip reference field names shorter by removing "device_" prefix. --- ch55xtool/ch55xtool.py | 44 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index 2b99468..420d86d 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -21,34 +21,34 @@ CH55X_IC_REF = {} CH55X_IC_REF[0x51] = { - 'device_name': 'CH551', - 'device_flash_size': 10240, - 'device_dataflash_size': 128, + 'name': 'CH551', + 'flash_size': 10240, + 'dataflash_size': 128, 'chip_id': 0x51} CH55X_IC_REF[0x52] = { - 'device_name': 'CH552', - 'device_flash_size': 16384, - 'device_dataflash_size': 128, + 'name': 'CH552', + 'flash_size': 16384, + 'dataflash_size': 128, 'chip_id': 0x52} CH55X_IC_REF[0x53] = { - 'device_name': 'CH553', - 'device_flash_size': 10240, - 'device_dataflash_size': 128, + 'name': 'CH553', + 'flash_size': 10240, + 'dataflash_size': 128, 'chip_id': 0x53} CH55X_IC_REF[0x54] = { - 'device_name': 'CH554', - 'device_flash_size': 14336, - 'device_dataflash_size': 128, + 'name': 'CH554', + 'flash_size': 14336, + 'dataflash_size': 128, 'chip_id': 0x54} CH55X_IC_REF[0x59] = { - 'device_name': 'CH559', - 'device_flash_size': 61440, - 'device_dataflash_size': 128, + 'name': 'CH559', + 'flash_size': 61440, + 'dataflash_size': 128, 'chip_id': 0x59} CH55X_IC_REF[0x68] = { - 'device_name': 'CH568', - 'device_flash_size': (128+64)*1024, - 'device_dataflash_size': 32*1024, + 'name': 'CH568', + 'flash_size': (128+64)*1024, + 'dataflash_size': 32*1024, 'chip_id': 0x68} # ============================================= WCH_CMDS = { "Detect": b'\xA1', @@ -302,7 +302,7 @@ def __flash_ops_write_verify(dev, key_xor_chksum, data, func="Write",max_packet_ def __erase_chip_ch5xx(dev, chip_ref): # We assume pages size is 1kb - erase_page_cnt = chip_ref['device_flash_size']>>10 + erase_page_cnt = chip_ref['flash_size']>>10 cmd_pl = erase_page_cnt.to_bytes(4,'little') ret, ret_pl = cmd_exec(dev,'FlashErase', cmd_pl) if ret_pl[0] == 0: @@ -363,7 +363,7 @@ def main(): print('Welcome to report this issue with a screen shot from the official CH5xx tool.') sys.exit(-1) - print('Found %s with SubId:%d' % (chip_ref['device_name'], chip_subid)) + print('Found %s with SubId:%d' % (chip_ref['name'], chip_subid)) ret, chip_cfg = __read_cfg_ch5xx(dev, CFG_FLAG_BOOTVER | CFG_FLAG_UID | CFG_FLAG_UNKNs, chip_id, chip_subid) if ret is None: @@ -390,9 +390,9 @@ def main(): file_data = list(open(flash_file, 'rb').read()) if flash_file.endswith('.hex') or flash_file.endswith('.ihx') or file_data[0]==58: print("WARNING: This looks like a hex file. This tool only supports binary files.") - if len(file_data) > chip_ref['device_flash_size']: + if len(file_data) > chip_ref['flash_size']: print('The binary is too large for the device.') - print('Binary size: %d, Flash size: %d' % (len(file_data),chip_ref['device_flash_size'])) + print('Binary size: %d, Flash size: %d' % (len(file_data),chip_ref['flash_size'])) sys.exit(-1) if(float(ver_str)<2.3): From 677f2a75237f6841e7311b46ba079df7451a1b87 Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Mon, 21 Mar 2022 17:37:56 +0200 Subject: [PATCH 07/21] Added chips: CH32V103, CH549, CH32V307, CH571/3/9, CH582. Reformated chips dictionary initial definition. --- ch55xtool/ch55xtool.py | 47 ++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index 420d86d..fbd5fda 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -19,37 +19,22 @@ USB_MAX_TIMEOUT = 2000 -CH55X_IC_REF = {} -CH55X_IC_REF[0x51] = { - 'name': 'CH551', - 'flash_size': 10240, - 'dataflash_size': 128, - 'chip_id': 0x51} -CH55X_IC_REF[0x52] = { - 'name': 'CH552', - 'flash_size': 16384, - 'dataflash_size': 128, - 'chip_id': 0x52} -CH55X_IC_REF[0x53] = { - 'name': 'CH553', - 'flash_size': 10240, - 'dataflash_size': 128, - 'chip_id': 0x53} -CH55X_IC_REF[0x54] = { - 'name': 'CH554', - 'flash_size': 14336, - 'dataflash_size': 128, - 'chip_id': 0x54} -CH55X_IC_REF[0x59] = { - 'name': 'CH559', - 'flash_size': 61440, - 'dataflash_size': 128, - 'chip_id': 0x59} -CH55X_IC_REF[0x68] = { - 'name': 'CH568', - 'flash_size': (128+64)*1024, - 'dataflash_size': 32*1024, - 'chip_id': 0x68} +CH55X_IC_REF = { + 0x3f:{'name':'CH32V103', 'flash_size': 64*1024, 'dataflash_size': 0, 'chip_id': 0x3f, 'erase_required_pages':True}, + 0x49:{'name':'CH549', 'flash_size': 60*1024, 'dataflash_size': 1024, 'chip_id': 0x49, 'erase_required_pages':False}, + 0x51:{'name':'CH551', 'flash_size': 10240, 'dataflash_size': 128, 'chip_id': 0x51, 'erase_required_pages':False}, + 0x52:{'name':'CH552', 'flash_size': 16384, 'dataflash_size': 128, 'chip_id': 0x52, 'erase_required_pages':False}, + 0x53:{'name':'CH553', 'flash_size': 10240, 'dataflash_size': 128, 'chip_id': 0x53, 'erase_required_pages':False}, + 0x54:{'name':'CH554', 'flash_size': 14336, 'dataflash_size': 128, 'chip_id': 0x54, 'erase_required_pages':False}, + 0x59:{'name':'CH559', 'flash_size': 61440, 'dataflash_size': 128, 'chip_id': 0x59, 'erase_required_pages':False}, + 0x68:{'name':'CH568', 'flash_size': 192*1024, 'dataflash_size': 32*1024, 'chip_id': 0x68, 'erase_required_pages':False}, + 0x70:{'name':'CH32V307', 'flash_size': 256*1024, 'dataflash_size': 128, 'chip_id': 0x70, 'erase_required_pages':False}, + 0x71:{'name':'CH571', 'flash_size': 192*1024, 'dataflash_size': 0, 'chip_id': 0x71, 'erase_required_pages':True}, + 0x73:{'name':'CH573', 'flash_size': 448*1024, 'dataflash_size': 0, 'chip_id': 0x73, 'erase_required_pages':True}, + 0x79:{'name':'CH579', 'flash_size': 256*1024, 'dataflash_size': 0, 'chip_id': 0x79, 'erase_required_pages':True}, + 0x82:{'name':'CH582', 'flash_size': 448*1024, 'dataflash_size': 0, 'chip_id': 0x82, 'erase_required_pages':True}, +} + # ============================================= WCH_CMDS = { "Detect": b'\xA1', "End": b'\xA2', From db8c180398e0c02e921e268f089dd27194c83f74 Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Mon, 21 Mar 2022 19:20:51 +0200 Subject: [PATCH 08/21] Splitt comand line functions and added new. Fixed behavior/error if empty file is given. Command line parameters, all of them could work individualy : -f/--flash Flashing file, include chip erase, is mandatory. -e/--erase_flash Erase whole program flash. --verify_flash [filename] Perform program flash verifying with given file, [filename] is optional and if ommited perform verifying with flashed program. -r/--reset_at_end Perform chip reset and program run at the end of communication. --- README.md | 6 +- ch55xtool/ch55xtool.py | 133 ++++++++++++++++++++++++++--------------- 2 files changed, 89 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 0a031a1..92c02a9 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,10 @@ An open sourced python command line flash tool for flashing WinChipHead CH55x se Usage ------------ -* __-f \__ Erase the whole chip, and flash the bin file to the CH55x. -* __-r__ Issue reset and run after the flashing. +* __-f/--flash \__ Erase the whole chip, and flash the bin file to the CH55x. +* __-e/--erase\_flash__ Erase the whole chip. +* __--verify\_flash__ [filename] Verify program flash contend with given file, if filename ommited verifying with flashed data. No verifying perormed without this flag. +* __-r/--reset\_at\_end__ Issue reset and run after all. ```bash python3 -m ch55xtool -f THE_BINARY_FILE.bin diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index fbd5fda..e784b2b 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -309,10 +309,14 @@ def main(): description="USBISP Tool For WinChipHead CH55x/CH56x .") parser.add_argument( '-f', '--flash', type=str, default='', - help="The target file to be flashed. This must be a binary file (hex files are not supported).") + help="The target file to be flashed. This must be a binary file (hex files are not supported). Flashing include chipe erase in front.") parser.add_argument( - '-e', '--erase', action='store_true', default=False, + '-e', '--erase_flash', action='store_true', default=False, help="Erase chip program flash.") + parser.add_argument( + '--verify_flash', type=str, action='store', nargs='?', const='', default=None, + help="Verify flash.") + parser.add_argument( '-c', '--clean', action='store_true', default=False, help="Clean chip data eeprom.") @@ -367,59 +371,92 @@ def main(): uid_str = '%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X' % (uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]) print('UID:%s' % uid_str) - verb = True - + if(float(ver_str)<2.3): + sys.exit('Bootloader version not supported.') + + chk_sum = __chip_uid_chk_sum(chip_subid, uid) + flash_file = args.flash - - if flash_file != '': - file_data = list(open(flash_file, 'rb').read()) - if flash_file.endswith('.hex') or flash_file.endswith('.ihx') or file_data[0]==58: + if(flash_file != ''): + flash_write_data = list(open(flash_file, 'rb').read()) + if(flash_file.endswith('.hex') or flash_file.endswith('.ihx')): print("WARNING: This looks like a hex file. This tool only supports binary files.") - if len(file_data) > chip_ref['flash_size']: - print('The binary is too large for the device.') - print('Binary size: %d, Flash size: %d' % (len(file_data),chip_ref['flash_size'])) + if len(flash_write_data) > chip_ref['flash_size']: + print('The binary for flashing is too large for the device.') + print('Binary size: %d, Flash size: %d' % (len(flash_write_data),chip_ref['flash_size'])) sys.exit(-1) - - if(float(ver_str)<2.3): - sys.exit('Bootloader version not supported.') - - chk_sum = __chip_uid_chk_sum(chip_subid, uid) - - enc_key, key_b = __gen_key_values(chip_id, chk_sum) - ret = __send_key_base(dev,key_b) - if ret is None: - sys.exit('Failed to write key for flash write to CH5xx.') + if(flash_file != '' or args.erase_flash==True): + print('Erasing chip flash.',end="") ret = __erase_chip_ch5xx(dev,chip_ref) if ret is None: - sys.exit('Failed to erase CH55x.') - - ret = __flash_ops_write_verify(dev, enc_key, file_data, func="Write") - if ret is None: - sys.exit('Failed to flash firmware of CH55x.') - - enc_key, key_b = __gen_key_values(chip_id, chk_sum) - ret = __send_key_base(dev,key_b) - if ret is None: - sys.exit('Failed to write key for flash verify to CH5xx.') - - ret = __flash_ops_write_verify(dev, enc_key, file_data, func="Verify") - if ret is None: - sys.exit('Failed to verify firmware of CH55x.') - - ret, ret_pl = __end_flash_ch5xx(dev, restart_after = args.reset_at_end) - if(ret is True): - print('Flash done.',end="") - print(' Restart and run.') - elif(ret is None): - sys.exit('Failed to end flash process. No response.') + sys.exit(' Failed to erase CH55x.') + else: + print(' Done.') + + if(flash_file != ''): + if(len(flash_write_data)>0): + if(flash_write_data[0]==58): + print("WARNING: Flashing data looks like a hex file. This tool only supports binary files.") + enc_key, key_b = __gen_key_values(chip_id, chk_sum) + ret = __send_key_base(dev,key_b) + if ret is None: + sys.exit('Failed to write key for flash write to CH5xx.') + print('Flashing chip.',end='') + ret = __flash_ops_write_verify(dev, enc_key, flash_write_data, func="Write") + if ret is None: + sys.exit('Failed to flash firmware of CH55x.') + else: + print(' Done.') + else: + print('Nothing to write to program flash.') + + if(args.verify_flash != None): + if(args.verify_flash != ''): + flash_verify_data = list(open(args.verify_flash, 'rb').read()) + if(args.verify_flash.endswith('.hex') or args.verify_flash.endswith('.ihx')): + print("WARNING: This looks like a hex file. This tool only supports binary files.") + if len(flash_verify_data) > chip_ref['flash_size']: + print('The binary for verifying is too large for the device.') + print('Binary size: %d, Flash size: %d' % (len(flash_verify_data),chip_ref['flash_size'])) + sys.exit(-1) + else: + if(flash_file == ''): + flash_verify_data = b'' + else: + flash_verify_data = flash_write_data + + if(len(flash_verify_data)>0): + if(flash_verify_data[0]==58): + print("WARNING: Verifying data looks like a hex file. This tool only supports binary files.") + enc_key, key_b = __gen_key_values(chip_id, chk_sum) + ret = __send_key_base(dev,key_b) + if ret is None: + sys.exit('Failed to write key for flash verify to CH5xx.') + print('Verifying flash.',end='') + ret = __flash_ops_write_verify(dev, enc_key, flash_verify_data, func="Verify") + if ret is None: + sys.exit(' Failed to verify firmware of CH55x.') + else: + print(' Done.') + else: + print('Nothing to verifying with program flash.') + + print('Finalize communication.',end="") + ret, ret_pl = __end_flash_ch5xx(dev, restart_after = args.reset_at_end) + if(ret is True): + print(' Restart and run.') + elif(ret is None): + sys.exit('Failed to finish communication. No response.') + else: + if(ret_pl != None): + if ret_pl[0] != 0x00: + resp_str = ' Response: %02x' % (ret_pl[0]) + sys.exit('Failed to finish communication.'+ resp_str) + else: + print(' Done.') else: - if(ret_pl != None): - if ret_pl[0] != 0x00: - resp_str = ' Response: %02x' % (ret_pl[0]) - sys.exit('Failed to end flash process.'+ resp_str) - else: - print('Flash done.') + sys.exit('Failed to finish communication. Response without value.') if __name__ == '__main__': sys.exit(main()) From 4124fd82172dfeb7c6df758f3691d2e6496c3a4f Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Mon, 21 Mar 2022 21:10:18 +0200 Subject: [PATCH 09/21] Added data flash operations. Added command lines and related functions, all those additional work individualy too.: -g/--read_dataflash -d/--data -c/--erase_dataflash --verify_data [filename] --- README.md | 7 +- ch55xtool/ch55xtool.py | 147 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 141 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 92c02a9..6617299 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,14 @@ An open sourced python command line flash tool for flashing WinChipHead CH55x se Usage ------------ * __-f/--flash \__ Erase the whole chip, and flash the bin file to the CH55x. -* __-e/--erase\_flash__ Erase the whole chip. +* __-e/--erase\_flash__ Erase the whole program flash. * __--verify\_flash__ [filename] Verify program flash contend with given file, if filename ommited verifying with flashed data. No verifying perormed without this flag. * __-r/--reset\_at\_end__ Issue reset and run after all. +* __-d/--data \__ Erase the whole data flash and write the bin file to the CH55x. +* __-e/--erase\_flash__ Erase the whole data flash. +* __--verify\_data__ [filename] Verify data flash contend with given file, if filename ommited verifying with written data. No verifying perormed without this flag. +* __-g/--read\_dataflash__ Read content of data flash to file. + ```bash python3 -m ch55xtool -f THE_BINARY_FILE.bin diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index e784b2b..6470335 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -250,11 +250,15 @@ def __send_key_base(dev, key_base): else: return None -def __flash_ops_write_verify(dev, key_xor_chksum, data, func="Write",max_packet_size=64): - if(func not in [ 'Write' , 'Verify'] ): +def __flash_ops_write_verify(dev, key_xor_chksum, data, func="FlashWrite"): + if(func not in [ 'FlashWrite' , 'FlashVerify', 'DataWrite'] ): return None data_length = len(data) curr_addr = 0 + cfg = dev.get_active_configuration() + intf = cfg[(0,0)] + ep_out = usb.util.find_descriptor(intf, bEndpointAddress=EP_OUT_ADDR) + max_packet_size = ep_out.wMaxPacketSize max_data_len_perpack = max_packet_size - 3 - 5 data_buff = bytearray(max_data_len_perpack) while curr_addr < data_length: @@ -276,7 +280,7 @@ def __flash_ops_write_verify(dev, key_xor_chksum, data, func="Write",max_packet_ cmd_pl = curr_addr.to_bytes(4,'little') + bytes([random.randint(0,255)]) + data_buff[:pkt_length] - ret, ret_pl = cmd_exec(dev, 'Flash'+func, cmd_pl) + ret, ret_pl = cmd_exec(dev, func, cmd_pl) if( ret == None or ret_pl[0] != 0x00): return None curr_addr = curr_addr + pkt_length @@ -285,7 +289,32 @@ def __flash_ops_write_verify(dev, key_xor_chksum, data, func="Write",max_packet_ else: return curr_addr -def __erase_chip_ch5xx(dev, chip_ref): +def __data_flash_read(dev, data_flash_size): + curr_addr = 0 + read_data = b'' + cfg = dev.get_active_configuration() + intf = cfg[(0,0)] + ep_in = usb.util.find_descriptor(intf, bEndpointAddress=EP_IN_ADDR) + max_packet_size = ep_in.wMaxPacketSize + max_rcv_len_perpack = max_packet_size - 4 - 2 + while curr_addr < data_flash_size: + left_len = data_flash_size - curr_addr + if (left_len) > max_rcv_len_perpack: + rcv_pkt_length = max_rcv_len_perpack + else: + rcv_pkt_length = left_len + cmd_pl = curr_addr.to_bytes(4,'little') + rcv_pkt_length.to_bytes(2,'little') + ret, ret_pl = cmd_exec(dev, 'DataRead', cmd_pl) + if( ret == None or ret_pl[0] != 0x00): + return None, read_data + read_data += bytes(ret_pl[2:]) + curr_addr = curr_addr + len(ret_pl[2:]) + if(curr_addr > data_flash_size): + return data_flash_size, read_data + else: + return curr_addr, read_data + +def __erase_program_flash_ch5xx(dev, chip_ref): # We assume pages size is 1kb erase_page_cnt = chip_ref['flash_size']>>10 cmd_pl = erase_page_cnt.to_bytes(4,'little') @@ -295,6 +324,16 @@ def __erase_chip_ch5xx(dev, chip_ref): else: return None +def __erase_data_flash_ch5xx(dev, chip_ref): + # We assume pages size is 1kb + erase_page_cnt = chip_ref['dataflash_size']>>10 + cmd_pl = int(0).to_bytes(4,'little') + erase_page_cnt.to_bytes(1,'little') + ret, ret_pl = cmd_exec(dev,'DataErase', cmd_pl) + if ret_pl[0] == 0: + return True + else: + return None + def __end_flash_ch5xx(dev, restart_after = False): cmd_pl = bytes([restart_after]) if(restart_after): @@ -307,9 +346,10 @@ def __end_flash_ch5xx(dev, restart_after = False): def main(): parser = argparse.ArgumentParser( description="USBISP Tool For WinChipHead CH55x/CH56x .") + parser.add_argument( '-f', '--flash', type=str, default='', - help="The target file to be flashed. This must be a binary file (hex files are not supported). Flashing include chipe erase in front.") + help="The target file to be written to program flash. This must be a binary file (hex files are not supported). Flashing include chipe erase in front.") parser.add_argument( '-e', '--erase_flash', action='store_true', default=False, help="Erase chip program flash.") @@ -318,8 +358,18 @@ def main(): help="Verify flash.") parser.add_argument( - '-c', '--clean', action='store_true', default=False, + '-d', '--data', type=str, default='', + help="The target file to be written to data flash. This must be a binary file (hex files are not supported). Flashing include chipe erase in front.") + parser.add_argument( + '-c', '--erase_dataflash', action='store_true', default=False, help="Clean chip data eeprom.") + parser.add_argument( + '-g', '--read_dataflash', type=str, default='', + help="Read chip data eeprom.") + parser.add_argument( + '--verify_data', type=str, action='store', nargs='?', const='', default=None, + help="Verify data flash.") + parser.add_argument( '-r', '--reset_at_end', action='store_true', default=False, @@ -376,9 +426,82 @@ def main(): chk_sum = __chip_uid_chk_sum(chip_subid, uid) + if(args.read_dataflash !=''): + ret, ret_data = __data_flash_read(dev, chip_ref['dataflash_size']) + if(ret is not None): + data_write_file = open(args.read_dataflash,'wb') + data_write_file.write(ret_data) + data_write_file.close() + + if(args.data != ''): + dataflash_write_data = open(args.data, 'rb').read() + if(args.data.endswith('.hex') or args.data.endswith('.ihx')): + print("WARNING: This looks like a hex file. This tool only supports binary files.") + if len(dataflash_write_data) > chip_ref['dataflash_size']: + print('The binary for Data flashing is too large for the device.') + print('Binary size: %d, DataFlash size: %d' % (len(dataflash_write_data),chip_ref['dataflash_size'])) + sys.exit(-1) + + if(args.data != '' or args.erase_dataflash==True): + print('Erasing chip data flash.',end="") + ret = __erase_data_flash_ch5xx(dev,chip_ref) + if ret is None: + sys.exit(' Failed.') + else: + print(' Done.') + + if(args.data != ''): + if(len(dataflash_write_data)>0): + if(dataflash_write_data[0]==58): + print("WARNING: Flashing data looks like a hex file. This tool only supports binary files.") + enc_key, key_b = __gen_key_values(chip_id, chk_sum) + ret = __send_key_base(dev,key_b) + if ret is None: + sys.exit('Failed to write key for DataFlash write to CH5xx.') + print('DataFlashing chip.',end='') + ret = __flash_ops_write_verify(dev, enc_key, dataflash_write_data, func="DataWrite") + if ret is None: + sys.exit('Failed.') + else: + print(' Done.') + else: + print('Nothing to write to program flash.') + + if(args.verify_data != None): + if(args.verify_data != ''): + dataflash_verify_data = open(args.verify_data, 'rb').read() + if(args.verify_data.endswith('.hex') or args.verify_data.endswith('.ihx')): + print("WARNING: This looks like a hex file. This tool only supports binary files.") + if len(dataflash_verify_data) > chip_ref['dataflash_size']: + print('The binary for verifying is too large for the device.') + print('Binary size: %d, DataFlash size: %d' % (len(dataflash_verify_data),chip_ref['dataflash_size'])) + sys.exit(-1) + else: + if(args.data == ''): + dataflash_verify_data = b'' + else: + dataflash_verify_data = dataflash_write_data + + if(len(dataflash_verify_data)>0): + if(dataflash_verify_data[0]==58): + print("WARNING: Verifying data looks like a hex file. This tool only supports binary files.") + + print('Verifying Dataflash.',end='') + ret, ret_data = __data_flash_read(dev, len(dataflash_verify_data)) + if ret is None: + sys.exit(' Data read failed.') + elif(ret_data != dataflash_verify_data): + print(ret_data) + print(dataflash_verify_data) + sys.exit(' Compare failed.') + else: + print(' Done.') + else: + print('Nothing to verifying with data flash.') + flash_file = args.flash if(flash_file != ''): - flash_write_data = list(open(flash_file, 'rb').read()) + flash_write_data = open(flash_file, 'rb').read() if(flash_file.endswith('.hex') or flash_file.endswith('.ihx')): print("WARNING: This looks like a hex file. This tool only supports binary files.") if len(flash_write_data) > chip_ref['flash_size']: @@ -388,9 +511,9 @@ def main(): if(flash_file != '' or args.erase_flash==True): print('Erasing chip flash.',end="") - ret = __erase_chip_ch5xx(dev,chip_ref) + ret = __erase_program_flash_ch5xx(dev,chip_ref) if ret is None: - sys.exit(' Failed to erase CH55x.') + sys.exit(' Failed.') else: print(' Done.') @@ -403,7 +526,7 @@ def main(): if ret is None: sys.exit('Failed to write key for flash write to CH5xx.') print('Flashing chip.',end='') - ret = __flash_ops_write_verify(dev, enc_key, flash_write_data, func="Write") + ret = __flash_ops_write_verify(dev, enc_key, flash_write_data, func="FlashWrite") if ret is None: sys.exit('Failed to flash firmware of CH55x.') else: @@ -413,7 +536,7 @@ def main(): if(args.verify_flash != None): if(args.verify_flash != ''): - flash_verify_data = list(open(args.verify_flash, 'rb').read()) + flash_verify_data = open(args.verify_flash, 'rb').read() if(args.verify_flash.endswith('.hex') or args.verify_flash.endswith('.ihx')): print("WARNING: This looks like a hex file. This tool only supports binary files.") if len(flash_verify_data) > chip_ref['flash_size']: @@ -434,7 +557,7 @@ def main(): if ret is None: sys.exit('Failed to write key for flash verify to CH5xx.') print('Verifying flash.',end='') - ret = __flash_ops_write_verify(dev, enc_key, flash_verify_data, func="Verify") + ret = __flash_ops_write_verify(dev, enc_key, flash_verify_data, func="FlashVerify") if ret is None: sys.exit(' Failed to verify firmware of CH55x.') else: From ec269533cce55ebe433a64edbc4045be0cba840e Mon Sep 17 00:00:00 2001 From: Pe3ucTop <16417349+Pe3ucTop@users.noreply.github.com> Date: Mon, 21 Mar 2022 21:27:39 +0200 Subject: [PATCH 10/21] Update README.md Fix command for data flash erase. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6617299..4c708ce 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Usage * __--verify\_flash__ [filename] Verify program flash contend with given file, if filename ommited verifying with flashed data. No verifying perormed without this flag. * __-r/--reset\_at\_end__ Issue reset and run after all. * __-d/--data \__ Erase the whole data flash and write the bin file to the CH55x. -* __-e/--erase\_flash__ Erase the whole data flash. +* __-c/--erase\_dataflash__ Erase the whole data flash. * __--verify\_data__ [filename] Verify data flash contend with given file, if filename ommited verifying with written data. No verifying perormed without this flag. * __-g/--read\_dataflash__ Read content of data flash to file. From 308584ae63efad5a5aadbd59ce244b68666048ed Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Tue, 22 Mar 2022 12:57:20 +0200 Subject: [PATCH 11/21] Reworked chips definition (parameters) to be taken from attached original "WCHISP/ChipType/typeall.wcfg" INI type file. --- ch55xtool/ch55xtool.py | 39 ++-- ch55xtool/typeall.wcfg | 456 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 478 insertions(+), 17 deletions(-) create mode 100644 ch55xtool/typeall.wcfg diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index 6470335..5e9f762 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -10,6 +10,7 @@ import usb.core import usb.util +import configparser # ======= Some C-like static constants ======= DFU_ID_VENDOR = 0x4348 DFU_ID_PRODUCT = 0x55e0 @@ -19,22 +20,6 @@ USB_MAX_TIMEOUT = 2000 -CH55X_IC_REF = { - 0x3f:{'name':'CH32V103', 'flash_size': 64*1024, 'dataflash_size': 0, 'chip_id': 0x3f, 'erase_required_pages':True}, - 0x49:{'name':'CH549', 'flash_size': 60*1024, 'dataflash_size': 1024, 'chip_id': 0x49, 'erase_required_pages':False}, - 0x51:{'name':'CH551', 'flash_size': 10240, 'dataflash_size': 128, 'chip_id': 0x51, 'erase_required_pages':False}, - 0x52:{'name':'CH552', 'flash_size': 16384, 'dataflash_size': 128, 'chip_id': 0x52, 'erase_required_pages':False}, - 0x53:{'name':'CH553', 'flash_size': 10240, 'dataflash_size': 128, 'chip_id': 0x53, 'erase_required_pages':False}, - 0x54:{'name':'CH554', 'flash_size': 14336, 'dataflash_size': 128, 'chip_id': 0x54, 'erase_required_pages':False}, - 0x59:{'name':'CH559', 'flash_size': 61440, 'dataflash_size': 128, 'chip_id': 0x59, 'erase_required_pages':False}, - 0x68:{'name':'CH568', 'flash_size': 192*1024, 'dataflash_size': 32*1024, 'chip_id': 0x68, 'erase_required_pages':False}, - 0x70:{'name':'CH32V307', 'flash_size': 256*1024, 'dataflash_size': 128, 'chip_id': 0x70, 'erase_required_pages':False}, - 0x71:{'name':'CH571', 'flash_size': 192*1024, 'dataflash_size': 0, 'chip_id': 0x71, 'erase_required_pages':True}, - 0x73:{'name':'CH573', 'flash_size': 448*1024, 'dataflash_size': 0, 'chip_id': 0x73, 'erase_required_pages':True}, - 0x79:{'name':'CH579', 'flash_size': 256*1024, 'dataflash_size': 0, 'chip_id': 0x79, 'erase_required_pages':True}, - 0x82:{'name':'CH582', 'flash_size': 448*1024, 'dataflash_size': 0, 'chip_id': 0x82, 'erase_required_pages':True}, -} - # ============================================= WCH_CMDS = { "Detect": b'\xA1', "End": b'\xA2', @@ -64,6 +49,23 @@ CFG_FLAG_UID = 0x10 # ============================================= +def get_chip_parameters(chip_id,wcfg_path): + chip_params = {} + params_ini = configparser.ConfigParser() + params_ini.optionxform = lambda option: option + params_ini.read(wcfg_path+'/typeall.wcfg') + for section in params_ini.sections(): + if(params_ini.has_option(section,'chipid')): + if(params_ini.getint(section,'chipid') == chip_id): + chip_params.update({'name':section}) + chip_params.update({'chip_id':chip_id}) + chip_params.update({'flash_size':params_ini.getint(section,'MaxFlashSize')}) + chip_params.update({'dataflash_size':params_ini.getint(section,'MaxEepromSize')}) + chip_params.update({'McuType':params_ini.getint(section,'McuType')}) + break + else: + chip_params = None + return chip_params def cmd_send(dev, cmd_bin, payload): pl_len = len(payload) @@ -344,6 +346,9 @@ def __end_flash_ch5xx(dev, restart_after = False): return cmd_exec(dev, "End", cmd_pl) def main(): + pathname = os.path.dirname(sys.argv[0]) + fullpath = os.path.abspath(pathname) + parser = argparse.ArgumentParser( description="USBISP Tool For WinChipHead CH55x/CH56x .") @@ -396,7 +401,7 @@ def main(): print('Welcome to report this issue with a screen shot from the official CH5xx tool.') sys.exit(-1) - chip_ref = CH55X_IC_REF.get(chip_id) + chip_ref = get_chip_parameters(chip_id, fullpath) if chip_ref is None: print('Chip ID: %x is not known = not supported' % chip_id) print('Welcome to report this issue with a screen shot from the official CH5xx tool.') diff --git a/ch55xtool/typeall.wcfg b/ch55xtool/typeall.wcfg new file mode 100644 index 0000000..d9281f6 --- /dev/null +++ b/ch55xtool/typeall.wcfg @@ -0,0 +1,456 @@ +[WCHCHIP] +ChipName0=CH561 +ChipName1=CH563 +ChipName2=CH565 +ChipName3=CH566 +ChipName4=CH567 +ChipName5=CH568 +ChipName6=CH569 +ChipName7=CH551 +ChipName8=CH552 +ChipName9=CH554 +ChipName10=CH555 +ChipName11=CH556 +ChipName12=CH557 +ChipName13=CH558 +ChipName14=CH559 +ChipName15=CH544 +ChipName16=CH545 +ChipName17=CH546 +ChipName18=CH547 +ChipName19=CH548 +ChipName20=CH549 +ChipName21=CH571 +ChipName22=CH573 +ChipName23=CH577 +ChipName24=CH578 +ChipName25=CH579 +ChipName26=CH32F103 +ChipName27=CH32V103 +ChipName28=CH581 +ChipName29=CH582 +ChipName30=CH583 +ChipName31=CH32V303 +ChipName32=CH32V305 +ChipName33=CH32V307 +ChipName34=CH32F203 +ChipName35=CH32F205 +ChipName36=CH32F207 +ChipName37=CH32F208 +ChipName38= +ChipName39= +ChipName40= + +[CH561] +McuType=0 +MaxFlashSize=65536 +MaxEepromSize=28672 +IsNetworkDown=1 +IsUsbDown=0 +IsSerialDown=1 +chipid=97 + +[CH563] +McuType=0 +MaxFlashSize=229376 +MaxEepromSize=28672 +IsNetworkDown=1 +IsUsbDown=1 +IsSerialDown=1 +chipid=99 + +[CH565] +McuType=0 +MaxFlashSize=458752 +MaxEepromSize=32768 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=101 +eepromStartAddr=0 +Introduction = "" + +[CH566] +McuType=0 +MaxFlashSize=65536 +MaxEepromSize=32768 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=102 +eepromStartAddr=0 +Introduction = "" + +[CH567] +McuType=0 +MaxFlashSize=196608 +MaxEepromSize=32768 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=103 +eepromStartAddr=0 +Introduction = "" + +[CH568] +McuType=0 +MaxFlashSize=196608 +MaxEepromSize=32768 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=104 +eepromStartAddr=0 +Introduction = "" + +[CH569] +McuType=0 +MaxFlashSize=458752 +MaxEepromSize=32768 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=105 +eepromStartAddr=0 +Introduction = "" + +[CH551] +McuType=1 +MaxFlashSize=10240 +MaxEepromSize=128 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=0 +chipid=81 +eepromStartAddr=49152 +Introduction = "" + +[CH552] +McuType=1 +MaxFlashSize=14336 +MaxEepromSize=128 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=82 +eepromStartAddr=49152 +Introduction = "" + +[CH554] +McuType=1 +MaxFlashSize=14336 +MaxEepromSize=128 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=84 +eepromStartAddr=49152 +Introduction = "" + +[CH555] +McuType=1 +MaxFlashSize=61440 +MaxEepromSize=1024 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=85 +eepromStartAddr=61440 +Introduction = "" + +[CH556] +McuType=1 +MaxFlashSize=61440 +MaxEepromSize=1024 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=86 +eepromStartAddr=61440 +Introduction = "" + +[CH557] +McuType=1 +MaxFlashSize=61440 +MaxEepromSize=1024 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=87 +eepromStartAddr=61440 +Introduction = "" + +[CH558] +McuType=1 +MaxFlashSize=32768 +MaxEepromSize=5120 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=88 +eepromStartAddr=57344 +Introduction = "" + +[CH559] +McuType=1 +MaxFlashSize=61440 +MaxEepromSize=1024 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=89 +eepromStartAddr=61440 +Introduction = "" + +[CH544] +McuType=2 +MaxFlashSize=61440 +MaxEepromSize=3072 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=68 +eepromStartAddr=61440 +Introduction = "" + +[CH545] +McuType=2 +MaxFlashSize=61440 +MaxEepromSize=3072 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=69 +eepromStartAddr=61440 +Introduction = "" + +[CH546] +McuType=2 +MaxFlashSize=32768 +MaxEepromSize=1024 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=70 +eepromStartAddr=61440 +Introduction = "" + +[CH547] +McuType=2 +MaxFlashSize=61440 +MaxEepromSize=1024 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=71 +eepromStartAddr=61440 +Introduction = "" + +[CH548] +McuType=2 +MaxFlashSize=32768 +MaxEepromSize=1024 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=72 +eepromStartAddr=61440 +Introduction = "" + +[CH549] +McuType=2 +MaxFlashSize=61440 +MaxEepromSize=1024 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=73 +eepromStartAddr=61440 +Introduction = "" + +[CH571] +McuType=3 +MaxFlashSize=196608 +MaxEepromSize=32768 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=113 +eepromStartAddr=256000 +Introduction = "" + +[CH573] +McuType=3 +MaxFlashSize=458752 +MaxEepromSize=32768 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=115 +eepromStartAddr=256000 +Introduction = "" + +[CH577] +McuType=3 +MaxFlashSize=131072 +MaxEepromSize=2048 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=119 +eepromStartAddr=131072 +Introduction = "" + +[CH578] +McuType=3 +MaxFlashSize=163840 +MaxEepromSize=2048 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=120 +eepromStartAddr=163840 +Introduction = "" + +[CH579] +McuType=3 +MaxFlashSize=256000 +MaxEepromSize=2048 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=121 +eepromStartAddr=256000 +Introduction = "" + +[CH32F103] +McuType=4 +MaxFlashSize=65536 +MaxEepromSize=0 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=50 +eepromStartAddr=0 +Introduction = "" + +[CH32V103] +McuType=5 +MaxFlashSize=65536 +MaxEepromSize=0 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=50 +eepromStartAddr=0 +Introduction = "" + +[CH581] +McuType=6 +MaxFlashSize=196608 +MaxEepromSize=32768 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=129 +eepromStartAddr=0 +Introduction = "" + +[CH582] +McuType=6 +MaxFlashSize=458752 +MaxEepromSize=32768 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=130 +eepromStartAddr=0 +Introduction = "" + +[CH583] +McuType=6 +MaxFlashSize=458752 +MaxEepromSize=557056 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=131 +eepromStartAddr=0 +Introduction = "" + +[CH32V303] +McuType=7 +MaxFlashSize=262144 +MaxEepromSize=0 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=48 +eepromStartAddr=0 +Introduction = "" + +[CH32V305] +McuType=7 +MaxFlashSize=131072 +MaxEepromSize=0 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=80 +eepromStartAddr=0 +Introduction = "" + +[CH32V307] +McuType=7 +MaxFlashSize=262144 +MaxEepromSize=0 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=112 +eepromStartAddr=0 +Introduction = "" + +[CH32F203] +McuType=8 +MaxFlashSize=262144 +MaxEepromSize=0 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=48 +eepromStartAddr=0 +Introduction = "" + +[CH32F205] +McuType=8 +MaxFlashSize=131072 +MaxEepromSize=0 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=80 +eepromStartAddr=0 +Introduction = "" + +[CH32F207] +McuType=8 +MaxFlashSize=262144 +MaxEepromSize=0 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=112 +eepromStartAddr=0 +Introduction = "" + +[CH32F208] +McuType=8 +MaxFlashSize=131072 +MaxEepromSize=0 +IsNetworkDown=0 +IsUsbDown=1 +IsSerialDown=1 +chipid=128 +eepromStartAddr=0 +Introduction = "" \ No newline at end of file From 081a3d2626a92b76e5c38c1cc10375498c65e15c Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Tue, 22 Mar 2022 13:30:11 +0200 Subject: [PATCH 12/21] Adder chip configuration bits printout option. --- README.md | 1 + ch55xtool/ch55xtool.py | 93 +++++++++++++++++++++++++----------------- 2 files changed, 56 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 4c708ce..b45e6d7 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Usage * __-c/--erase\_dataflash__ Erase the whole data flash. * __--verify\_data__ [filename] Verify data flash contend with given file, if filename ommited verifying with written data. No verifying perormed without this flag. * __-g/--read\_dataflash__ Read content of data flash to file. +* __-p/--print\_chip\_cfg__ Read and print chip configuration bits 3 x 32 bit values. ```bash diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index 5e9f762..3a6e49d 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -40,13 +40,13 @@ DETECT_APP_ID_B = b'MCU ISP & WCH.CN' # Unknown bits work only all together like 0x07 !! -CFG_FLAG_UNKN1 = 0x01 -CFG_FLAG_UNKN2 = 0x02 -CFG_FLAG_UNKN3 = 0x04 -CFG_FLAG_UNKNs = CFG_FLAG_UNKN1 | CFG_FLAG_UNKN2 | CFG_FLAG_UNKN3 +FLAG_CFG1 = 0x01 +FLAG_CFG2 = 0x02 +FLAG_CFG3 = 0x04 +FLAG_CFGs = FLAG_CFG1 | FLAG_CFG2 | FLAG_CFG3 # Those bits work individualy -CFG_FLAG_BOOTVER = 0x08 -CFG_FLAG_UID = 0x10 +FLAG_BOOTVER = 0x08 +FLAG_UID = 0x10 # ============================================= def get_chip_parameters(chip_id,wcfg_path): @@ -136,11 +136,11 @@ def __detect_ch5xx(dev): def __read_cfg_ch5xx(dev, req_fields, chip_id, chip_subid): predict_ret_pl_len = 2 # 2 byte for fields - if(req_fields & CFG_FLAG_UNKN1): predict_ret_pl_len += 4 - if(req_fields & CFG_FLAG_UNKN2): predict_ret_pl_len += 4 - if(req_fields & CFG_FLAG_UNKN3): predict_ret_pl_len += 4 - if(req_fields & CFG_FLAG_BOOTVER): predict_ret_pl_len += 4 - if(req_fields & CFG_FLAG_UID): predict_ret_pl_len += 8 + if(req_fields & FLAG_CFG1): predict_ret_pl_len += 4 + if(req_fields & FLAG_CFG2): predict_ret_pl_len += 4 + if(req_fields & FLAG_CFG3): predict_ret_pl_len += 4 + if(req_fields & FLAG_BOOTVER): predict_ret_pl_len += 4 + if(req_fields & FLAG_UID): predict_ret_pl_len += 8 cmd_pl = req_fields.to_bytes(2,'little') ret, ret_pl = cmd_exec(dev, 'ReadConfig', cmd_pl) @@ -158,27 +158,27 @@ def __read_cfg_ch5xx(dev, req_fields, chip_id, chip_subid): print("Reply fields do not match requested!") cfg_dict["Fields"] = reply_fields - if(reply_fields & CFG_FLAG_UNKN1): - cfg_dict[CFG_FLAG_UNKN1] = int.from_bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4],'little') + if(reply_fields & FLAG_CFG1): + cfg_dict[FLAG_CFG1] = int.from_bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4],'little') reply_prc_bytes += 4 - if(reply_fields & CFG_FLAG_UNKN2): - cfg_dict[CFG_FLAG_UNKN2] = int.from_bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4],'little') + if(reply_fields & FLAG_CFG2): + cfg_dict[FLAG_CFG2] = int.from_bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4],'little') reply_prc_bytes += 4 - if(reply_fields & CFG_FLAG_UNKN3): - cfg_dict[CFG_FLAG_UNKN3] = int.from_bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4],'little') + if(reply_fields & FLAG_CFG3): + cfg_dict[FLAG_CFG3] = int.from_bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4],'little') reply_prc_bytes += 4 - if(reply_fields & CFG_FLAG_BOOTVER): - cfg_dict[CFG_FLAG_BOOTVER] = bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4]) + if(reply_fields & FLAG_BOOTVER): + cfg_dict[FLAG_BOOTVER] = bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4]) reply_prc_bytes += 4 - if(reply_fields & CFG_FLAG_UID): + if(reply_fields & FLAG_UID): if((chip_subid == 0x11) and (chip_id not in [0x55, 0x56, 0x57])): - cfg_dict[CFG_FLAG_UID] = bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4]) + b'\x00'*4 + cfg_dict[FLAG_UID] = bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+4]) + b'\x00'*4 else: - cfg_dict[CFG_FLAG_UID] = bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+8]) + cfg_dict[FLAG_UID] = bytes(ret_pl[reply_prc_bytes:reply_prc_bytes+8]) reply_prc_bytes += 8 return ret, cfg_dict @@ -190,29 +190,29 @@ def __write_cfg_ch5xx(dev, cfg_dict): return None, None set_fields = 0 cmd_pl = b'' - if(cfg_fields & CFG_FLAG_UNKN1): - field_val = cfg_dict.get(CFG_FLAG_UNKN1) + if(cfg_fields & FLAG_CFG1): + field_val = cfg_dict.get(FLAG_CFG1) if(field_val != None and len(field_val) == 4): - set_fields |= CFG_FLAG_UNKN1 + set_fields |= FLAG_CFG1 cmd_pl += field_val.to_bytes(4,'little') else: - print("Incorrect or no value for cfg field 0x%02X"%(CFG_FLAG_UNKN1)) + print("Incorrect or no value for cfg field 0x%02X"%(FLAG_CFG1)) - if(cfg_fields & CFG_FLAG_UNKN2): - field_val = cfg_dict.get(CFG_FLAG_UNKN2) + if(cfg_fields & FLAG_CFG2): + field_val = cfg_dict.get(FLAG_CFG2) if(field_val != None and len(field_val) == 4): - set_fields |= CFG_FLAG_UNKN2 + set_fields |= FLAG_CFG2 cmd_pl += field_val.to_bytes(4,'little') else: - print("Incorrect or no value for cfg field 0x%02X"%(CFG_FLAG_UNKN2)) + print("Incorrect or no value for cfg field 0x%02X"%(FLAG_CFG2)) - if(cfg_fields & CFG_FLAG_UNKN3): - field_val = cfg_dict.get(CFG_FLAG_UNKN3) + if(cfg_fields & FLAG_CFG3): + field_val = cfg_dict.get(FLAG_CFG3) if(field_val != None and len(field_val) == 4): - set_fields |= CFG_FLAG_UNKN3 + set_fields |= FLAG_CFG3 cmd_pl += field_val.to_bytes(4,'little') else: - print("Incorrect or no value for cfg field 0x%02X"%(CFG_FLAG_UNKN3)) + print("Incorrect or no value for cfg field 0x%02X"%(FLAG_CFG3)) if(set_fields > 0): cmd_pl = set_fields.to_bytes(2,'little') + cmd_pl @@ -375,6 +375,9 @@ def main(): '--verify_data', type=str, action='store', nargs='?', const='', default=None, help="Verify data flash.") + parser.add_argument( + '-p', '--print_chip_cfg', action='store_true', default=False, + help="Read and print chip configuration bits 3 x 32bit values.") parser.add_argument( '-r', '--reset_at_end', action='store_true', default=False, @@ -409,13 +412,13 @@ def main(): print('Found %s with SubId:%d' % (chip_ref['name'], chip_subid)) - ret, chip_cfg = __read_cfg_ch5xx(dev, CFG_FLAG_BOOTVER | CFG_FLAG_UID | CFG_FLAG_UNKNs, chip_id, chip_subid) + ret, chip_cfg = __read_cfg_ch5xx(dev, FLAG_BOOTVER | FLAG_UID, chip_id, chip_subid) if ret is None: - print('Cannot read chip configuration!') + print('Cannot read chip bootloader version/uniqe ID.') sys.exit(-1) else: - bootver = chip_cfg.get(CFG_FLAG_BOOTVER) - uid = chip_cfg.get(CFG_FLAG_UID) + bootver = chip_cfg.get(FLAG_BOOTVER) + uid = chip_cfg.get(FLAG_UID) if( bootver is None or uid is None): print('Cannot read chip bootloader version or uniqe ID.') sys.exit(-1) @@ -431,6 +434,20 @@ def main(): chk_sum = __chip_uid_chk_sum(chip_subid, uid) + if(args.print_chip_cfg): + ret, chip_cfg = __read_cfg_ch5xx(dev, FLAG_CFGs, chip_id, chip_subid) + if ret is None: + print('Cannot read chip configs variables.') + sys.exit(-1) + else: + cfg1 = chip_cfg.get(FLAG_CFG1) + cfg2 = chip_cfg.get(FLAG_CFG2) + cfg3 = chip_cfg.get(FLAG_CFG3) + if( cfg1 is None or cfg2 is None or cfg3 is None): + print('Cannot find chip configurations after read.') + sys.exit(-1) + print("Chip configs 0x%08X 0x%08X 0x%08X" % (cfg1, cfg2, cfg3) ) + if(args.read_dataflash !=''): ret, ret_data = __data_flash_read(dev, chip_ref['dataflash_size']) if(ret is not None): From b589fe03dfd7536513484abbcb6ae4a55631c1c7 Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Tue, 22 Mar 2022 18:03:21 +0200 Subject: [PATCH 13/21] Updated USB_MAX_TIMEOUT to 5000 to not fail long erase case. --- ch55xtool/ch55xtool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index 3a6e49d..71a47a8 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -18,7 +18,7 @@ EP_OUT_ADDR = 0x02 EP_IN_ADDR = 0x82 -USB_MAX_TIMEOUT = 2000 +USB_MAX_TIMEOUT = 5000 # ============================================= WCH_CMDS = { "Detect": b'\xA1', From 6fed693f435abc4e2bf66ef8df338475902ca719 Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Wed, 23 Mar 2022 12:57:14 +0200 Subject: [PATCH 14/21] Update Data(EEPROM) erase function to pass value 1 even if size is less than 1kib. --- ch55xtool/ch55xtool.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index 71a47a8..5f0d8a0 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -329,6 +329,8 @@ def __erase_program_flash_ch5xx(dev, chip_ref): def __erase_data_flash_ch5xx(dev, chip_ref): # We assume pages size is 1kb erase_page_cnt = chip_ref['dataflash_size']>>10 + if(erase_page_cnt == 0): + erase_page_cnt = 1 cmd_pl = int(0).to_bytes(4,'little') + erase_page_cnt.to_bytes(1,'little') ret, ret_pl = cmd_exec(dev,'DataErase', cmd_pl) if ret_pl[0] == 0: From a36ca783567778e52fdad8c79544dc1cc8cb6ee6 Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Wed, 23 Mar 2022 18:23:58 +0200 Subject: [PATCH 15/21] Added OTP Read/Write definitions, added option to read and print OTP, need to pass value from 0 to 255 (meaning not known). For test purposes only. --- ch55xtool/ch55xtool.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index 5f0d8a0..b3f7021 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -32,6 +32,8 @@ "DataErase": b'\xA9', "DataWrite": b'\xAA', "DataRead": b'\xAB', + "ReadOTP": b'\xC4', + "WriteOTP": b'\xC3', } # Meaning of those two values not yet clear :( @@ -381,6 +383,10 @@ def main(): '-p', '--print_chip_cfg', action='store_true', default=False, help="Read and print chip configuration bits 3 x 32bit values.") + parser.add_argument( + '--print_otp', type=int, + help="Read and print OTP.") + parser.add_argument( '-r', '--reset_at_end', action='store_true', default=False, help="Reset as the end of operations.") @@ -450,6 +456,19 @@ def main(): sys.exit(-1) print("Chip configs 0x%08X 0x%08X 0x%08X" % (cfg1, cfg2, cfg3) ) + if(args.print_otp is not None): + cmd_pl = args.print_otp.to_bytes(1,"little") + print("Reading OTP",end="") + ret, chip_otp = cmd_exec(dev, "ReadOTP", cmd_pl) + if(ret is None): + print('Cannot read chip OTP.') + sys.exit(-1) + else: + if(chip_otp[0] == 0 and chip_otp[1] == 0 and len(chip_otp)>2 ) : + print(":", list(chip_otp[2:])) + else: + print(" Respond failure:",list(chip_otp) ) + if(args.read_dataflash !=''): ret, ret_data = __data_flash_read(dev, chip_ref['dataflash_size']) if(ret is not None): From 983a01448601740a74b58a05724a398ec1eda69f Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Wed, 23 Mar 2022 19:18:24 +0200 Subject: [PATCH 16/21] Added option for more verbose output. Added Fail address report. --- ch55xtool/ch55xtool.py | 62 ++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index b3f7021..d0f3c11 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -256,7 +256,7 @@ def __send_key_base(dev, key_base): def __flash_ops_write_verify(dev, key_xor_chksum, data, func="FlashWrite"): if(func not in [ 'FlashWrite' , 'FlashVerify', 'DataWrite'] ): - return None + return False, -1 data_length = len(data) curr_addr = 0 cfg = dev.get_active_configuration() @@ -286,12 +286,13 @@ def __flash_ops_write_verify(dev, key_xor_chksum, data, func="FlashWrite"): ret, ret_pl = cmd_exec(dev, func, cmd_pl) if( ret == None or ret_pl[0] != 0x00): - return None + return False, curr_addr + curr_addr = curr_addr + pkt_length if(curr_addr > data_length): - return data_length + return True, data_length else: - return curr_addr + return True, curr_addr def __data_flash_read(dev, data_flash_size): curr_addr = 0 @@ -399,6 +400,8 @@ def main(): args = parser.parse_args() + verb = args.verbose + addr = 0 ret = __get_dfu_device() if ret[0] is None: print('Failed to get device, please check your libusb installation.') @@ -502,11 +505,14 @@ def main(): if ret is None: sys.exit('Failed to write key for DataFlash write to CH5xx.') print('DataFlashing chip.',end='') - ret = __flash_ops_write_verify(dev, enc_key, dataflash_write_data, func="DataWrite") - if ret is None: - sys.exit('Failed.') + ret, addr = __flash_ops_write_verify(dev, enc_key, dataflash_write_data, func="DataWrite") + if(ret): + if(verb): + print(' Done. Amount: %d ' % (addr) ) + else: + print(' Done. ') else: - print(' Done.') + sys.exit(' Failed. Address %d' %(addr) ) else: print('Nothing to write to program flash.') @@ -532,13 +538,21 @@ def main(): print('Verifying Dataflash.',end='') ret, ret_data = __data_flash_read(dev, len(dataflash_verify_data)) if ret is None: - sys.exit(' Data read failed.') + sys.exit(' Data read failed. Read amount %d.' %(len(ret_data))) + elif(len(ret_data) != len(dataflash_verify_data)): + sys.exit(' Failed. Sizes differ: received %d to compare %d' %(len(ret_data), len(dataflash_verify_data)) ) elif(ret_data != dataflash_verify_data): - print(ret_data) - print(dataflash_verify_data) - sys.exit(' Compare failed.') + print(' Compare failed ', end='') + for i in range(len(ret_data)): + if(ret_data[i] != dataflash_verify_data[i]): + print('at address %d.' %(i)) + break + sys.exit(-1) else: - print(' Done.') + if(verb): + print(' Done. Amount: %d ' % (len(ret_data)) ) + else: + print(' Done. ') else: print('Nothing to verifying with data flash.') @@ -569,11 +583,14 @@ def main(): if ret is None: sys.exit('Failed to write key for flash write to CH5xx.') print('Flashing chip.',end='') - ret = __flash_ops_write_verify(dev, enc_key, flash_write_data, func="FlashWrite") - if ret is None: - sys.exit('Failed to flash firmware of CH55x.') + ret, addr = __flash_ops_write_verify(dev, enc_key, flash_write_data, func="FlashWrite") + if(ret): + if(verb): + print(' Done. Amount: %d ' % (addr) ) + else: + print(' Done. ') else: - print(' Done.') + sys.exit(' Failed. Address %d' %(addr) ) else: print('Nothing to write to program flash.') @@ -600,11 +617,14 @@ def main(): if ret is None: sys.exit('Failed to write key for flash verify to CH5xx.') print('Verifying flash.',end='') - ret = __flash_ops_write_verify(dev, enc_key, flash_verify_data, func="FlashVerify") - if ret is None: - sys.exit(' Failed to verify firmware of CH55x.') + ret, addr = __flash_ops_write_verify(dev, enc_key, flash_verify_data, func="FlashVerify") + if(ret): + if(verb): + print(' Done. Amount: %d ' % (addr) ) + else: + print(' Done. ') else: - print(' Done.') + sys.exit(' Failed. Address %d' %(addr) ) else: print('Nothing to verifying with program flash.') From b92f21dddd8d84864041888637b04a522c6f1fab Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Wed, 30 Mar 2022 11:21:49 +0300 Subject: [PATCH 17/21] Prevent 'detection break' by reading CFGs bits as additional last operation. --- ch55xtool/ch55xtool.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index d0f3c11..d7c73d8 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -628,6 +628,9 @@ def main(): else: print('Nothing to verifying with program flash.') + # To prevent "detection break" + _,_ = __read_cfg_ch5xx(dev, FLAG_CFGs, chip_id, chip_subid) + print('Finalize communication.',end="") ret, ret_pl = __end_flash_ch5xx(dev, restart_after = args.reset_at_end) if(ret is True): From a43f01a1bfebf1eeb29fdb7101dd07d5cd26334e Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Wed, 30 Mar 2022 16:43:14 +0300 Subject: [PATCH 18/21] First implementation of config option definition in extended and optional user file. Passing config option in command line (test/simulation). Added: - processing of extended chip defines and with possible parameters "Tested" and config bits "CFGs" , see example in extended.wcfg - command line parameter '-u' to pass additional user file with chip defines / extended defines. - added command line parameters "-o / --cfg_options" and "-a / --cfg_options_after" (only first implemented simulation). Accept repeated use with space and comma separated options. --- ch55xtool/ch55xtool.py | 97 ++++++++++++++++++++++++++++++++++++++--- ch55xtool/extended.wcfg | 32 ++++++++++++++ 2 files changed, 123 insertions(+), 6 deletions(-) create mode 100644 ch55xtool/extended.wcfg diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index d7c73d8..36bcdee 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -51,10 +51,10 @@ FLAG_UID = 0x10 # ============================================= -def get_chip_parameters(chip_id,wcfg_path): +def get_chip_parameters(chip_id,wcfg_path, user_param_file='' ): chip_params = {} params_ini = configparser.ConfigParser() - params_ini.optionxform = lambda option: option + #params_ini.optionxform = lambda option: option params_ini.read(wcfg_path+'/typeall.wcfg') for section in params_ini.sections(): if(params_ini.has_option(section,'chipid')): @@ -65,8 +65,50 @@ def get_chip_parameters(chip_id,wcfg_path): chip_params.update({'dataflash_size':params_ini.getint(section,'MaxEepromSize')}) chip_params.update({'McuType':params_ini.getint(section,'McuType')}) break - else: - chip_params = None + + params_ini_ext = configparser.ConfigParser() + #params_ini_ext.optionxform = lambda option: option + params_ini_ext.read(wcfg_path+'/extended.wcfg') + for section in params_ini_ext.sections(): + if(params_ini_ext.has_option(section,'chipid')): + if(params_ini_ext.getint(section,'chipid') == chip_id): + chip_params.update({'name':section}) + chip_params.update({'chip_id':chip_id}) + chip_params.update({'flash_size':params_ini_ext.getint(section,'MaxFlashSize')}) + chip_params.update({'dataflash_size':params_ini_ext.getint(section,'MaxEepromSize')}) + if(params_ini_ext.has_option(section,'McuType')): + chip_params.update({'McuType':params_ini_ext.getint(section,'McuType')}) + break + + # Check we found any and all mandatory params exist + if(chip_params.get('chip_id') == None or chip_params.get('name') == None): + return None + missing_defs = [] + if( chip_params.get('flash_size') == None): missing_defs.append('MaxFlashSize') + if( chip_params.get('dataflash_size') == None): missing_defs.append('MaxEepromSize') + if(missing_defs): + print('Chip configuration definitions shortage, mandatory fiels',missing_defs) + return None + + section = chip_params.get('name') + if(params_ini_ext.has_section(section)): + if(params_ini_ext.has_option(section,'Tested')): + chip_params.update({'tested':params_ini_ext.getboolean(section,'Tested')}) + if(params_ini_ext.has_option(section,'CFGs')): + chip_params.update({'cfgs_bits':eval(params_ini_ext.get(section,'CFGs'))}) + + if(user_param_file): + params_ini_usr = configparser.ConfigParser() + #params_ini_usr.optionxform = lambda option: option + params_ini_usr.read(user_param_file) + if(params_ini_usr.has_section(section)): + if(params_ini_usr.has_option(section,'Tested')): + chip_params.update({'tested':params_ini_usr.getboolean(section,'Tested')}) + if(params_ini_usr.has_option(section,'CFGs')): + if(chip_params.get('cfgs_bits') == None): + chip_params.update({'cfgs_bits':eval(params_ini_usr.get(section,'CFGs'))}) + else: + chip_params['cfgs_bits'].update(eval(params_ini_usr.get(section,'CFGs'))) return chip_params def cmd_send(dev, cmd_bin, payload): @@ -388,6 +430,18 @@ def main(): '--print_otp', type=int, help="Read and print OTP.") + parser.add_argument( + '-o', '--cfgs_options', action='append', nargs='+', + help="Apply configuration options before operations.") + + parser.add_argument( + '-a', '--cfgs_options_after', action='append', nargs='+', + help="Apply configuration options after operations.") + + parser.add_argument( + '-u', '--user_def', type=str, default='', + help="Use additional user chip definition INI file.") + parser.add_argument( '-r', '--reset_at_end', action='store_true', default=False, help="Reset as the end of operations.") @@ -414,8 +468,12 @@ def main(): print('Unable to detect CH5xx.') print('Welcome to report this issue with a screen shot from the official CH5xx tool.') sys.exit(-1) - - chip_ref = get_chip_parameters(chip_id, fullpath) + + if(args.user_def): + chip_ref = get_chip_parameters(chip_id, fullpath, args.user_def) + else: + chip_ref = get_chip_parameters(chip_id, fullpath) + if chip_ref is None: print('Chip ID: %x is not known = not supported' % chip_id) print('Welcome to report this issue with a screen shot from the official CH5xx tool.') @@ -445,6 +503,33 @@ def main(): chk_sum = __chip_uid_chk_sum(chip_subid, uid) + if(args.cfgs_options): + opt_list = [] + for opt_l in args.cfgs_options: + for opt in opt_l: + for spl_opt in opt.split(','): + opt_list.append(spl_opt.split('=')) + # Check all options exist + opt_errors = False + if(chip_ref.get('cfgs_bits')): + for opt in opt_list: + if(chip_ref['cfgs_bits'].get(opt[0]) == None): + print("Chip %s do not have option: %s" % (chip_ref['name'], opt[0]) ) + opt_errors = True + elif(chip_ref['cfgs_bits'][opt[0]].get('need_value') and len(opt)<2 ): + print("Chip %s option: %s need value be given by %s=value" % (chip_ref['name'], opt[0], opt[0]) ) + opt_errors = True + elif(len(opt)>1 and not chip_ref['cfgs_bits'][opt[0]].get('need_value') ): + print("Chip %s option: %s do not accept value but given =%d" % (chip_ref['name'], opt[0], eval(opt[1]) ) ) + opt_errors = True + else: + if(len(opt)>1): + print("Chip %s Good option: %s value %d" % (chip_ref['name'], opt[0], eval(opt[1]) ) ) + else: + print("Chip %s Good option: %s" % (chip_ref['name'], opt[0]) ) + else: + print("Chip %s do not have any config options to use." % (chip_ref['name'])) + if(args.print_chip_cfg): ret, chip_cfg = __read_cfg_ch5xx(dev, FLAG_CFGs, chip_id, chip_subid) if ret is None: diff --git a/ch55xtool/extended.wcfg b/ch55xtool/extended.wcfg new file mode 100644 index 0000000..51ce6e9 --- /dev/null +++ b/ch55xtool/extended.wcfg @@ -0,0 +1,32 @@ +[CH552] +Tested=1 +CFGs={ + '_reserved': { + FLAG_CFG1 :{'mask':0xffffffff,'value':0xffffffff }, + FLAG_CFG2 :{'mask':0xfffffff0,'value':0x00000000 }, + FLAG_CFG3 :{'mask':0xffff0fff,'value':0x000002ff } + }, + 'default': { + FLAG_CFG2 :{'mask':0x0f,'value':0x03 }, + FLAG_CFG3 :{'mask':0x0000f000,'value':0x00004000 }, + 'help':'Write default CFGs values' + }, + 'cfg2_val': { + 'need_value': True, + FLAG_CFG2 :{'mask':0xf }, + 'help':'Direct define value for CFG2 in mask 0x0000000F' + }, + 'cfg3_val': { + 'need_value': True, + FLAG_CFG3 :{'mask':0xf000 }, + 'help':'Direct define value for CFG3 in mask 0x0000F00' + }, + 'En_RST_RESET': { + FLAG_CFG3 :{'mask': 1<<12 , 'value': 1<<12 }, + 'help':'Enable RST pin as manual reset input pin.' + }, + 'Dis_RST_RESET': { + FLAG_CFG3 :{'mask': 1<<12, 'value':0 }, + 'help':'Disable RST pin as manual reset input pin.' + } + } From a10ab1dc382636125cce9b9210dc56874cc07708 Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Wed, 30 Mar 2022 20:30:02 +0300 Subject: [PATCH 19/21] Implemented real Config Bits writing, use at YOUR OWN RISK for now, need special option to force real action. Manu other bug fixes. --- ch55xtool/ch55xtool.py | 191 +++++++++++++++++++++++++++++++++------- ch55xtool/extended.wcfg | 2 +- 2 files changed, 158 insertions(+), 35 deletions(-) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index 36bcdee..778c61b 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -228,15 +228,15 @@ def __read_cfg_ch5xx(dev, req_fields, chip_id, chip_subid): return ret, cfg_dict def __write_cfg_ch5xx(dev, cfg_dict): - cfg_fileds = cfg_dict.get("Fields") - if(cfg_fileds is None): + cfg_fields = cfg_dict.get("Fields") + if(cfg_fields is None): print("Not defined fields to set configuration.") return None, None set_fields = 0 cmd_pl = b'' if(cfg_fields & FLAG_CFG1): field_val = cfg_dict.get(FLAG_CFG1) - if(field_val != None and len(field_val) == 4): + if(field_val != None): set_fields |= FLAG_CFG1 cmd_pl += field_val.to_bytes(4,'little') else: @@ -244,7 +244,7 @@ def __write_cfg_ch5xx(dev, cfg_dict): if(cfg_fields & FLAG_CFG2): field_val = cfg_dict.get(FLAG_CFG2) - if(field_val != None and len(field_val) == 4): + if(field_val != None): set_fields |= FLAG_CFG2 cmd_pl += field_val.to_bytes(4,'little') else: @@ -252,7 +252,7 @@ def __write_cfg_ch5xx(dev, cfg_dict): if(cfg_fields & FLAG_CFG3): field_val = cfg_dict.get(FLAG_CFG3) - if(field_val != None and len(field_val) == 4): + if(field_val != None): set_fields |= FLAG_CFG3 cmd_pl += field_val.to_bytes(4,'little') else: @@ -261,7 +261,7 @@ def __write_cfg_ch5xx(dev, cfg_dict): if(set_fields > 0): cmd_pl = set_fields.to_bytes(2,'little') + cmd_pl ret, ret_pl = cmd_exec(dev, 'WriteConfig', cmd_pl) - return ret, cfg_dict + return ret, ret_pl else: print("No setable chip fields in given config.") return None, None @@ -392,6 +392,79 @@ def __end_flash_ch5xx(dev, restart_after = False): else: return cmd_exec(dev, "End", cmd_pl) +def __get_list_from_given_options(options): + opt_list = [] + for opt_l in options: + for opt in opt_l: + for spl_opt in opt.split(','): + opt_list.append(spl_opt.split('=')) + return opt_list + +def __check_option_list(opt_list, chip_ref, verbose=False): + opt_good = True + if(chip_ref.get('cfgs_bits')): + for opt in opt_list: + if(chip_ref['cfgs_bits'].get(opt[0]) == None): + print("Chip %s do not have option: %s" % (chip_ref['name'], opt[0]) ) + opt_good = False + elif(chip_ref['cfgs_bits'][opt[0]].get('need_value') and len(opt)<2 ): + print("Chip %s option: %s need value be given by %s=value" % (chip_ref['name'], opt[0], opt[0]) ) + opt_good = False + elif(len(opt)>1 and not chip_ref['cfgs_bits'][opt[0]].get('need_value') ): + print("Chip %s option: %s do not accept value but given =%d" % (chip_ref['name'], opt[0], eval(opt[1]) ) ) + opt_good = False + else: + cfg_opt_dict = chip_ref['cfgs_bits'].get(opt[0]) + if(len(opt)>1): + value = eval(opt[1]) + for cfg_flag in [FLAG_CFG1 , FLAG_CFG2, FLAG_CFG3]: + cfg_flag_dict = chip_ref['cfgs_bits'][opt[0]].get(cfg_flag) + if(cfg_flag_dict): + cfg_flag_v = cfg_flag + break + if(cfg_flag_dict): + #if(cfg_flag_dict.get('mask')): + val_mask = chip_ref['cfgs_bits'][opt[0]][cfg_flag].get('mask') + if(value & val_mask != value): + print("Chip %s option: %s given value 0x%08x out of mask 0x%08x" % (chip_ref['name'], opt[0], value , val_mask) ) + opt_good = False + elif(verbose): + print("Chip %s Good option: %s value %d" % (chip_ref['name'], opt[0], eval(opt[1]) ) ) + else: + if(verbose): + print("Chip %s Good option: %s" % (chip_ref['name'], opt[0]) ) + if(not opt_good and not verbose): + break + else: + print("Chip %s do not have any config options to use." % (chip_ref['name'])) + opt_good = False + return opt_good + +def __apply_option_list(opt_list, chip_ref, chip_cfgs, verbose=False): + cfgs_changed = False + result_d = {} + result_d.update(chip_cfgs.copy()) + for opt in [['_reserved']] + opt_list: + cfg_opt_dict = chip_ref['cfgs_bits'].get(opt[0]) + for cfg_flag in [FLAG_CFG1 , FLAG_CFG2, FLAG_CFG3]: + cfg_flag_dict = cfg_opt_dict.get(cfg_flag) + if(cfg_flag_dict and (chip_cfgs['Fields'] & cfg_flag == cfg_flag) ): + if(cfg_opt_dict.get('need_value')): + value = eval(opt[1]) + else: + value = cfg_flag_dict.get('value') + new_val = ( result_d[cfg_flag] & ( 0xffffffff ^ cfg_flag_dict.get('mask') ) ) | value + if( opt[0] not in ['_reserved']): + if( result_d[cfg_flag] != new_val ): + cfgs_changed = True + print("Config get changed") + else: + print("Configuration option %s already in chip configs." % (opt[0])) + result_d.update( { cfg_flag : new_val } ) + if(cfg_opt_dict.get('need_value')): + break + return cfgs_changed, result_d + def main(): pathname = os.path.dirname(sys.argv[0]) fullpath = os.path.abspath(pathname) @@ -433,10 +506,15 @@ def main(): parser.add_argument( '-o', '--cfgs_options', action='append', nargs='+', help="Apply configuration options before operations.") - parser.add_argument( '-a', '--cfgs_options_after', action='append', nargs='+', help="Apply configuration options after operations.") + parser.add_argument( + '--cfgs_options_force_action', action='store_true', default=False, + help="!Warning! Use on own risk, configuration options enable action (writing).") + parser.add_argument( + '--cfgs_options_list', type=str, action='store', nargs='?', const='', default=None, + help="List configuration options for detected chip or optional given chip name.") parser.add_argument( '-u', '--user_def', type=str, default='', @@ -492,6 +570,9 @@ def main(): print('Cannot read chip bootloader version or uniqe ID.') sys.exit(-1) + # To prevent "detection break" + _, _, _ = __detect_ch5xx(dev) + ver_str = '%d%d.%d%d' % (bootver[0], bootver[1], bootver[2], bootver[3]) print('BTVER:%s' % ver_str) @@ -504,31 +585,32 @@ def main(): chk_sum = __chip_uid_chk_sum(chip_subid, uid) if(args.cfgs_options): - opt_list = [] - for opt_l in args.cfgs_options: - for opt in opt_l: - for spl_opt in opt.split(','): - opt_list.append(spl_opt.split('=')) - # Check all options exist - opt_errors = False - if(chip_ref.get('cfgs_bits')): - for opt in opt_list: - if(chip_ref['cfgs_bits'].get(opt[0]) == None): - print("Chip %s do not have option: %s" % (chip_ref['name'], opt[0]) ) - opt_errors = True - elif(chip_ref['cfgs_bits'][opt[0]].get('need_value') and len(opt)<2 ): - print("Chip %s option: %s need value be given by %s=value" % (chip_ref['name'], opt[0], opt[0]) ) - opt_errors = True - elif(len(opt)>1 and not chip_ref['cfgs_bits'][opt[0]].get('need_value') ): - print("Chip %s option: %s do not accept value but given =%d" % (chip_ref['name'], opt[0], eval(opt[1]) ) ) - opt_errors = True - else: - if(len(opt)>1): - print("Chip %s Good option: %s value %d" % (chip_ref['name'], opt[0], eval(opt[1]) ) ) - else: - print("Chip %s Good option: %s" % (chip_ref['name'], opt[0]) ) + if(args.cfgs_options_force_action): + print(" Configuration options action is high RISK, you take action on YOUR OWN RISK !!") else: - print("Chip %s do not have any config options to use." % (chip_ref['name'])) + print(" Configuration options work in simulation mode. No real action (updating/writing).\r\n To force real action at YOUR OWN RISK use '--cfgs_options_force_action'!!") + opt_list = __get_list_from_given_options(args.cfgs_options) + # Check all options exist and meet defines + if(not __check_option_list(opt_list,chip_ref, verb)): + print('Config options error.') + sys.exit(-1) + + if(args.cfgs_options_after): + if(args.cfgs_options_force_action == None): + print(" Configuration options action is high RISK, you take action on YOUR OWN RISK !!") + else: + print(" Configuration options work in simulation mode. No real action (updating/writing).\r\n To force real action at YOUR OWN RISK use '--cfgs_options_force_action'!!") + + opt_list_after = __get_list_from_given_options(args.cfgs_options_after) + # Check all options exist and meet defines + if(not __check_option_list(opt_list_after,chip_ref, verb)): + print('Config after options error.') + sys.exit(-1) + ret, chip_cfg = __read_cfg_ch5xx(dev, FLAG_CFGs, chip_id, chip_subid) + if ret is None: + print('Cannot read chip configs variables.') + sys.exit(-1) + if(args.print_chip_cfg): ret, chip_cfg = __read_cfg_ch5xx(dev, FLAG_CFGs, chip_id, chip_subid) @@ -543,6 +625,9 @@ def main(): print('Cannot find chip configurations after read.') sys.exit(-1) print("Chip configs 0x%08X 0x%08X 0x%08X" % (cfg1, cfg2, cfg3) ) + + # To prevent "detection break" + _, _, _ = __detect_ch5xx(dev) if(args.print_otp is not None): cmd_pl = args.print_otp.to_bytes(1,"little") @@ -557,6 +642,47 @@ def main(): else: print(" Respond failure:",list(chip_otp) ) + if(args.cfgs_options): + ret, chip_cfg = __read_cfg_ch5xx(dev, FLAG_CFGs, chip_id, chip_subid) + if(ret is None): + print('Cannot read chip configs variables.') + sys.exit(-1) + if( chip_cfg.get(FLAG_CFG1) is None or + chip_cfg.get(FLAG_CFG2) is None or + chip_cfg.get(FLAG_CFG3) is None + ): + print('Cannot find chip configurations after read.') + sys.exit(-1) + + cfg_changed, new_cfg = __apply_option_list(opt_list,chip_ref,chip_cfg) + + if(verb): + cfg1 = chip_cfg.get(FLAG_CFG1) + cfg2 = chip_cfg.get(FLAG_CFG2) + cfg3 = chip_cfg.get(FLAG_CFG3) + + ncfg1 = new_cfg.get(FLAG_CFG1) + ncfg2 = new_cfg.get(FLAG_CFG2) + ncfg3 = new_cfg.get(FLAG_CFG3) + print("Chip configs before apply 0x%08X 0x%08X 0x%08X" % (cfg1, cfg2, cfg3) ) + print("Chip configs after apply 0x%08X 0x%08X 0x%08X" % (ncfg1, ncfg2, ncfg3) ) + + if(args.cfgs_options_force_action and cfg_changed): + ret, ret_pl = __write_cfg_ch5xx(dev, new_cfg) + if(ret is None): + print('Cannot write chip configs variables.') + sys.exit(-1) + elif(ret_pl[0]): + print('Error at writing chip configs variables. Resp: ', ret_pl[:]) + sys.exit(-1) + # To repeat original SW + _, _ = __read_cfg_ch5xx(dev, FLAG_CFGs, chip_id, chip_subid) + elif(not cfg_changed): + print('All give configuration options already set, nothing to realy write.') + # To prevent "detection break" + _, _, _ = __detect_ch5xx(dev) + + if(args.read_dataflash !=''): ret, ret_data = __data_flash_read(dev, chip_ref['dataflash_size']) if(ret is not None): @@ -713,9 +839,6 @@ def main(): else: print('Nothing to verifying with program flash.') - # To prevent "detection break" - _,_ = __read_cfg_ch5xx(dev, FLAG_CFGs, chip_id, chip_subid) - print('Finalize communication.',end="") ret, ret_pl = __end_flash_ch5xx(dev, restart_after = args.reset_at_end) if(ret is True): diff --git a/ch55xtool/extended.wcfg b/ch55xtool/extended.wcfg index 51ce6e9..bf054fa 100644 --- a/ch55xtool/extended.wcfg +++ b/ch55xtool/extended.wcfg @@ -26,7 +26,7 @@ CFGs={ 'help':'Enable RST pin as manual reset input pin.' }, 'Dis_RST_RESET': { - FLAG_CFG3 :{'mask': 1<<12, 'value':0 }, + FLAG_CFG3 :{'mask': 1<<12, 'value': 0 }, 'help':'Disable RST pin as manual reset input pin.' } } From 5fa3686de42a5c99a416c849abb710dc690b02b0 Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Wed, 30 Mar 2022 20:47:36 +0300 Subject: [PATCH 20/21] Added parameter to list configuration options for detected chip. --- ch55xtool/ch55xtool.py | 23 +++++++++++++++++++++-- ch55xtool/extended.wcfg | 2 +- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index 778c61b..bd579cd 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -584,6 +584,27 @@ def main(): chk_sum = __chip_uid_chk_sum(chip_subid, uid) + if(args.cfgs_options_list != None): + if(args.cfgs_options_list != ''): + print("Printing options for given name not supported") + else: + cfgs_opt_dict = chip_ref.get('cfgs_bits') + if(cfgs_opt_dict): + for opt_name in cfgs_opt_dict.keys(): + if(cfgs_opt_dict[opt_name].get('need_value')): + val_str = '=xxx' + else: + val_str = '' + if(opt_name in ['_reserved']): + continue + opt_help = cfgs_opt_dict[opt_name].get('help') + if(opt_help): + print("Option '%s'\t - %s" % (opt_name+val_str, opt_help)) + else: + print("Option '%s'\t - no description" % (opt_name+val_str)) + else: + print("No known options for found chip.") + if(args.cfgs_options): if(args.cfgs_options_force_action): print(" Configuration options action is high RISK, you take action on YOUR OWN RISK !!") @@ -611,7 +632,6 @@ def main(): print('Cannot read chip configs variables.') sys.exit(-1) - if(args.print_chip_cfg): ret, chip_cfg = __read_cfg_ch5xx(dev, FLAG_CFGs, chip_id, chip_subid) if ret is None: @@ -682,7 +702,6 @@ def main(): # To prevent "detection break" _, _, _ = __detect_ch5xx(dev) - if(args.read_dataflash !=''): ret, ret_data = __data_flash_read(dev, chip_ref['dataflash_size']) if(ret is not None): diff --git a/ch55xtool/extended.wcfg b/ch55xtool/extended.wcfg index bf054fa..0f099eb 100644 --- a/ch55xtool/extended.wcfg +++ b/ch55xtool/extended.wcfg @@ -19,7 +19,7 @@ CFGs={ 'cfg3_val': { 'need_value': True, FLAG_CFG3 :{'mask':0xf000 }, - 'help':'Direct define value for CFG3 in mask 0x0000F00' + 'help':'Direct define value for CFG3 in mask 0x0000F000' }, 'En_RST_RESET': { FLAG_CFG3 :{'mask': 1<<12 , 'value': 1<<12 }, From 04646da95b801dc0c9e3173e0fa308ac1bfec49e Mon Sep 17 00:00:00 2001 From: Maksims Matjakubovs Date: Wed, 30 Mar 2022 20:56:30 +0300 Subject: [PATCH 21/21] Added processing of option settings after all operations. --- ch55xtool/ch55xtool.py | 45 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/ch55xtool/ch55xtool.py b/ch55xtool/ch55xtool.py index bd579cd..0483c3e 100644 --- a/ch55xtool/ch55xtool.py +++ b/ch55xtool/ch55xtool.py @@ -617,7 +617,7 @@ def main(): sys.exit(-1) if(args.cfgs_options_after): - if(args.cfgs_options_force_action == None): + if(args.cfgs_options_force_action): print(" Configuration options action is high RISK, you take action on YOUR OWN RISK !!") else: print(" Configuration options work in simulation mode. No real action (updating/writing).\r\n To force real action at YOUR OWN RISK use '--cfgs_options_force_action'!!") @@ -698,7 +698,7 @@ def main(): # To repeat original SW _, _ = __read_cfg_ch5xx(dev, FLAG_CFGs, chip_id, chip_subid) elif(not cfg_changed): - print('All give configuration options already set, nothing to realy write.') + print('All given configuration options already set, nothing to realy write.') # To prevent "detection break" _, _, _ = __detect_ch5xx(dev) @@ -858,6 +858,47 @@ def main(): else: print('Nothing to verifying with program flash.') + if(args.cfgs_options_after): + ret, chip_cfg = __read_cfg_ch5xx(dev, FLAG_CFGs, chip_id, chip_subid) + if(ret is None): + print('Cannot read chip configs variables.') + sys.exit(-1) + if( chip_cfg.get(FLAG_CFG1) is None or + chip_cfg.get(FLAG_CFG2) is None or + chip_cfg.get(FLAG_CFG3) is None + ): + print('Cannot find chip configurations after read.') + sys.exit(-1) + + cfg_changed, new_cfg = __apply_option_list(opt_list_after,chip_ref,chip_cfg) + + if(verb): + cfg1 = chip_cfg.get(FLAG_CFG1) + cfg2 = chip_cfg.get(FLAG_CFG2) + cfg3 = chip_cfg.get(FLAG_CFG3) + + ncfg1 = new_cfg.get(FLAG_CFG1) + ncfg2 = new_cfg.get(FLAG_CFG2) + ncfg3 = new_cfg.get(FLAG_CFG3) + print("Chip configs before apply 0x%08X 0x%08X 0x%08X" % (cfg1, cfg2, cfg3) ) + print("Chip configs after apply 0x%08X 0x%08X 0x%08X" % (ncfg1, ncfg2, ncfg3) ) + + if(args.cfgs_options_force_action and cfg_changed): + ret, ret_pl = __write_cfg_ch5xx(dev, new_cfg) + if(ret is None): + print('Cannot write chip configs variables.') + sys.exit(-1) + elif(ret_pl[0]): + print('Error at writing chip configs variables. Resp: ', ret_pl[:]) + sys.exit(-1) + # To repeat original SW + _, _ = __read_cfg_ch5xx(dev, FLAG_CFGs, chip_id, chip_subid) + elif(not cfg_changed): + print('All given configuration options already set, nothing to realy write.') + + # To prevent "detection break" + _, _, _ = __detect_ch5xx(dev) + print('Finalize communication.',end="") ret, ret_pl = __end_flash_ch5xx(dev, restart_after = args.reset_at_end) if(ret is True):