chprog 2.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- chprog-2.4.0/LICENSE +21 -0
- chprog-2.4.0/PKG-INFO +83 -0
- chprog-2.4.0/README.md +39 -0
- chprog-2.4.0/chprog/__init__.py +1 -0
- chprog-2.4.0/chprog/chprog.py +361 -0
- chprog-2.4.0/chprog.egg-info/PKG-INFO +83 -0
- chprog-2.4.0/chprog.egg-info/SOURCES.txt +12 -0
- chprog-2.4.0/chprog.egg-info/dependency_links.txt +1 -0
- chprog-2.4.0/chprog.egg-info/entry_points.txt +2 -0
- chprog-2.4.0/chprog.egg-info/requires.txt +1 -0
- chprog-2.4.0/chprog.egg-info/top_level.txt +1 -0
- chprog-2.4.0/pyproject.toml +37 -0
- chprog-2.4.0/setup.cfg +4 -0
- chprog-2.4.0/setup.py +15 -0
chprog-2.4.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Stefan Wagner
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
chprog-2.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: chprog
|
|
3
|
+
Version: 2.4.0
|
|
4
|
+
Summary: USB Programming Tool for WCH Microcontrollers
|
|
5
|
+
Home-page: https://github.com/wagiminator/MCU-Flash-Tools
|
|
6
|
+
Author: Stefan Wagner
|
|
7
|
+
Author-email: Stefan Wagner <wagiminator@web.de>
|
|
8
|
+
Maintainer-email: Stefan Wagner <wagiminator@web.de>
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2022 Stefan Wagner
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
Project-URL: Homepage, https://wagiminator.github.io/
|
|
31
|
+
Project-URL: Repository, https://github.com/wagiminator/MCU-Flash-Tools
|
|
32
|
+
Project-URL: Issues, https://github.com/wagiminator/MCU-Flash-Tools/issues
|
|
33
|
+
Keywords: WCH,CH552,CH32V003,CH32X035,microcontroller
|
|
34
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
35
|
+
Classifier: Programming Language :: Python :: 3
|
|
36
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
37
|
+
Classifier: Operating System :: OS Independent
|
|
38
|
+
Classifier: Intended Audience :: Developers
|
|
39
|
+
Classifier: Topic :: Software Development :: Embedded Systems
|
|
40
|
+
Requires-Python: >=3.8
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
License-File: LICENSE
|
|
43
|
+
Requires-Dist: pyusb
|
|
44
|
+
|
|
45
|
+
# chprog - USB Programming Tool for WCH Microcontrollers
|
|
46
|
+
## Description
|
|
47
|
+
With this tool, almost all WCH microcontrollers (CH5xx, CH32Fxxx, CH32Vxxx, CH32Xxxx, and CH32Lxxx) which have a factory-builtin bootloader (v2.x.x) can be flashed via USB.
|
|
48
|
+
|
|
49
|
+
## Preparations
|
|
50
|
+
On Linux you do not need to install a driver for the USB bootloader. However, by default Linux will not expose enough permission to upload your code. In order to fix this, open a terminal and run the following commands:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="4348", ATTR{idProduct}=="55e0", MODE="666"' | sudo tee /etc/udev/rules.d/99-ch55x.rules
|
|
54
|
+
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="55e0", MODE="666"' | sudo tee -a /etc/udev/rules.d/99-ch55x.rules
|
|
55
|
+
sudo udevadm control --reload-rules
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
For Windows, you need the [CH372 driver](http://www.wch-ic.com/downloads/CH372DRV_EXE.html). Alternatively, you can also use the [Zadig Tool](https://zadig.akeo.ie/) to install the correct driver. Here, click "Options" -> "List All Devices" and select the USB module. Then install the libusb-win32 driver. To do this, the board must be connected and the microcontroller must be in bootloader mode.
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
- Install [Python3](https://www.pythontutorial.net/getting-started/install-python/).
|
|
62
|
+
- Install [pip](https://pip.pypa.io/en/stable/installation/).
|
|
63
|
+
- Install chprog:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
pip install chprog
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Usage
|
|
70
|
+
The bootloader must be started manually for new uploads. To do this, the board must first be disconnected from the USB port and all voltage sources. Now press the BOOT button and keep it pressed while reconnecting the board to the USB port of your PC. The chip now starts in bootloader mode, the BOOT button can be released and new firmware can be uploaded via USB. Alternatively, you can leave the board connected to the USB port, press and hold the BOOT button, press and release the RESET button and then release the BOOT button to enter the bootloader mode. If there is no BOOT button on the board, look at the datasheet to find out which pin needs to be pulled to which voltage level for the microcontroller to go into boot mode.
|
|
71
|
+
|
|
72
|
+
Now run the following command (example):
|
|
73
|
+
```
|
|
74
|
+
chprog firmware.bin
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Links
|
|
78
|
+
- [MCU Flash Tools](https://github.com/wagiminator/MCU-Flash-Tools)
|
|
79
|
+
- [MCU Templates](https://github.com/wagiminator/MCU-Templates)
|
|
80
|
+
- [MCU Development Boards](https://github.com/wagiminator/Development-Boards)
|
|
81
|
+
- [AVR Development Boards](https://github.com/wagiminator/AVR-Development-Boards)
|
|
82
|
+
- [AVR Programmers](https://github.com/wagiminator/AVR-Programmer)
|
|
83
|
+
- [SAMD Development Boards](https://github.com/wagiminator/SAMD-Development-Boards)
|
chprog-2.4.0/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# chprog - USB Programming Tool for WCH Microcontrollers
|
|
2
|
+
## Description
|
|
3
|
+
With this tool, almost all WCH microcontrollers (CH5xx, CH32Fxxx, CH32Vxxx, CH32Xxxx, and CH32Lxxx) which have a factory-builtin bootloader (v2.x.x) can be flashed via USB.
|
|
4
|
+
|
|
5
|
+
## Preparations
|
|
6
|
+
On Linux you do not need to install a driver for the USB bootloader. However, by default Linux will not expose enough permission to upload your code. In order to fix this, open a terminal and run the following commands:
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="4348", ATTR{idProduct}=="55e0", MODE="666"' | sudo tee /etc/udev/rules.d/99-ch55x.rules
|
|
10
|
+
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="55e0", MODE="666"' | sudo tee -a /etc/udev/rules.d/99-ch55x.rules
|
|
11
|
+
sudo udevadm control --reload-rules
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
For Windows, you need the [CH372 driver](http://www.wch-ic.com/downloads/CH372DRV_EXE.html). Alternatively, you can also use the [Zadig Tool](https://zadig.akeo.ie/) to install the correct driver. Here, click "Options" -> "List All Devices" and select the USB module. Then install the libusb-win32 driver. To do this, the board must be connected and the microcontroller must be in bootloader mode.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
- Install [Python3](https://www.pythontutorial.net/getting-started/install-python/).
|
|
18
|
+
- Install [pip](https://pip.pypa.io/en/stable/installation/).
|
|
19
|
+
- Install chprog:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
pip install chprog
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
The bootloader must be started manually for new uploads. To do this, the board must first be disconnected from the USB port and all voltage sources. Now press the BOOT button and keep it pressed while reconnecting the board to the USB port of your PC. The chip now starts in bootloader mode, the BOOT button can be released and new firmware can be uploaded via USB. Alternatively, you can leave the board connected to the USB port, press and hold the BOOT button, press and release the RESET button and then release the BOOT button to enter the bootloader mode. If there is no BOOT button on the board, look at the datasheet to find out which pin needs to be pulled to which voltage level for the microcontroller to go into boot mode.
|
|
27
|
+
|
|
28
|
+
Now run the following command (example):
|
|
29
|
+
```
|
|
30
|
+
chprog firmware.bin
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Links
|
|
34
|
+
- [MCU Flash Tools](https://github.com/wagiminator/MCU-Flash-Tools)
|
|
35
|
+
- [MCU Templates](https://github.com/wagiminator/MCU-Templates)
|
|
36
|
+
- [MCU Development Boards](https://github.com/wagiminator/Development-Boards)
|
|
37
|
+
- [AVR Development Boards](https://github.com/wagiminator/AVR-Development-Boards)
|
|
38
|
+
- [AVR Programmers](https://github.com/wagiminator/AVR-Programmer)
|
|
39
|
+
- [SAMD Development Boards](https://github.com/wagiminator/SAMD-Development-Boards)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .chprog import _main
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# ===================================================================================
|
|
3
|
+
# Project: chprog - USB Programming Tool for WCH Microcontrollers
|
|
4
|
+
# Version: v2.4
|
|
5
|
+
# Year: 2022
|
|
6
|
+
# Author: Stefan Wagner
|
|
7
|
+
# Github: https://github.com/wagiminator
|
|
8
|
+
# License: MIT License
|
|
9
|
+
# ===================================================================================
|
|
10
|
+
#
|
|
11
|
+
# Description:
|
|
12
|
+
# ------------
|
|
13
|
+
# Simple Python tool for flashing WCH microcontrollers
|
|
14
|
+
# (CH5xx, CH32Fxxx, CH32Vxxx, CH32Xxxx, CH32Lxxx)
|
|
15
|
+
# via USB with factory built-in bootloader versions 2.x.x.
|
|
16
|
+
#
|
|
17
|
+
# References:
|
|
18
|
+
# -----------
|
|
19
|
+
# chprog is based on isp55e0, chflasher, and wchprog:
|
|
20
|
+
# - Frank Zago, https://github.com/frank-zago/isp55e0
|
|
21
|
+
# - Aaron Christophel, https://github.com/atc1441/chflasher
|
|
22
|
+
# - juliuswwj, https://github.com/juliuswwj/wchprog
|
|
23
|
+
#
|
|
24
|
+
# Dependencies:
|
|
25
|
+
# -------------
|
|
26
|
+
# - pyusb
|
|
27
|
+
#
|
|
28
|
+
# Operating Instructions:
|
|
29
|
+
# -----------------------
|
|
30
|
+
# You need to install PyUSB to use chprog. Install it via "python3 -m pip install pyusb".
|
|
31
|
+
#
|
|
32
|
+
# Linux users need permission to access the device. Run:
|
|
33
|
+
# echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="4348", ATTR{idProduct}=="55e0", MODE="666"' | sudo tee /etc/udev/rules.d/99-ch55x.rules
|
|
34
|
+
# echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="55e0", MODE="666"' | sudo tee -a /etc/udev/rules.d/99-ch55x.rules
|
|
35
|
+
# sudo udevadm control --reload-rules
|
|
36
|
+
#
|
|
37
|
+
# On Windows you will need the Zadig tool (https://zadig.akeo.ie/) to install the
|
|
38
|
+
# correct driver. Click "Options" and "List All Devices" to select the USB module.
|
|
39
|
+
# Then install the libusb-win32 driver.
|
|
40
|
+
#
|
|
41
|
+
# Connect the MCU via USB to your PC. The MCU must be in bootloader mode!
|
|
42
|
+
# Run "python3 chprog.py firmware.bin".
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
import usb.core
|
|
46
|
+
import usb.util
|
|
47
|
+
import sys
|
|
48
|
+
|
|
49
|
+
# ===================================================================================
|
|
50
|
+
# Main Function
|
|
51
|
+
# ===================================================================================
|
|
52
|
+
|
|
53
|
+
def _main():
|
|
54
|
+
if len(sys.argv) != 2:
|
|
55
|
+
sys.stderr.write('ERROR: No bin file selected!\n')
|
|
56
|
+
sys.exit(1)
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
print('Connecting to bootloader ...')
|
|
60
|
+
isp = Programmer()
|
|
61
|
+
isp.detect()
|
|
62
|
+
print('Found %s with bootloader v%s.' % (isp.chipname, isp.bootloader))
|
|
63
|
+
print('Flashing %s to %s ...' % (sys.argv[1], isp.chipname))
|
|
64
|
+
with open(sys.argv[1], 'rb') as f: data = f.read()
|
|
65
|
+
isp.flash(data)
|
|
66
|
+
print('Verifying %d bytes ...' % len(data))
|
|
67
|
+
isp.verify(data)
|
|
68
|
+
isp.exit()
|
|
69
|
+
except Exception as ex:
|
|
70
|
+
sys.stderr.write('ERROR: %s!\n' % str(ex))
|
|
71
|
+
sys.exit(1)
|
|
72
|
+
print('DONE.')
|
|
73
|
+
sys.exit(0)
|
|
74
|
+
|
|
75
|
+
# ===================================================================================
|
|
76
|
+
# Programmer Class
|
|
77
|
+
# ===================================================================================
|
|
78
|
+
|
|
79
|
+
class Programmer:
|
|
80
|
+
# Init programming interface
|
|
81
|
+
def __init__(self):
|
|
82
|
+
# Find device
|
|
83
|
+
self.dev = usb.core.find(idVendor = CH_USB_VENDOR_ID1, idProduct = CH_USB_PRODUCT_ID)
|
|
84
|
+
if self.dev is None:
|
|
85
|
+
self.dev = usb.core.find(idVendor = CH_USB_VENDOR_ID2, idProduct = CH_USB_PRODUCT_ID)
|
|
86
|
+
if self.dev is None:
|
|
87
|
+
raise Exception('MCU not found. Check if device is in BOOT mode')
|
|
88
|
+
|
|
89
|
+
# Set configuration
|
|
90
|
+
try:
|
|
91
|
+
self.dev.set_configuration()
|
|
92
|
+
except:
|
|
93
|
+
raise Exception('Failed to access USB Device. Check permissions')
|
|
94
|
+
|
|
95
|
+
# Clear USB receive buffer
|
|
96
|
+
try: self.dev.read(CH_USB_EP_IN, 1024, 1)
|
|
97
|
+
except: None
|
|
98
|
+
|
|
99
|
+
# Set initial chip parameters
|
|
100
|
+
self.device = None
|
|
101
|
+
self.uidlen = 4
|
|
102
|
+
self.lastwrite = False
|
|
103
|
+
self.wpremove = False
|
|
104
|
+
self.xorkey = bytearray(CH_XOR_KEY_LEN)
|
|
105
|
+
|
|
106
|
+
# Send command and return reply
|
|
107
|
+
def sendcommand(self, stream):
|
|
108
|
+
self.dev.write(CH_USB_EP_OUT, stream)
|
|
109
|
+
try: return self.dev.read(CH_USB_EP_IN, CH_USB_PACKET_SIZE, CH_USB_TIMEOUT)
|
|
110
|
+
except: return None
|
|
111
|
+
|
|
112
|
+
# Detect, identify and setup chip
|
|
113
|
+
def detect(self):
|
|
114
|
+
# Read type of chip
|
|
115
|
+
identanswer = self.sendcommand(CH_STR_CHIP_DETECT)
|
|
116
|
+
if len(identanswer) != 6:
|
|
117
|
+
raise Exception('Failed to identify chip')
|
|
118
|
+
|
|
119
|
+
# Read configuration
|
|
120
|
+
cfganswer = self.sendcommand(CH_STR_CONFIG_READ)
|
|
121
|
+
if len(cfganswer) != 30:
|
|
122
|
+
raise Exception('Failed to read chip configuration')
|
|
123
|
+
|
|
124
|
+
# Set chip and configuration values
|
|
125
|
+
self.configdata = cfganswer[6:18]
|
|
126
|
+
self.bootloader = '%d.%d.%d' % (cfganswer[19], cfganswer[20], cfganswer[21])
|
|
127
|
+
self.chiptype = identanswer[4]
|
|
128
|
+
self.chipfamily = identanswer[5]
|
|
129
|
+
self.chipid = (self.chipfamily << 8) + self.chiptype
|
|
130
|
+
|
|
131
|
+
# Find device in dictionary
|
|
132
|
+
for d in DEVICES:
|
|
133
|
+
if d['id'] == self.chipid:
|
|
134
|
+
self.device = d
|
|
135
|
+
if self.device is None:
|
|
136
|
+
raise Exception('Unsupported chip (ID: 0x%04x)' % self.chipid)
|
|
137
|
+
|
|
138
|
+
# Set parameters according to dictionary
|
|
139
|
+
self.chipname = self.device['name']
|
|
140
|
+
self.code_flash_size = self.device['code_size']
|
|
141
|
+
self.data_flash_size = self.device['data_size']
|
|
142
|
+
if self.chipfamily > 0x11:
|
|
143
|
+
self.uidlen = 8
|
|
144
|
+
if self.chipfamily in LASTWRITELIST:
|
|
145
|
+
self.lastwrite = True
|
|
146
|
+
if self.chipfamily in WPREMOVELIST:
|
|
147
|
+
self.wpremove = True
|
|
148
|
+
self.chipuid = cfganswer[22:(22 + self.uidlen)]
|
|
149
|
+
|
|
150
|
+
# Create local encryption key
|
|
151
|
+
sum = 0
|
|
152
|
+
for x in range(self.uidlen):
|
|
153
|
+
sum += self.chipuid[x]
|
|
154
|
+
for x in range(CH_XOR_KEY_LEN - 1):
|
|
155
|
+
self.xorkey[x] = sum & 0xff
|
|
156
|
+
self.xorkey[CH_XOR_KEY_LEN - 1] = (sum + self.chiptype) & 0xff
|
|
157
|
+
|
|
158
|
+
# Send encryption key
|
|
159
|
+
sum = 0
|
|
160
|
+
for x in range(CH_XOR_KEY_LEN):
|
|
161
|
+
sum += self.xorkey[x]
|
|
162
|
+
stream = bytes((CH_CMD_KEY_SET, 0x1e, 0x00)) + bytes(0x1e)
|
|
163
|
+
reply = self.sendcommand(stream)
|
|
164
|
+
if reply[4] != (sum & 0xff):
|
|
165
|
+
raise Exception('Failed to set encryption key')
|
|
166
|
+
|
|
167
|
+
# Unlock chip (remove read protection)
|
|
168
|
+
if (self.wpremove) and (self.configdata[0] == 0xff):
|
|
169
|
+
self.configdata[0] = 0xa5
|
|
170
|
+
self.sendcommand(b'\xa8\x0e\x00\x07\x00' + self.configdata)
|
|
171
|
+
if self.chipid == 0x1379:
|
|
172
|
+
self.configdata[8] &= 0x7f
|
|
173
|
+
self.sendcommand(b'\xa8\x0e\x00\x07\x00' + self.configdata)
|
|
174
|
+
|
|
175
|
+
# Erase code flash
|
|
176
|
+
def erase(self, size):
|
|
177
|
+
if size > self.code_flash_size:
|
|
178
|
+
raise Exception('Not enough memory')
|
|
179
|
+
size = (size + 1023) // 1024
|
|
180
|
+
if size < 8: size = 8
|
|
181
|
+
stream = (CH_CMD_CODE_ERASE, 0x04, 0x00, size & 0xff, size >> 8, 0x00, 0x00)
|
|
182
|
+
reply = self.sendcommand(stream)
|
|
183
|
+
if reply[4] != 0x00:
|
|
184
|
+
raise Exception('Failed to erase chip')
|
|
185
|
+
|
|
186
|
+
# Write data stream to code flash
|
|
187
|
+
def flash(self, data):
|
|
188
|
+
self.erase(len(data))
|
|
189
|
+
self.writeflash(data, CH_CMD_CODE_WRITE)
|
|
190
|
+
|
|
191
|
+
# Verify data stream in code flash
|
|
192
|
+
def verify(self, data):
|
|
193
|
+
if len(data) > self.code_flash_size:
|
|
194
|
+
raise Exception('Not enough memory')
|
|
195
|
+
self.writeflash(data, CH_CMD_CODE_VERIFY)
|
|
196
|
+
|
|
197
|
+
# Reboot and exit
|
|
198
|
+
def exit(self):
|
|
199
|
+
self.sendcommand(CH_STR_REBOOT)
|
|
200
|
+
|
|
201
|
+
# Perform flash operations
|
|
202
|
+
def writeflash(self, data, mode):
|
|
203
|
+
# Encrypt data
|
|
204
|
+
if (len(data) % CH_XOR_KEY_LEN) > 0:
|
|
205
|
+
data += b'0xff' * (CH_XOR_KEY_LEN - (len(data) % CH_XOR_KEY_LEN))
|
|
206
|
+
data = bytearray(data)
|
|
207
|
+
for x in range(len(data)):
|
|
208
|
+
data[x] ^= self.xorkey[x % CH_XOR_KEY_LEN]
|
|
209
|
+
|
|
210
|
+
# Send data in chunks of 56 bytes
|
|
211
|
+
rest = len(data)
|
|
212
|
+
offset = 0
|
|
213
|
+
pkt_len = 0
|
|
214
|
+
while rest > 0:
|
|
215
|
+
pkt_len = min(rest, 0x38)
|
|
216
|
+
stream = bytes((mode, pkt_len + 5, 0))
|
|
217
|
+
stream += offset.to_bytes(4, byteorder='little')
|
|
218
|
+
stream += (rest & 0xff).to_bytes(1, byteorder='little')
|
|
219
|
+
stream += data[offset:(offset + pkt_len)]
|
|
220
|
+
reply = self.sendcommand(stream)
|
|
221
|
+
if reply[4] != 0x00 and reply[4] != 0xfe and reply[4] != 0xf5:
|
|
222
|
+
if mode == CH_CMD_CODE_WRITE:
|
|
223
|
+
raise Exception('Failed to write at offset 0x%08x' % offset)
|
|
224
|
+
elif mode == CH_CMD_CODE_VERIFY:
|
|
225
|
+
raise Exception('Failed to verify at offset 0x%08x' % offset)
|
|
226
|
+
offset += pkt_len
|
|
227
|
+
rest -= pkt_len
|
|
228
|
+
|
|
229
|
+
# Some chips need a last empty write
|
|
230
|
+
if (self.lastwrite) and (mode == CH_CMD_CODE_WRITE):
|
|
231
|
+
stream = bytes((mode, 5, 0)) + offset.to_bytes(4, byteorder='little') + b'\x00'
|
|
232
|
+
self.sendcommand(stream)
|
|
233
|
+
|
|
234
|
+
# ===================================================================================
|
|
235
|
+
# Protocol Constants
|
|
236
|
+
# ===================================================================================
|
|
237
|
+
|
|
238
|
+
CH_USB_VENDOR_ID1 = 0x4348 # VID 1
|
|
239
|
+
CH_USB_VENDOR_ID2 = 0x1a86 # VID 2
|
|
240
|
+
CH_USB_PRODUCT_ID = 0x55e0 # PID
|
|
241
|
+
CH_USB_INTERFACE = 0 # interface number
|
|
242
|
+
CH_USB_EP_OUT = 0x02 # endpoint for command transfer out
|
|
243
|
+
CH_USB_EP_IN = 0x82 # endpoint for reply transfer in
|
|
244
|
+
CH_USB_PACKET_SIZE = 64 # packet size
|
|
245
|
+
CH_USB_TIMEOUT = 5000 # timeout for USB operations
|
|
246
|
+
|
|
247
|
+
CH_CMD_CHIP_TYPE = 0xa1
|
|
248
|
+
CH_CMD_REBOOT = 0xa2
|
|
249
|
+
CH_CMD_KEY_SET = 0xa3
|
|
250
|
+
CH_CMD_CODE_ERASE = 0xa4
|
|
251
|
+
CH_CMD_CODE_WRITE = 0xa5
|
|
252
|
+
CH_CMD_CODE_VERIFY = 0xa6
|
|
253
|
+
CH_CMD_CONFIG_READ = 0xa7
|
|
254
|
+
CH_CMD_CONFIG_WRITE = 0xa8
|
|
255
|
+
CH_CMD_DATA_ERASE = 0xa9
|
|
256
|
+
CH_CMD_DATA_WRITE = 0xaa
|
|
257
|
+
CH_CMD_DATA_READ = 0xab
|
|
258
|
+
|
|
259
|
+
CH_STR_CHIP_DETECT = b'\xa1\x12\x00\x52\x11MCU ISP & WCH.CN'
|
|
260
|
+
CH_STR_CONFIG_READ = (0xa7, 0x02, 0x00, 0x1f, 0x00)
|
|
261
|
+
CH_STR_CODE_ERASE = (0xa4, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00)
|
|
262
|
+
CH_STR_DATA_ERASE = (0xa9, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02)
|
|
263
|
+
CH_STR_REBOOT = (0xa2, 0x01, 0x00, 0x01)
|
|
264
|
+
|
|
265
|
+
CH_XOR_KEY_LEN = 8
|
|
266
|
+
|
|
267
|
+
# ===================================================================================
|
|
268
|
+
# Device definitions
|
|
269
|
+
# ===================================================================================
|
|
270
|
+
|
|
271
|
+
DEVICES = [
|
|
272
|
+
{'name': 'CH543', 'id': 0x1243, 'code_size': 14336, 'data_size': 256},
|
|
273
|
+
{'name': 'CH544', 'id': 0x1244, 'code_size': 61440, 'data_size': 1024},
|
|
274
|
+
{'name': 'CH545', 'id': 0x1245, 'code_size': 61440, 'data_size': 1024},
|
|
275
|
+
{'name': 'CH546', 'id': 0x1246, 'code_size': 32768, 'data_size': 1024},
|
|
276
|
+
{'name': 'CH547', 'id': 0x1247, 'code_size': 61440, 'data_size': 1024},
|
|
277
|
+
{'name': 'CH548', 'id': 0x1248, 'code_size': 32768, 'data_size': 1024},
|
|
278
|
+
{'name': 'CH549', 'id': 0x1249, 'code_size': 61440, 'data_size': 1024},
|
|
279
|
+
|
|
280
|
+
{'name': 'CH551', 'id': 0x1151, 'code_size': 10240, 'data_size': 128},
|
|
281
|
+
{'name': 'CH552', 'id': 0x1152, 'code_size': 14336, 'data_size': 128},
|
|
282
|
+
{'name': 'CH554', 'id': 0x1154, 'code_size': 14336, 'data_size': 128},
|
|
283
|
+
{'name': 'CH555', 'id': 0x1155, 'code_size': 61440, 'data_size': 1024},
|
|
284
|
+
{'name': 'CH556', 'id': 0x1156, 'code_size': 61440, 'data_size': 1024},
|
|
285
|
+
{'name': 'CH557', 'id': 0x1157, 'code_size': 61440, 'data_size': 1024},
|
|
286
|
+
{'name': 'CH558', 'id': 0x1158, 'code_size': 61440, 'data_size': 1024},
|
|
287
|
+
{'name': 'CH559', 'id': 0x1159, 'code_size': 61440, 'data_size': 1024},
|
|
288
|
+
|
|
289
|
+
{'name': 'CH573', 'id': 0x1373, 'code_size': 458752, 'data_size': 32768},
|
|
290
|
+
{'name': 'CH579', 'id': 0x1379, 'code_size': 256000, 'data_size': 2048},
|
|
291
|
+
{'name': 'CH582', 'id': 0x1682, 'code_size': 458752, 'data_size': 32768},
|
|
292
|
+
|
|
293
|
+
{'name': 'CH32F103x6', 'id': 0x1432, 'code_size': 32768, 'data_size': 0},
|
|
294
|
+
{'name': 'CH32F103x8', 'id': 0x143f, 'code_size': 65536, 'data_size': 0},
|
|
295
|
+
|
|
296
|
+
{'name': 'CH32F203VCT6', 'id': 0x1830, 'code_size': 262144, 'data_size': 0},
|
|
297
|
+
{'name': 'CH32F203RCT6', 'id': 0x1831, 'code_size': 262144, 'data_size': 0},
|
|
298
|
+
{'name': 'CH32F203CBT6', 'id': 0x1832, 'code_size': 131072, 'data_size': 0},
|
|
299
|
+
{'name': 'CH32F203RBT6', 'id': 0x1833, 'code_size': 131072, 'data_size': 0},
|
|
300
|
+
{'name': 'CH32F205RBT6', 'id': 0x1850, 'code_size': 131072, 'data_size': 0},
|
|
301
|
+
{'name': 'CH32F207VCT6', 'id': 0x1870, 'code_size': 262144, 'data_size': 0},
|
|
302
|
+
|
|
303
|
+
{'name': 'CH32F203C8U6', 'id': 0x1a30, 'code_size': 65536, 'data_size': 0},
|
|
304
|
+
{'name': 'CH32F203C8T6', 'id': 0x1a31, 'code_size': 65536, 'data_size': 0},
|
|
305
|
+
{'name': 'CH32F203K8T6', 'id': 0x1a32, 'code_size': 65536, 'data_size': 0},
|
|
306
|
+
{'name': 'CH32F203C6T6', 'id': 0x1a33, 'code_size': 32768, 'data_size': 0},
|
|
307
|
+
{'name': 'CH32F208WBU6', 'id': 0x1a80, 'code_size': 491520, 'data_size': 0},
|
|
308
|
+
{'name': 'CH32F208RBT6', 'id': 0x1a81, 'code_size': 131072, 'data_size': 0},
|
|
309
|
+
|
|
310
|
+
{'name': 'CH32V103x6', 'id': 0x1532, 'code_size': 32768, 'data_size': 0},
|
|
311
|
+
{'name': 'CH32V103x8', 'id': 0x153f, 'code_size': 65536, 'data_size': 0},
|
|
312
|
+
|
|
313
|
+
{'name': 'CH32V203C8U6', 'id': 0x1930, 'code_size': 65536, 'data_size': 0},
|
|
314
|
+
{'name': 'CH32V203C8T6', 'id': 0x1931, 'code_size': 65536, 'data_size': 0},
|
|
315
|
+
{'name': 'CH32V203K8T6', 'id': 0x1932, 'code_size': 65536, 'data_size': 0},
|
|
316
|
+
{'name': 'CH32V203C6T6', 'id': 0x1933, 'code_size': 32768, 'data_size': 0},
|
|
317
|
+
{'name': 'CH32V203RBT6', 'id': 0x1934, 'code_size': 131072, 'data_size': 0},
|
|
318
|
+
{'name': 'CH32V203K6T6', 'id': 0x1935, 'code_size': 32768, 'data_size': 0},
|
|
319
|
+
{'name': 'CH32V203G6U6', 'id': 0x1936, 'code_size': 32768, 'data_size': 0},
|
|
320
|
+
{'name': 'CH32V203F6P6', 'id': 0x1937, 'code_size': 32768, 'data_size': 0},
|
|
321
|
+
{'name': 'CH32V203F8P6', 'id': 0x193a, 'code_size': 65536, 'data_size': 0},
|
|
322
|
+
{'name': 'CH32V203G8R6', 'id': 0x193b, 'code_size': 65536, 'data_size': 0},
|
|
323
|
+
{'name': 'CH32V208WBU6', 'id': 0x1980, 'code_size': 491520, 'data_size': 0},
|
|
324
|
+
{'name': 'CH32V208RBT6', 'id': 0x1981, 'code_size': 131072, 'data_size': 0},
|
|
325
|
+
{'name': 'CH32V208CBU6', 'id': 0x1982, 'code_size': 131072, 'data_size': 0},
|
|
326
|
+
{'name': 'CH32V208GBU6', 'id': 0x1983, 'code_size': 131072, 'data_size': 0},
|
|
327
|
+
|
|
328
|
+
{'name': 'CH32V303VCT6', 'id': 0x1730, 'code_size': 262144, 'data_size': 0},
|
|
329
|
+
{'name': 'CH32V303RCT6', 'id': 0x1731, 'code_size': 262144, 'data_size': 0},
|
|
330
|
+
{'name': 'CH32V303RBT6', 'id': 0x1733, 'code_size': 131072, 'data_size': 0},
|
|
331
|
+
{'name': 'CH32V303CBT6', 'id': 0x1734, 'code_size': 131072, 'data_size': 0},
|
|
332
|
+
{'name': 'CH32V305RBT6', 'id': 0x1750, 'code_size': 131072, 'data_size': 0},
|
|
333
|
+
{'name': 'CH32V305FBP6', 'id': 0x1752, 'code_size': 131072, 'data_size': 0},
|
|
334
|
+
{'name': 'CH32V307VCT6', 'id': 0x1770, 'code_size': 262144, 'data_size': 0},
|
|
335
|
+
{'name': 'CH32V307RCT6', 'id': 0x1771, 'code_size': 262144, 'data_size': 0},
|
|
336
|
+
{'name': 'CH32V307WCU6', 'id': 0x1773, 'code_size': 262144, 'data_size': 0},
|
|
337
|
+
|
|
338
|
+
{'name': 'CH32X033F8P6', 'id': 0x235a, 'code_size': 63488, 'data_size': 0},
|
|
339
|
+
{'name': 'CH32X035R8T6', 'id': 0x2350, 'code_size': 63488, 'data_size': 0},
|
|
340
|
+
{'name': 'CH32X035C8T6', 'id': 0x2351, 'code_size': 63488, 'data_size': 0},
|
|
341
|
+
{'name': 'CH32X035F8U6', 'id': 0x235e, 'code_size': 63488, 'data_size': 0},
|
|
342
|
+
{'name': 'CH32X035G8U6', 'id': 0x2356, 'code_size': 63488, 'data_size': 0},
|
|
343
|
+
{'name': 'CH32X035G8R6', 'id': 0x235b, 'code_size': 63488, 'data_size': 0},
|
|
344
|
+
{'name': 'CH32X035F7P6', 'id': 0x2357, 'code_size': 49152, 'data_size': 0},
|
|
345
|
+
|
|
346
|
+
{'name': 'CH32L103C8U6', 'id': 0x2530, 'code_size': 65536, 'data_size': 0},
|
|
347
|
+
{'name': 'CH32L103C8T6', 'id': 0x2531, 'code_size': 65536, 'data_size': 0},
|
|
348
|
+
{'name': 'CH32L103F8P6', 'id': 0x253a, 'code_size': 65536, 'data_size': 0},
|
|
349
|
+
{'name': 'CH32L103G8R6', 'id': 0x253b, 'code_size': 65536, 'data_size': 0},
|
|
350
|
+
{'name': 'CH32L103K8U6', 'id': 0x2532, 'code_size': 65536, 'data_size': 0},
|
|
351
|
+
{'name': 'CH32L103F8U6', 'id': 0x253d, 'code_size': 65536, 'data_size': 0},
|
|
352
|
+
{'name': 'CH32L103F7P6', 'id': 0x2537, 'code_size': 49152, 'data_size': 0}
|
|
353
|
+
]
|
|
354
|
+
|
|
355
|
+
LASTWRITELIST = (0x12, 0x14, 0x15, 0x17, 0x18,0x19, 0x1a, 0x23, 0x25)
|
|
356
|
+
WPREMOVELIST = (0x14, 0x15, 0x17, 0x18, 0x19, 0x1a, 0x23, 0x25)
|
|
357
|
+
|
|
358
|
+
# ===================================================================================
|
|
359
|
+
|
|
360
|
+
if __name__ == "__main__":
|
|
361
|
+
_main()
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: chprog
|
|
3
|
+
Version: 2.4.0
|
|
4
|
+
Summary: USB Programming Tool for WCH Microcontrollers
|
|
5
|
+
Home-page: https://github.com/wagiminator/MCU-Flash-Tools
|
|
6
|
+
Author: Stefan Wagner
|
|
7
|
+
Author-email: Stefan Wagner <wagiminator@web.de>
|
|
8
|
+
Maintainer-email: Stefan Wagner <wagiminator@web.de>
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2022 Stefan Wagner
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
Project-URL: Homepage, https://wagiminator.github.io/
|
|
31
|
+
Project-URL: Repository, https://github.com/wagiminator/MCU-Flash-Tools
|
|
32
|
+
Project-URL: Issues, https://github.com/wagiminator/MCU-Flash-Tools/issues
|
|
33
|
+
Keywords: WCH,CH552,CH32V003,CH32X035,microcontroller
|
|
34
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
35
|
+
Classifier: Programming Language :: Python :: 3
|
|
36
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
37
|
+
Classifier: Operating System :: OS Independent
|
|
38
|
+
Classifier: Intended Audience :: Developers
|
|
39
|
+
Classifier: Topic :: Software Development :: Embedded Systems
|
|
40
|
+
Requires-Python: >=3.8
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
License-File: LICENSE
|
|
43
|
+
Requires-Dist: pyusb
|
|
44
|
+
|
|
45
|
+
# chprog - USB Programming Tool for WCH Microcontrollers
|
|
46
|
+
## Description
|
|
47
|
+
With this tool, almost all WCH microcontrollers (CH5xx, CH32Fxxx, CH32Vxxx, CH32Xxxx, and CH32Lxxx) which have a factory-builtin bootloader (v2.x.x) can be flashed via USB.
|
|
48
|
+
|
|
49
|
+
## Preparations
|
|
50
|
+
On Linux you do not need to install a driver for the USB bootloader. However, by default Linux will not expose enough permission to upload your code. In order to fix this, open a terminal and run the following commands:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="4348", ATTR{idProduct}=="55e0", MODE="666"' | sudo tee /etc/udev/rules.d/99-ch55x.rules
|
|
54
|
+
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="55e0", MODE="666"' | sudo tee -a /etc/udev/rules.d/99-ch55x.rules
|
|
55
|
+
sudo udevadm control --reload-rules
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
For Windows, you need the [CH372 driver](http://www.wch-ic.com/downloads/CH372DRV_EXE.html). Alternatively, you can also use the [Zadig Tool](https://zadig.akeo.ie/) to install the correct driver. Here, click "Options" -> "List All Devices" and select the USB module. Then install the libusb-win32 driver. To do this, the board must be connected and the microcontroller must be in bootloader mode.
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
- Install [Python3](https://www.pythontutorial.net/getting-started/install-python/).
|
|
62
|
+
- Install [pip](https://pip.pypa.io/en/stable/installation/).
|
|
63
|
+
- Install chprog:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
pip install chprog
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Usage
|
|
70
|
+
The bootloader must be started manually for new uploads. To do this, the board must first be disconnected from the USB port and all voltage sources. Now press the BOOT button and keep it pressed while reconnecting the board to the USB port of your PC. The chip now starts in bootloader mode, the BOOT button can be released and new firmware can be uploaded via USB. Alternatively, you can leave the board connected to the USB port, press and hold the BOOT button, press and release the RESET button and then release the BOOT button to enter the bootloader mode. If there is no BOOT button on the board, look at the datasheet to find out which pin needs to be pulled to which voltage level for the microcontroller to go into boot mode.
|
|
71
|
+
|
|
72
|
+
Now run the following command (example):
|
|
73
|
+
```
|
|
74
|
+
chprog firmware.bin
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Links
|
|
78
|
+
- [MCU Flash Tools](https://github.com/wagiminator/MCU-Flash-Tools)
|
|
79
|
+
- [MCU Templates](https://github.com/wagiminator/MCU-Templates)
|
|
80
|
+
- [MCU Development Boards](https://github.com/wagiminator/Development-Boards)
|
|
81
|
+
- [AVR Development Boards](https://github.com/wagiminator/AVR-Development-Boards)
|
|
82
|
+
- [AVR Programmers](https://github.com/wagiminator/AVR-Programmer)
|
|
83
|
+
- [SAMD Development Boards](https://github.com/wagiminator/SAMD-Development-Boards)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
setup.py
|
|
5
|
+
chprog/__init__.py
|
|
6
|
+
chprog/chprog.py
|
|
7
|
+
chprog.egg-info/PKG-INFO
|
|
8
|
+
chprog.egg-info/SOURCES.txt
|
|
9
|
+
chprog.egg-info/dependency_links.txt
|
|
10
|
+
chprog.egg-info/entry_points.txt
|
|
11
|
+
chprog.egg-info/requires.txt
|
|
12
|
+
chprog.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyusb
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
chprog
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "chprog"
|
|
7
|
+
version = "2.4.0"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name="Stefan Wagner", email="wagiminator@web.de" },
|
|
10
|
+
]
|
|
11
|
+
maintainers = [
|
|
12
|
+
{ name="Stefan Wagner", email="wagiminator@web.de" },
|
|
13
|
+
]
|
|
14
|
+
description = "USB Programming Tool for WCH Microcontrollers"
|
|
15
|
+
readme = "README.md"
|
|
16
|
+
license = {file = "LICENSE"}
|
|
17
|
+
requires-python = ">=3.8"
|
|
18
|
+
dependencies = [
|
|
19
|
+
"pyusb",
|
|
20
|
+
]
|
|
21
|
+
keywords = ["WCH", "CH552", "CH32V003", "CH32X035", "microcontroller"]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Development Status :: 5 - Production/Stable",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"License :: OSI Approved :: MIT License",
|
|
26
|
+
"Operating System :: OS Independent",
|
|
27
|
+
"Intended Audience :: Developers",
|
|
28
|
+
"Topic :: Software Development :: Embedded Systems",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.scripts]
|
|
32
|
+
chprog = "chprog:_main"
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://wagiminator.github.io/"
|
|
36
|
+
Repository = "https://github.com/wagiminator/MCU-Flash-Tools"
|
|
37
|
+
Issues = "https://github.com/wagiminator/MCU-Flash-Tools/issues"
|
chprog-2.4.0/setup.cfg
ADDED
chprog-2.4.0/setup.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name='chprog',
|
|
5
|
+
version='2.4.0',
|
|
6
|
+
description='USB Programming Tool for WCH Microcontrollers',
|
|
7
|
+
url='https://github.com/wagiminator/MCU-Flash-Tools',
|
|
8
|
+
author='Stefan Wagner',
|
|
9
|
+
author_email='wagiminator@web.de',
|
|
10
|
+
license='MIT License',
|
|
11
|
+
packages=['chprog'],
|
|
12
|
+
install_requires=[
|
|
13
|
+
'pyusb',
|
|
14
|
+
],
|
|
15
|
+
)
|