rvprog 1.5.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.
- rvprog-1.5.0/LICENSE +21 -0
- rvprog-1.5.0/PKG-INFO +113 -0
- rvprog-1.5.0/README.md +69 -0
- rvprog-1.5.0/pyproject.toml +37 -0
- rvprog-1.5.0/rvprog/__init__.py +1 -0
- rvprog-1.5.0/rvprog/rvprog.py +568 -0
- rvprog-1.5.0/rvprog.egg-info/PKG-INFO +113 -0
- rvprog-1.5.0/rvprog.egg-info/SOURCES.txt +12 -0
- rvprog-1.5.0/rvprog.egg-info/dependency_links.txt +1 -0
- rvprog-1.5.0/rvprog.egg-info/entry_points.txt +2 -0
- rvprog-1.5.0/rvprog.egg-info/requires.txt +1 -0
- rvprog-1.5.0/rvprog.egg-info/top_level.txt +1 -0
- rvprog-1.5.0/setup.cfg +4 -0
- rvprog-1.5.0/setup.py +15 -0
rvprog-1.5.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 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.
|
rvprog-1.5.0/PKG-INFO
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: rvprog
|
|
3
|
+
Version: 1.5.0
|
|
4
|
+
Summary: Programming Tool for WCH-LinkE and CH32Vxxx and CH32Xxxx
|
|
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) 2023 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,RISC-V,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
|
+
# rvprog - Programming Tool for WCH-LinkE and CH32Vxxx and CH32Xxxx
|
|
46
|
+
## Description
|
|
47
|
+
With this tool, the WCH RISC-V microcontrollers CH32Vxxx and CH32Xxxx can be programmed with the [WCH-LinkE](http://www.wch-ic.com/products/WCH-Link.html) (pay attention to the "E" in the name) via its serial debug interface.
|
|
48
|
+
|
|
49
|
+
## Preparations
|
|
50
|
+
To use the WCH-Link on Linux, you need to grant access permissions beforehand by executing the following commands:
|
|
51
|
+
```
|
|
52
|
+
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="8010", MODE="666"' | sudo tee /etc/udev/rules.d/99-WCH-LinkE.rules
|
|
53
|
+
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="8012", MODE="666"' | sudo tee -a /etc/udev/rules.d/99-WCH-LinkE.rules
|
|
54
|
+
sudo udevadm control --reload-rules
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
On Windows, if you need to you can install the WinUSB driver over the WCH interface 1 using the [Zadig Tool](https://zadig.akeo.ie/).
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
- Install [Python3](https://www.pythontutorial.net/getting-started/install-python/).
|
|
61
|
+
- Install [pip](https://pip.pypa.io/en/stable/installation/).
|
|
62
|
+
- Install rvprog:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
pip install rvprog
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Usage
|
|
69
|
+
To upload firmware, you should make the following connections to the WCH-LinkE (SWCLK is not present on the CH32V003 and therefore does not need to be connected):
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
WCH-LinkE CH32V/X
|
|
73
|
+
+-------+ +-------+
|
|
74
|
+
| SWCLK| ---> |SWCLK |
|
|
75
|
+
| SWDIO| <--> |SWDIO |
|
|
76
|
+
| GND| ---> |GND |
|
|
77
|
+
| 3V3| ---> |VDD |
|
|
78
|
+
+-------+ +-------+
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
If the blue LED on the WCH-LinkE remains illuminated once it is connected to the USB port, it means that the device is currently in ARM mode and must be switched to RISC-V mode initially. There are a few ways to accomplish this:
|
|
82
|
+
- You can utilize the rvprog tool with the -v option (see below).
|
|
83
|
+
- Alternatively, you can select "WCH-LinkRV" in the software provided by WCH, such as MounRiver Studio or WCH-LinkUtility.
|
|
84
|
+
- Another option is to hold down the ModeS button on the device while plugging it into the USB port.
|
|
85
|
+
|
|
86
|
+
More information can be found in the [WCH-Link User Manual](http://www.wch-ic.com/downloads/WCH-LinkUserManual_PDF.html).
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
Usage: rvprog [-h] [-a] [-v] [-b] [-u] [-l] [-e] [-G] [-R] [-f FLASH]
|
|
90
|
+
|
|
91
|
+
Optional arguments:
|
|
92
|
+
-h, --help show help message and exit
|
|
93
|
+
-a, --armmode switch WCH-Link to ARM mode
|
|
94
|
+
-v, --rvmode switch WCH-Link to RISC-V mode
|
|
95
|
+
-b, --unbrick unbrick chip
|
|
96
|
+
-u, --unlock unlock chip (remove read protection)
|
|
97
|
+
-l, --lock lock chip (set read protection)
|
|
98
|
+
-e, --erase perform a whole chip erase
|
|
99
|
+
-G, --pingpio make nRST pin a GPIO pin (CH32V003 only)
|
|
100
|
+
-R, --pinreset make nRST pin a reset pin (CH32V003 only)
|
|
101
|
+
-f FLASH, --flash FLASH write BIN file to flash
|
|
102
|
+
|
|
103
|
+
Example:
|
|
104
|
+
rvprog -f firmware.bin
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Links
|
|
108
|
+
- [MCU Flash Tools](https://github.com/wagiminator/MCU-Flash-Tools)
|
|
109
|
+
- [MCU Templates](https://github.com/wagiminator/MCU-Templates)
|
|
110
|
+
- [MCU Development Boards](https://github.com/wagiminator/Development-Boards)
|
|
111
|
+
- [AVR Development Boards](https://github.com/wagiminator/AVR-Development-Boards)
|
|
112
|
+
- [AVR Programmers](https://github.com/wagiminator/AVR-Programmer)
|
|
113
|
+
- [SAMD Development Boards](https://github.com/wagiminator/SAMD-Development-Boards)
|
rvprog-1.5.0/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# rvprog - Programming Tool for WCH-LinkE and CH32Vxxx and CH32Xxxx
|
|
2
|
+
## Description
|
|
3
|
+
With this tool, the WCH RISC-V microcontrollers CH32Vxxx and CH32Xxxx can be programmed with the [WCH-LinkE](http://www.wch-ic.com/products/WCH-Link.html) (pay attention to the "E" in the name) via its serial debug interface.
|
|
4
|
+
|
|
5
|
+
## Preparations
|
|
6
|
+
To use the WCH-Link on Linux, you need to grant access permissions beforehand by executing the following commands:
|
|
7
|
+
```
|
|
8
|
+
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="8010", MODE="666"' | sudo tee /etc/udev/rules.d/99-WCH-LinkE.rules
|
|
9
|
+
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="8012", MODE="666"' | sudo tee -a /etc/udev/rules.d/99-WCH-LinkE.rules
|
|
10
|
+
sudo udevadm control --reload-rules
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
On Windows, if you need to you can install the WinUSB driver over the WCH interface 1 using the [Zadig Tool](https://zadig.akeo.ie/).
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
- Install [Python3](https://www.pythontutorial.net/getting-started/install-python/).
|
|
17
|
+
- Install [pip](https://pip.pypa.io/en/stable/installation/).
|
|
18
|
+
- Install rvprog:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
pip install rvprog
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
To upload firmware, you should make the following connections to the WCH-LinkE (SWCLK is not present on the CH32V003 and therefore does not need to be connected):
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
WCH-LinkE CH32V/X
|
|
29
|
+
+-------+ +-------+
|
|
30
|
+
| SWCLK| ---> |SWCLK |
|
|
31
|
+
| SWDIO| <--> |SWDIO |
|
|
32
|
+
| GND| ---> |GND |
|
|
33
|
+
| 3V3| ---> |VDD |
|
|
34
|
+
+-------+ +-------+
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
If the blue LED on the WCH-LinkE remains illuminated once it is connected to the USB port, it means that the device is currently in ARM mode and must be switched to RISC-V mode initially. There are a few ways to accomplish this:
|
|
38
|
+
- You can utilize the rvprog tool with the -v option (see below).
|
|
39
|
+
- Alternatively, you can select "WCH-LinkRV" in the software provided by WCH, such as MounRiver Studio or WCH-LinkUtility.
|
|
40
|
+
- Another option is to hold down the ModeS button on the device while plugging it into the USB port.
|
|
41
|
+
|
|
42
|
+
More information can be found in the [WCH-Link User Manual](http://www.wch-ic.com/downloads/WCH-LinkUserManual_PDF.html).
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
Usage: rvprog [-h] [-a] [-v] [-b] [-u] [-l] [-e] [-G] [-R] [-f FLASH]
|
|
46
|
+
|
|
47
|
+
Optional arguments:
|
|
48
|
+
-h, --help show help message and exit
|
|
49
|
+
-a, --armmode switch WCH-Link to ARM mode
|
|
50
|
+
-v, --rvmode switch WCH-Link to RISC-V mode
|
|
51
|
+
-b, --unbrick unbrick chip
|
|
52
|
+
-u, --unlock unlock chip (remove read protection)
|
|
53
|
+
-l, --lock lock chip (set read protection)
|
|
54
|
+
-e, --erase perform a whole chip erase
|
|
55
|
+
-G, --pingpio make nRST pin a GPIO pin (CH32V003 only)
|
|
56
|
+
-R, --pinreset make nRST pin a reset pin (CH32V003 only)
|
|
57
|
+
-f FLASH, --flash FLASH write BIN file to flash
|
|
58
|
+
|
|
59
|
+
Example:
|
|
60
|
+
rvprog -f firmware.bin
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Links
|
|
64
|
+
- [MCU Flash Tools](https://github.com/wagiminator/MCU-Flash-Tools)
|
|
65
|
+
- [MCU Templates](https://github.com/wagiminator/MCU-Templates)
|
|
66
|
+
- [MCU Development Boards](https://github.com/wagiminator/Development-Boards)
|
|
67
|
+
- [AVR Development Boards](https://github.com/wagiminator/AVR-Development-Boards)
|
|
68
|
+
- [AVR Programmers](https://github.com/wagiminator/AVR-Programmer)
|
|
69
|
+
- [SAMD Development Boards](https://github.com/wagiminator/SAMD-Development-Boards)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "rvprog"
|
|
7
|
+
version = "1.5.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 = "Programming Tool for WCH-LinkE and CH32Vxxx and CH32Xxxx"
|
|
15
|
+
readme = "README.md"
|
|
16
|
+
license = {file = "LICENSE"}
|
|
17
|
+
requires-python = ">=3.8"
|
|
18
|
+
dependencies = [
|
|
19
|
+
"pyusb",
|
|
20
|
+
]
|
|
21
|
+
keywords = ["WCH", "CH552", "CH32V003", "CH32X035", "RISC-V", "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
|
+
rvprog = "rvprog:_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"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .rvprog import _main
|
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# ===================================================================================
|
|
3
|
+
# Project: rvprog - Programming Tool for WCH-LinkE and CH32Vxxx and CH32Xxxx.
|
|
4
|
+
# Version: v1.5
|
|
5
|
+
# Year: 2023
|
|
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 CH32V and CH32X microcontrollers using the WCH-LinkE
|
|
14
|
+
# or compatible programmers/debuggers. The code is based on CNLohr's minichlink.
|
|
15
|
+
# Currently supports: CH32V003, CH32V103, CH32V203, CH32V208, CH32V303, CH32V305,
|
|
16
|
+
# CH32V307, CH32X033, CH32X035.
|
|
17
|
+
#
|
|
18
|
+
# References:
|
|
19
|
+
# -----------
|
|
20
|
+
# - CNLohr minichlink: https://github.com/cnlohr/ch32v003fun/tree/master/minichlink
|
|
21
|
+
# - My mighty USB sniffer
|
|
22
|
+
#
|
|
23
|
+
# Dependencies:
|
|
24
|
+
# -------------
|
|
25
|
+
# - PyUSB
|
|
26
|
+
#
|
|
27
|
+
# Operating Instructions:
|
|
28
|
+
# -----------------------
|
|
29
|
+
# You need to install PyUSB to use rvprog. Install it via "python -m pip install pyusb".
|
|
30
|
+
#
|
|
31
|
+
# Linux users need permission to access the device. Run:
|
|
32
|
+
# echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="8010", MODE="666"' | sudo tee /etc/udev/rules.d/99-WCH-LinkE.rules
|
|
33
|
+
# echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="8012", MODE="666"' | sudo tee -a /etc/udev/rules.d/99-WCH-LinkE.rules
|
|
34
|
+
# sudo udevadm control --reload-rules
|
|
35
|
+
#
|
|
36
|
+
# Connect the WCH-LinkE to your PC and to your CH32Vxxx board. The WCH-LinkE must be
|
|
37
|
+
# in LinkRV mode (blue LED off)! If not, run: python rvprog.py -v
|
|
38
|
+
# Run:
|
|
39
|
+
# - python3 rvprog.py [-h] [-a] [-v] [-b] [-u] [-l] [-e] [-G] [-R] [-f FLASH]
|
|
40
|
+
# -h, --help show help message and exit
|
|
41
|
+
# -a, --armmode switch WCH-Link to ARM mode
|
|
42
|
+
# -v, --rvmode switch WCH-Link to RISC-V mode
|
|
43
|
+
# -b, --unbrick unbrick chip (CH32V003 only)
|
|
44
|
+
# -u, --unlock unlock chip (remove read protection)
|
|
45
|
+
# -l, --lock lock chip (set read protection)
|
|
46
|
+
# -e, --erase perform a whole chip erase
|
|
47
|
+
# -G, --pingpio make nRST pin a GPIO pin (CH32V003 only)
|
|
48
|
+
# -R, --pinreset make nRST pin a reset pin (CH32V003 only)
|
|
49
|
+
# -f FLASH, --flash FLASH write BIN file to flash
|
|
50
|
+
#
|
|
51
|
+
# - Example:
|
|
52
|
+
# python3 rvprog.py -f firmware.bin
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
import usb.core
|
|
56
|
+
import usb.util
|
|
57
|
+
import sys
|
|
58
|
+
import time
|
|
59
|
+
import argparse
|
|
60
|
+
|
|
61
|
+
# ===================================================================================
|
|
62
|
+
# Main Function
|
|
63
|
+
# ===================================================================================
|
|
64
|
+
|
|
65
|
+
def _main():
|
|
66
|
+
# Parse command line arguments
|
|
67
|
+
parser = argparse.ArgumentParser(description='Minimal command line interface for CH32Vxxx programming')
|
|
68
|
+
parser.add_argument('-a', '--armmode', action='store_true', help='switch WCH-LinkE to ARM mode')
|
|
69
|
+
parser.add_argument('-v', '--rvmode', action='store_true', help='switch WCH-LinkE to RISC-V mode')
|
|
70
|
+
parser.add_argument('-b', '--unbrick', action='store_true', help='unbrick chip (CH32V003 only)')
|
|
71
|
+
parser.add_argument('-u', '--unlock', action='store_true', help='unlock chip (remove read protection)')
|
|
72
|
+
parser.add_argument('-l', '--lock', action='store_true', help='lock chip (set read protection)')
|
|
73
|
+
parser.add_argument('-e', '--erase', action='store_true', help='perform a whole chip erase')
|
|
74
|
+
parser.add_argument('-G', '--pingpio', action='store_true', help='make nRST pin a GPIO pin (CH32V003 only)')
|
|
75
|
+
parser.add_argument('-R', '--pinreset', action='store_true', help='make nRST pin a reset pin (CH32V003 only)')
|
|
76
|
+
parser.add_argument('-f', '--flash', help='write BIN file to flash and verify')
|
|
77
|
+
args = parser.parse_args(sys.argv[1:])
|
|
78
|
+
|
|
79
|
+
# Check arguments
|
|
80
|
+
if not any( (args.armmode, args.rvmode, args.unbrick, args.unlock, args.lock, args.erase, args.pingpio, args.pinreset, args.flash) ):
|
|
81
|
+
print('No arguments - no action!')
|
|
82
|
+
sys.exit(0)
|
|
83
|
+
|
|
84
|
+
# Switch WCH-Link to RISC-V mode
|
|
85
|
+
try:
|
|
86
|
+
if args.rvmode:
|
|
87
|
+
print('Searching for WCH-LinkE in ARM mode ...')
|
|
88
|
+
armlink = usb.core.find(idVendor = CH_VENDOR_ID, idProduct = CH_ARM_ID)
|
|
89
|
+
if armlink is None:
|
|
90
|
+
raise Exception('No WCH-LinkE in ARM mode found!')
|
|
91
|
+
print('SUCCESS: Found WCH-LinkE in ARM mode.')
|
|
92
|
+
print('Switching WCH-LinkE to RISC-V mode ...')
|
|
93
|
+
armlink.write(0x02, b'\x81\xff\x01\x52')
|
|
94
|
+
time.sleep(2)
|
|
95
|
+
print('DONE.')
|
|
96
|
+
except Exception as ex:
|
|
97
|
+
sys.stderr.write('ERROR: %s!\n' % str(ex))
|
|
98
|
+
|
|
99
|
+
# Establish connection to WCH-Link
|
|
100
|
+
try:
|
|
101
|
+
print('Searching for WCH-LinkE in RISC-V mode ...')
|
|
102
|
+
isp = Programmer()
|
|
103
|
+
print('SUCCESS: Found %s v%s in RISC-V mode.' % (isp.linkname, isp.linkversion))
|
|
104
|
+
except Exception as ex:
|
|
105
|
+
sys.stderr.write('ERROR: %s!\n' % str(ex))
|
|
106
|
+
sys.exit(1)
|
|
107
|
+
|
|
108
|
+
# Performing actions
|
|
109
|
+
try:
|
|
110
|
+
# Unbrick chip
|
|
111
|
+
if args.unbrick:
|
|
112
|
+
print('Unbricking chip ...')
|
|
113
|
+
isp.unbrick()
|
|
114
|
+
print('SUCCESS: Chip is unbricked.')
|
|
115
|
+
|
|
116
|
+
# Establish connection to target MCU
|
|
117
|
+
if any( (args.unlock, args.lock, args.erase, args.flash, args.pingpio, args.pinreset) ):
|
|
118
|
+
print('Connecting to MCU ...')
|
|
119
|
+
isp.connect()
|
|
120
|
+
print('SUCCESS: Connected to %s with %d bytes of flash.' % (isp.chipname, isp.flashsize))
|
|
121
|
+
|
|
122
|
+
# Unlock chip
|
|
123
|
+
if args.unlock:
|
|
124
|
+
print('Unlocking chip ...')
|
|
125
|
+
isp.unlock()
|
|
126
|
+
print('SUCCESS: Chip is unlocked.')
|
|
127
|
+
|
|
128
|
+
# Perform chip erase
|
|
129
|
+
if args.erase:
|
|
130
|
+
print('Performing whole chip erase ...')
|
|
131
|
+
isp.erase()
|
|
132
|
+
print('SUCCESS: Chip is erased.')
|
|
133
|
+
|
|
134
|
+
# Flash binary file
|
|
135
|
+
if args.flash is not None:
|
|
136
|
+
print('Flashing %s to %s ...' % (args.flash, isp.chipname))
|
|
137
|
+
with open(args.flash, 'rb') as f: data = f.read()
|
|
138
|
+
isp.flash_data(data)
|
|
139
|
+
print('SUCCESS: %d bytes written and verified.' % len(data))
|
|
140
|
+
|
|
141
|
+
# Make nRST pin a normal GPIO pin
|
|
142
|
+
if args.pingpio:
|
|
143
|
+
print('Configuring nRST pin as GPIO ...')
|
|
144
|
+
isp.setnrstasgpio(1)
|
|
145
|
+
print('SUCCESS: nRST pin is now a GPIO pin.')
|
|
146
|
+
|
|
147
|
+
# Make nRST pin a reset pin
|
|
148
|
+
if args.pinreset:
|
|
149
|
+
print('Configuring nRST pin as reset ...')
|
|
150
|
+
isp.setnrstasgpio(0)
|
|
151
|
+
print('SUCCESS: nRST pin is now a reset pin.')
|
|
152
|
+
|
|
153
|
+
# Lock chip
|
|
154
|
+
if args.lock:
|
|
155
|
+
print('Locking chip ...')
|
|
156
|
+
isp.lock()
|
|
157
|
+
print('SUCCESS: Chip is locked.')
|
|
158
|
+
|
|
159
|
+
# Switch device to ARM mode
|
|
160
|
+
if args.armmode:
|
|
161
|
+
print('Switching WCH-Link to ARM mode ...')
|
|
162
|
+
isp.exit()
|
|
163
|
+
isp.dev.write(CH_EP_OUT, b'\x81\xff\x01\x41')
|
|
164
|
+
print('DONE: Check if blue LED lights up!')
|
|
165
|
+
sys.exit(0)
|
|
166
|
+
|
|
167
|
+
isp.exit()
|
|
168
|
+
|
|
169
|
+
except Exception as ex:
|
|
170
|
+
sys.stderr.write('ERROR: %s!\n' % str(ex))
|
|
171
|
+
isp.exit()
|
|
172
|
+
sys.exit(1)
|
|
173
|
+
|
|
174
|
+
print('DONE.')
|
|
175
|
+
sys.exit(0)
|
|
176
|
+
|
|
177
|
+
# ===================================================================================
|
|
178
|
+
# Programmer Class
|
|
179
|
+
# ===================================================================================
|
|
180
|
+
|
|
181
|
+
class Programmer:
|
|
182
|
+
# Init programmer
|
|
183
|
+
def __init__(self):
|
|
184
|
+
# Find programmer
|
|
185
|
+
self.dev = usb.core.find(idVendor = CH_VENDOR_ID, idProduct = CH_PRODUCT_ID)
|
|
186
|
+
if self.dev is None:
|
|
187
|
+
raise Exception('WCH-LinkE not found. Check if device is in RISC-V mode')
|
|
188
|
+
|
|
189
|
+
# Clear receive buffers
|
|
190
|
+
self.clearreply()
|
|
191
|
+
|
|
192
|
+
# Get programmer info
|
|
193
|
+
reply = self.sendcommand(b'\x81\x0d\x01\x01')
|
|
194
|
+
if not reply[5] == 0x12:
|
|
195
|
+
raise Exception('Programmer is not a WCH-LinkE')
|
|
196
|
+
self.linkname = 'WCH-LinkE'
|
|
197
|
+
self.linkdevice = reply[5]
|
|
198
|
+
self.linkversion = '%d.%d' % (reply[3], reply[4])
|
|
199
|
+
|
|
200
|
+
# Connect programmer to MCU
|
|
201
|
+
def connect(self):
|
|
202
|
+
# Connect to target MCU and get type
|
|
203
|
+
success = 0
|
|
204
|
+
for i in range(3):
|
|
205
|
+
if i > 0:
|
|
206
|
+
print('Failed to connect, trying to unbrick MCU ...')
|
|
207
|
+
self.sendcommand(b'\x81\x0d\x01\x0f\x09')
|
|
208
|
+
reply = self.sendcommand(b'\x81\x0d\x01\x02')
|
|
209
|
+
if len(reply) < 8 or set(reply[:4]) == set((0x81, 0x55, 0x01, 0x01)):
|
|
210
|
+
time.sleep(0.2)
|
|
211
|
+
continue
|
|
212
|
+
|
|
213
|
+
# Get chip identification data
|
|
214
|
+
self.chipmark = reply[3]
|
|
215
|
+
self.chipseries = reply[4]
|
|
216
|
+
self.chiptype = reply[5]
|
|
217
|
+
self.chipid = (reply[4] << 8) + reply[5]
|
|
218
|
+
self.device = None
|
|
219
|
+
|
|
220
|
+
# Find device in dictionary
|
|
221
|
+
for d in DEVICES:
|
|
222
|
+
if d['id'] == self.chipid:
|
|
223
|
+
self.device = d
|
|
224
|
+
if self.device is None:
|
|
225
|
+
if not self.chipid == 0:
|
|
226
|
+
print('Unsupported chip (ID: 0x%04x)?' % self.chipid)
|
|
227
|
+
continue
|
|
228
|
+
|
|
229
|
+
# Success
|
|
230
|
+
self.chipname = self.device['name']
|
|
231
|
+
success = 1
|
|
232
|
+
break
|
|
233
|
+
if success == 0:
|
|
234
|
+
raise Exception('Failed to connect to target MCU')
|
|
235
|
+
|
|
236
|
+
# Read some chip data
|
|
237
|
+
reply = self.sendcommand((0x81, 0x11, 0x01, self.chipmark))
|
|
238
|
+
self.flashsize = int.from_bytes(reply[2:4], byteorder='big') * 1024
|
|
239
|
+
|
|
240
|
+
# Send command to programmer
|
|
241
|
+
def sendcommand(self, stream):
|
|
242
|
+
self.dev.write(CH_EP_OUT, stream)
|
|
243
|
+
return self.dev.read(CH_EP_IN, CH_PACKET_SIZE, CH_TIMEOUT)
|
|
244
|
+
|
|
245
|
+
# Clear USB receive buffers
|
|
246
|
+
def clearreply(self):
|
|
247
|
+
try: self.dev.read(CH_EP_IN, CH_PACKET_SIZE, 1)
|
|
248
|
+
except: None
|
|
249
|
+
try: self.dev.read(CH_EP_IN_RAW, CH_PACKET_SIZE, 1)
|
|
250
|
+
except: None
|
|
251
|
+
|
|
252
|
+
# Write to MCU register
|
|
253
|
+
def writereg(self, addr, data):
|
|
254
|
+
stream = bytes((0x81, 0x08, 0x06, addr)) + data.to_bytes(4, byteorder='big') + b'\x02'
|
|
255
|
+
reply = self.sendcommand(stream)
|
|
256
|
+
if (len(reply) != 9) or (reply[3] != addr):
|
|
257
|
+
raise Exception('Failed to write register')
|
|
258
|
+
|
|
259
|
+
# Read from MCU register
|
|
260
|
+
def readreg(self, addr):
|
|
261
|
+
stream = (0x81, 0x08, 0x06, addr, 0, 0, 0, 0, 1)
|
|
262
|
+
reply = self.sendcommand(stream)
|
|
263
|
+
if (len(reply) != 9) or (reply[3] != addr):
|
|
264
|
+
raise Exception('Failed to read register')
|
|
265
|
+
return int.from_bytes(reply[4:8], byteorder='big')
|
|
266
|
+
|
|
267
|
+
# Unbrick MCU
|
|
268
|
+
def unbrick(self):
|
|
269
|
+
self.sendcommand(b'\x81\x0d\x01\x0f\x09')
|
|
270
|
+
|
|
271
|
+
# Lock MCU (set read protection)
|
|
272
|
+
def lock(self):
|
|
273
|
+
if self.chipseries == 0x00:
|
|
274
|
+
self.sendcommand(b'\x81\x06\x08\x03\xf7\xff\xff\xff\xff\xff\xff')
|
|
275
|
+
elif self.chipseries == 0x25 or self.chipseries == 0x03:
|
|
276
|
+
self.sendcommand(b'\x81\x06\x08\x03\xff\xff\xff\xff\xff\xff\xff')
|
|
277
|
+
elif self.chipseries == 0x20 or self.chipseries == 0x30:
|
|
278
|
+
self.sendcommand(b'\x81\x06\x08\x03\x3f\xff\xff\xff\xff\xff\xff')
|
|
279
|
+
|
|
280
|
+
# Unlock MCU (remove read protection -> erase chip!!!)
|
|
281
|
+
def unlock(self):
|
|
282
|
+
reply = self.sendcommand(b'\x81\x06\x01\x01')
|
|
283
|
+
if reply[3] == 0x01:
|
|
284
|
+
if self.chipseries == 0x00:
|
|
285
|
+
self.sendcommand(b'\x81\x06\x08\x02\xf7\xff\xff\xff\xff\xff\xff')
|
|
286
|
+
elif self.chipseries == 0x25 or self.chipseries == 0x03:
|
|
287
|
+
self.sendcommand(b'\x81\x06\x08\x02\xff\xff\xff\xff\xff\xff\xff')
|
|
288
|
+
elif self.chipseries == 0x20 or self.chipseries == 0x30:
|
|
289
|
+
self.sendcommand(b'\x81\x06\x08\x02\x3f\xff\xff\xff\xff\xff\xff')
|
|
290
|
+
|
|
291
|
+
# Perform a whole chip erase
|
|
292
|
+
def erase(self):
|
|
293
|
+
self.sendcommand(b'\x81\x02\x01\x01')
|
|
294
|
+
self.sendcommand(b'\x81\x0d\x01\x02')
|
|
295
|
+
|
|
296
|
+
# Make reset pin a normal GPIO pin (0=RESET, 1=GPIO)
|
|
297
|
+
def setnrstasgpio(self, state):
|
|
298
|
+
if self.chipseries == 0x00:
|
|
299
|
+
if state:
|
|
300
|
+
self.sendcommand(b'\x81\x06\x08\x02\xff\xff\xff\xff\xff\xff\xff')
|
|
301
|
+
else:
|
|
302
|
+
self.sendcommand(b'\x81\x06\x08\x02\xf7\xff\xff\xff\xff\xff\xff')
|
|
303
|
+
else:
|
|
304
|
+
raise Exception('RST pin option not available for this MCU')
|
|
305
|
+
|
|
306
|
+
# Enable/disable programmer's 3V3 output
|
|
307
|
+
def poweron3v3(self):
|
|
308
|
+
self.sendcommand(b'\x81\x0d\x01\x09')
|
|
309
|
+
def poweroff3v3(self):
|
|
310
|
+
self.sendcommand(b'\x81\x0d\x01\x0a')
|
|
311
|
+
|
|
312
|
+
# Enable/disable programmer's 5V output
|
|
313
|
+
def poweron5v(self):
|
|
314
|
+
self.sendcommand(b'\x81\x0d\x01\x0b')
|
|
315
|
+
def poweroff5v(self):
|
|
316
|
+
self.sendcommand(b'\x81\x0d\x01\x0c')
|
|
317
|
+
|
|
318
|
+
# Disconnect from MCU
|
|
319
|
+
def exit(self):
|
|
320
|
+
self.sendcommand(b'\x81\x0b\x01\x01')
|
|
321
|
+
self.sendcommand(b'\x81\x0d\x01\xff')
|
|
322
|
+
|
|
323
|
+
#--------------------------------------------------------------
|
|
324
|
+
|
|
325
|
+
# Get padded data length
|
|
326
|
+
def padlen(self, data, pagesize):
|
|
327
|
+
if (len(data) % pagesize) == 0:
|
|
328
|
+
return len(data)
|
|
329
|
+
else:
|
|
330
|
+
return (len(data) + (pagesize - (len(data) % pagesize)))
|
|
331
|
+
|
|
332
|
+
# Pad data and divide into pages
|
|
333
|
+
def page_data(self, data, pagesize):
|
|
334
|
+
if (len(data) % pagesize) > 0:
|
|
335
|
+
data += b'\xff' * (pagesize - (len(data) % pagesize))
|
|
336
|
+
result = list()
|
|
337
|
+
while len(data):
|
|
338
|
+
result.append(data[:pagesize])
|
|
339
|
+
data = data[pagesize:]
|
|
340
|
+
return result
|
|
341
|
+
|
|
342
|
+
# Write data blob to flash
|
|
343
|
+
def writebinaryblob(self, addr, blocksize, bootloader, data):
|
|
344
|
+
if addr & (blocksize - 1):
|
|
345
|
+
raise Exception('Blob is not %d byte aligned' % blocksize)
|
|
346
|
+
self.unlock()
|
|
347
|
+
stream = b'\x81\x01\x08' \
|
|
348
|
+
+ addr.to_bytes(4, byteorder='big') \
|
|
349
|
+
+ self.padlen(data, blocksize).to_bytes(4, byteorder='big')
|
|
350
|
+
self.sendcommand(stream)
|
|
351
|
+
self.sendcommand(b'\x81\x02\x01\x05')
|
|
352
|
+
pages = self.page_data(bootloader, 128)
|
|
353
|
+
for page in pages:
|
|
354
|
+
self.dev.write(CH_EP_OUT_RAW, page)
|
|
355
|
+
self.sendcommand(b'\x81\x02\x01\x07')
|
|
356
|
+
self.sendcommand(b'\x81\x02\x01\x04')
|
|
357
|
+
pages = self.page_data(data, blocksize)
|
|
358
|
+
for page in pages:
|
|
359
|
+
self.dev.write(CH_EP_OUT_RAW, page)
|
|
360
|
+
reply = self.dev.read(CH_EP_IN_RAW, CH_PACKET_SIZE, CH_TIMEOUT)
|
|
361
|
+
if set(reply) != set((0x41, 0x01, 0x01, 0x04)):
|
|
362
|
+
raise Exception('Failed writing/verifying data blob')
|
|
363
|
+
|
|
364
|
+
# Write data to code flash
|
|
365
|
+
def flash_data(self, data):
|
|
366
|
+
if len(data) > self.flashsize:
|
|
367
|
+
raise Exception('Not enough memory')
|
|
368
|
+
self.writebinaryblob(CH_CODE_BASE, self.device['block-size'], self.device['loader'], data)
|
|
369
|
+
|
|
370
|
+
# ===================================================================================
|
|
371
|
+
# Device Constants
|
|
372
|
+
# ===================================================================================
|
|
373
|
+
|
|
374
|
+
# USB device settings
|
|
375
|
+
CH_VENDOR_ID = 0x1A86 # VID
|
|
376
|
+
CH_PRODUCT_ID = 0x8010 # PID in RISC-V mode
|
|
377
|
+
CH_ARM_ID = 0x8012 # PID in ARM mode
|
|
378
|
+
CH_PACKET_SIZE = 1024 # packet size
|
|
379
|
+
CH_INTERFACE = 0 # interface number
|
|
380
|
+
CH_EP_OUT = 0x01 # endpoint for command transfer out
|
|
381
|
+
CH_EP_IN = 0x81 # endpoint for reply transfer in
|
|
382
|
+
CH_EP_OUT_RAW = 0x02 # endpoint for raw data transfer out
|
|
383
|
+
CH_EP_IN_RAW = 0x82 # endpoint for raw data transfer in
|
|
384
|
+
CH_TIMEOUT = 5000 # timeout for USB operations
|
|
385
|
+
|
|
386
|
+
# Memory constants
|
|
387
|
+
CH_RAM_BASE = 0x20000000
|
|
388
|
+
CH_CODE_BASE = 0x08000000
|
|
389
|
+
CH_BOOT_BASE = 0x1FFFF000
|
|
390
|
+
|
|
391
|
+
# ===================================================================================
|
|
392
|
+
# Flash Bootloader
|
|
393
|
+
# ===================================================================================
|
|
394
|
+
|
|
395
|
+
LOADER_V003 = \
|
|
396
|
+
b"\x21\x11\x22\xca\x26\xc8\x93\x77\x15\x00\x99\xcf\xb7\x06\x67\x45" \
|
|
397
|
+
+b"\xb7\x27\x02\x40\x93\x86\x36\x12\x37\x97\xef\xcd\xd4\xc3\x13\x07" \
|
|
398
|
+
+b"\xb7\x9a\xd8\xc3\xd4\xd3\xd8\xd3\x93\x77\x25\x00\x9d\xc7\xb7\x27" \
|
|
399
|
+
+b"\x02\x40\x98\x4b\xad\x66\x37\x33\x00\x40\x13\x67\x47\x00\x98\xcb" \
|
|
400
|
+
+b"\x98\x4b\x93\x86\xa6\xaa\x13\x67\x07\x04\x98\xcb\xd8\x47\x05\x8b" \
|
|
401
|
+
+b"\x63\x16\x07\x10\x98\x4b\x6d\x9b\x98\xcb\x93\x77\x45\x00\xa9\xcb" \
|
|
402
|
+
+b"\x93\x07\xf6\x03\x99\x83\x2e\xc0\x2d\x63\x81\x76\x3e\xc4\xb7\x32" \
|
|
403
|
+
+b"\x00\x40\xb7\x27\x02\x40\x13\x03\xa3\xaa\xfd\x16\x98\x4b\xb7\x03" \
|
|
404
|
+
+b"\x02\x00\x33\x67\x77\x00\x98\xcb\x02\x47\xd8\xcb\x98\x4b\x13\x67" \
|
|
405
|
+
+b"\x07\x04\x98\xcb\xd8\x47\x05\x8b\x69\xe7\x98\x4b\x75\x8f\x98\xcb" \
|
|
406
|
+
+b"\x02\x47\x13\x07\x07\x04\x3a\xc0\x22\x47\x7d\x17\x3a\xc4\x79\xf7" \
|
|
407
|
+
+b"\x93\x77\x85\x00\xf1\xcf\x93\x07\xf6\x03\x2e\xc0\x99\x83\x37\x27" \
|
|
408
|
+
+b"\x02\x40\x3e\xc4\x1c\x4b\xc1\x66\x2d\x63\xd5\x8f\x1c\xcb\x37\x07" \
|
|
409
|
+
+b"\x00\x20\x13\x07\x07\x20\xb7\x27\x02\x40\xb7\x03\x08\x00\xb7\x32" \
|
|
410
|
+
+b"\x00\x40\x13\x03\xa3\xaa\x94\x4b\xb3\xe6\x76\x00\x94\xcb\xd4\x47" \
|
|
411
|
+
+b"\x85\x8a\xf5\xfe\x82\x46\xba\x84\x37\x04\x04\x00\x36\xc2\xc1\x46" \
|
|
412
|
+
+b"\x36\xc6\x92\x46\x84\x40\x11\x07\x84\xc2\x94\x4b\xc1\x8e\x94\xcb" \
|
|
413
|
+
+b"\xd4\x47\x85\x8a\xb1\xea\x92\x46\xba\x84\x91\x06\x36\xc2\xb2\x46" \
|
|
414
|
+
+b"\xfd\x16\x36\xc6\xf9\xfe\x82\x46\xd4\xcb\x94\x4b\x93\xe6\x06\x04" \
|
|
415
|
+
+b"\x94\xcb\xd4\x47\x85\x8a\x85\xee\xd4\x47\xc1\x8a\x85\xce\xd8\x47" \
|
|
416
|
+
+b"\xb7\x06\xf3\xff\xfd\x16\x13\x67\x07\x01\xd8\xc7\x98\x4b\x21\x45" \
|
|
417
|
+
+b"\x75\x8f\x98\xcb\x52\x44\xc2\x44\x61\x01\x02\x90\x23\x20\xd3\x00" \
|
|
418
|
+
+b"\xf5\xb5\x23\xa0\x62\x00\x3d\xb7\x23\xa0\x62\x00\x55\xb7\x23\xa0" \
|
|
419
|
+
+b"\x62\x00\xc1\xb7\x82\x46\x93\x86\x06\x04\x36\xc0\xa2\x46\xfd\x16" \
|
|
420
|
+
+b"\x36\xc4\xb5\xf2\x98\x4b\xb7\x06\xf3\xff\xfd\x16\x75\x8f\x98\xcb" \
|
|
421
|
+
+b"\x41\x89\x05\xcd\x2e\xc0\x0d\x06\x02\xc4\x09\x82\xb7\x07\x00\x20" \
|
|
422
|
+
+b"\x32\xc6\x93\x87\x07\x20\x98\x43\x13\x86\x47\x00\xa2\x47\x82\x46" \
|
|
423
|
+
+b"\x8a\x07\xb6\x97\x9c\x43\x63\x1c\xf7\x00\xa2\x47\x85\x07\x3e\xc4" \
|
|
424
|
+
+b"\xa2\x46\x32\x47\xb2\x87\xe3\xe0\xe6\xfe\x01\x45\x61\xb7\x41\x45" \
|
|
425
|
+
+b"\x51\xb7"
|
|
426
|
+
|
|
427
|
+
LOADER_V103 = \
|
|
428
|
+
b"\x93\x77\x15\x00\x41\x11\x99\xcf\xb7\x06\x67\x45\xb7\x27\x02\x40" \
|
|
429
|
+
+b"\x93\x86\x36\x12\x37\x97\xef\xcd\xd4\xc3\x13\x07\xb7\x9a\xd8\xc3" \
|
|
430
|
+
+b"\xd4\xd3\xd8\xd3\x93\x77\x25\x00\x9d\xc7\xb7\x27\x02\x40\x98\x4b" \
|
|
431
|
+
+b"\xad\x66\x37\x38\x00\x40\x13\x67\x47\x00\x98\xcb\x98\x4b\x93\x86" \
|
|
432
|
+
+b"\xa6\xaa\x13\x67\x07\x04\x98\xcb\xd8\x47\x05\x8b\x63\x1f\x07\x10" \
|
|
433
|
+
+b"\x98\x4b\x6d\x9b\x98\xcb\x93\x77\x45\x00\xa9\xcb\x93\x07\xf6\x07" \
|
|
434
|
+
+b"\x9d\x83\x2e\xc0\x2d\x68\x81\x76\x3e\xc4\xb7\x08\x02\x00\xb7\x27" \
|
|
435
|
+
+b"\x02\x40\x37\x33\x00\x40\x13\x08\xa8\xaa\xfd\x16\x98\x4b\x33\x67" \
|
|
436
|
+
+b"\x17\x01\x98\xcb\x02\x47\xd8\xcb\x98\x4b\x13\x67\x07\x04\x98\xcb" \
|
|
437
|
+
+b"\xd8\x47\x05\x8b\x71\xef\x98\x4b\x75\x8f\x98\xcb\x02\x47\x13\x07" \
|
|
438
|
+
+b"\x07\x08\x3a\xc0\x22\x47\x7d\x17\x3a\xc4\x69\xfb\x93\x77\x85\x00" \
|
|
439
|
+
+b"\xed\xc3\x93\x07\xf6\x07\x2e\xc0\x9d\x83\x37\x27\x02\x40\x3e\xc4" \
|
|
440
|
+
+b"\x1c\x4b\xc1\x66\x37\x08\x08\x00\xd5\x8f\x1c\xcb\xa1\x48\x37\x17" \
|
|
441
|
+
+b"\x00\x20\xb7\x27\x02\x40\x37\x03\x04\x00\x94\x4b\xb3\xe6\x06\x01" \
|
|
442
|
+
+b"\x94\xcb\xd4\x47\x85\x8a\xf5\xfe\x82\x46\x3a\x8e\x36\xc2\x46\xc6" \
|
|
443
|
+
+b"\x92\x46\x83\x2e\x07\x00\x41\x07\x23\xa0\xd6\x01\x92\x46\x83\x2e" \
|
|
444
|
+
+b"\x47\xff\x23\xa2\xd6\x01\x92\x46\x83\x2e\x87\xff\x23\xa4\xd6\x01" \
|
|
445
|
+
+b"\x92\x46\x03\x2e\xce\x00\x23\xa6\xc6\x01\x94\x4b\xb3\xe6\x66\x00" \
|
|
446
|
+
+b"\x94\xcb\xd4\x47\x85\x8a\xf5\xfe\x92\x46\x3a\x8e\xc1\x06\x36\xc2" \
|
|
447
|
+
+b"\xb2\x46\xfd\x16\x36\xc6\xcd\xfe\x82\x46\xd4\xcb\x94\x4b\x93\xe6" \
|
|
448
|
+
+b"\x06\x04\x94\xcb\xd4\x47\x85\x8a\xf5\xfe\xd4\x47\xd1\x8a\x85\xc6" \
|
|
449
|
+
+b"\xd8\x47\xb7\x06\xf3\xff\xfd\x16\x13\x67\x47\x01\xd8\xc7\x98\x4b" \
|
|
450
|
+
+b"\x21\x45\x75\x8f\x98\xcb\x41\x01\x02\x90\x23\x20\xd8\x00\xe9\xbd" \
|
|
451
|
+
+b"\x23\x20\x03\x01\x31\xbf\x82\x46\x93\x86\x06\x08\x36\xc0\xa2\x46" \
|
|
452
|
+
+b"\xfd\x16\x36\xc4\xb9\xfa\x98\x4b\xb7\x06\xf3\xff\xfd\x16\x75\x8f" \
|
|
453
|
+
+b"\x98\xcb\x41\x89\x15\xc9\x2e\xc0\x0d\x06\x02\xc4\x09\x82\x32\xc6" \
|
|
454
|
+
+b"\xb7\x17\x00\x20\x98\x43\x13\x86\x47\x00\xa2\x47\x82\x46\x8a\x07" \
|
|
455
|
+
+b"\xb6\x97\x9c\x43\x63\x1c\xf7\x00\xa2\x47\x85\x07\x3e\xc4\xa2\x46" \
|
|
456
|
+
+b"\x32\x47\xb2\x87\xe3\xe0\xe6\xfe\x01\x45\x71\xbf\x41\x45\x61\xbf"
|
|
457
|
+
|
|
458
|
+
LOADER_V203 = \
|
|
459
|
+
b"\x93\x77\x15\x00\x41\x11\x99\xcf\xb7\x06\x67\x45\xb7\x27\x02\x40" \
|
|
460
|
+
+b"\x93\x86\x36\x12\x37\x97\xef\xcd\xd4\xc3\x13\x07\xb7\x9a\xd8\xc3" \
|
|
461
|
+
+b"\xd4\xd3\xd8\xd3\x93\x77\x25\x00\x95\xc7\xb7\x27\x02\x40\x98\x4b" \
|
|
462
|
+
+b"\xad\x66\x37\x38\x00\x40\x13\x67\x47\x00\x98\xcb\x98\x4b\x93\x86" \
|
|
463
|
+
+b"\xa6\xaa\x13\x67\x07\x04\x98\xcb\xd8\x47\x05\x8b\x61\xeb\x98\x4b" \
|
|
464
|
+
+b"\x6d\x9b\x98\xcb\x93\x77\x45\x00\xa9\xcb\x93\x07\xf6\x0f\xa1\x83" \
|
|
465
|
+
+b"\x2e\xc0\x2d\x68\x81\x76\x3e\xc4\xb7\x08\x02\x00\xb7\x27\x02\x40" \
|
|
466
|
+
+b"\x37\x33\x00\x40\x13\x08\xa8\xaa\xfd\x16\x98\x4b\x33\x67\x17\x01" \
|
|
467
|
+
+b"\x98\xcb\x02\x47\xd8\xcb\x98\x4b\x13\x67\x07\x04\x98\xcb\xd8\x47" \
|
|
468
|
+
+b"\x05\x8b\x41\xeb\x98\x4b\x75\x8f\x98\xcb\x02\x47\x13\x07\x07\x10" \
|
|
469
|
+
+b"\x3a\xc0\x22\x47\x7d\x17\x3a\xc4\x69\xfb\x93\x77\x85\x00\xd5\xcb" \
|
|
470
|
+
+b"\x93\x07\xf6\x0f\x2e\xc0\xa1\x83\x3e\xc4\x37\x27\x02\x40\x1c\x4b" \
|
|
471
|
+
+b"\xc1\x66\x41\x68\xd5\x8f\x1c\xcb\xb7\x16\x00\x20\xb7\x27\x02\x40" \
|
|
472
|
+
+b"\x93\x08\x00\x04\x37\x03\x20\x00\x98\x4b\x33\x67\x07\x01\x98\xcb" \
|
|
473
|
+
+b"\xd8\x47\x05\x8b\x75\xff\x02\x47\x3a\xc2\x46\xc6\x32\x47\x0d\xef" \
|
|
474
|
+
+b"\x98\x4b\x33\x67\x67\x00\x98\xcb\xd8\x47\x05\x8b\x75\xff\xd8\x47" \
|
|
475
|
+
+b"\x41\x8b\x39\xc3\xd8\x47\xc1\x76\xfd\x16\x13\x67\x07\x01\xd8\xc7" \
|
|
476
|
+
+b"\x98\x4b\x21\x45\x75\x8f\x98\xcb\x41\x01\x02\x90\x23\x20\xd8\x00" \
|
|
477
|
+
+b"\x25\xb7\x23\x20\x03\x01\xa5\xb7\x12\x47\x13\x8e\x46\x00\x94\x42" \
|
|
478
|
+
+b"\x14\xc3\x12\x47\x11\x07\x3a\xc2\x32\x47\x7d\x17\x3a\xc6\xd8\x47" \
|
|
479
|
+
+b"\x09\x8b\x75\xff\xf2\x86\x5d\xb7\x02\x47\x13\x07\x07\x10\x3a\xc0" \
|
|
480
|
+
+b"\x22\x47\x7d\x17\x3a\xc4\x49\xf3\x98\x4b\xc1\x76\xfd\x16\x75\x8f" \
|
|
481
|
+
+b"\x98\xcb\x41\x89\x15\xc9\x2e\xc0\x0d\x06\x02\xc4\x09\x82\x32\xc6" \
|
|
482
|
+
+b"\xb7\x17\x00\x20\x98\x43\x13\x86\x47\x00\xa2\x47\x82\x46\x8a\x07" \
|
|
483
|
+
+b"\xb6\x97\x9c\x43\x63\x1c\xf7\x00\xa2\x47\x85\x07\x3e\xc4\xa2\x46" \
|
|
484
|
+
+b"\x32\x47\xb2\x87\xe3\xe0\xe6\xfe\x01\x45\xbd\xbf\x41\x45\xad\xbf"
|
|
485
|
+
|
|
486
|
+
LOADER_X035 = \
|
|
487
|
+
b"\x01\x11\x02\xce\x93\x77\x15\x00\x99\xcf\xb7\x06\x67\x45\xb7\x27" \
|
|
488
|
+
+b"\x02\x40\x93\x86\x36\x12\x37\x97\xef\xcd\xd4\xc3\x13\x07\xb7\x9a" \
|
|
489
|
+
+b"\xd8\xc3\xd4\xd3\xd8\xd3\x93\x77\x25\x00\x9d\xc7\xb7\x27\x02\x40" \
|
|
490
|
+
+b"\x98\x4b\xad\x66\x37\x38\x00\x40\x13\x67\x47\x00\x98\xcb\x98\x4b" \
|
|
491
|
+
+b"\x93\x86\xa6\xaa\x13\x67\x07\x04\x98\xcb\xd8\x47\x05\x8b\x63\x16" \
|
|
492
|
+
+b"\x07\x10\x98\x4b\x6d\x9b\x98\xcb\x93\x77\x45\x00\xa9\xcb\x93\x07" \
|
|
493
|
+
+b"\xf6\x0f\xa1\x83\x2e\xc6\x2d\x68\x81\x76\x3e\xca\xb7\x08\x02\x00" \
|
|
494
|
+
+b"\xb7\x27\x02\x40\x37\x33\x00\x40\x13\x08\xa8\xaa\xfd\x16\x98\x4b" \
|
|
495
|
+
+b"\x33\x67\x17\x01\x98\xcb\x32\x47\xd8\xcb\x98\x4b\x13\x67\x07\x04" \
|
|
496
|
+
+b"\x98\xcb\xd8\x47\x05\x8b\x69\xe7\x98\x4b\x75\x8f\x98\xcb\x32\x47" \
|
|
497
|
+
+b"\x13\x07\x07\x10\x3a\xc6\x52\x47\x7d\x17\x3a\xca\x69\xfb\x93\x77" \
|
|
498
|
+
+b"\x85\x00\xf1\xcf\x93\x07\xf6\x0f\x2e\xc6\xa1\x83\x3e\xca\x37\x27" \
|
|
499
|
+
+b"\x02\x40\x1c\x4b\xc1\x66\x2d\x68\xd5\x8f\x1c\xcb\xb7\x16\x00\x20" \
|
|
500
|
+
+b"\xb7\x27\x02\x40\x37\x03\x08\x00\x13\x0e\x00\x04\xb7\x0e\x04\x00" \
|
|
501
|
+
+b"\xb7\x38\x00\x40\x13\x08\xa8\xaa\x98\x4b\x33\x67\x67\x00\x98\xcb" \
|
|
502
|
+
+b"\xd8\x47\x05\x8b\x75\xff\x32\x47\x36\x8f\x3a\xc8\x72\xcc\x42\x47" \
|
|
503
|
+
+b"\x03\x2f\x0f\x00\x91\x06\x23\x20\xe7\x01\x98\x4b\x33\x67\xd7\x01" \
|
|
504
|
+
+b"\x98\xcb\xd8\x47\x05\x8b\x21\xeb\x42\x47\x36\x8f\x11\x07\x3a\xc8" \
|
|
505
|
+
+b"\x62\x47\x7d\x17\x3a\xcc\x61\xff\x32\x47\xd8\xcb\x98\x4b\x13\x67" \
|
|
506
|
+
+b"\x07\x04\x98\xcb\xd8\x47\x05\x8b\x15\xeb\xd8\x47\x41\x8b\x15\xcb" \
|
|
507
|
+
+b"\xd8\x47\xb7\x06\xf3\xff\xfd\x16\x13\x67\x07\x01\xd8\xc7\x98\x4b" \
|
|
508
|
+
+b"\x21\x45\x75\x8f\x98\xcb\x05\x61\x02\x90\x23\x20\xd8\x00\xf5\xb5" \
|
|
509
|
+
+b"\x23\x20\x03\x01\x3d\xb7\x23\xa0\x08\x01\x65\xb7\x23\xa0\x08\x01" \
|
|
510
|
+
+b"\xd1\xb7\x32\x47\x13\x07\x07\x10\x3a\xc6\x52\x47\x7d\x17\x3a\xca" \
|
|
511
|
+
+b"\x25\xf7\x98\x4b\xb7\x06\xf3\xff\xfd\x16\x75\x8f\x98\xcb\x41\x89" \
|
|
512
|
+
+b"\x19\xe1\x01\x45\xc9\xb7\x2e\xc6\x0d\x06\x02\xca\x09\x82\x32\xcc" \
|
|
513
|
+
+b"\xb7\x17\x00\x20\x98\x43\x13\x86\x47\x00\xd2\x47\xb2\x46\x8a\x07" \
|
|
514
|
+
+b"\xb6\x97\x9c\x43\x63\x18\xf7\x02\xd2\x47\x32\x47\x8a\x07\xba\x97" \
|
|
515
|
+
+b"\x98\x43\xf2\x47\xba\x97\x3e\xce\xd2\x47\x85\x07\x3e\xca\xd2\x46" \
|
|
516
|
+
+b"\x62\x47\xb2\x87\xe3\xe8\xe6\xfc\xb7\x27\x00\x20\x98\x4b\xf2\x47" \
|
|
517
|
+
+b"\xe3\x09\xf7\xfa\x41\x45\x85\xbf"
|
|
518
|
+
|
|
519
|
+
# ===================================================================================
|
|
520
|
+
# Device definitions
|
|
521
|
+
# ===================================================================================
|
|
522
|
+
|
|
523
|
+
DEVICES = [
|
|
524
|
+
{'name': 'CH32V003J4M6', 'id': 0x0033, 'block-size': 64, 'loader': LOADER_V003},
|
|
525
|
+
{'name': 'CH32V003A4M6', 'id': 0x0032, 'block-size': 64, 'loader': LOADER_V003},
|
|
526
|
+
{'name': 'CH32V003F4U6', 'id': 0x0031, 'block-size': 64, 'loader': LOADER_V003},
|
|
527
|
+
{'name': 'CH32V003F4P6', 'id': 0x0030, 'block-size': 64, 'loader': LOADER_V003},
|
|
528
|
+
|
|
529
|
+
{'name': 'CH32V103', 'id': 0x2500, 'block-size': 128, 'loader': LOADER_V103},
|
|
530
|
+
|
|
531
|
+
{'name': 'CH32V203C8U6', 'id': 0x2030, 'block-size': 256, 'loader': LOADER_V203},
|
|
532
|
+
{'name': 'CH32V203C8T6', 'id': 0x2031, 'block-size': 256, 'loader': LOADER_V203},
|
|
533
|
+
{'name': 'CH32V203K8T6', 'id': 0x2032, 'block-size': 256, 'loader': LOADER_V203},
|
|
534
|
+
{'name': 'CH32V203C6T6', 'id': 0x2033, 'block-size': 256, 'loader': LOADER_V203},
|
|
535
|
+
{'name': 'CH32V203RBT6', 'id': 0x2034, 'block-size': 256, 'loader': LOADER_V203},
|
|
536
|
+
{'name': 'CH32V203K6T6', 'id': 0x2035, 'block-size': 256, 'loader': LOADER_V203},
|
|
537
|
+
{'name': 'CH32V203G6U6', 'id': 0x2036, 'block-size': 256, 'loader': LOADER_V203},
|
|
538
|
+
{'name': 'CH32V203F6P6', 'id': 0x2037, 'block-size': 256, 'loader': LOADER_V203},
|
|
539
|
+
{'name': 'CH32V203F8P6', 'id': 0x203a, 'block-size': 256, 'loader': LOADER_V203},
|
|
540
|
+
{'name': 'CH32V203G8R6', 'id': 0x203b, 'block-size': 256, 'loader': LOADER_V203},
|
|
541
|
+
{'name': 'CH32V208WBU6', 'id': 0x2080, 'block-size': 256, 'loader': LOADER_V203},
|
|
542
|
+
{'name': 'CH32V208RBT6', 'id': 0x2081, 'block-size': 256, 'loader': LOADER_V203},
|
|
543
|
+
{'name': 'CH32V208CBU6', 'id': 0x2082, 'block-size': 256, 'loader': LOADER_V203},
|
|
544
|
+
{'name': 'CH32V208GBU6', 'id': 0x2083, 'block-size': 256, 'loader': LOADER_V203},
|
|
545
|
+
|
|
546
|
+
{'name': 'CH32V303VCT6', 'id': 0x3030, 'block-size': 256, 'loader': LOADER_V203},
|
|
547
|
+
{'name': 'CH32V303RCT6', 'id': 0x3031, 'block-size': 256, 'loader': LOADER_V203},
|
|
548
|
+
{'name': 'CH32V303RBT6', 'id': 0x3033, 'block-size': 256, 'loader': LOADER_V203},
|
|
549
|
+
{'name': 'CH32V303CBT6', 'id': 0x3034, 'block-size': 256, 'loader': LOADER_V203},
|
|
550
|
+
{'name': 'CH32V305RBT6', 'id': 0x3050, 'block-size': 256, 'loader': LOADER_V203},
|
|
551
|
+
{'name': 'CH32V305FBP6', 'id': 0x3052, 'block-size': 256, 'loader': LOADER_V203},
|
|
552
|
+
{'name': 'CH32V307VCT6', 'id': 0x3070, 'block-size': 256, 'loader': LOADER_V203},
|
|
553
|
+
{'name': 'CH32V307RCT6', 'id': 0x3071, 'block-size': 256, 'loader': LOADER_V203},
|
|
554
|
+
{'name': 'CH32V307WCU6', 'id': 0x3073, 'block-size': 256, 'loader': LOADER_V203},
|
|
555
|
+
|
|
556
|
+
{'name': 'CH32X033F8P6', 'id': 0x035a, 'block-size': 256, 'loader': LOADER_X035},
|
|
557
|
+
{'name': 'CH32X035R8T6', 'id': 0x0350, 'block-size': 256, 'loader': LOADER_X035},
|
|
558
|
+
{'name': 'CH32X035C8T6', 'id': 0x0351, 'block-size': 256, 'loader': LOADER_X035},
|
|
559
|
+
{'name': 'CH32X035F8U6', 'id': 0x035e, 'block-size': 256, 'loader': LOADER_X035},
|
|
560
|
+
{'name': 'CH32X035G8U6', 'id': 0x0356, 'block-size': 256, 'loader': LOADER_X035},
|
|
561
|
+
{'name': 'CH32X035G8R6', 'id': 0x035b, 'block-size': 256, 'loader': LOADER_X035},
|
|
562
|
+
{'name': 'CH32X035F7P6', 'id': 0x0357, 'block-size': 256, 'loader': LOADER_X035}
|
|
563
|
+
]
|
|
564
|
+
|
|
565
|
+
# ===================================================================================
|
|
566
|
+
|
|
567
|
+
if __name__ == "__main__":
|
|
568
|
+
_main()
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: rvprog
|
|
3
|
+
Version: 1.5.0
|
|
4
|
+
Summary: Programming Tool for WCH-LinkE and CH32Vxxx and CH32Xxxx
|
|
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) 2023 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,RISC-V,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
|
+
# rvprog - Programming Tool for WCH-LinkE and CH32Vxxx and CH32Xxxx
|
|
46
|
+
## Description
|
|
47
|
+
With this tool, the WCH RISC-V microcontrollers CH32Vxxx and CH32Xxxx can be programmed with the [WCH-LinkE](http://www.wch-ic.com/products/WCH-Link.html) (pay attention to the "E" in the name) via its serial debug interface.
|
|
48
|
+
|
|
49
|
+
## Preparations
|
|
50
|
+
To use the WCH-Link on Linux, you need to grant access permissions beforehand by executing the following commands:
|
|
51
|
+
```
|
|
52
|
+
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="8010", MODE="666"' | sudo tee /etc/udev/rules.d/99-WCH-LinkE.rules
|
|
53
|
+
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="8012", MODE="666"' | sudo tee -a /etc/udev/rules.d/99-WCH-LinkE.rules
|
|
54
|
+
sudo udevadm control --reload-rules
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
On Windows, if you need to you can install the WinUSB driver over the WCH interface 1 using the [Zadig Tool](https://zadig.akeo.ie/).
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
- Install [Python3](https://www.pythontutorial.net/getting-started/install-python/).
|
|
61
|
+
- Install [pip](https://pip.pypa.io/en/stable/installation/).
|
|
62
|
+
- Install rvprog:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
pip install rvprog
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Usage
|
|
69
|
+
To upload firmware, you should make the following connections to the WCH-LinkE (SWCLK is not present on the CH32V003 and therefore does not need to be connected):
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
WCH-LinkE CH32V/X
|
|
73
|
+
+-------+ +-------+
|
|
74
|
+
| SWCLK| ---> |SWCLK |
|
|
75
|
+
| SWDIO| <--> |SWDIO |
|
|
76
|
+
| GND| ---> |GND |
|
|
77
|
+
| 3V3| ---> |VDD |
|
|
78
|
+
+-------+ +-------+
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
If the blue LED on the WCH-LinkE remains illuminated once it is connected to the USB port, it means that the device is currently in ARM mode and must be switched to RISC-V mode initially. There are a few ways to accomplish this:
|
|
82
|
+
- You can utilize the rvprog tool with the -v option (see below).
|
|
83
|
+
- Alternatively, you can select "WCH-LinkRV" in the software provided by WCH, such as MounRiver Studio or WCH-LinkUtility.
|
|
84
|
+
- Another option is to hold down the ModeS button on the device while plugging it into the USB port.
|
|
85
|
+
|
|
86
|
+
More information can be found in the [WCH-Link User Manual](http://www.wch-ic.com/downloads/WCH-LinkUserManual_PDF.html).
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
Usage: rvprog [-h] [-a] [-v] [-b] [-u] [-l] [-e] [-G] [-R] [-f FLASH]
|
|
90
|
+
|
|
91
|
+
Optional arguments:
|
|
92
|
+
-h, --help show help message and exit
|
|
93
|
+
-a, --armmode switch WCH-Link to ARM mode
|
|
94
|
+
-v, --rvmode switch WCH-Link to RISC-V mode
|
|
95
|
+
-b, --unbrick unbrick chip
|
|
96
|
+
-u, --unlock unlock chip (remove read protection)
|
|
97
|
+
-l, --lock lock chip (set read protection)
|
|
98
|
+
-e, --erase perform a whole chip erase
|
|
99
|
+
-G, --pingpio make nRST pin a GPIO pin (CH32V003 only)
|
|
100
|
+
-R, --pinreset make nRST pin a reset pin (CH32V003 only)
|
|
101
|
+
-f FLASH, --flash FLASH write BIN file to flash
|
|
102
|
+
|
|
103
|
+
Example:
|
|
104
|
+
rvprog -f firmware.bin
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Links
|
|
108
|
+
- [MCU Flash Tools](https://github.com/wagiminator/MCU-Flash-Tools)
|
|
109
|
+
- [MCU Templates](https://github.com/wagiminator/MCU-Templates)
|
|
110
|
+
- [MCU Development Boards](https://github.com/wagiminator/Development-Boards)
|
|
111
|
+
- [AVR Development Boards](https://github.com/wagiminator/AVR-Development-Boards)
|
|
112
|
+
- [AVR Programmers](https://github.com/wagiminator/AVR-Programmer)
|
|
113
|
+
- [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
|
+
rvprog/__init__.py
|
|
6
|
+
rvprog/rvprog.py
|
|
7
|
+
rvprog.egg-info/PKG-INFO
|
|
8
|
+
rvprog.egg-info/SOURCES.txt
|
|
9
|
+
rvprog.egg-info/dependency_links.txt
|
|
10
|
+
rvprog.egg-info/entry_points.txt
|
|
11
|
+
rvprog.egg-info/requires.txt
|
|
12
|
+
rvprog.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyusb
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
rvprog
|
rvprog-1.5.0/setup.cfg
ADDED
rvprog-1.5.0/setup.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name='rvprog',
|
|
5
|
+
version='1.5.0',
|
|
6
|
+
description='Programming Tool for WCH-LinkE and CH32Vxxx and CH32Xxxx',
|
|
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=['rvprog'],
|
|
12
|
+
install_requires=[
|
|
13
|
+
'pyusb',
|
|
14
|
+
],
|
|
15
|
+
)
|