fix more
This commit is contained in:
parent
cf5e5ae969
commit
ab96cb2a5d
12
README.md
12
README.md
@ -17,10 +17,22 @@
|
||||
[![sites](docs/CH55.png)](http://www.wch.cn/products/category/5.html)
|
||||
[![sites](docs/CH552.png)](http://www.wch.cn/products/CH552.html)
|
||||
|
||||
* 芯片封装:TSSOP20、MSOP10、QFN16、SOP16
|
||||
|
||||
[![sites](docs/sop.png)](http://www.wch.cn/products/CH554.html)
|
||||
[![sites](docs/package.png)](http://www.wch.cn/products/CH554.html)
|
||||
|
||||
### [资源收录](https://github.com/sochub/CH552)
|
||||
|
||||
* [参考文档](docs/)
|
||||
* [参考资源](src/)
|
||||
* [相关工具](tools/)
|
||||
|
||||
#### [外部资源](https://github.com/sochub)
|
||||
|
||||
* [OS-Q H05](https://github.com/OS-Q/H02)
|
||||
* [编译器SDCC](https://github.com/sochub/sdcc)
|
||||
|
||||
|
||||
### [选型建议](https://github.com/sochub)
|
||||
|
||||
|
BIN
docs/package.png
Normal file
BIN
docs/package.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 87 KiB |
BIN
docs/sop.png
Normal file
BIN
docs/sop.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
53
tools/README.md
Normal file
53
tools/README.md
Normal file
@ -0,0 +1,53 @@
|
||||
ch55x-tool
|
||||
------------
|
||||
|
||||
An open sourced python command line flash tool for flashing WinChipHead CH55x series 8051 USB micro controllers, including CH551, CH552, CH553, CH554, and CH559 with bootloader version 2.30 or 2.31.
|
||||
|
||||
Usage
|
||||
------------
|
||||
* __-f \<filename\>__ Erase the whole chip, and flash the bin file to the CH55x.
|
||||
* __-r__ Issue reset and run after the flashing.
|
||||
* __-d__ Debug mode, if enabled, will print out all USB communications.
|
||||
|
||||
Tool Setup
|
||||
------------
|
||||
* Linux Distros
|
||||
> Most Linux distros come with libusb, so you only need to install the pyusb packge.
|
||||
```bash
|
||||
python3 -mpip install pyusb
|
||||
```
|
||||
|
||||
* Mac OS
|
||||
> For Mac OS, you need to install both libusb and pyusb.
|
||||
|
||||
```bash
|
||||
# If you dont have brew installed.
|
||||
# /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
brew install libusb
|
||||
python3 -mpip install pyusb
|
||||
```
|
||||
|
||||
* As for Windows, oh no... :(
|
||||
> 1. First, you need to download the [Zadig](https://zadig.akeo.ie/) for replacing the CH375 driver from WCH to libusb.
|
||||
> 2. Click the Options->List all devices, to show all devices
|
||||
> 3. Find the device marked with __USB Module__, which presented driver is __CH375_balabala__
|
||||
> 4. Replace the driver with libusb-win32.
|
||||
> 5. Install the pyusb package.
|
||||
```
|
||||
python -mpip install pyusb #Since for windows, they dont use python3, but you have to make sure you have the pythono3 in the PATH
|
||||
```
|
||||
> 6. If you want to use the WCH Toolchain, open the device manager, find the device marked with __libusb-win32 deives__, right clicked on it, and Uninstall the driver and delete the driver. You can also check the FAQ of Zadig [HERE](https://github.com/pbatard/libwdi/wiki/Zadig).
|
||||
|
||||
FAQ
|
||||
---------
|
||||
* Why I got a __Error: No backend available__ ?
|
||||
> On windows, this means you dont a valid libusb device, see the guide above. For other system, you might dont have the libusb installed, follow the guide above.
|
||||
|
||||
* Why it said __NO_DEV_FOUND__ ?
|
||||
> Pyusb unable to fine the device with given PID&VID. Maybe you dont power on your device, or it is not in DFU mode.
|
||||
|
||||
* I got a __USB_ERROR_CANNOT_DETACH_KERNEL_DRIVER__, __USB_ERROR_CANNOT_SET_CONFIG__, or __USB_ERROR_CANNOT_CLAIM_INTERFACE__ error.
|
||||
> I never met with those problems on a working CH552. Checking the power, the previliage, and praying may help.
|
||||
|
||||
* What if it return __Bootloader version not supported__?
|
||||
> The program dont support BTVER lower than 2.30(welcome PR, but since they are too old, I dont have plan to support them). Or maybe they have a newer verison, for this situlation, it is welcome for you to open an issue.
|
338
tools/ch55xtool.py
Normal file
338
tools/ch55xtool.py
Normal file
@ -0,0 +1,338 @@
|
||||
import sys, os
|
||||
import time
|
||||
import array
|
||||
import math
|
||||
import argparse
|
||||
|
||||
import usb.core
|
||||
import usb.util
|
||||
|
||||
#======= Some C-like static constants =======
|
||||
DFU_ID_VENDOR = 0x4348
|
||||
DFU_ID_PRODUCT = 0x55e0
|
||||
|
||||
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}
|
||||
CH55X_IC_REF[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}
|
||||
CH55X_IC_REF[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}
|
||||
#=============================================
|
||||
|
||||
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:
|
||||
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 = payload + [0] * ((math.ceil(len(payload) / 56) * 56) - len(payload)) # Payload needs to be padded, 56 is a good number
|
||||
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 = payload + [0] * ((math.ceil(len(payload) / 56) * 56) - len(payload)) # Payload needs to be padded, 56 is a good number
|
||||
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 = payload + [0] * ((math.ceil(len(payload) / 56) * 56) - len(payload)) # Payload needs to be padded, 56 is a good number
|
||||
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 = payload + [0] * ((math.ceil(len(payload) / 56) * 56) - len(payload)) # Payload needs to be padded, 56 is a good number
|
||||
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 __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
|
||||
|
||||
def __restart_run_ch55x_v2(dev):
|
||||
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.")
|
||||
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:
|
||||
sys.exit(ret[1])
|
||||
dev = ret[0]
|
||||
|
||||
ret = __detect_ch55x_v2(dev)
|
||||
if ret is None:
|
||||
print('Unable to detect CH55x.')
|
||||
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 ret[0] == '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] == 'V2.31':
|
||||
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.')
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
__main()
|
Loading…
Reference in New Issue
Block a user