stc8isp 0.3.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.
stc8isp-0.3.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.
stc8isp-0.3.0/PKG-INFO ADDED
@@ -0,0 +1,96 @@
1
+ Metadata-Version: 2.1
2
+ Name: stc8isp
3
+ Version: 0.3.0
4
+ Summary: Programming Tool for STC8G/8H 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) 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: STC,STC8,STC8G,STC8H,microcontroller
34
+ Classifier: Development Status :: 4 - Beta
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: pyserial
44
+
45
+ # stc8isp - Programming Tool for STC8G/8H Microcontrollers
46
+ ## Description
47
+ With this tool, STC8G/8H microcontrollers can be flashed via a simple USB-to-serial converter by utilizing the factory built-in embedded bootloader.
48
+
49
+ ## Preparations
50
+ If necessary, a driver for the USB-to-serial converter used must be installed.
51
+
52
+ ## Installation
53
+ - Install [Python3](https://www.pythontutorial.net/getting-started/install-python/).
54
+ - Install [pip](https://pip.pypa.io/en/stable/installation/).
55
+ - Install stc8isp:
56
+
57
+ ```
58
+ pip install stc8isp
59
+ ```
60
+
61
+ ## Usage
62
+ - Connect your USB-to-serial converter to your MCU as shown below.
63
+ - Run stc8isp.py (see below for arguments).
64
+ - Perform a power cycle of your MCU (reconnect to power) when prompted.
65
+
66
+ ```
67
+ USB2SERIAL STC8G/8H
68
+ +--------+ +------+
69
+ | VCC| --/ --> |VCC | interruptible (for power cycle)
70
+ | RXD| --|R|-- |P3.1 | resistor (100R - 1000R)
71
+ | TXD| --|<|-- |P3.0 | diode (e.g. 1N5819)
72
+ | GND| ------- |GND | common ground
73
+ +--------+ +------+
74
+ ```
75
+
76
+ ```
77
+ Usage: stc8isp [-h] [-p PORT] [-t TRIM] [-e] [-f FLASH]
78
+
79
+ Optional arguments:
80
+ -h, --help show this help message and exit
81
+ -p PORT, --port PORT set COM port (default: /dev/ttyUSB0)
82
+ -t TRIM, --trim TRIM trim IRC to frequency in Hz (128000 - 36000000)
83
+ -e, --erase perform chip erase (implied with -f)
84
+ -f FLASH, --flash FLASH write BIN file to flash
85
+
86
+ Example:
87
+ stc8isp -p /dev/ttyUSB0 -t 24000000 -f firmware.bin
88
+ ```
89
+
90
+ ## Links
91
+ - [MCU Flash Tools](https://github.com/wagiminator/MCU-Flash-Tools)
92
+ - [MCU Templates](https://github.com/wagiminator/MCU-Templates)
93
+ - [MCU Development Boards](https://github.com/wagiminator/Development-Boards)
94
+ - [AVR Development Boards](https://github.com/wagiminator/AVR-Development-Boards)
95
+ - [AVR Programmers](https://github.com/wagiminator/AVR-Programmer)
96
+ - [SAMD Development Boards](https://github.com/wagiminator/SAMD-Development-Boards)
@@ -0,0 +1,52 @@
1
+ # stc8isp - Programming Tool for STC8G/8H Microcontrollers
2
+ ## Description
3
+ With this tool, STC8G/8H microcontrollers can be flashed via a simple USB-to-serial converter by utilizing the factory built-in embedded bootloader.
4
+
5
+ ## Preparations
6
+ If necessary, a driver for the USB-to-serial converter used must be installed.
7
+
8
+ ## Installation
9
+ - Install [Python3](https://www.pythontutorial.net/getting-started/install-python/).
10
+ - Install [pip](https://pip.pypa.io/en/stable/installation/).
11
+ - Install stc8isp:
12
+
13
+ ```
14
+ pip install stc8isp
15
+ ```
16
+
17
+ ## Usage
18
+ - Connect your USB-to-serial converter to your MCU as shown below.
19
+ - Run stc8isp.py (see below for arguments).
20
+ - Perform a power cycle of your MCU (reconnect to power) when prompted.
21
+
22
+ ```
23
+ USB2SERIAL STC8G/8H
24
+ +--------+ +------+
25
+ | VCC| --/ --> |VCC | interruptible (for power cycle)
26
+ | RXD| --|R|-- |P3.1 | resistor (100R - 1000R)
27
+ | TXD| --|<|-- |P3.0 | diode (e.g. 1N5819)
28
+ | GND| ------- |GND | common ground
29
+ +--------+ +------+
30
+ ```
31
+
32
+ ```
33
+ Usage: stc8isp [-h] [-p PORT] [-t TRIM] [-e] [-f FLASH]
34
+
35
+ Optional arguments:
36
+ -h, --help show this help message and exit
37
+ -p PORT, --port PORT set COM port (default: /dev/ttyUSB0)
38
+ -t TRIM, --trim TRIM trim IRC to frequency in Hz (128000 - 36000000)
39
+ -e, --erase perform chip erase (implied with -f)
40
+ -f FLASH, --flash FLASH write BIN file to flash
41
+
42
+ Example:
43
+ stc8isp -p /dev/ttyUSB0 -t 24000000 -f firmware.bin
44
+ ```
45
+
46
+ ## Links
47
+ - [MCU Flash Tools](https://github.com/wagiminator/MCU-Flash-Tools)
48
+ - [MCU Templates](https://github.com/wagiminator/MCU-Templates)
49
+ - [MCU Development Boards](https://github.com/wagiminator/Development-Boards)
50
+ - [AVR Development Boards](https://github.com/wagiminator/AVR-Development-Boards)
51
+ - [AVR Programmers](https://github.com/wagiminator/AVR-Programmer)
52
+ - [SAMD Development Boards](https://github.com/wagiminator/SAMD-Development-Boards)
@@ -0,0 +1,43 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "stc8isp"
7
+ version = "0.3.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 STC8G/8H Microcontrollers"
15
+ readme = "README.md"
16
+ license = {file = "LICENSE"}
17
+ requires-python = ">=3.8"
18
+ dependencies = [
19
+ "pyserial",
20
+ ]
21
+ keywords = [
22
+ "STC",
23
+ "STC8",
24
+ "STC8G",
25
+ "STC8H",
26
+ "microcontroller",
27
+ ]
28
+ classifiers = [
29
+ "Development Status :: 4 - Beta",
30
+ "Programming Language :: Python :: 3",
31
+ "License :: OSI Approved :: MIT License",
32
+ "Operating System :: OS Independent",
33
+ "Intended Audience :: Developers",
34
+ "Topic :: Software Development :: Embedded Systems",
35
+ ]
36
+
37
+ [project.scripts]
38
+ stc8isp = "stc8isp:_main"
39
+
40
+ [project.urls]
41
+ Homepage = "https://wagiminator.github.io/"
42
+ Repository = "https://github.com/wagiminator/MCU-Flash-Tools"
43
+ Issues = "https://github.com/wagiminator/MCU-Flash-Tools/issues"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
stc8isp-0.3.0/setup.py ADDED
@@ -0,0 +1,15 @@
1
+ from setuptools import setup
2
+
3
+ setup(
4
+ name='stc8isp',
5
+ version='0.3.0',
6
+ description='Programming Tool for STC8G/8H 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=['stc8isp'],
12
+ install_requires=[
13
+ 'pyserial',
14
+ ],
15
+ )
@@ -0,0 +1 @@
1
+ from .stc8isp import _main
@@ -0,0 +1,503 @@
1
+ #!/usr/bin/env python3
2
+ # ===================================================================================
3
+ # Project: stc8isp - Programming Tool for STC8G/8H Microcontrollers
4
+ # Version: v0.3
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 STC8G/8H microcontrollers via USB-to-serial
14
+ # converter utilizing the factory built-in embedded boot loader.
15
+ # !!! THIS TOOL IS IN AN EARLY STAGE OF DEVELOPMENT !!!
16
+ #
17
+ # Dependencies:
18
+ # -------------
19
+ # - pyserial
20
+ #
21
+ # Operating Instructions:
22
+ # -----------------------
23
+ # You need to install PySerial to use stc8isp.
24
+ # Install it via "python3 -m pip install pyserial".
25
+ # You may need to install a driver for your USB-to-serial converter.
26
+ #
27
+ # Connect your USB-to-serial converter to your MCU:
28
+ # USB2SERIAL STC8G/8H
29
+ # VCC --/ --> VCC interruptible (for power cycle)
30
+ # RXD --|R|-- P3.1 resistor (100R - 1000R)
31
+ # TXD --|<|-- P3.0 diode (e.g. 1N5819)
32
+ # GND ------- GND common ground
33
+ #
34
+ # Run "python3 stc8isp.py -p /dev/ttyUSB0 -t 24000000 -f firmware.bin".
35
+ # Perform a power cycle of your MCU (reconnect to power) when prompted.
36
+
37
+
38
+ # ===================================================================================
39
+ # Software Settings
40
+ # ===================================================================================
41
+
42
+ # If the PID/VID of the USB-to-Serial converter is known, it can be defined here.
43
+ # The specified COM port is then ignored, and all ports are automatically searched
44
+ # for the device. Comment the lines to ignore PID/VID.
45
+ #STC_VID = '1A86'
46
+ #STC_PID = '7523'
47
+
48
+ # Define the default COM port here. This will be used if no VID/PID is defined and
49
+ # no COM port is specified within the command line arguments.
50
+ STC_PORT = '/dev/ttyUSB0'
51
+
52
+ # Define the default BAUD rates here. The minimum BAUD rate is used to calibrate the
53
+ # oscillator and should be low to achieve higher accuracy. The maximum BAUD rate is
54
+ # used to transfer the firmware and should be high to achieve higher speed.
55
+ STC_BAUD_MIN = 2400
56
+ STC_BAUD_MAX = 115200
57
+
58
+ # Define time to wait for power cycle in seconds, default: 10
59
+ STC_WAIT = 10
60
+
61
+ # Define minimum and maximum IRC frequency in Hz, that can be specified by the
62
+ # respective command line argument. Expanding the limit values can lead to problems!
63
+ STC_FCPU_MIN = 128000
64
+ STC_FCPU_MAX = 36000000
65
+
66
+ # ===================================================================================
67
+ # Libraries
68
+ # ===================================================================================
69
+
70
+ # Libraries
71
+ import sys
72
+ import time
73
+ import argparse
74
+ import serial
75
+ from serial import Serial
76
+ from serial.tools.list_ports import comports
77
+
78
+ # ===================================================================================
79
+ # Main Function
80
+ # ===================================================================================
81
+
82
+ def _main():
83
+ # Parse command line arguments
84
+ parser = argparse.ArgumentParser(description='Minimal command line interface for stc8isp')
85
+ parser.add_argument('-p', '--port', default=STC_PORT, help='set COM port')
86
+ parser.add_argument('-t', '--trim', help='trim IRC to frequency in Hz')
87
+ parser.add_argument('-e', '--erase', action='store_true', help='perform chip erase (implied with -f)')
88
+ parser.add_argument('-f', '--flash', help='write BIN file to flash')
89
+ args = parser.parse_args(sys.argv[1:])
90
+
91
+ # Checking command line arguments
92
+ if (args.trim is not None) and (int(args.trim) < STC_FCPU_MIN or int(args.trim) > STC_FCPU_MAX):
93
+ sys.stderr.write('ERROR: Trim value out of range (%d - %d)!\n' % (STC_FCPU_MIN, STC_FCPU_MAX))
94
+ sys.exit(1)
95
+
96
+ # Establish connection to USB-to-serial converter
97
+ try:
98
+ print('Connecting to USB-to-serial converter ...')
99
+ isp = Programmer(args.port)
100
+ print('SUCCESS: Connected via', isp.port + '.')
101
+ except Exception as ex:
102
+ sys.stderr.write('ERROR: ' + str(ex) + '!\n')
103
+ sys.exit(1)
104
+
105
+ # Performing actions
106
+ try:
107
+ # Connect to and identify MCU
108
+ print('Waiting for MCU power cycle ...')
109
+ isp.connect()
110
+ print('SUCCESS: Found %s v%s @ %s.' % (isp.chipname, isp.chipverstr, isp.foscstr))
111
+
112
+ # Calibrate user IRC oscillator frequency
113
+ if args.trim is not None:
114
+ print('Calibrating user IRC frequency to %s Hz ...' % args.trim)
115
+ isp.trim(int(args.trim))
116
+ print('SUCCESS: Trimmed to %d Hz (error %.2f%%).' % (isp.osc_freq, 100 * isp.osc_error))
117
+
118
+ # Switch BAUD rate
119
+ print('Switching BAUD rate ...')
120
+ isp.setbaud(STC_BAUD_MAX)
121
+ print('SUCCESS: BAUD rate set to %d.' % STC_BAUD_MAX)
122
+
123
+ # Perform chip erase
124
+ if (args.erase) or (args.flash is not None) or (args.trim is not None):
125
+ print('Performing chip erase ...')
126
+ isp.erase()
127
+ print('SUCCESS: Chip is erased.')
128
+
129
+ # Flash binary file
130
+ if args.flash is not None:
131
+ print('Flashing %s to MCU ...' % args.flash)
132
+ with open(args.flash, 'rb') as f: data = f.read()
133
+ isp.writeflash(0, data)
134
+ print('SUCCESS: %d bytes written.' % len(data))
135
+
136
+ # Write option bytes
137
+ if args.trim is not None:
138
+ print('Writing option bytes ...')
139
+ isp.writeoptions()
140
+ print('SUCCESS: Option bytes written.')
141
+
142
+ # Close connection
143
+ isp.disconnect()
144
+
145
+ except Exception as ex:
146
+ sys.stderr.write('ERROR: ' + str(ex) + '!\n')
147
+ isp.close()
148
+ sys.exit(1)
149
+
150
+ print('DONE.')
151
+ sys.exit(0)
152
+
153
+ # ===================================================================================
154
+ # Programmer Class
155
+ # ===================================================================================
156
+
157
+ class Programmer(Serial):
158
+ def __init__(self, port=STC_PORT, baud=STC_BAUD_MIN):
159
+ # Data frame: 1 start bit, 8 data bit, 1 parity bit set to even, 1 stop bit
160
+ super().__init__(baudrate = baud, parity = serial.PARITY_EVEN, timeout = 0.01)
161
+
162
+ # Use COM port to define device
163
+ if 'STC_VID' not in globals() or 'STC_PID' not in globals():
164
+ self.port = port
165
+
166
+ # Use VID/PID to find device
167
+ else:
168
+ for p in comports():
169
+ if (STC_VID in p.hwid) and (STC_PID in p.hwid):
170
+ self.port = p.device
171
+ break
172
+
173
+ # Open connection
174
+ try:
175
+ self.open()
176
+ except:
177
+ raise Exception('Failed to connect to USB-to-serial converter')
178
+
179
+ #--------------------------------------------------------------------------------
180
+
181
+ # Transmit data block
182
+ def transmit(self, data):
183
+ size = len(data) + 6
184
+ parity = STC_TX_CODE + (size >> 8) + (size & 0xff)
185
+ for x in range(len(data)):
186
+ parity += data[x]
187
+ block = [STC_PREFIX, STC_PREFIX ^ 0xff, STC_TX_CODE]
188
+ block += size.to_bytes(2, byteorder='big')
189
+ block += data
190
+ block += parity.to_bytes(2, byteorder='big')
191
+ block += [STC_SUFFIX]
192
+ self.write(block)
193
+
194
+ # Receive and check data block
195
+ def receive(self):
196
+ reply = self.read(1)
197
+ if len(reply) == 0 or reply[0] != STC_PREFIX:
198
+ return None
199
+ self.timeout = 1
200
+ reply = self.read(2)
201
+ if len(reply) != 2 or reply[0] != (STC_PREFIX ^ 0xff) or reply[1] != STC_RX_CODE:
202
+ raise Exception('Invalid data prefix from MCU')
203
+ size = int.from_bytes(self.read(2), byteorder='big')
204
+ if size < 7:
205
+ raise Exception('Invalid data size from MCU')
206
+ data = self.read(size - 6)
207
+ if len(data) != size - 6:
208
+ raise Exception('Missing data from MCU')
209
+ check = int.from_bytes(self.read(2), byteorder='big')
210
+ suffix = self.read(1)[0]
211
+ if suffix != STC_SUFFIX:
212
+ raise Exception('Invalid data suffix from MCU')
213
+ parity = STC_RX_CODE + (size >> 8) + (size & 0xff)
214
+ for x in range(len(data)):
215
+ parity += data[x]
216
+ if (parity & 0xffff) != check:
217
+ raise Exception('Invalid data checksum from MCU')
218
+ return data
219
+
220
+ # Repeat sending sync character until reply or timeout
221
+ def pulse(self, char, pulsetime=0.01, timeout=10):
222
+ counter = timeout
223
+ while self.in_waiting == 0:
224
+ self.write([char])
225
+ time.sleep(pulsetime)
226
+ counter -= pulsetime
227
+ if counter <= 0:
228
+ raise Exception('Timout waiting for response')
229
+
230
+ #--------------------------------------------------------------------------------
231
+
232
+ # Connect to and identify MCU
233
+ def connect(self):
234
+ # Ping MCU, wait for power cycle, read info bytes
235
+ self.reset_input_buffer()
236
+ waitcounter = STC_WAIT * 100
237
+ reply = None
238
+ while (waitcounter > 0) and (reply is None):
239
+ self.write([STC_CHAR_SYNC])
240
+ reply = self.receive()
241
+ waitcounter -= 1
242
+ if waitcounter == 0:
243
+ raise Exception('Timeout, failed to connect to MCU')
244
+ if reply is None or len(reply) < 42 or reply[0] != STC_RPL_INFO:
245
+ raise Exception('Invalid response from MCU')
246
+
247
+ # Get chip ID
248
+ self.chipid = int.from_bytes(reply[20:22], byteorder='big')
249
+
250
+ # Find chip in dictionary
251
+ self.device = None
252
+ for d in DEVICES:
253
+ if d['id'] == self.chipid:
254
+ self.device = d
255
+ if self.device is None:
256
+ raise Exception('Unsupported chip (ID: 0x%04x)' % self.chipid)
257
+ self.chipname = self.device['name']
258
+ self.flash_size = self.device['flash_size']
259
+
260
+ # Get chip version
261
+ self.chipversion = reply[17]
262
+ self.chipverstr = '%d.%d.%d%c' % (reply[17] >> 4, reply[17] & 0x0f, \
263
+ reply[22] & 0x0f, reply[18])
264
+
265
+ # Get ISP-IRC and USER-IRC oscillator frequencies
266
+ self.fisp = int.from_bytes(reply[13:15], byteorder='big') * self.baudrate
267
+ self.fosc = int.from_bytes(reply[1:5], byteorder='big')
268
+ if self.fosc == 0xffffffff:
269
+ self.foscstr = 'untrimmed frequency'
270
+ else:
271
+ self.foscstr = str(self.fosc) + ' Hz'
272
+
273
+ # Get option bytes
274
+ self.options = reply[9:12] + reply[15:17]
275
+
276
+ # Disconnect from MCU and USB-to-serial converter
277
+ def disconnect(self):
278
+ self.transmit([STC_CMD_EXIT])
279
+ self.close()
280
+
281
+ #--------------------------------------------------------------------------------
282
+
283
+ # Set and calibrate USER-IRC oscillator frequency
284
+ def trim(self, freq):
285
+ # Get global trim values
286
+ self.transmit(STC_BLOCK_TRIM)
287
+ self.pulse(STC_CHAR_TRIM)
288
+ reply = self.receive()
289
+ if reply is None or reply[0] != STC_CMD_TRIM:
290
+ raise Exception('Invalid responde from MCU')
291
+
292
+ # Calculate mean trim value for specified frequency
293
+ freq1 = int.from_bytes(reply[ 2: 4], byteorder='big') * self.baudrate
294
+ freq2 = int.from_bytes(reply[ 4: 6], byteorder='big') * self.baudrate
295
+ freq3 = int.from_bytes(reply[ 6: 8], byteorder='big') * self.baudrate
296
+ freq4 = int.from_bytes(reply[ 8:10], byteorder='big') * self.baudrate
297
+ freq5 = int.from_bytes(reply[10:12], byteorder='big') * self.baudrate
298
+ self.osc_div = 1
299
+ while freq * self.osc_div < freq1: self.osc_div += 1
300
+ if freq * self.osc_div < freq5:
301
+ self.osc_trimx = round( (freq * self.osc_div - freq1) *
302
+ (STC_BLOCK_TRIM[4] - STC_BLOCK_TRIM[2]) / (freq2 - freq1) + STC_BLOCK_TRIM[2] )
303
+ self.osc_bandx = STC_BLOCK_TRIM[3]
304
+ else:
305
+ self.osc_trimx = round( (freq * self.osc_div - freq3) *
306
+ (STC_BLOCK_TRIM[8] - STC_BLOCK_TRIM[6]) / (freq4 - freq3) + STC_BLOCK_TRIM[2] )
307
+ self.osc_bandx = STC_BLOCK_TRIM[7]
308
+
309
+ # Get fine tuned trim values for specified frequency
310
+ count = 24
311
+ block = [0x00, count]
312
+ for x in range(count):
313
+ block += [self.osc_trimx - 2 + (x>>2), self.osc_bandx + (x & 0x03)]
314
+ self.transmit(block)
315
+ self.pulse(STC_CHAR_TRIM)
316
+ reply = self.receive()
317
+ if reply is None or reply[0] != STC_CMD_TRIM:
318
+ raise Exception('Invalid responde from MCU')
319
+
320
+ # Find optimal trim value
321
+ best = sys.maxsize
322
+ for x in range(count):
323
+ freq1 = int.from_bytes(reply[2*x+2:2*x+4], byteorder='big') * self.baudrate
324
+ if abs(freq * self.osc_div - freq1) < best:
325
+ best = abs(freq * self.osc_div - freq1)
326
+ self.osc_freq = round(freq1 / self.osc_div)
327
+ self.osc_trim = self.osc_trimx - 2 + (x>>2)
328
+ self.osc_band = self.osc_bandx + (x & 0x03)
329
+ self.osc_error = (self.osc_freq - freq) / freq
330
+
331
+ # Set/switch BAUD rate
332
+ def setbaud(self, baud=STC_BAUD_MAX):
333
+ # Set BAUD rate
334
+ count = round(65536 - (self.fisp / (4 * baud)))
335
+ block = [STC_CMD_BAUD_SET, self.fosc & 0xff, 0x40]
336
+ block += count.to_bytes(2, byteorder='big')
337
+ block += [0x00, 0x00, 0x97]
338
+ self.transmit(block)
339
+ reply = self.receive()
340
+ if reply is None or reply[0] != STC_CMD_BAUD_SET:
341
+ raise Exception('Failed to set BAUD rate')
342
+ self.baudrate = baud
343
+ time.sleep(0.01)
344
+
345
+ # Check BAUD rate
346
+ if self.chipversion < 0x72:
347
+ self.transmit([STC_CMD_BAUD_CHECK])
348
+ else:
349
+ self.transmit([STC_CMD_BAUD_CHECK, 0, 0, STC_BREAK, STC_BREAK ^ 0xff])
350
+ reply = self.receive()
351
+ if reply is None or reply[0] != STC_CMD_BAUD_CHECK:
352
+ raise Exception('Failed to check BAUD rate')
353
+
354
+ #--------------------------------------------------------------------------------
355
+
356
+ # Erase flash
357
+ def erase(self):
358
+ self.transmit([STC_CMD_ERASE, 0, 0, STC_BREAK, STC_BREAK ^ 0xff])
359
+ reply = self.receive()
360
+ if reply is None or reply[0] != STC_CMD_ERASE:
361
+ raise Exception('Failed to erase flash')
362
+
363
+ # Write data to flash
364
+ def writeflash(self, addr, data):
365
+ size = len(data)
366
+ if size > (self.flash_size - addr):
367
+ raise Exception('Not enough memory')
368
+ cmd = STC_CMD_WRITE
369
+ while size > 0:
370
+ blocksize = min(size, STC_PAGE_SIZE)
371
+ block = [cmd]
372
+ block += addr.to_bytes(2, byteorder='big')
373
+ block += [STC_BREAK, STC_BREAK ^ 0xff]
374
+ block += data[:blocksize]
375
+ self.transmit(block)
376
+ reply = self.receive()
377
+ if reply is None or reply[0] != STC_CMD_WRITE_CONT:
378
+ raise Exception('Failed to write to address 0x%04x' % addr)
379
+ cmd = STC_CMD_WRITE_CONT
380
+ data = data[blocksize:]
381
+ addr += blocksize
382
+ size -= blocksize
383
+
384
+ # Write option bytes
385
+ def writeoptions(self):
386
+ block = [STC_CMD_OPTIONS, 0, 0, STC_BREAK, STC_BREAK ^ 0xff]
387
+ block += STC_BLOCK_OPTIONS1
388
+ block += self.osc_freq.to_bytes(4, byteorder='big')
389
+ block += [self.osc_trim, self.osc_band, self.osc_div]
390
+ block += STC_BLOCK_OPTIONS2
391
+ self.transmit(block)
392
+ reply = self.receive()
393
+ if reply is None or reply[0] != STC_CMD_OPTIONS:
394
+ raise Exception('Failed to write option bytes')
395
+
396
+ # ===================================================================================
397
+ # Device Constants
398
+ # ===================================================================================
399
+
400
+ STC_PAGE_SIZE = 128
401
+
402
+ STC_CHAR_SYNC = 0x7f
403
+ STC_CHAR_TRIM = 0x66
404
+
405
+ STC_PREFIX = 0x46
406
+ STC_BREAK = 0x5a
407
+ STC_SUFFIX = 0x16
408
+ STC_TX_CODE = 0x6a
409
+ STC_RX_CODE = 0x68
410
+ STC_RPL_INFO = 0x50
411
+
412
+ STC_CMD_TRIM = 0x00
413
+ STC_CMD_BAUD_SET = 0x01
414
+ STC_CMD_BAUD_CHECK = 0x05
415
+ STC_CMD_ERASE = 0x03
416
+ STC_CMD_OPTIONS = 0x04
417
+ STC_CMD_WRITE = 0x22
418
+ STC_CMD_WRITE_CONT = 0x02
419
+ STC_CMD_EXIT = 0xff
420
+
421
+ STC_BLOCK_TRIM = [0x00, 0x05, 0x02, 0x00, 0x80, 0x00, 0x00, 0x80,
422
+ 0x80, 0x80, 0xfd, 0x00]
423
+ STC_BLOCK_OPTIONS1 = [0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff,
424
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
425
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff]
426
+ STC_BLOCK_OPTIONS2 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, 0xf7, 0xff]
427
+
428
+ # ===================================================================================
429
+ # Device Dictionary
430
+ # ===================================================================================
431
+
432
+ DEVICES = [
433
+ {'name': 'STC8H1K16', 'id': 0xF721, 'flash_size': 16384},
434
+ {'name': 'STC8H1K20', 'id': 0xF722, 'flash_size': 20480},
435
+ {'name': 'STC8H1K24', 'id': 0xF723, 'flash_size': 24576},
436
+ {'name': 'STC8H1K28', 'id': 0xF724, 'flash_size': 28672},
437
+ {'name': 'STC8H1K33', 'id': 0xF725, 'flash_size': 33792},
438
+ {'name': 'STC8H1K02', 'id': 0xF731, 'flash_size': 2048},
439
+ {'name': 'STC8H1K04', 'id': 0xF732, 'flash_size': 4096},
440
+ {'name': 'STC8H1K06', 'id': 0xF733, 'flash_size': 6144},
441
+ {'name': 'STC8H1K08', 'id': 0xF734, 'flash_size': 8192},
442
+ {'name': 'STC8H1K10', 'id': 0xF735, 'flash_size': 10240},
443
+ {'name': 'STC8H1K12', 'id': 0xF736, 'flash_size': 12288},
444
+ {'name': 'STC8H1K17', 'id': 0xF737, 'flash_size': 17408},
445
+ {'name': 'STC8H3K16S4', 'id': 0xF741, 'flash_size': 16384},
446
+ {'name': 'STC8H3K32S4', 'id': 0xF742, 'flash_size': 32768},
447
+ {'name': 'STC8H3K60S4', 'id': 0xF743, 'flash_size': 61440},
448
+ {'name': 'STC8H3K64S4', 'id': 0xF744, 'flash_size': 65024},
449
+ {'name': 'STC8H3K48S4', 'id': 0xF745, 'flash_size': 49152},
450
+ {'name': 'STC8H3K16S2', 'id': 0xF749, 'flash_size': 16384},
451
+ {'name': 'STC8H3K32S2', 'id': 0xF74A, 'flash_size': 32768},
452
+ {'name': 'STC8H3K60S2', 'id': 0xF74B, 'flash_size': 61440},
453
+ {'name': 'STC8H3K64S2', 'id': 0xF74C, 'flash_size': 65024},
454
+ {'name': 'STC8H3K48S2', 'id': 0xF74D, 'flash_size': 49152},
455
+ {'name': 'STC8G1K02-20/16P', 'id': 0xF751, 'flash_size': 2048},
456
+ {'name': 'STC8G1K04-20/16P', 'id': 0xF752, 'flash_size': 4096},
457
+ {'name': 'STC8G1K06-20/16P', 'id': 0xF753, 'flash_size': 6144},
458
+ {'name': 'STC8G1K08-20/16P', 'id': 0xF754, 'flash_size': 8192},
459
+ {'name': 'STC8G1K10-20/16P', 'id': 0xF755, 'flash_size': 10240},
460
+ {'name': 'STC8G1K12-20/16P', 'id': 0xF756, 'flash_size': 12288},
461
+ {'name': 'STC8G1K17-20/16P', 'id': 0xF757, 'flash_size': 17408},
462
+ {'name': 'STC8G2K16S4', 'id': 0xF761, 'flash_size': 16384},
463
+ {'name': 'STC8G2K32S4', 'id': 0xF762, 'flash_size': 32768},
464
+ {'name': 'STC8G2K60S4', 'id': 0xF763, 'flash_size': 61440},
465
+ {'name': 'STC8G2K64S4', 'id': 0xF764, 'flash_size': 65024},
466
+ {'name': 'STC8G2K48S4', 'id': 0xF765, 'flash_size': 49152},
467
+ {'name': 'STC8G2K16S2', 'id': 0xF769, 'flash_size': 16384},
468
+ {'name': 'STC8G2K32S2', 'id': 0xF76A, 'flash_size': 32768},
469
+ {'name': 'STC8G2K60S2', 'id': 0xF76B, 'flash_size': 61440},
470
+ {'name': 'STC8G2K64S2', 'id': 0xF76C, 'flash_size': 65024},
471
+ {'name': 'STC8G2K48S2', 'id': 0xF76D, 'flash_size': 49152},
472
+ {'name': 'STC8G1K02T', 'id': 0xF771, 'flash_size': 2048},
473
+ {'name': 'STC8G1K04T', 'id': 0xF772, 'flash_size': 4096},
474
+ {'name': 'STC8G1K06T', 'id': 0xF773, 'flash_size': 6144},
475
+ {'name': 'STC8G1K08T', 'id': 0xF774, 'flash_size': 8192},
476
+ {'name': 'STC8G1K10T', 'id': 0xF775, 'flash_size': 10240},
477
+ {'name': 'STC8G1K12T', 'id': 0xF776, 'flash_size': 12288},
478
+ {'name': 'STC8G1K17T', 'id': 0xF777, 'flash_size': 17408},
479
+ {'name': 'STC8H8K16U', 'id': 0xF781, 'flash_size': 16384},
480
+ {'name': 'STC8H8K32U', 'id': 0xF782, 'flash_size': 32768},
481
+ {'name': 'STC8H8K60U', 'id': 0xF783, 'flash_size': 61440},
482
+ {'name': 'STC8H8K64U', 'id': 0xF784, 'flash_size': 65024},
483
+ {'name': 'STC8H8K48U', 'id': 0xF785, 'flash_size': 49152},
484
+ {'name': 'STC8G1K02A-8P', 'id': 0xF791, 'flash_size': 2048},
485
+ {'name': 'STC8G1K04A-8P', 'id': 0xF792, 'flash_size': 4096},
486
+ {'name': 'STC8G1K06A-8P', 'id': 0xF793, 'flash_size': 6144},
487
+ {'name': 'STC8G1K08A-8P', 'id': 0xF794, 'flash_size': 8192},
488
+ {'name': 'STC8G1K10A-8P', 'id': 0xF795, 'flash_size': 10240},
489
+ {'name': 'STC8G1K12A-8P', 'id': 0xF796, 'flash_size': 12288},
490
+ {'name': 'STC8G1K17A-8P', 'id': 0xF797, 'flash_size': 17408},
491
+ {'name': 'STC8G1K02-8P', 'id': 0xF7A1, 'flash_size': 2048},
492
+ {'name': 'STC8G1K04-8P', 'id': 0xF7A2, 'flash_size': 4096},
493
+ {'name': 'STC8G1K06-8P', 'id': 0xF7A3, 'flash_size': 6144},
494
+ {'name': 'STC8G1K08-8P', 'id': 0xF7A4, 'flash_size': 8192},
495
+ {'name': 'STC8G1K10-8P', 'id': 0xF7A5, 'flash_size': 10240},
496
+ {'name': 'STC8G1K12-8P', 'id': 0xF7A6, 'flash_size': 12288},
497
+ {'name': 'STC8G1K17-8P', 'id': 0xF7A7, 'flash_size': 17408}
498
+ ]
499
+
500
+ # ===================================================================================
501
+
502
+ if __name__ == "__main__":
503
+ _main()
@@ -0,0 +1,96 @@
1
+ Metadata-Version: 2.1
2
+ Name: stc8isp
3
+ Version: 0.3.0
4
+ Summary: Programming Tool for STC8G/8H 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) 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: STC,STC8,STC8G,STC8H,microcontroller
34
+ Classifier: Development Status :: 4 - Beta
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: pyserial
44
+
45
+ # stc8isp - Programming Tool for STC8G/8H Microcontrollers
46
+ ## Description
47
+ With this tool, STC8G/8H microcontrollers can be flashed via a simple USB-to-serial converter by utilizing the factory built-in embedded bootloader.
48
+
49
+ ## Preparations
50
+ If necessary, a driver for the USB-to-serial converter used must be installed.
51
+
52
+ ## Installation
53
+ - Install [Python3](https://www.pythontutorial.net/getting-started/install-python/).
54
+ - Install [pip](https://pip.pypa.io/en/stable/installation/).
55
+ - Install stc8isp:
56
+
57
+ ```
58
+ pip install stc8isp
59
+ ```
60
+
61
+ ## Usage
62
+ - Connect your USB-to-serial converter to your MCU as shown below.
63
+ - Run stc8isp.py (see below for arguments).
64
+ - Perform a power cycle of your MCU (reconnect to power) when prompted.
65
+
66
+ ```
67
+ USB2SERIAL STC8G/8H
68
+ +--------+ +------+
69
+ | VCC| --/ --> |VCC | interruptible (for power cycle)
70
+ | RXD| --|R|-- |P3.1 | resistor (100R - 1000R)
71
+ | TXD| --|<|-- |P3.0 | diode (e.g. 1N5819)
72
+ | GND| ------- |GND | common ground
73
+ +--------+ +------+
74
+ ```
75
+
76
+ ```
77
+ Usage: stc8isp [-h] [-p PORT] [-t TRIM] [-e] [-f FLASH]
78
+
79
+ Optional arguments:
80
+ -h, --help show this help message and exit
81
+ -p PORT, --port PORT set COM port (default: /dev/ttyUSB0)
82
+ -t TRIM, --trim TRIM trim IRC to frequency in Hz (128000 - 36000000)
83
+ -e, --erase perform chip erase (implied with -f)
84
+ -f FLASH, --flash FLASH write BIN file to flash
85
+
86
+ Example:
87
+ stc8isp -p /dev/ttyUSB0 -t 24000000 -f firmware.bin
88
+ ```
89
+
90
+ ## Links
91
+ - [MCU Flash Tools](https://github.com/wagiminator/MCU-Flash-Tools)
92
+ - [MCU Templates](https://github.com/wagiminator/MCU-Templates)
93
+ - [MCU Development Boards](https://github.com/wagiminator/Development-Boards)
94
+ - [AVR Development Boards](https://github.com/wagiminator/AVR-Development-Boards)
95
+ - [AVR Programmers](https://github.com/wagiminator/AVR-Programmer)
96
+ - [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
+ stc8isp/__init__.py
6
+ stc8isp/stc8isp.py
7
+ stc8isp.egg-info/PKG-INFO
8
+ stc8isp.egg-info/SOURCES.txt
9
+ stc8isp.egg-info/dependency_links.txt
10
+ stc8isp.egg-info/entry_points.txt
11
+ stc8isp.egg-info/requires.txt
12
+ stc8isp.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ stc8isp = stc8isp:_main
@@ -0,0 +1 @@
1
+ pyserial
@@ -0,0 +1 @@
1
+ stc8isp