Compare commits
34 Commits
stc12b
...
delay-calc
Author | SHA1 | Date | |
---|---|---|---|
a414bfb864 | |||
68d19f7b88 | |||
ebcfeb467c | |||
d7e226df6b | |||
191a580469 | |||
c131a9d901 | |||
3f4263e8fe | |||
ba4faf9c43 | |||
f1bafb1e0d | |||
fdd6707d2d | |||
532363d97b | |||
5865b06f7f | |||
1b69257cd3 | |||
38ac5f0788 | |||
6dccf13fb6 | |||
0ca8b2ea2d | |||
53184b549e | |||
cf68e3c6dc | |||
5d10c06f1e | |||
7e84b8e0fb | |||
f34ba6644f | |||
f15b64f4f7 | |||
2e822375e0 | |||
7d6e8e9bfd | |||
506289b8ee | |||
f417b6eed5 | |||
86e289b65c | |||
53f9544281 | |||
65a7759647 | |||
8ad77586d4 | |||
276c696fa4 | |||
26ef34991b | |||
f90fe4152b | |||
d6ef028dc7 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@ __pycache__
|
|||||||
/build
|
/build
|
||||||
/dist
|
/dist
|
||||||
/deb_dist
|
/deb_dist
|
||||||
|
/.vscode
|
||||||
|
33
.travis.yml
Normal file
33
.travis.yml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
sudo: required
|
||||||
|
dist: trusty
|
||||||
|
language: python
|
||||||
|
cache:
|
||||||
|
- pip
|
||||||
|
python:
|
||||||
|
- "3.4"
|
||||||
|
- "3.5"
|
||||||
|
- "3.6"
|
||||||
|
- "pypy3"
|
||||||
|
before_install:
|
||||||
|
- sudo apt install rpm dpkg-dev debhelper dh-python python3-setuptools fakeroot python3-serial python3-yaml
|
||||||
|
install:
|
||||||
|
- pip install pyserial pyusb
|
||||||
|
script:
|
||||||
|
- python setup.py build
|
||||||
|
- python setup.py test
|
||||||
|
before_deploy:
|
||||||
|
- deactivate
|
||||||
|
- python3 setup.py bdist_rpm
|
||||||
|
- dpkg-buildpackage -uc -us
|
||||||
|
- cp ../*.deb dist/
|
||||||
|
deploy:
|
||||||
|
provider: releases
|
||||||
|
api_key: $GH_TOKEN
|
||||||
|
file_glob: true
|
||||||
|
file:
|
||||||
|
- dist/stcgal*_all.deb
|
||||||
|
- dist/stcgal*.noarch.rpm
|
||||||
|
skip_cleanup: true
|
||||||
|
on:
|
||||||
|
tags: true
|
||||||
|
python: "3.4"
|
41
README.md
41
README.md
@ -1,3 +1,5 @@
|
|||||||
|
[](https://travis-ci.org/grigorig/stcgal)
|
||||||
|
|
||||||
stcgal - STC MCU ISP flash tool
|
stcgal - STC MCU ISP flash tool
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
@ -25,14 +27,14 @@ stcgal should fully support STC 89/90/10/11/12/15 series MCUs.
|
|||||||
|
|
||||||
So far, stcgal was tested with the following MCU models:
|
So far, stcgal was tested with the following MCU models:
|
||||||
|
|
||||||
* STC89C52RC (BSL version: 4.3C)
|
* STC89C52RC (BSL version: 4.3C/6.6C)
|
||||||
* STC90C52RC (BSL version: 4.3C)
|
* STC90C52RC (BSL version: 4.3C)
|
||||||
* STC89C54RD+ (BSL version: 4.3C)
|
* STC89C54RD+ (BSL version: 4.3C)
|
||||||
* STC12C2052 (BSL version: 5.8D)
|
* STC12C2052 (BSL version: 5.8D)
|
||||||
* STC12C2052AD (BSL version: 5.8D)
|
* STC12C2052AD (BSL version: 5.8D)
|
||||||
* STC12C5608AD (BSL version: 6.0G)
|
* STC12C5608AD (BSL version: 6.0G)
|
||||||
* STC12C5A16S2 (BSL version: 6.2I)
|
* STC12C5A16S2 (BSL version: 6.2I)
|
||||||
* STC12C5A60S2 (BSL version: 6.2I)
|
* STC12C5A60S2 (BSL version: 6.2I/7.1I)
|
||||||
* STC11F02E (BSL version: 6.5K)
|
* STC11F02E (BSL version: 6.5K)
|
||||||
* STC10F04XE (BSL version: 6.5J)
|
* STC10F04XE (BSL version: 6.5J)
|
||||||
* STC11F08XE (BSL version: 6.5M)
|
* STC11F08XE (BSL version: 6.5M)
|
||||||
@ -59,7 +61,7 @@ Features
|
|||||||
* Set device options
|
* Set device options
|
||||||
* Read unique device ID (STC 10/11/12/15)
|
* Read unique device ID (STC 10/11/12/15)
|
||||||
* Trim RC oscillator frequency (STC 15)
|
* Trim RC oscillator frequency (STC 15)
|
||||||
* Automatic power-cycling with DTR toggle
|
* Automatic power-cycling with DTR toggle or a custom shell command
|
||||||
* Automatic UART protocol detection
|
* Automatic UART protocol detection
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
@ -94,6 +96,9 @@ positional arguments:
|
|||||||
optional arguments:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
-a, --autoreset cycle power automatically by asserting DTR
|
-a, --autoreset cycle power automatically by asserting DTR
|
||||||
|
-r RESETCMD, --resetcmd RESETCMD
|
||||||
|
Use this shell command for board power-cycling
|
||||||
|
(instead of DTR assertion)
|
||||||
-P {stc89,stc12a,stc12,stc15a,stc15,auto}, --protocol {stc89,stc12a,stc12,stc15a,stc15,auto}
|
-P {stc89,stc12a,stc12,stc15a,stc15,auto}, --protocol {stc89,stc12a,stc12,stc15a,stc15,auto}
|
||||||
protocol version
|
protocol version
|
||||||
-p PORT, --port PORT serial port device
|
-p PORT, --port PORT serial port device
|
||||||
@ -111,17 +116,18 @@ Most importantly, ```-p``` sets the serial port to be used for programming.
|
|||||||
### Protocols
|
### Protocols
|
||||||
|
|
||||||
STC MCUs use a variety of related but incompatible protocols for the
|
STC MCUs use a variety of related but incompatible protocols for the
|
||||||
BSL. The protocol can be specified with the ```-P``` flag. Optionally,
|
BSL. The protocol can be specified with the ```-P``` flag. By default
|
||||||
experimental protocol autodetection can be used. The mapping between
|
UART protocol autodetection is used. The mapping between protocols
|
||||||
protocols and MCU series is as follows:
|
and MCU series is as follows:
|
||||||
|
|
||||||
* ```stc89``` STC89/90 series
|
* ```stc89``` STC89/90 series
|
||||||
* ```stc12a``` STC12Cx052AD and possibly others
|
* ```stc12a``` STC12x052 series and possibly others
|
||||||
* ```stc12``` Most STC10/11/12 series (default)
|
* ```stc12b``` STC12x52 series, STC12x56 series and possibly others
|
||||||
|
* ```stc12``` Most STC10/11/12 series
|
||||||
* ```stc15a``` STC15x104E and STC15x204E(A) series
|
* ```stc15a``` STC15x104E and STC15x204E(A) series
|
||||||
* ```stc15``` Most STC15 series
|
* ```stc15``` Most STC15 series
|
||||||
* ```usb15``` USB support on STC15W4 series
|
* ```usb15``` USB support on STC15W4 series
|
||||||
* ```auto``` Automatic detection of UART based protocols
|
* ```auto``` Automatic detection of UART based protocols (default)
|
||||||
|
|
||||||
The text files in the doc/ subdirectory provide an overview over
|
The text files in the doc/ subdirectory provide an overview over
|
||||||
the reverse engineered protocols used by the BSLs. For more details,
|
the reverse engineered protocols used by the BSLs. For more details,
|
||||||
@ -273,7 +279,22 @@ serial interface to automate this. The DTR signal is asserted for
|
|||||||
approximately 500 ms when the autoreset feature is enabled with the
|
approximately 500 ms when the autoreset feature is enabled with the
|
||||||
```-a``` flag. This requires external circuitry to actually switch the
|
```-a``` flag. This requires external circuitry to actually switch the
|
||||||
power. In some cases, when the microcontroller draws only little power,
|
power. In some cases, when the microcontroller draws only little power,
|
||||||
it is possible to directly supply power from the DTR signal, however.
|
it is possible to directly supply power from the DTR signal.
|
||||||
|
|
||||||
|
As an alternative to DTR, you can use a custom shell command or an external
|
||||||
|
script (via -r option) to reset the device. You should specify the command
|
||||||
|
along with -a option. Do not forget the quotes!
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./stcgal.py -P stc15 -a -r "echo 1 > /sys/class/gpio/gpio666/value"
|
||||||
|
```
|
||||||
|
or
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./stcgal.py -P stc15 -a -r "./powercycle.sh"
|
||||||
|
```
|
||||||
|
|
||||||
### Exit status
|
### Exit status
|
||||||
|
|
||||||
|
19
debian/changelog
vendored
19
debian/changelog
vendored
@ -1,3 +1,22 @@
|
|||||||
|
stcgal (1.4) unstable; urgency=low
|
||||||
|
|
||||||
|
* Update to 1.4
|
||||||
|
|
||||||
|
-- Grigori <greg@chown.ath.cx> Tue, 19 Sep 2017 17:57:11 +0200
|
||||||
|
|
||||||
|
stcgal (1.3) unstable; urgency=low
|
||||||
|
|
||||||
|
* Update to 1.3
|
||||||
|
|
||||||
|
-- Grigori Goronzy <greg@chown.ath.cx> Sat, 10 Jun 2017 10:01:07 +0200
|
||||||
|
|
||||||
|
stcgal (1.2) unstable; urgency=low
|
||||||
|
|
||||||
|
* Update to 1.2
|
||||||
|
* Add optional python3-usb dependency
|
||||||
|
|
||||||
|
-- Grigori Goronzy <greg@chown.ath.cx> Fri, 20 May 2016 03:21:25 +0200
|
||||||
|
|
||||||
stcgal (1.0git) unstable; urgency=low
|
stcgal (1.0git) unstable; urgency=low
|
||||||
|
|
||||||
* Initial Debianized Release
|
* Initial Debianized Release
|
||||||
|
18
debian/control
vendored
18
debian/control
vendored
@ -10,17 +10,17 @@ X-Python3-Version: >= 3.2
|
|||||||
Package: stcgal
|
Package: stcgal
|
||||||
Architecture: all
|
Architecture: all
|
||||||
Depends: ${misc:Depends}, python3, python3-serial
|
Depends: ${misc:Depends}, python3, python3-serial
|
||||||
|
Recommends: python3-usb (>= 1.0.0~b2)
|
||||||
Description: STC MCU ISP flash tool
|
Description: STC MCU ISP flash tool
|
||||||
stcgal is a command line flash programming tool for STC MCU Ltd. 8051
|
stcgal is a command line flash programming tool for STC MCU Ltd.
|
||||||
compatible microcontrollers. The name was inspired by avrdude.
|
8051 compatible microcontrollers. The name was inspired by avrdude.
|
||||||
.
|
.
|
||||||
STC microcontrollers have a UART based boot strap loader (BSL). It
|
STC microcontrollers have an UART/USB based boot strap loader (BSL). It
|
||||||
utilizes a packet-based protocol to flash the code memory and
|
utilizes a packet-based protocol to flash the code memory and IAP
|
||||||
IAP memory over a serial link. This is referred to as in-system
|
memory over a serial link. This is referred to as in-system programming
|
||||||
programming (ISP). The BSL is also used to configure various
|
(ISP). The BSL is also used to configure various (fuse-like) device
|
||||||
(fuse-like) device options. Unfortunately, this protocol is not
|
options. Unfortunately, this protocol is not publicly documented and
|
||||||
publicly documented and STC only provide a (crude) Windows GUI
|
STC only provide a (crude) Windows GUI application for programming.
|
||||||
application for programming.
|
|
||||||
.
|
.
|
||||||
stcgal is a full-featured Open Source replacement for STC's Windows
|
stcgal is a full-featured Open Source replacement for STC's Windows
|
||||||
software; it supports a wide range of MCUs, it is very portable and
|
software; it supports a wide range of MCUs, it is very portable and
|
||||||
|
46
doc/stc15-usb-protocol.txt
Normal file
46
doc/stc15-usb-protocol.txt
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
STC15 series USB ISP protocol
|
||||||
|
=============================
|
||||||
|
|
||||||
|
General principle
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
- host does OUT and IN control transfers for write and read
|
||||||
|
- IN transfer with wLength = 132, wValue = 0, wIndex = 0, bRequest = 0 are used for all reads
|
||||||
|
- OUT transfers with with specific bRequest, wValue, wIndex are used for writes
|
||||||
|
|
||||||
|
|
||||||
|
Packet coding
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- packets from MCU
|
||||||
|
always start with 0x46 0xb9, similar to serial protocols
|
||||||
|
third byte is packet length, followed by data bytes
|
||||||
|
checksum at the end: 8 bit modular sum
|
||||||
|
|
||||||
|
- packets from host
|
||||||
|
no header bytes
|
||||||
|
bRequest sets packet type
|
||||||
|
wValue, wIndex interpretation according to packet type
|
||||||
|
8 bit modular checksum for every 7 bytes, interleaved
|
||||||
|
|
||||||
|
- packet types derived from the serial protocol
|
||||||
|
|
||||||
|
Specific packet information
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
- flash data
|
||||||
|
wIndex specifies write address
|
||||||
|
wValue is 0xa55a
|
||||||
|
bRequest is 0x22 for first packet, 0x02 for the following ones
|
||||||
|
unusually encoded: a total of 128 bytes per packet,
|
||||||
|
with every 7 byte checksummed in some way,
|
||||||
|
for a total of 18x7 byte segments and a final 2 byte segment
|
||||||
|
checksum: 8 bit modular sum
|
||||||
|
|
||||||
|
- option packet
|
||||||
|
generally same as with serial protocol, some header stuff omitted
|
||||||
|
wIndex is 0
|
||||||
|
wValue is 0xa55a
|
||||||
|
bRequest is 4
|
||||||
|
seems to use the same checksumming scheme as flash writes
|
||||||
|
|
4
setup.py
4
setup.py
@ -27,7 +27,7 @@ from setuptools import setup, find_packages
|
|||||||
setup(
|
setup(
|
||||||
name = "stcgal",
|
name = "stcgal",
|
||||||
version = stcgal.__version__,
|
version = stcgal.__version__,
|
||||||
packages = find_packages(exclude=["doc"]),
|
packages = find_packages(exclude=["doc", "test"]),
|
||||||
install_requires = ["pyserial"],
|
install_requires = ["pyserial"],
|
||||||
extras_require = {
|
extras_require = {
|
||||||
"usb": ["pyusb>=1.0.0"]
|
"usb": ["pyusb>=1.0.0"]
|
||||||
@ -55,4 +55,6 @@ setup(
|
|||||||
"Topic :: Software Development :: Embedded Systems",
|
"Topic :: Software Development :: Embedded Systems",
|
||||||
"Topic :: Software Development",
|
"Topic :: Software Development",
|
||||||
],
|
],
|
||||||
|
test_suite = "test",
|
||||||
|
tests_require = ["PyYAML"],
|
||||||
)
|
)
|
||||||
|
@ -1 +1 @@
|
|||||||
__version__ = "1.0"
|
__version__ = "1.4"
|
||||||
|
27
stcgal/__main__.py
Executable file
27
stcgal/__main__.py
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2013-2015 Grigori Goronzy <greg@chown.ath.cx>
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import stcgal.frontend
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(stcgal.frontend.cli())
|
@ -20,10 +20,10 @@
|
|||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
#
|
#
|
||||||
|
|
||||||
import sys, os, time, struct
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
import stcgal
|
import stcgal
|
||||||
from stcgal.utils import Utils, BaudType
|
from stcgal.utils import BaudType
|
||||||
from stcgal.protocols import *
|
from stcgal.protocols import *
|
||||||
from stcgal.ihex import IHex
|
from stcgal.ihex import IHex
|
||||||
|
|
||||||
@ -37,6 +37,8 @@ class StcGal:
|
|||||||
self.protocol = Stc89Protocol(opts.port, opts.handshake, opts.baud)
|
self.protocol = Stc89Protocol(opts.port, opts.handshake, opts.baud)
|
||||||
elif opts.protocol == "stc12a":
|
elif opts.protocol == "stc12a":
|
||||||
self.protocol = Stc12AProtocol(opts.port, opts.handshake, opts.baud)
|
self.protocol = Stc12AProtocol(opts.port, opts.handshake, opts.baud)
|
||||||
|
elif opts.protocol == "stc12b":
|
||||||
|
self.protocol = Stc12BProtocol(opts.port, opts.handshake, opts.baud)
|
||||||
elif opts.protocol == "stc12":
|
elif opts.protocol == "stc12":
|
||||||
self.protocol = Stc12Protocol(opts.port, opts.handshake, opts.baud)
|
self.protocol = Stc12Protocol(opts.port, opts.handshake, opts.baud)
|
||||||
elif opts.protocol == "stc15a":
|
elif opts.protocol == "stc15a":
|
||||||
@ -53,13 +55,16 @@ class StcGal:
|
|||||||
self.protocol.debug = opts.debug
|
self.protocol.debug = opts.debug
|
||||||
|
|
||||||
def emit_options(self, options):
|
def emit_options(self, options):
|
||||||
for o in options:
|
"""Set options from command line to protocol handler."""
|
||||||
|
|
||||||
|
for opt in options:
|
||||||
try:
|
try:
|
||||||
kv = o.split("=", 1)
|
kv = opt.split("=", 1)
|
||||||
if len(kv) < 2: raise ValueError("incorrect format")
|
if len(kv) < 2:
|
||||||
|
raise ValueError("incorrect format")
|
||||||
self.protocol.set_option(kv[0], kv[1])
|
self.protocol.set_option(kv[0], kv[1])
|
||||||
except ValueError as e:
|
except ValueError as ex:
|
||||||
raise NameError("invalid option '%s' (%s)" % (kv[0], e))
|
raise NameError("invalid option '%s' (%s)" % (kv[0], ex))
|
||||||
|
|
||||||
def load_file_auto(self, fileobj):
|
def load_file_auto(self, fileobj):
|
||||||
"""Load file with Intel Hex autodetection."""
|
"""Load file with Intel Hex autodetection."""
|
||||||
@ -72,14 +77,16 @@ class StcGal:
|
|||||||
binary = hexfile.extract_data()
|
binary = hexfile.extract_data()
|
||||||
print("%d bytes (Intel HEX)" %len(binary))
|
print("%d bytes (Intel HEX)" %len(binary))
|
||||||
return binary
|
return binary
|
||||||
except ValueError as e:
|
except ValueError as ex:
|
||||||
raise IOError("invalid Intel HEX file (%s)" %e)
|
raise IOError("invalid Intel HEX file (%s)" %ex)
|
||||||
else:
|
else:
|
||||||
binary = fileobj.read()
|
binary = fileobj.read()
|
||||||
print("%d bytes (Binary)" %len(binary))
|
print("%d bytes (Binary)" %len(binary))
|
||||||
return binary
|
return binary
|
||||||
|
|
||||||
def program_mcu(self):
|
def program_mcu(self):
|
||||||
|
"""Execute the standard programming flow."""
|
||||||
|
|
||||||
code_size = self.protocol.model.code
|
code_size = self.protocol.model.code
|
||||||
ee_size = self.protocol.model.eeprom
|
ee_size = self.protocol.model.eeprom
|
||||||
|
|
||||||
@ -122,9 +129,10 @@ class StcGal:
|
|||||||
self.protocol.disconnect()
|
self.protocol.disconnect()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
"""Run programmer, main entry point."""
|
||||||
self.protocol.connect(autoreset=self.opts.autoreset)
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.protocol.connect(autoreset=self.opts.autoreset, resetcmd=self.opts.resetcmd)
|
||||||
if self.opts.protocol == "auto":
|
if self.opts.protocol == "auto":
|
||||||
if not self.protocol.protocol_name:
|
if not self.protocol.protocol_name:
|
||||||
raise StcProtocolException("cannot detect protocol")
|
raise StcProtocolException("cannot detect protocol")
|
||||||
@ -138,21 +146,21 @@ class StcGal:
|
|||||||
|
|
||||||
self.protocol.initialize(base_protocol)
|
self.protocol.initialize(base_protocol)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sys.stdout.flush();
|
sys.stdout.flush()
|
||||||
print("interrupted")
|
print("interrupted")
|
||||||
return 2
|
return 2
|
||||||
except (StcFramingException, StcProtocolException) as e:
|
except (StcFramingException, StcProtocolException) as ex:
|
||||||
sys.stdout.flush();
|
sys.stdout.flush()
|
||||||
print("Protocol error: %s" % e, file=sys.stderr)
|
print("Protocol error: %s" % ex, file=sys.stderr)
|
||||||
self.protocol.disconnect()
|
self.protocol.disconnect()
|
||||||
return 1
|
return 1
|
||||||
except serial.SerialException as e:
|
except serial.SerialException as ex:
|
||||||
sys.stdout.flush();
|
sys.stdout.flush()
|
||||||
print("Serial port error: %s" % e, file=sys.stderr)
|
print("Serial port error: %s" % ex, file=sys.stderr)
|
||||||
return 1
|
return 1
|
||||||
except IOError as e:
|
except IOError as ex:
|
||||||
sys.stdout.flush();
|
sys.stdout.flush()
|
||||||
print("I/O error: %s" % e, file=sys.stderr)
|
print("I/O error: %s" % ex, file=sys.stderr)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -162,27 +170,27 @@ class StcGal:
|
|||||||
else:
|
else:
|
||||||
self.protocol.disconnect()
|
self.protocol.disconnect()
|
||||||
return 0
|
return 0
|
||||||
except NameError as e:
|
except NameError as ex:
|
||||||
sys.stdout.flush();
|
sys.stdout.flush()
|
||||||
print("Option error: %s" % e, file=sys.stderr)
|
print("Option error: %s" % ex, file=sys.stderr)
|
||||||
self.protocol.disconnect()
|
self.protocol.disconnect()
|
||||||
return 1
|
return 1
|
||||||
except (StcFramingException, StcProtocolException) as e:
|
except (StcFramingException, StcProtocolException) as ex:
|
||||||
sys.stdout.flush();
|
sys.stdout.flush()
|
||||||
print("Protocol error: %s" % e, file=sys.stderr)
|
print("Protocol error: %s" % ex, file=sys.stderr)
|
||||||
self.protocol.disconnect()
|
self.protocol.disconnect()
|
||||||
return 1
|
return 1
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sys.stdout.flush();
|
sys.stdout.flush()
|
||||||
print("interrupted", file=sys.stderr)
|
print("interrupted", file=sys.stderr)
|
||||||
self.protocol.disconnect()
|
self.protocol.disconnect()
|
||||||
return 2
|
return 2
|
||||||
except serial.SerialException as e:
|
except serial.SerialException as ex:
|
||||||
print("Serial port error: %s" % e, file=sys.stderr)
|
print("Serial port error: %s" % ex, file=sys.stderr)
|
||||||
return 1
|
return 1
|
||||||
except IOError as e:
|
except IOError as ex:
|
||||||
sys.stdout.flush();
|
sys.stdout.flush()
|
||||||
print("I/O error: %s" % e, file=sys.stderr)
|
print("I/O error: %s" % ex, file=sys.stderr)
|
||||||
self.protocol.disconnect()
|
self.protocol.disconnect()
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
@ -190,11 +198,12 @@ class StcGal:
|
|||||||
def cli():
|
def cli():
|
||||||
# check arguments
|
# check arguments
|
||||||
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
|
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
description="stcgal %s - an STC MCU ISP flash tool\n(C) 2014-2015 Grigori Goronzy\nhttps://github.com/grigorig/stcgal" %stcgal.__version__)
|
description="stcgal %s - an STC MCU ISP flash tool\n(C) 2014-2017 Grigori Goronzy\nhttps://github.com/grigorig/stcgal" %stcgal.__version__)
|
||||||
parser.add_argument("code_image", help="code segment file to flash (BIN/HEX)", type=argparse.FileType("rb"), nargs='?')
|
parser.add_argument("code_image", help="code segment file to flash (BIN/HEX)", type=argparse.FileType("rb"), nargs='?')
|
||||||
parser.add_argument("eeprom_image", help="eeprom segment file to flash (BIN/HEX)", type=argparse.FileType("rb"), nargs='?')
|
parser.add_argument("eeprom_image", help="eeprom segment file to flash (BIN/HEX)", type=argparse.FileType("rb"), nargs='?')
|
||||||
parser.add_argument("-a", "--autoreset", help="cycle power automatically by asserting DTR", action="store_true")
|
parser.add_argument("-a", "--autoreset", help="cycle power automatically by asserting DTR", action="store_true")
|
||||||
parser.add_argument("-P", "--protocol", help="protocol version", choices=["stc89", "stc12a", "stc12", "stc15a", "stc15", "usb15", "auto"], default="stc12")
|
parser.add_argument("-r", "--resetcmd", help="Use this shell command for board power-cycling (instead of DTR assertion)", action="store")
|
||||||
|
parser.add_argument("-P", "--protocol", help="protocol version (default: auto)", choices=["stc89", "stc12a", "stc12b", "stc12", "stc15a", "stc15", "usb15", "auto"], default="auto")
|
||||||
parser.add_argument("-p", "--port", help="serial port device", default="/dev/ttyUSB0")
|
parser.add_argument("-p", "--port", help="serial port device", default="/dev/ttyUSB0")
|
||||||
parser.add_argument("-b", "--baud", help="transfer baud rate (default: 19200)", type=BaudType(), default=19200)
|
parser.add_argument("-b", "--baud", help="transfer baud rate (default: 19200)", type=BaudType(), default=19200)
|
||||||
parser.add_argument("-l", "--handshake", help="handshake baud rate (default: 2400)", type=BaudType(), default=2400)
|
parser.add_argument("-l", "--handshake", help="handshake baud rate (default: 2400)", type=BaudType(), default=2400)
|
||||||
|
@ -973,6 +973,46 @@ class MCUModelDatabase:
|
|||||||
MCUModel(name='STC90LE513AD', magic=0xf18d, total=65536, code=53248, eeprom=10240),
|
MCUModel(name='STC90LE513AD', magic=0xf18d, total=65536, code=53248, eeprom=10240),
|
||||||
MCUModel(name='STC90LE514AD', magic=0xf18e, total=65536, code=57344, eeprom=6144),
|
MCUModel(name='STC90LE514AD', magic=0xf18e, total=65536, code=57344, eeprom=6144),
|
||||||
MCUModel(name='STC90LE516AD', magic=0xf190, total=65536, code=63488, eeprom=0),
|
MCUModel(name='STC90LE516AD', magic=0xf190, total=65536, code=63488, eeprom=0),
|
||||||
|
|
||||||
|
# Warning, these definitions lack a valid eeprom size.
|
||||||
|
MCUModel(name='STC15F04AD', magic=0xd444, total=4096, code=4096, eeprom=0),
|
||||||
|
MCUModel(name='STC15F06AD', magic=0xd446, total=6144, code=6144, eeprom=0),
|
||||||
|
MCUModel(name='STC15F08AD', magic=0xd448, total=8192, code=8192, eeprom=0),
|
||||||
|
MCUModel(name='STC15F10AD', magic=0xd44a, total=10240, code=10240, eeprom=0),
|
||||||
|
MCUModel(name='STC15F12AD', magic=0xd44c, total=12288, code=12288, eeprom=0),
|
||||||
|
MCUModel(name='STC15F04CCP', magic=0xd434, total=4096, code=4096, eeprom=0),
|
||||||
|
MCUModel(name='STC15F06CCP', magic=0xd436, total=6144, code=6144, eeprom=0),
|
||||||
|
MCUModel(name='STC15F08CCP', magic=0xd438, total=8192, code=8192, eeprom=0),
|
||||||
|
MCUModel(name='STC15F10CCP', magic=0xd43a, total=10240, code=10240, eeprom=0),
|
||||||
|
MCUModel(name='STC15F12CCP', magic=0xd43c, total=12288, code=12288, eeprom=0),
|
||||||
|
MCUModel(name='STC15F04', magic=0xd404, total=4096, code=4096, eeprom=0),
|
||||||
|
MCUModel(name='STC15F06', magic=0xd406, total=6144, code=6144, eeprom=0),
|
||||||
|
MCUModel(name='STC15F08', magic=0xd408, total=8192, code=8192, eeprom=0),
|
||||||
|
MCUModel(name='STC15F10', magic=0xd40a, total=10240, code=10240, eeprom=0),
|
||||||
|
MCUModel(name='STC15F12', magic=0xd40c, total=12288, code=12288, eeprom=0),
|
||||||
|
MCUModel(name='IAP15F08AD', magic=0xd458, total=8192, code=8192, eeprom=0),
|
||||||
|
MCUModel(name='IAP15F10AD', magic=0xd45a, total=10240, code=10240, eeprom=0),
|
||||||
|
MCUModel(name='IAP15F12AD', magic=0xd45c, total=12288, code=12288, eeprom=0),
|
||||||
|
MCUModel(name='IAP15F14AD', magic=0xd45e, total=14336, code=14336, eeprom=0),
|
||||||
|
MCUModel(name='STC15L04AD', magic=0xd4c4, total=4096, code=4096, eeprom=0),
|
||||||
|
MCUModel(name='STC15L06AD', magic=0xd4c6, total=6144, code=6144, eeprom=0),
|
||||||
|
MCUModel(name='STC15L08AD', magic=0xd4c8, total=8192, code=8192, eeprom=0),
|
||||||
|
MCUModel(name='STC15L10AD', magic=0xd4ca, total=10240, code=10240, eeprom=0),
|
||||||
|
MCUModel(name='STC15L12AD', magic=0xd4cc, total=12288, code=12288, eeprom=0),
|
||||||
|
MCUModel(name='STC15L04CCP', magic=0xd4b4, total=4096, code=4096, eeprom=0),
|
||||||
|
MCUModel(name='STC15L06CCP', magic=0xd4b6, total=6144, code=6144, eeprom=0),
|
||||||
|
MCUModel(name='STC15L08CCP', magic=0xd4b8, total=8192, code=8192, eeprom=0),
|
||||||
|
MCUModel(name='STC15L10CCP', magic=0xd4ba, total=10240, code=10240, eeprom=0),
|
||||||
|
MCUModel(name='STC15L12CCP', magic=0xd4bc, total=12288, code=12288, eeprom=0),
|
||||||
|
MCUModel(name='STC15L04', magic=0xd484, total=4096, code=4096, eeprom=0),
|
||||||
|
MCUModel(name='STC15L06', magic=0xd486, total=6144, code=6144, eeprom=0),
|
||||||
|
MCUModel(name='STC15L08', magic=0xd488, total=8192, code=8192, eeprom=0),
|
||||||
|
MCUModel(name='STC15L10', magic=0xd48a, total=10240, code=10240, eeprom=0),
|
||||||
|
MCUModel(name='STC15L12', magic=0xd48c, total=12288, code=12288, eeprom=0),
|
||||||
|
MCUModel(name='IAP15L08AD', magic=0xd4d8, total=8192, code=8192, eeprom=0),
|
||||||
|
MCUModel(name='IAP15L10AD', magic=0xd4da, total=10240, code=10240, eeprom=0),
|
||||||
|
MCUModel(name='IAP15L12AD', magic=0xd4dc, total=12288, code=12288, eeprom=0),
|
||||||
|
MCUModel(name='IAP15L14AD', magic=0xd4de, total=14336, code=14336, eeprom=0),
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -988,6 +1028,3 @@ class MCUModelDatabase:
|
|||||||
print(" Magic: %02X%02X" % (model.magic >> 8, model.magic & 0xff))
|
print(" Magic: %02X%02X" % (model.magic >> 8, model.magic & 0xff))
|
||||||
print(" Code flash: %.1f KB" % (model.code / 1024.0))
|
print(" Code flash: %.1f KB" % (model.code / 1024.0))
|
||||||
print(" EEPROM flash: %.1f KB" % (model.eeprom / 1024.0))
|
print(" EEPROM flash: %.1f KB" % (model.eeprom / 1024.0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ class Stc89Option(BaseOption):
|
|||||||
return not bool(self.msr & 1)
|
return not bool(self.msr & 1)
|
||||||
|
|
||||||
def set_t6(self, val):
|
def set_t6(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr &= 0xfe
|
self.msr &= 0xfe
|
||||||
self.msr |= 0x01 if not bool(val) else 0x00
|
self.msr |= 0x01 if not bool(val) else 0x00
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ class Stc89Option(BaseOption):
|
|||||||
return not bool(self.msr & 4)
|
return not bool(self.msr & 4)
|
||||||
|
|
||||||
def set_pindetect(self, val):
|
def set_pindetect(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr &= 0xfb
|
self.msr &= 0xfb
|
||||||
self.msr |= 0x04 if not bool(val) else 0x00
|
self.msr |= 0x04 if not bool(val) else 0x00
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ class Stc89Option(BaseOption):
|
|||||||
return not bool(self.msr & 8)
|
return not bool(self.msr & 8)
|
||||||
|
|
||||||
def set_ee_erase(self, val):
|
def set_ee_erase(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr &= 0xf7
|
self.msr &= 0xf7
|
||||||
self.msr |= 0x08 if not bool(val) else 0x00
|
self.msr |= 0x08 if not bool(val) else 0x00
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ class Stc89Option(BaseOption):
|
|||||||
return bool(self.msr & 32)
|
return bool(self.msr & 32)
|
||||||
|
|
||||||
def set_ale(self, val):
|
def set_ale(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr &= 0xdf
|
self.msr &= 0xdf
|
||||||
self.msr |= 0x20 if bool(val) else 0x00
|
self.msr |= 0x20 if bool(val) else 0x00
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ class Stc89Option(BaseOption):
|
|||||||
return bool(self.msr & 64)
|
return bool(self.msr & 64)
|
||||||
|
|
||||||
def set_xram(self, val):
|
def set_xram(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr &= 0xbf
|
self.msr &= 0xbf
|
||||||
self.msr |= 0x40 if bool(val) else 0x00
|
self.msr |= 0x40 if bool(val) else 0x00
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ class Stc89Option(BaseOption):
|
|||||||
return not bool(self.msr & 128)
|
return not bool(self.msr & 128)
|
||||||
|
|
||||||
def set_watchdog(self, val):
|
def set_watchdog(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr &= 0x7f
|
self.msr &= 0x7f
|
||||||
self.msr |= 0x80 if not bool(val) else 0x00
|
self.msr |= 0x80 if not bool(val) else 0x00
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ class Stc12AOption(BaseOption):
|
|||||||
def set_low_voltage_detect(self, val):
|
def set_low_voltage_detect(self, val):
|
||||||
lvds = {"low": 1, "high": 0}
|
lvds = {"low": 1, "high": 0}
|
||||||
if val not in lvds.keys():
|
if val not in lvds.keys():
|
||||||
raise ValueError("must be one of %s" % list(sources.keys()))
|
raise ValueError("must be one of %s" % list(lvds.keys()))
|
||||||
self.msr[3] &= 0xbf
|
self.msr[3] &= 0xbf
|
||||||
self.msr[3] |= lvds[val] << 6
|
self.msr[3] |= lvds[val] << 6
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ class Stc12AOption(BaseOption):
|
|||||||
return not bool(self.msr[1] & 32)
|
return not bool(self.msr[1] & 32)
|
||||||
|
|
||||||
def set_watchdog(self, val):
|
def set_watchdog(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[1] &= 0xdf
|
self.msr[1] &= 0xdf
|
||||||
self.msr[1] |= 0x20 if not val else 0x00
|
self.msr[1] |= 0x20 if not val else 0x00
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ class Stc12AOption(BaseOption):
|
|||||||
return not bool(self.msr[1] & 8)
|
return not bool(self.msr[1] & 8)
|
||||||
|
|
||||||
def set_watchdog_idle(self, val):
|
def set_watchdog_idle(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[1] &= 0xf7
|
self.msr[1] &= 0xf7
|
||||||
self.msr[1] |= 0x08 if not val else 0x00
|
self.msr[1] |= 0x08 if not val else 0x00
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ class Stc12AOption(BaseOption):
|
|||||||
return not bool(self.msr[2] & 2)
|
return not bool(self.msr[2] & 2)
|
||||||
|
|
||||||
def set_ee_erase(self, val):
|
def set_ee_erase(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[2] &= 0xfd
|
self.msr[2] &= 0xfd
|
||||||
self.msr[2] |= 0x02 if not val else 0x00
|
self.msr[2] |= 0x02 if not val else 0x00
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ class Stc12AOption(BaseOption):
|
|||||||
return not bool(self.msr[2] & 1)
|
return not bool(self.msr[2] & 1)
|
||||||
|
|
||||||
def set_pindetect(self, val):
|
def set_pindetect(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[2] &= 0xfe
|
self.msr[2] &= 0xfe
|
||||||
self.msr[2] |= 0x01 if not val else 0x00
|
self.msr[2] |= 0x01 if not val else 0x00
|
||||||
|
|
||||||
@ -235,7 +235,7 @@ class Stc12Option(BaseOption):
|
|||||||
return bool(self.msr[0] & 1)
|
return bool(self.msr[0] & 1)
|
||||||
|
|
||||||
def set_reset_pin_enabled(self, val):
|
def set_reset_pin_enabled(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[0] &= 0xfe
|
self.msr[0] &= 0xfe
|
||||||
self.msr[0] |= 0x01 if bool(val) else 0x00
|
self.msr[0] |= 0x01 if bool(val) else 0x00
|
||||||
|
|
||||||
@ -243,7 +243,7 @@ class Stc12Option(BaseOption):
|
|||||||
return not bool(self.msr[0] & 64)
|
return not bool(self.msr[0] & 64)
|
||||||
|
|
||||||
def set_low_voltage_detect(self, val):
|
def set_low_voltage_detect(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[0] &= 0xbf
|
self.msr[0] &= 0xbf
|
||||||
self.msr[0] |= 0x40 if not val else 0x00
|
self.msr[0] |= 0x40 if not val else 0x00
|
||||||
|
|
||||||
@ -295,7 +295,7 @@ class Stc12Option(BaseOption):
|
|||||||
return not bool(self.msr[2] & 32)
|
return not bool(self.msr[2] & 32)
|
||||||
|
|
||||||
def set_watchdog(self, val):
|
def set_watchdog(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[2] &= 0xdf
|
self.msr[2] &= 0xdf
|
||||||
self.msr[2] |= 0x20 if not val else 0x00
|
self.msr[2] |= 0x20 if not val else 0x00
|
||||||
|
|
||||||
@ -303,7 +303,7 @@ class Stc12Option(BaseOption):
|
|||||||
return not bool(self.msr[2] & 8)
|
return not bool(self.msr[2] & 8)
|
||||||
|
|
||||||
def set_watchdog_idle(self, val):
|
def set_watchdog_idle(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[2] &= 0xf7
|
self.msr[2] &= 0xf7
|
||||||
self.msr[2] |= 0x08 if not val else 0x00
|
self.msr[2] |= 0x08 if not val else 0x00
|
||||||
|
|
||||||
@ -322,7 +322,7 @@ class Stc12Option(BaseOption):
|
|||||||
return not bool(self.msr[3] & 2)
|
return not bool(self.msr[3] & 2)
|
||||||
|
|
||||||
def set_ee_erase(self, val):
|
def set_ee_erase(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[3] &= 0xfd
|
self.msr[3] &= 0xfd
|
||||||
self.msr[3] |= 0x02 if not val else 0x00
|
self.msr[3] |= 0x02 if not val else 0x00
|
||||||
|
|
||||||
@ -330,7 +330,7 @@ class Stc12Option(BaseOption):
|
|||||||
return not bool(self.msr[3] & 1)
|
return not bool(self.msr[3] & 1)
|
||||||
|
|
||||||
def set_pindetect(self, val):
|
def set_pindetect(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[3] &= 0xfe
|
self.msr[3] &= 0xfe
|
||||||
self.msr[3] |= 0x01 if not val else 0x00
|
self.msr[3] |= 0x01 if not val else 0x00
|
||||||
|
|
||||||
@ -359,7 +359,7 @@ class Stc15AOption(BaseOption):
|
|||||||
return bool(self.msr[0] & 16)
|
return bool(self.msr[0] & 16)
|
||||||
|
|
||||||
def set_reset_pin_enabled(self, val):
|
def set_reset_pin_enabled(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[0] &= 0xef
|
self.msr[0] &= 0xef
|
||||||
self.msr[0] |= 0x10 if bool(val) else 0x00
|
self.msr[0] |= 0x10 if bool(val) else 0x00
|
||||||
|
|
||||||
@ -367,7 +367,7 @@ class Stc15AOption(BaseOption):
|
|||||||
return not bool(self.msr[2] & 32)
|
return not bool(self.msr[2] & 32)
|
||||||
|
|
||||||
def set_watchdog(self, val):
|
def set_watchdog(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[2] &= 0xdf
|
self.msr[2] &= 0xdf
|
||||||
self.msr[2] |= 0x20 if not val else 0x00
|
self.msr[2] |= 0x20 if not val else 0x00
|
||||||
|
|
||||||
@ -375,7 +375,7 @@ class Stc15AOption(BaseOption):
|
|||||||
return not bool(self.msr[2] & 8)
|
return not bool(self.msr[2] & 8)
|
||||||
|
|
||||||
def set_watchdog_idle(self, val):
|
def set_watchdog_idle(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[2] &= 0xf7
|
self.msr[2] &= 0xf7
|
||||||
self.msr[2] |= 0x08 if not val else 0x00
|
self.msr[2] |= 0x08 if not val else 0x00
|
||||||
|
|
||||||
@ -394,7 +394,7 @@ class Stc15AOption(BaseOption):
|
|||||||
return bool(self.msr[1] & 64)
|
return bool(self.msr[1] & 64)
|
||||||
|
|
||||||
def set_lvrs(self, val):
|
def set_lvrs(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[1] &= 0xbf
|
self.msr[1] &= 0xbf
|
||||||
self.msr[1] |= 0x40 if val else 0x00
|
self.msr[1] |= 0x40 if val else 0x00
|
||||||
|
|
||||||
@ -402,7 +402,7 @@ class Stc15AOption(BaseOption):
|
|||||||
return bool(self.msr[1] & 128)
|
return bool(self.msr[1] & 128)
|
||||||
|
|
||||||
def set_eeprom_lvd(self, val):
|
def set_eeprom_lvd(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[1] &= 0x7f
|
self.msr[1] &= 0x7f
|
||||||
self.msr[1] |= 0x80 if val else 0x00
|
self.msr[1] |= 0x80 if val else 0x00
|
||||||
|
|
||||||
@ -420,7 +420,7 @@ class Stc15AOption(BaseOption):
|
|||||||
return not bool(self.msr[12] & 2)
|
return not bool(self.msr[12] & 2)
|
||||||
|
|
||||||
def set_ee_erase(self, val):
|
def set_ee_erase(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[12] &= 0xfd
|
self.msr[12] &= 0xfd
|
||||||
self.msr[12] |= 0x02 if not val else 0x00
|
self.msr[12] |= 0x02 if not val else 0x00
|
||||||
|
|
||||||
@ -428,7 +428,7 @@ class Stc15AOption(BaseOption):
|
|||||||
return not bool(self.msr[12] & 1)
|
return not bool(self.msr[12] & 1)
|
||||||
|
|
||||||
def set_pindetect(self, val):
|
def set_pindetect(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[12] &= 0xfe
|
self.msr[12] &= 0xfe
|
||||||
self.msr[12] |= 0x01 if not val else 0x00
|
self.msr[12] |= 0x01 if not val else 0x00
|
||||||
|
|
||||||
@ -463,7 +463,7 @@ class Stc15Option(BaseOption):
|
|||||||
return not bool(self.msr[2] & 16)
|
return not bool(self.msr[2] & 16)
|
||||||
|
|
||||||
def set_reset_pin_enabled(self, val):
|
def set_reset_pin_enabled(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[2] &= 0xef
|
self.msr[2] &= 0xef
|
||||||
self.msr[2] |= 0x10 if not bool(val) else 0x00
|
self.msr[2] |= 0x10 if not bool(val) else 0x00
|
||||||
|
|
||||||
@ -493,7 +493,7 @@ class Stc15Option(BaseOption):
|
|||||||
return not bool(self.msr[0] & 32)
|
return not bool(self.msr[0] & 32)
|
||||||
|
|
||||||
def set_watchdog(self, val):
|
def set_watchdog(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[0] &= 0xdf
|
self.msr[0] &= 0xdf
|
||||||
self.msr[0] |= 0x20 if not val else 0x00
|
self.msr[0] |= 0x20 if not val else 0x00
|
||||||
|
|
||||||
@ -501,7 +501,7 @@ class Stc15Option(BaseOption):
|
|||||||
return not bool(self.msr[0] & 8)
|
return not bool(self.msr[0] & 8)
|
||||||
|
|
||||||
def set_watchdog_idle(self, val):
|
def set_watchdog_idle(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[0] &= 0xf7
|
self.msr[0] &= 0xf7
|
||||||
self.msr[0] |= 0x08 if not val else 0x00
|
self.msr[0] |= 0x08 if not val else 0x00
|
||||||
|
|
||||||
@ -520,7 +520,7 @@ class Stc15Option(BaseOption):
|
|||||||
return not bool(self.msr[1] & 64)
|
return not bool(self.msr[1] & 64)
|
||||||
|
|
||||||
def set_lvrs(self, val):
|
def set_lvrs(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[1] &= 0xbf
|
self.msr[1] &= 0xbf
|
||||||
self.msr[1] |= 0x40 if not val else 0x00
|
self.msr[1] |= 0x40 if not val else 0x00
|
||||||
|
|
||||||
@ -528,7 +528,7 @@ class Stc15Option(BaseOption):
|
|||||||
return bool(self.msr[1] & 128)
|
return bool(self.msr[1] & 128)
|
||||||
|
|
||||||
def set_eeprom_lvd(self, val):
|
def set_eeprom_lvd(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[1] &= 0x7f
|
self.msr[1] &= 0x7f
|
||||||
self.msr[1] |= 0x80 if val else 0x00
|
self.msr[1] |= 0x80 if val else 0x00
|
||||||
|
|
||||||
@ -546,7 +546,7 @@ class Stc15Option(BaseOption):
|
|||||||
return bool(self.msr[3] & 2)
|
return bool(self.msr[3] & 2)
|
||||||
|
|
||||||
def set_ee_erase(self, val):
|
def set_ee_erase(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[3] &= 0xfd
|
self.msr[3] &= 0xfd
|
||||||
self.msr[3] |= 0x02 if val else 0x00
|
self.msr[3] |= 0x02 if val else 0x00
|
||||||
|
|
||||||
@ -554,7 +554,7 @@ class Stc15Option(BaseOption):
|
|||||||
return not bool(self.msr[3] & 1)
|
return not bool(self.msr[3] & 1)
|
||||||
|
|
||||||
def set_pindetect(self, val):
|
def set_pindetect(self, val):
|
||||||
val = Utils.to_bool(val);
|
val = Utils.to_bool(val)
|
||||||
self.msr[3] &= 0xfe
|
self.msr[3] &= 0xfe
|
||||||
self.msr[3] |= 0x01 if not val else 0x00
|
self.msr[3] |= 0x01 if not val else 0x00
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import serial
|
import serial
|
||||||
import sys, os, time, struct, re
|
import sys, os, time, struct, re, errno
|
||||||
import argparse
|
import argparse
|
||||||
import collections
|
import collections
|
||||||
from stcgal.models import MCUModelDatabase
|
from stcgal.models import MCUModelDatabase
|
||||||
@ -142,7 +142,7 @@ class StcBaseProtocol:
|
|||||||
packet += self.read_bytes_safe(packet_len - 3)
|
packet += self.read_bytes_safe(packet_len - 3)
|
||||||
|
|
||||||
# verify checksum and extract payload
|
# verify checksum and extract payload
|
||||||
payload = self.extract_payload(packet);
|
payload = self.extract_payload(packet)
|
||||||
|
|
||||||
self.dump_packet(packet, receive=True)
|
self.dump_packet(packet, receive=True)
|
||||||
|
|
||||||
@ -192,11 +192,12 @@ class StcBaseProtocol:
|
|||||||
mcu_name += "E" if self.status_packet[17] < 0x70 else "W"
|
mcu_name += "E" if self.status_packet[17] < 0x70 else "W"
|
||||||
self.model = self.model._replace(name = mcu_name)
|
self.model = self.model._replace(name = mcu_name)
|
||||||
|
|
||||||
protocol_database = [("stc89", "STC(89|90)(C|LE)\d"),
|
protocol_database = [("stc89", r"STC(89|90)(C|LE)\d"),
|
||||||
("stc12a", "STC12(C|LE)\d052"),
|
("stc12a", r"STC12(C|LE)\d052"),
|
||||||
("stc12", "(STC|IAP)(10|11|12)\D"),
|
("stc12b", r"STC12(C|LE)(52|56)"),
|
||||||
("stc15a", "(STC|IAP)15[FL][01]0\d(E|EA|)$"),
|
("stc12", r"(STC|IAP)(10|11|12)\D"),
|
||||||
("stc15", "(STC|IAP|IRC)15\D")]
|
("stc15a", r"(STC|IAP)15[FL][01]0\d(E|EA|)$"),
|
||||||
|
("stc15", r"(STC|IAP|IRC)15\D")]
|
||||||
|
|
||||||
for protocol_name, pattern in protocol_database:
|
for protocol_name, pattern in protocol_database:
|
||||||
if re.match(pattern, self.model.name):
|
if re.match(pattern, self.model.name):
|
||||||
@ -237,10 +238,39 @@ class StcBaseProtocol:
|
|||||||
|
|
||||||
return iap_wait
|
return iap_wait
|
||||||
|
|
||||||
|
def delay_safely_written(self, length):
|
||||||
|
"""
|
||||||
|
Delay until data has been safely written and sent to device.
|
||||||
|
Some buggy serial drivers don't implement tcdrain/flush correctly.
|
||||||
|
That is, they wait until all data has been written to USB, but they
|
||||||
|
do not wait until the data has actually finished transmission.
|
||||||
|
Add additional delay to work around.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bit_time = 1.0 / self.ser.baudrate
|
||||||
|
byte_time = bit_time * 11.0 # start, 8 data bits, stop, parity
|
||||||
|
clock_safety_factor = 2.5 # additional delay in case clock is slow
|
||||||
|
time.sleep(byte_time * length * clock_safety_factor)
|
||||||
|
|
||||||
def set_option(self, name, value):
|
def set_option(self, name, value):
|
||||||
self.options.set_option(name, value)
|
self.options.set_option(name, value)
|
||||||
|
|
||||||
def connect(self, autoreset=False):
|
def reset_device(self, resetcmd=False):
|
||||||
|
if not resetcmd:
|
||||||
|
print("Cycling power: ", end="")
|
||||||
|
sys.stdout.flush()
|
||||||
|
self.ser.setDTR(True)
|
||||||
|
time.sleep(0.5)
|
||||||
|
self.ser.setDTR(False)
|
||||||
|
print("done")
|
||||||
|
else:
|
||||||
|
print("Cycling power via shell cmd: " + resetcmd)
|
||||||
|
os.system(resetcmd)
|
||||||
|
|
||||||
|
print("Waiting for MCU: ", end="")
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
def connect(self, autoreset=False, resetcmd=False):
|
||||||
"""Connect to MCU and initialize communication.
|
"""Connect to MCU and initialize communication.
|
||||||
|
|
||||||
Set up serial port, send sync sequence and get part info.
|
Set up serial port, send sync sequence and get part info.
|
||||||
@ -259,14 +289,7 @@ class StcBaseProtocol:
|
|||||||
self.ser.flushInput()
|
self.ser.flushInput()
|
||||||
|
|
||||||
if autoreset:
|
if autoreset:
|
||||||
print("Cycling power: ", end="")
|
self.reset_device(resetcmd)
|
||||||
sys.stdout.flush()
|
|
||||||
self.ser.setDTR(True)
|
|
||||||
time.sleep(0.5)
|
|
||||||
self.ser.setDTR(False)
|
|
||||||
print("done")
|
|
||||||
print("Waiting for MCU: ", end="")
|
|
||||||
sys.stdout.flush()
|
|
||||||
else:
|
else:
|
||||||
print("Waiting for MCU, please cycle power: ", end="")
|
print("Waiting for MCU, please cycle power: ", end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
@ -439,7 +462,7 @@ class Stc89Protocol(StcBaseProtocol):
|
|||||||
packet += struct.pack(">H", brt)
|
packet += struct.pack(">H", brt)
|
||||||
packet += bytes([0xff - (brt >> 8), brt_csum, delay, iap])
|
packet += bytes([0xff - (brt >> 8), brt_csum, delay, iap])
|
||||||
self.write_packet(packet)
|
self.write_packet(packet)
|
||||||
time.sleep(0.2)
|
self.delay_safely_written(len(packet))
|
||||||
self.ser.baudrate = self.baud_transfer
|
self.ser.baudrate = self.baud_transfer
|
||||||
response = self.read_packet()
|
response = self.read_packet()
|
||||||
self.ser.baudrate = self.baud_handshake
|
self.ser.baudrate = self.baud_handshake
|
||||||
@ -453,7 +476,7 @@ class Stc89Protocol(StcBaseProtocol):
|
|||||||
packet += struct.pack(">H", brt)
|
packet += struct.pack(">H", brt)
|
||||||
packet += bytes([0xff - (brt >> 8), brt_csum, delay])
|
packet += bytes([0xff - (brt >> 8), brt_csum, delay])
|
||||||
self.write_packet(packet)
|
self.write_packet(packet)
|
||||||
time.sleep(0.2)
|
self.delay_safely_written(len(packet))
|
||||||
self.ser.baudrate = self.baud_transfer
|
self.ser.baudrate = self.baud_transfer
|
||||||
response = self.read_packet()
|
response = self.read_packet()
|
||||||
if response[0] != 0x8e:
|
if response[0] != 0x8e:
|
||||||
@ -529,7 +552,37 @@ class Stc89Protocol(StcBaseProtocol):
|
|||||||
print("done")
|
print("done")
|
||||||
|
|
||||||
|
|
||||||
class Stc12AProtocol(Stc89Protocol):
|
class Stc12AOptionsMixIn:
|
||||||
|
def program_options(self):
|
||||||
|
print("Setting options: ", end="")
|
||||||
|
sys.stdout.flush()
|
||||||
|
msr = self.options.get_msr()
|
||||||
|
packet = bytes([0x8d, msr[0], msr[1], msr[2], 0xff, msr[3]])
|
||||||
|
packet += struct.pack(">I", int(self.mcu_clock_hz))
|
||||||
|
packet += bytes([msr[3]])
|
||||||
|
packet += bytes([0xff, msr[0], msr[1], 0xff, 0xff, 0xff, 0xff, msr[2]])
|
||||||
|
packet += bytes([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
|
||||||
|
packet += struct.pack(">I", int(self.mcu_clock_hz))
|
||||||
|
packet += bytes([0xff, 0xff, 0xff])
|
||||||
|
|
||||||
|
self.write_packet(packet)
|
||||||
|
response = self.read_packet()
|
||||||
|
if response[0] != 0x80:
|
||||||
|
raise StcProtocolException("incorrect magic in option packet")
|
||||||
|
|
||||||
|
# XXX: this is done by STC-ISP on newer parts. not sure why, but let's
|
||||||
|
# just replicate it, just to be sure.
|
||||||
|
if self.bsl_version >= 0x66:
|
||||||
|
packet = bytes([0x50])
|
||||||
|
self.write_packet(packet)
|
||||||
|
response = self.read_packet()
|
||||||
|
if response[0] != 0x10:
|
||||||
|
raise StcProtocolException("incorrect magic in option packet")
|
||||||
|
|
||||||
|
print("done")
|
||||||
|
|
||||||
|
|
||||||
|
class Stc12AProtocol(Stc12AOptionsMixIn, Stc89Protocol):
|
||||||
|
|
||||||
"""countdown value for flash erase"""
|
"""countdown value for flash erase"""
|
||||||
ERASE_COUNTDOWN = 0x0d
|
ERASE_COUNTDOWN = 0x0d
|
||||||
@ -599,7 +652,7 @@ class Stc12AProtocol(Stc89Protocol):
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
packet = bytes([0x8f, 0xc0, brt, 0x3f, brt_csum, delay, iap])
|
packet = bytes([0x8f, 0xc0, brt, 0x3f, brt_csum, delay, iap])
|
||||||
self.write_packet(packet)
|
self.write_packet(packet)
|
||||||
time.sleep(0.2)
|
self.delay_safely_written(len(packet))
|
||||||
self.ser.baudrate = self.baud_transfer
|
self.ser.baudrate = self.baud_transfer
|
||||||
response = self.read_packet()
|
response = self.read_packet()
|
||||||
self.ser.baudrate = self.baud_handshake
|
self.ser.baudrate = self.baud_handshake
|
||||||
@ -611,7 +664,7 @@ class Stc12AProtocol(Stc89Protocol):
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
packet = bytes([0x8e, 0xc0, brt, 0x3f, brt_csum, delay])
|
packet = bytes([0x8e, 0xc0, brt, 0x3f, brt_csum, delay])
|
||||||
self.write_packet(packet)
|
self.write_packet(packet)
|
||||||
time.sleep(0.2)
|
self.delay_safely_written(len(packet))
|
||||||
self.ser.baudrate = self.baud_transfer
|
self.ser.baudrate = self.baud_transfer
|
||||||
response = self.read_packet()
|
response = self.read_packet()
|
||||||
if response[0] != 0x8e:
|
if response[0] != 0x8e:
|
||||||
@ -650,37 +703,34 @@ class Stc12AProtocol(Stc89Protocol):
|
|||||||
raise StcProtocolException("incorrect magic in erase packet")
|
raise StcProtocolException("incorrect magic in erase packet")
|
||||||
print("done")
|
print("done")
|
||||||
|
|
||||||
|
|
||||||
|
class Stc12OptionsMixIn:
|
||||||
def program_options(self):
|
def program_options(self):
|
||||||
print("Setting options: ", end="")
|
print("Setting options: ", end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
msr = self.options.get_msr()
|
msr = self.options.get_msr()
|
||||||
packet = bytes([0x8d, msr[0], msr[1], msr[2], 0xff, msr[3]])
|
# XXX: it's not 100% clear if the index of msr[3] is consistent
|
||||||
packet += struct.pack(">I", int(self.mcu_clock_hz))
|
# between devices, so write it to both indices.
|
||||||
packet += bytes([msr[3]])
|
packet = bytes([0x8d, msr[0], msr[1], msr[2], msr[3],
|
||||||
packet += bytes([0xff, msr[0], msr[1], 0xff, 0xff, 0xff, 0xff, msr[2]])
|
0xff, 0xff, 0xff, 0xff, msr[3], 0xff,
|
||||||
packet += bytes([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
|
||||||
packet += struct.pack(">I", int(self.mcu_clock_hz))
|
|
||||||
packet += bytes([0xff, 0xff, 0xff])
|
|
||||||
|
|
||||||
|
packet += struct.pack(">I", int(self.mcu_clock_hz))
|
||||||
self.write_packet(packet)
|
self.write_packet(packet)
|
||||||
response = self.read_packet()
|
response = self.read_packet()
|
||||||
if response[0] != 0x80:
|
if response[0] != 0x50:
|
||||||
raise StcProtocolException("incorrect magic in option packet")
|
raise StcProtocolException("incorrect magic in option packet")
|
||||||
|
|
||||||
# XXX: this is done by STC-ISP on newer parts. not sure why, but let's
|
|
||||||
# just replicate it, just to be sure.
|
|
||||||
if self.bsl_version >= 0x66:
|
|
||||||
packet = bytes([0x50])
|
|
||||||
self.write_packet(packet)
|
|
||||||
response = self.read_packet()
|
|
||||||
if response[0] != 0x10:
|
|
||||||
raise StcProtocolException("incorrect magic in option packet")
|
|
||||||
|
|
||||||
print("done")
|
print("done")
|
||||||
|
|
||||||
|
# If UID wasn't sent with erase acknowledge, it should be in this packet
|
||||||
|
if not self.uid:
|
||||||
|
self.uid = response[18:25]
|
||||||
|
|
||||||
class Stc12Protocol(StcBaseProtocol):
|
print("Target UID: %s" % Utils.hexstr(self.uid))
|
||||||
"""Protocol handler for STC 10/11/12 series"""
|
|
||||||
|
|
||||||
|
class Stc12BaseProtocol(StcBaseProtocol):
|
||||||
|
"""Base class for STC 10/11/12 series protocol handlers"""
|
||||||
|
|
||||||
"""block size for programming flash"""
|
"""block size for programming flash"""
|
||||||
PROGRAM_BLOCKSIZE = 128
|
PROGRAM_BLOCKSIZE = 128
|
||||||
@ -742,6 +792,8 @@ class Stc12Protocol(StcBaseProtocol):
|
|||||||
self.mcu_bsl_version = "%d.%d%s" % (bl_version >> 4, bl_version & 0x0f,
|
self.mcu_bsl_version = "%d.%d%s" % (bl_version >> 4, bl_version & 0x0f,
|
||||||
chr(bl_stepping))
|
chr(bl_stepping))
|
||||||
|
|
||||||
|
self.bsl_version = bl_version
|
||||||
|
|
||||||
def calculate_baud(self):
|
def calculate_baud(self):
|
||||||
"""Calculate MCU baudrate setting.
|
"""Calculate MCU baudrate setting.
|
||||||
|
|
||||||
@ -797,7 +849,7 @@ class Stc12Protocol(StcBaseProtocol):
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
packet = bytes([0x8f, 0xc0, brt, 0x3f, brt_csum, delay, iap])
|
packet = bytes([0x8f, 0xc0, brt, 0x3f, brt_csum, delay, iap])
|
||||||
self.write_packet(packet)
|
self.write_packet(packet)
|
||||||
time.sleep(0.2)
|
self.delay_safely_written(len(packet))
|
||||||
self.ser.baudrate = self.baud_transfer
|
self.ser.baudrate = self.baud_transfer
|
||||||
response = self.read_packet()
|
response = self.read_packet()
|
||||||
self.ser.baudrate = self.baud_handshake
|
self.ser.baudrate = self.baud_handshake
|
||||||
@ -809,7 +861,7 @@ class Stc12Protocol(StcBaseProtocol):
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
packet = bytes([0x8e, 0xc0, brt, 0x3f, brt_csum, delay])
|
packet = bytes([0x8e, 0xc0, brt, 0x3f, brt_csum, delay])
|
||||||
self.write_packet(packet)
|
self.write_packet(packet)
|
||||||
time.sleep(0.2)
|
self.delay_safely_written(len(packet))
|
||||||
self.ser.baudrate = self.baud_transfer
|
self.ser.baudrate = self.baud_transfer
|
||||||
response = self.read_packet()
|
response = self.read_packet()
|
||||||
if response[0] != 0x84:
|
if response[0] != 0x84:
|
||||||
@ -856,13 +908,10 @@ class Stc12Protocol(StcBaseProtocol):
|
|||||||
packet += struct.pack(">H", self.PROGRAM_BLOCKSIZE)
|
packet += struct.pack(">H", self.PROGRAM_BLOCKSIZE)
|
||||||
packet += data[i:i+self.PROGRAM_BLOCKSIZE]
|
packet += data[i:i+self.PROGRAM_BLOCKSIZE]
|
||||||
while len(packet) < self.PROGRAM_BLOCKSIZE + 7: packet += b"\x00"
|
while len(packet) < self.PROGRAM_BLOCKSIZE + 7: packet += b"\x00"
|
||||||
csum = sum(packet[7:]) & 0xff
|
|
||||||
self.write_packet(packet)
|
self.write_packet(packet)
|
||||||
response = self.read_packet()
|
response = self.read_packet()
|
||||||
if response[0] != 0x00:
|
if response[0] != 0x00:
|
||||||
raise StcProtocolException("incorrect magic in write packet")
|
raise StcProtocolException("incorrect magic in write packet")
|
||||||
elif response[1] != csum:
|
|
||||||
raise StcProtocolException("verification checksum mismatch")
|
|
||||||
print(".", end="")
|
print(".", end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
print(" done")
|
print(" done")
|
||||||
@ -877,28 +926,19 @@ class Stc12Protocol(StcBaseProtocol):
|
|||||||
raise StcProtocolException("incorrect magic in finish packet")
|
raise StcProtocolException("incorrect magic in finish packet")
|
||||||
print("done")
|
print("done")
|
||||||
|
|
||||||
def program_options(self):
|
|
||||||
print("Setting options: ", end="")
|
|
||||||
sys.stdout.flush()
|
|
||||||
msr = self.options.get_msr()
|
|
||||||
# XXX: it's not 100% clear if the index of msr[3] is consistent
|
|
||||||
# between devices, so write it to both indices.
|
|
||||||
packet = bytes([0x8d, msr[0], msr[1], msr[2], msr[3],
|
|
||||||
0xff, 0xff, 0xff, 0xff, msr[3], 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
|
|
||||||
|
|
||||||
packet += struct.pack(">I", int(self.mcu_clock_hz))
|
class Stc12Protocol(Stc12OptionsMixIn, Stc12BaseProtocol):
|
||||||
self.write_packet(packet)
|
"""STC 10/11/12 series protocol handler"""
|
||||||
response = self.read_packet()
|
|
||||||
if response[0] != 0x50:
|
|
||||||
raise StcProtocolException("incorrect magic in option packet")
|
|
||||||
print("done")
|
|
||||||
|
|
||||||
# If UID wasn't sent with erase acknowledge, it should be in this packet
|
def __init__(self, port, handshake, baud):
|
||||||
if not self.uid:
|
Stc12BaseProtocol.__init__(self, port, handshake, baud)
|
||||||
self.uid = response[18:25]
|
|
||||||
|
|
||||||
print("Target UID: %s" % Utils.hexstr(self.uid))
|
|
||||||
|
class Stc12BProtocol(Stc12AOptionsMixIn, Stc12BaseProtocol):
|
||||||
|
"""STC 10/11/12 variant protocol handler"""
|
||||||
|
|
||||||
|
def __init__(self, port, handshake, baud):
|
||||||
|
Stc12BaseProtocol.__init__(self, port, handshake, baud)
|
||||||
|
|
||||||
|
|
||||||
class Stc15AProtocol(Stc12Protocol):
|
class Stc15AProtocol(Stc12Protocol):
|
||||||
@ -1000,7 +1040,8 @@ class Stc15AProtocol(Stc12Protocol):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
user_speed = self.trim_frequency
|
user_speed = self.trim_frequency
|
||||||
if user_speed <= 0: user_speed = self.mcu_clock_hz
|
if user_speed <= 0:
|
||||||
|
user_speed = self.mcu_clock_hz
|
||||||
program_speed = 22118400
|
program_speed = 22118400
|
||||||
|
|
||||||
user_count = int(self.freq_counter * (user_speed / self.mcu_clock_hz))
|
user_count = int(self.freq_counter * (user_speed / self.mcu_clock_hz))
|
||||||
@ -1094,7 +1135,7 @@ class Stc15AProtocol(Stc12Protocol):
|
|||||||
packet += struct.pack(">B", 230400 // self.baud_transfer)
|
packet += struct.pack(">B", 230400 // self.baud_transfer)
|
||||||
packet += bytes([0xa1, 0x64, 0xb8, 0x00, iap_wait, 0x20, 0xff, 0x00])
|
packet += bytes([0xa1, 0x64, 0xb8, 0x00, iap_wait, 0x20, 0xff, 0x00])
|
||||||
self.write_packet(packet)
|
self.write_packet(packet)
|
||||||
time.sleep(0.2)
|
self.delay_safely_written(len(packet))
|
||||||
self.ser.baudrate = self.baud_transfer
|
self.ser.baudrate = self.baud_transfer
|
||||||
response = self.read_packet()
|
response = self.read_packet()
|
||||||
if response[0] != 0x84:
|
if response[0] != 0x84:
|
||||||
@ -1158,8 +1199,7 @@ class Stc15Protocol(Stc15AProtocol):
|
|||||||
bl_version, bl_stepping = struct.unpack("BB", packet[17:19])
|
bl_version, bl_stepping = struct.unpack("BB", packet[17:19])
|
||||||
bl_minor = packet[22] & 0x0f
|
bl_minor = packet[22] & 0x0f
|
||||||
self.mcu_bsl_version = "%d.%d.%d%s" % (bl_version >> 4, bl_version & 0x0f,
|
self.mcu_bsl_version = "%d.%d.%d%s" % (bl_version >> 4, bl_version & 0x0f,
|
||||||
bl_minor,
|
bl_minor, chr(bl_stepping))
|
||||||
chr(bl_stepping))
|
|
||||||
self.bsl_version = bl_version
|
self.bsl_version = bl_version
|
||||||
|
|
||||||
def print_mcu_info(self):
|
def print_mcu_info(self):
|
||||||
@ -1274,14 +1314,13 @@ class Stc15Protocol(Stc15AProtocol):
|
|||||||
# This is a bit of a hack, but it works.
|
# This is a bit of a hack, but it works.
|
||||||
bauds = self.baud_transfer if (self.mcu_magic >> 8) == 0xf2 else self.baud_transfer * 4
|
bauds = self.baud_transfer if (self.mcu_magic >> 8) == 0xf2 else self.baud_transfer * 4
|
||||||
packet += struct.pack(">H", int(65535 - program_speed / bauds))
|
packet += struct.pack(">H", int(65535 - program_speed / bauds))
|
||||||
packet += struct.pack(">H", int(65535 - (program_speed / bauds) * 1.5))
|
packet += bytes(user_trim)
|
||||||
iap_wait = self.get_iap_delay(program_speed)
|
iap_wait = self.get_iap_delay(program_speed)
|
||||||
packet += bytes([iap_wait])
|
packet += bytes([iap_wait])
|
||||||
self.write_packet(packet)
|
self.write_packet(packet)
|
||||||
response = self.read_packet()
|
response = self.read_packet()
|
||||||
if response[0] != 0x01:
|
if response[0] != 0x01:
|
||||||
raise StcProtocolException("incorrect magic in handshake packet")
|
raise StcProtocolException("incorrect magic in handshake packet")
|
||||||
time.sleep(0.2)
|
|
||||||
self.ser.baudrate = self.baud_transfer
|
self.ser.baudrate = self.baud_transfer
|
||||||
|
|
||||||
def switch_baud_ext(self):
|
def switch_baud_ext(self):
|
||||||
@ -1298,7 +1337,6 @@ class Stc15Protocol(Stc15AProtocol):
|
|||||||
response = self.read_packet()
|
response = self.read_packet()
|
||||||
if response[0] != 0x01:
|
if response[0] != 0x01:
|
||||||
raise StcProtocolException("incorrect magic in handshake packet")
|
raise StcProtocolException("incorrect magic in handshake packet")
|
||||||
time.sleep(0.2)
|
|
||||||
self.ser.baudrate = self.baud_transfer
|
self.ser.baudrate = self.baud_transfer
|
||||||
|
|
||||||
# for switching back to RC, program factory values
|
# for switching back to RC, program factory values
|
||||||
@ -1442,8 +1480,9 @@ class StcUsb15Protocol(Stc15Protocol):
|
|||||||
|
|
||||||
def dump_packet(self, data, request=0, value=0, index=0, receive=True):
|
def dump_packet(self, data, request=0, value=0, index=0, receive=True):
|
||||||
if self.debug:
|
if self.debug:
|
||||||
print("%s bRequest=%02X wValue=%04X wIndex=%04X data: %s" % (("<-" if receive else "->"),
|
print("%s bRequest=%02X wValue=%04X wIndex=%04X data: %s" %
|
||||||
request, value, index, Utils.hexstr(data, " ")), file=sys.stderr)
|
(("<-" if receive else "->"), request, value, index,
|
||||||
|
Utils.hexstr(data, " ")), file=sys.stderr)
|
||||||
|
|
||||||
def read_packet(self):
|
def read_packet(self):
|
||||||
"""Read a packet from the MCU"""
|
"""Read a packet from the MCU"""
|
||||||
@ -1483,15 +1522,16 @@ class StcUsb15Protocol(Stc15Protocol):
|
|||||||
|
|
||||||
self.dump_packet(chunks, request, value, index, receive=False)
|
self.dump_packet(chunks, request, value, index, receive=False)
|
||||||
host2dev = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_RECIPIENT_DEVICE | usb.util.CTRL_OUT
|
host2dev = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_RECIPIENT_DEVICE | usb.util.CTRL_OUT
|
||||||
self.dev.ctrl_transfer(host2dev, request, value, index, chunks);
|
self.dev.ctrl_transfer(host2dev, request, value, index, chunks)
|
||||||
|
|
||||||
def connect(self, autoreset=False):
|
def connect(self, autoreset=False, resetcmd=False):
|
||||||
"""Connect to USB device and read info packet"""
|
"""Connect to USB device and read info packet"""
|
||||||
|
|
||||||
# USB support is optional. Provide an error if pyusb is not available.
|
# USB support is optional. Provide an error if pyusb is not available.
|
||||||
if _usb_available == False:
|
if not _usb_available:
|
||||||
raise StcProtocolException("USB support not available. "
|
raise StcProtocolException(
|
||||||
+ "pyusb is not installed or not working correctly.")
|
"USB support not available. " +
|
||||||
|
"pyusb is not installed or not working correctly.")
|
||||||
|
|
||||||
print("Waiting for MCU, please cycle power: ", end="")
|
print("Waiting for MCU, please cycle power: ", end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
@ -1507,7 +1547,11 @@ class StcUsb15Protocol(Stc15Protocol):
|
|||||||
self.status_packet = None
|
self.status_packet = None
|
||||||
raise StcFramingException
|
raise StcFramingException
|
||||||
else: raise StcFramingException
|
else: raise StcFramingException
|
||||||
except (StcFramingException, usb.core.USBError): time.sleep(0.5)
|
except StcFramingException:
|
||||||
|
time.sleep(0.5)
|
||||||
|
except usb.core.USBError as err:
|
||||||
|
if err.errno == errno.EACCES:
|
||||||
|
raise IOError(err.strerror)
|
||||||
|
|
||||||
self.initialize_model()
|
self.initialize_model()
|
||||||
print("done")
|
print("done")
|
||||||
|
@ -19,31 +19,41 @@
|
|||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
#
|
#
|
||||||
|
|
||||||
import serial
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import serial
|
||||||
|
|
||||||
class Utils:
|
class Utils:
|
||||||
|
"""Common utility functions"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def to_bool(self, val):
|
def to_bool(cls, val):
|
||||||
"""make sensible boolean from string or other type value"""
|
"""make sensible boolean from string or other type value"""
|
||||||
|
|
||||||
if isinstance(val, bool): return val
|
if val is None:
|
||||||
if isinstance(val, int): return bool(val)
|
return False
|
||||||
if len(val) == 0: return False
|
if isinstance(val, bool):
|
||||||
|
return val
|
||||||
|
elif isinstance(val, int):
|
||||||
|
return bool(val)
|
||||||
|
elif len(val) == 0:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
return True if val[0].lower() == "t" or val[0] == "1" else False
|
return True if val[0].lower() == "t" or val[0] == "1" else False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def to_int(self, val):
|
def to_int(cls, val):
|
||||||
"""make int from any value, nice error message if not possible"""
|
"""make int from any value, nice error message if not possible"""
|
||||||
|
|
||||||
try: return int(val, 0)
|
try:
|
||||||
except: raise ValueError("invalid integer")
|
return int(val, 0)
|
||||||
|
except:
|
||||||
|
raise ValueError("invalid integer")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def hexstr(self, bytestr, sep=""):
|
def hexstr(cls, bytestr, sep=""):
|
||||||
"""make formatted hex string output from byte sequence"""
|
"""make formatted hex string output from byte sequence"""
|
||||||
|
|
||||||
return sep.join(["%02X" % x for x in bytestr])
|
return sep.join(["%02X" % x for x in bytes(bytestr)])
|
||||||
|
|
||||||
|
|
||||||
class BaudType:
|
class BaudType:
|
||||||
@ -55,5 +65,5 @@ class BaudType:
|
|||||||
raise argparse.ArgumentTypeError("illegal baudrate")
|
raise argparse.ArgumentTypeError("illegal baudrate")
|
||||||
return baud
|
return baud
|
||||||
|
|
||||||
def __repr__(self): return "baudrate"
|
def __repr__(self):
|
||||||
|
return "baudrate"
|
||||||
|
0
test/__init__.py
Normal file
0
test/__init__.py
Normal file
19
test/iap15f2k61s2.yml
Normal file
19
test/iap15f2k61s2.yml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name: IAP15F2K61S2 programming test
|
||||||
|
protocol: stc15
|
||||||
|
code_data: [49, 50, 51, 52, 53, 54, 55, 56, 57]
|
||||||
|
responses:
|
||||||
|
- [0x50, 0x87, 0xD3, 0x75, 0x9C, 0xF5, 0x3B, 0x17, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x09, 0x81, 0x00, 0x00, 0x71, 0x53, 0x00, 0xF4, 0x49, 0x04, 0x06, 0x58, 0x9C, 0x02, 0x0E, 0x14, 0x17, 0x19, 0x19, 0x00, 0xF4, 0xF4, 0x04, 0xD2]
|
||||||
|
- [0x00, 0x0B, 0x03, 0x37, 0x04, 0x9A, 0x06, 0x02, 0x06, 0x6B, 0x09, 0x27, 0x0B, 0xE8, 0x0D, 0x0A, 0x12, 0x5A, 0x17, 0x9B, 0x14, 0x8F, 0x1C, 0x96, 0x00, 0x00]
|
||||||
|
- [0x00, 0x0C, 0x09, 0x04, 0x09, 0x09, 0x09, 0x0E, 0x09, 0x0E, 0x09, 0x18, 0x09, 0x1D, 0x12, 0x00, 0x12, 0x0F, 0x12, 0x19, 0x12, 0x23, 0x12, 0x2D, 0x12, 0x37]
|
||||||
|
- [0x01]
|
||||||
|
- [0x05]
|
||||||
|
- [0x03, 0x0D, 0x00, 0x00, 0x21, 0x02, 0x26, 0x32]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x04, 0x54]
|
19
test/stc12c2052ad.yml
Normal file
19
test/stc12c2052ad.yml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name: STC12C2052AD programming test
|
||||||
|
protocol: stc12a
|
||||||
|
code_data: [49, 50, 51, 52, 53, 54, 55, 56, 57]
|
||||||
|
responses:
|
||||||
|
- [0x00, 0x04, 0xEC, 0x04, 0xEC, 0x04, 0xEC, 0x04, 0xEC, 0x04, 0xEC, 0x04, 0xEC, 0x04, 0xEB, 0x04, 0xEB, 0x58, 0x44, 0x00, 0xF2, 0x12, 0x83, 0xFD, 0xF7, 0xF7, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFD, 0xF7, 0xF7, 0xFF]
|
||||||
|
- [0x8F, 0xC0, 0x79, 0x3F, 0xFE, 0x28, 0x85]
|
||||||
|
- [0x8E, 0xC0, 0x79, 0x3F, 0xFE, 0x28]
|
||||||
|
- [0x80]
|
||||||
|
- [0x80]
|
||||||
|
- [0x80]
|
||||||
|
- [0x80]
|
||||||
|
- [0x80]
|
||||||
|
- [0x80, 0x66]
|
||||||
|
- [0x80, 0x80]
|
||||||
|
- [0x80, 0x80]
|
||||||
|
- [0x80, 0x80]
|
||||||
|
- [0x80, 0xEE]
|
||||||
|
- [0x10, 0xC0, 0x16, 0xF7, 0xFF, 0xBF, 0x03, 0xFF, 0x58, 0x44, 0xFD, 0xF7, 0xF7, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFD, 0xF7, 0xF7, 0xFF]
|
||||||
|
- [0x80]
|
15
test/stc12c5a60s2.yml
Normal file
15
test/stc12c5a60s2.yml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
name: STC12C5A60S2 programming test
|
||||||
|
protocol: stc12
|
||||||
|
code_data: [49, 50, 51, 52, 53, 54, 55, 56, 57]
|
||||||
|
responses:
|
||||||
|
- [0x50, 0x04, 0xBD, 0x04, 0xBC, 0x04, 0xBC, 0x04, 0xBD, 0x04, 0xBC, 0x04, 0xBC, 0x04, 0xBC, 0x04, 0xBC, 0x62, 0x49, 0x00, 0xD1, 0x7E, 0x8C, 0xFF, 0x7F, 0xF7, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x00, 0xB0, 0x02, 0x2E, 0x6B, 0x00, 0xCD, 0x80, 0x00, 0x00]
|
||||||
|
- [0x8F]
|
||||||
|
- [0x8F, 0xC0, 0x7E, 0x3F, 0xFE, 0xA0, 0x83, 0x04]
|
||||||
|
- [0x84, 0xC0, 0x7E, 0x3F, 0xFE, 0xA0, 0x04]
|
||||||
|
- [0x00]
|
||||||
|
- [0x00, 0x03]
|
||||||
|
- [0x00, 0x00]
|
||||||
|
- [0x00, 0x00]
|
||||||
|
- [0x00, 0x00]
|
||||||
|
- [0x8D]
|
||||||
|
- [0x50, 0xFF, 0x7F, 0xF7, 0xFF, 0xFF, 0x03, 0xFF, 0x62, 0x49, 0xFF, 0x7F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x03, 0x00, 0xB0, 0x02, 0x2E, 0x6B, 0x00, 0xCD, 0x80, 0x00, 0x00]
|
20
test/stc15f104e.yml
Normal file
20
test/stc15f104e.yml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
name: STC15F104E programming test
|
||||||
|
protocol: stc15a
|
||||||
|
code_data: [49, 50, 51, 52, 53, 54, 55, 56, 57]
|
||||||
|
responses:
|
||||||
|
- [0x50, 0x02, 0xB0, 0x02, 0xB0, 0x02, 0xAF, 0x02, 0xB0, 0x02, 0xE6, 0x02, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x67, 0x51, 0xFF, 0xF2, 0x94, 0x8C, 0xEF, 0x3B, 0xF5, 0x58, 0x34, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x50, 0x0C, 0x94, 0x21, 0xFF, 0x29]
|
||||||
|
- [0x8f]
|
||||||
|
- [0x65, 0x58, 0x50, 0x0C, 0x95, 0x21, 0xFF, 0x2B, 0xFF, 0xFF, 0x06, 0x06, 0x58, 0x00, 0x02, 0x00, 0x58, 0x80, 0x02, 0x00, 0x58, 0x80, 0x02, 0x00, 0x58, 0xFF, 0x02, 0x00, 0x58, 0x00, 0x02, 0x00, 0x58, 0x80, 0x02, 0x00]
|
||||||
|
- [0x65, 0x58, 0x50, 0x0C, 0x95, 0x21, 0xFF, 0x2B, 0xFF, 0xFF, 0x06, 0x0B, 0x58, 0x24, 0x02, 0x00, 0x58, 0x25, 0x02, 0x00, 0x58, 0x26, 0x02, 0x00, 0x58, 0x27, 0x02, 0x00, 0x58, 0x28, 0x02, 0x00, 0x58, 0x29, 0x02, 0x00, 0x58, 0x2A, 0x02, 0x00, 0x58, 0x2B, 0x02, 0x00, 0x58, 0x2C, 0x02, 0x00, 0x58, 0x2D, 0x02, 0x00, 0x58, 0x2E, 0x02, 0x00]
|
||||||
|
- [0x01]
|
||||||
|
- [0x05]
|
||||||
|
- [0x03, 0x0C, 0x00, 0x00, 0x17, 0x01, 0xA0, 0xE0]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x04, 0x54]
|
19
test/stc15l104w.yml
Normal file
19
test/stc15l104w.yml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name: STC15L104W programming test
|
||||||
|
protocol: stc15
|
||||||
|
code_data: [49, 50, 51, 52, 53, 54, 55, 56, 57]
|
||||||
|
responses:
|
||||||
|
- [0x50, 0x66, 0x3C, 0x93, 0xBA, 0xF7, 0xBB, 0x9F, 0x00, 0x5B, 0x68, 0x00, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x71, 0x51, 0x03, 0xF2, 0xD4, 0x04, 0x06, 0x58, 0xBA, 0x02, 0x2A, 0x31, 0x32, 0x38, 0x30, 0x80, 0x14, 0x10, 0x04, 0xD9]
|
||||||
|
- [0x00, 0x0B, 0x03, 0x0A, 0x04, 0x4F, 0x05, 0x9E, 0x06, 0x20, 0x08, 0xB9, 0x0B, 0x5C, 0x0C, 0x6A, 0x11, 0x7E, 0x16, 0x79, 0x13, 0x77, 0x1A, 0xB1, 0x00, 0x00]
|
||||||
|
- [0x00, 0x0C, 0x04, 0xD6, 0x04, 0xDB, 0x04, 0xE0, 0x04, 0xE0, 0x04, 0xE0, 0x04, 0xE5, 0x11, 0xE2, 0x11, 0xF1, 0x11, 0xFB, 0x12, 0x05, 0x12, 0x0A, 0x12, 0x19]
|
||||||
|
- [0x01]
|
||||||
|
- [0x05]
|
||||||
|
- [0x03, 0x0C, 0x00, 0x00, 0x17, 0x01, 0xA0, 0xE0]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x04, 0x54]
|
20
test/stc15w4k56s4.yml
Normal file
20
test/stc15w4k56s4.yml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
name: STC15W4K56S4 programming test
|
||||||
|
protocol: stc15
|
||||||
|
code_data: [49, 50, 51, 52, 53, 54, 55, 56, 57]
|
||||||
|
responses:
|
||||||
|
- [0x50, 0x8D, 0xFF, 0x73, 0x96, 0xF5, 0x7B, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x27, 0xED, 0x00, 0x00, 0x73, 0x54, 0x00, 0xF5, 0x28, 0x04, 0x06, 0x70, 0x96, 0x02, 0x15, 0x19, 0x1C, 0x1E, 0x23, 0x00, 0xEC, 0xE0, 0x04, 0xD7, 0xF8, 0x73, 0xBF, 0xFF, 0xFF, 0x15, 0x09, 0x25, 0x60]
|
||||||
|
- [0x00, 0x0B, 0x0D, 0x21, 0x12, 0xBC, 0x18, 0x3E, 0x1A, 0x05, 0x24, 0xFA, 0x2F, 0xB3, 0x34, 0xD1, 0x4A, 0x52, 0x5E, 0xC0, 0x52, 0xDB, 0x73, 0x1A, 0x00, 0x00]
|
||||||
|
- [0x00, 0x0C, 0x23, 0xBF, 0x23, 0xD3, 0x23, 0xE7, 0x23, 0xF6, 0x24, 0x0F, 0x24, 0x23, 0x47, 0x73, 0x47, 0xB9, 0x47, 0xE1, 0x48, 0x09, 0x48, 0x36, 0x48, 0x59]
|
||||||
|
- [0x01]
|
||||||
|
- [0x05]
|
||||||
|
- [0x03, 0xF5, 0x28, 0x00, 0xA5, 0x03, 0x27, 0x49]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x02, 0x54]
|
||||||
|
- [0x07, 0x54]
|
||||||
|
- [0x04, 0x54]
|
19
test/stc89c52rc.yml
Normal file
19
test/stc89c52rc.yml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name: STC89C52RC programming test
|
||||||
|
protocol: stc89
|
||||||
|
code_data: [49, 50, 51, 52, 53, 54, 55, 56, 57]
|
||||||
|
responses:
|
||||||
|
- [0x00, 0x25, 0xE6, 0x25, 0xE6, 0x25, 0xE6, 0x25, 0xE6, 0x25, 0xE6, 0x25, 0xE6, 0x25, 0xE2, 0x25, 0xE6, 0x43, 0x43, 0xFC, 0xF0, 0x02, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
|
||||||
|
- [0x8F, 0xFD, 0xF8, 0x02, 0x10, 0x28, 0x81]
|
||||||
|
- [0x8E, 0xFD, 0xF8, 0x02, 0x10, 0x28]
|
||||||
|
- [0x80]
|
||||||
|
- [0x80]
|
||||||
|
- [0x80]
|
||||||
|
- [0x80]
|
||||||
|
- [0x80]
|
||||||
|
- [0x80, 0x66]
|
||||||
|
- [0x80, 0x80]
|
||||||
|
- [0x80, 0x80]
|
||||||
|
- [0x80, 0x80]
|
||||||
|
- [0x8D, 0xFC, 0xFF, 0xF6, 0xFF]
|
||||||
|
- [0x10, 0xC0, 0x16, 0xF6, 0xFF, 0xF1, 0x03, 0xFF, 0x43, 0x43, 0xFC]
|
||||||
|
- [0x80]
|
136
test/test_program.py
Normal file
136
test/test_program.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2017 Grigori Goronzy <greg@chown.ath.cx>
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""Tests that simulate a whole programming cycle"""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from unittest.mock import patch
|
||||||
|
import yaml
|
||||||
|
import stcgal.frontend
|
||||||
|
import stcgal.protocols
|
||||||
|
|
||||||
|
def convert_to_bytes(list_of_lists):
|
||||||
|
"""Convert lists of integer lists to list of byte lists"""
|
||||||
|
return [bytes(x) for x in list_of_lists]
|
||||||
|
|
||||||
|
def get_default_opts():
|
||||||
|
"""Get a default preconfigured option object"""
|
||||||
|
opts = unittest.mock.MagicMock()
|
||||||
|
opts.protocol = "stc89"
|
||||||
|
opts.autoreset = False
|
||||||
|
opts.port = ""
|
||||||
|
opts.baud = 19200
|
||||||
|
opts.handshake = 9600
|
||||||
|
opts.trim = 22118
|
||||||
|
opts.eeprom_image = None
|
||||||
|
opts.debug = False
|
||||||
|
opts.code_image.name = "test.bin"
|
||||||
|
opts.code_image.read.return_value = b"123456789"
|
||||||
|
return opts
|
||||||
|
|
||||||
|
class ProgramTests(unittest.TestCase):
|
||||||
|
"""Test MCU programming cycles for different families, based on traces"""
|
||||||
|
|
||||||
|
@patch("stcgal.protocols.StcBaseProtocol.read_packet")
|
||||||
|
@patch("stcgal.protocols.Stc89Protocol.write_packet")
|
||||||
|
@patch("stcgal.protocols.serial.Serial", autospec=True)
|
||||||
|
@patch("stcgal.protocols.time.sleep")
|
||||||
|
@patch("sys.stdout")
|
||||||
|
def test_program_stc89(self, out, sleep_mock, serial_mock, write_mock, read_mock):
|
||||||
|
"""Test a programming cycle with STC89 protocol"""
|
||||||
|
self._program_yml("./test/stc89c52rc.yml", serial_mock, read_mock)
|
||||||
|
|
||||||
|
@patch("stcgal.protocols.StcBaseProtocol.read_packet")
|
||||||
|
@patch("stcgal.protocols.Stc89Protocol.write_packet")
|
||||||
|
@patch("stcgal.protocols.serial.Serial", autospec=True)
|
||||||
|
@patch("stcgal.protocols.time.sleep")
|
||||||
|
@patch("sys.stdout")
|
||||||
|
def test_program_stc12(self, out, sleep_mock, serial_mock, write_mock, read_mock):
|
||||||
|
"""Test a programming cycle with STC12 protocol"""
|
||||||
|
self._program_yml("./test/stc12c5a60s2.yml", serial_mock, read_mock)
|
||||||
|
|
||||||
|
@patch("stcgal.protocols.StcBaseProtocol.read_packet")
|
||||||
|
@patch("stcgal.protocols.Stc89Protocol.write_packet")
|
||||||
|
@patch("stcgal.protocols.serial.Serial", autospec=True)
|
||||||
|
@patch("stcgal.protocols.time.sleep")
|
||||||
|
@patch("sys.stdout")
|
||||||
|
def test_program_stc12a(self, out, sleep_mock, serial_mock, write_mock, read_mock):
|
||||||
|
"""Test a programming cycle with STC12A protocol"""
|
||||||
|
self._program_yml("./test/stc12c2052ad.yml", serial_mock, read_mock)
|
||||||
|
|
||||||
|
def test_program_stc12b(self):
|
||||||
|
"""Test a programming cycle with STC12B protocol"""
|
||||||
|
self.skipTest("trace missing")
|
||||||
|
|
||||||
|
@patch("stcgal.protocols.StcBaseProtocol.read_packet")
|
||||||
|
@patch("stcgal.protocols.Stc89Protocol.write_packet")
|
||||||
|
@patch("stcgal.protocols.serial.Serial", autospec=True)
|
||||||
|
@patch("stcgal.protocols.time.sleep")
|
||||||
|
@patch("sys.stdout")
|
||||||
|
def test_program_stc15f2(self, out, sleep_mock, serial_mock, write_mock, read_mock):
|
||||||
|
"""Test a programming cycle with STC15 protocol, F2 series"""
|
||||||
|
self._program_yml("./test/iap15f2k61s2.yml", serial_mock, read_mock)
|
||||||
|
|
||||||
|
@patch("stcgal.protocols.StcBaseProtocol.read_packet")
|
||||||
|
@patch("stcgal.protocols.Stc89Protocol.write_packet")
|
||||||
|
@patch("stcgal.protocols.serial.Serial", autospec=True)
|
||||||
|
@patch("stcgal.protocols.time.sleep")
|
||||||
|
@patch("sys.stdout")
|
||||||
|
def test_program_stc15w4(self, out, sleep_mock, serial_mock, write_mock, read_mock):
|
||||||
|
"""Test a programming cycle with STC15 protocol, W4 series"""
|
||||||
|
self._program_yml("./test/stc15w4k56s4.yml", serial_mock, read_mock)
|
||||||
|
|
||||||
|
@unittest.skip("trace is broken")
|
||||||
|
@patch("stcgal.protocols.StcBaseProtocol.read_packet")
|
||||||
|
@patch("stcgal.protocols.Stc89Protocol.write_packet")
|
||||||
|
@patch("stcgal.protocols.serial.Serial", autospec=True)
|
||||||
|
@patch("stcgal.protocols.time.sleep")
|
||||||
|
@patch("sys.stdout")
|
||||||
|
def test_program_stc15a(self, out, sleep_mock, serial_mock, write_mock, read_mock):
|
||||||
|
"""Test a programming cycle with STC15A protocol"""
|
||||||
|
self._program_yml("./test/stc15f104e.yml", serial_mock, read_mock)
|
||||||
|
|
||||||
|
@patch("stcgal.protocols.StcBaseProtocol.read_packet")
|
||||||
|
@patch("stcgal.protocols.Stc89Protocol.write_packet")
|
||||||
|
@patch("stcgal.protocols.serial.Serial", autospec=True)
|
||||||
|
@patch("stcgal.protocols.time.sleep")
|
||||||
|
@patch("sys.stdout")
|
||||||
|
def test_program_stc15l1(self, out, sleep_mock, serial_mock, write_mock, read_mock):
|
||||||
|
"""Test a programming cycle with STC15 protocol, L1 series"""
|
||||||
|
self._program_yml("./test/stc15l104w.yml", serial_mock, read_mock)
|
||||||
|
|
||||||
|
def test_program_stc15w4_usb(self):
|
||||||
|
"""Test a programming cycle with STC15W4 USB protocol"""
|
||||||
|
self.skipTest("USB not supported yet, trace missing")
|
||||||
|
|
||||||
|
def _program_yml(self, yml, serial_mock, read_mock):
|
||||||
|
"""Program MCU with data from YAML file"""
|
||||||
|
with open(yml) as test_file:
|
||||||
|
test_data = yaml.load(test_file.read())
|
||||||
|
opts = get_default_opts()
|
||||||
|
opts.protocol = test_data["protocol"]
|
||||||
|
opts.code_image.read.return_value = bytes(test_data["code_data"])
|
||||||
|
serial_mock.return_value.inWaiting.return_value = 1
|
||||||
|
read_mock.side_effect = convert_to_bytes(test_data["responses"])
|
||||||
|
gal = stcgal.frontend.StcGal(opts)
|
||||||
|
self.assertEqual(gal.run(), 0)
|
||||||
|
|
77
test/test_utils.py
Normal file
77
test/test_utils.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2017 Grigori Goronzy <greg@chown.ath.cx>
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""Tests for utility functions and other misc parts"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import unittest
|
||||||
|
from unittest.mock import patch
|
||||||
|
from stcgal.utils import Utils, BaudType
|
||||||
|
|
||||||
|
class TestUtils(unittest.TestCase):
|
||||||
|
"""Test for utility functions in the Utils class"""
|
||||||
|
|
||||||
|
def test_to_bool(self):
|
||||||
|
"""Test special utility function for bool conversion"""
|
||||||
|
self.assertTrue(Utils.to_bool(True))
|
||||||
|
self.assertTrue(Utils.to_bool("true"))
|
||||||
|
self.assertTrue(Utils.to_bool("True"))
|
||||||
|
self.assertTrue(Utils.to_bool("t"))
|
||||||
|
self.assertTrue(Utils.to_bool("T"))
|
||||||
|
self.assertTrue(Utils.to_bool(1))
|
||||||
|
self.assertTrue(Utils.to_bool(-1))
|
||||||
|
self.assertFalse(Utils.to_bool(0))
|
||||||
|
self.assertFalse(Utils.to_bool(None))
|
||||||
|
self.assertFalse(Utils.to_bool("false"))
|
||||||
|
self.assertFalse(Utils.to_bool("False"))
|
||||||
|
self.assertFalse(Utils.to_bool("f"))
|
||||||
|
self.assertFalse(Utils.to_bool("F"))
|
||||||
|
self.assertFalse(Utils.to_bool(""))
|
||||||
|
|
||||||
|
def test_to_int(self):
|
||||||
|
"""Test wrapped integer conversion"""
|
||||||
|
self.assertEqual(Utils.to_int("2"), 2)
|
||||||
|
self.assertEqual(Utils.to_int("0x10"), 16)
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Utils.to_int("a")
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Utils.to_int("")
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Utils.to_int(None)
|
||||||
|
|
||||||
|
def test_hexstr(self):
|
||||||
|
"""Test byte array formatter"""
|
||||||
|
self.assertEqual(Utils.hexstr([10]), "0A")
|
||||||
|
self.assertEqual(Utils.hexstr([1, 2, 3]), "010203")
|
||||||
|
with self.assertRaises(Exception):
|
||||||
|
Utils.hexstr([400, 500])
|
||||||
|
|
||||||
|
class TestBaudType(unittest.TestCase):
|
||||||
|
"""Test BaudType class"""
|
||||||
|
|
||||||
|
def test_create_baud_type(self):
|
||||||
|
"""Test creation of BaudType instances"""
|
||||||
|
baud_type = BaudType()
|
||||||
|
self.assertEqual(baud_type("2400"), 2400)
|
||||||
|
self.assertEqual(baud_type("115200"), 115200)
|
||||||
|
with self.assertRaises(argparse.ArgumentTypeError):
|
||||||
|
baud_type("2374882")
|
Reference in New Issue
Block a user