Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
3ce6b565ef | |||
2e822375e0 | |||
7d6e8e9bfd | |||
506289b8ee | |||
f417b6eed5 | |||
86e289b65c | |||
53f9544281 | |||
65a7759647 | |||
8ad77586d4 | |||
276c696fa4 | |||
26ef34991b | |||
f90fe4152b | |||
d6ef028dc7 | |||
979d7f513f | |||
fce2f01232 | |||
854f36100b | |||
92f4def11a | |||
6c0af88551 | |||
366a3a5bd3 | |||
c046e886e3 | |||
7ba95eab68 | |||
61a4fa0e4f | |||
da5f6678c5 | |||
a8f141584d |
21
README.md
21
README.md
@ -25,14 +25,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)
|
||||||
@ -111,17 +111,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,
|
||||||
@ -240,7 +241,9 @@ Option key | Possible values | Protocols/Models | Descri
|
|||||||
```ale_enabled``` | true/false | STC89 only | ALE pin enabled if true, normal GPIO if false
|
```ale_enabled``` | true/false | STC89 only | ALE pin enabled if true, normal GPIO if false
|
||||||
```xram_enabled``` | true/false | STC89 only | Use internal XRAM (STC89 only)
|
```xram_enabled``` | true/false | STC89 only | Use internal XRAM (STC89 only)
|
||||||
```watchdog_por_enabled``` | true/false | All | Watchdog state after power-on reset (POR)
|
```watchdog_por_enabled``` | true/false | All | Watchdog state after power-on reset (POR)
|
||||||
```low_voltage_reset ``` | true/false | STC12A+ | Low-voltage reset (brownout)
|
```low_voltage_reset``` | low/high | STC12A/STC12 | Low-voltage reset level (low: ~3.3V, high: ~3.7V)
|
||||||
|
```low_voltage_reset``` | true/false | STC12 | Enable RESET2 pin low voltage detect
|
||||||
|
```low_voltage_reset``` | true/false | STC15A | Enable low-voltage reset (brownout)
|
||||||
```clock_source``` | internal/external | STC12A+ with XTAL | Use internal (RC) or external (crystal) clock
|
```clock_source``` | internal/external | STC12A+ with XTAL | Use internal (RC) or external (crystal) clock
|
||||||
```watchdog_stop_idle``` | true/false | STC12A+ | Stop watchdog in IDLE mode
|
```watchdog_stop_idle``` | true/false | STC12A+ | Stop watchdog in IDLE mode
|
||||||
```watchdog_prescale``` | 2,4,8,...,256 | STC12A+ | Watchdog timer prescaler, must be a power of two.
|
```watchdog_prescale``` | 2,4,8,...,256 | STC12A+ | Watchdog timer prescaler, must be a power of two.
|
||||||
|
13
debian/changelog
vendored
13
debian/changelog
vendored
@ -1,3 +1,16 @@
|
|||||||
|
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
|
||||||
|
@ -25,12 +25,12 @@ for i in range(MCU_TABLE_SIZE):
|
|||||||
inp.seek(mcu_name_offset)
|
inp.seek(mcu_name_offset)
|
||||||
name_str = inp.read(16).split(b'\00')[0].decode("ascii")
|
name_str = inp.read(16).split(b'\00')[0].decode("ascii")
|
||||||
|
|
||||||
# XXX: 1 KB are reserved one *some* MCUs for some reason
|
# TODO: With some MCUs, the amount of available EEPROM depends on the BSL version.
|
||||||
#if ee_size > 0 and not name_str.startswith("IAP"):
|
# Generally, newer BSLs free up a KB of additional EEPROM. Currently, always the
|
||||||
# ee_size -= 1024
|
# maximum amount (with newer BSL) is reported.
|
||||||
|
|
||||||
# STC12C54xx always have 12 KB eeprom
|
# STC12x54xx always have 12 KB eeprom
|
||||||
if name_str.startswith("STC12C54"):
|
if name_str.startswith("STC12C54") or name_str.startswith("STC12LE54"):
|
||||||
ee_size = 12 * 1024
|
ee_size = 12 * 1024
|
||||||
|
|
||||||
print("MCUModel(name='%s', magic=0x%02x%02x, total=%d, code=%d, eeprom=%d)," %
|
print("MCUModel(name='%s', magic=0x%02x%02x, total=%d, code=%d, eeprom=%d)," %
|
||||||
|
@ -4,7 +4,7 @@ Placement of configuration values
|
|||||||
"~" means the bit is a negated boolean. Sometimes values overlap,
|
"~" means the bit is a negated boolean. Sometimes values overlap,
|
||||||
depending on MCU model.
|
depending on MCU model.
|
||||||
|
|
||||||
In STC12A series, the first 4 MCS bytes have active
|
In STC12A series, the first 7 MCS bytes have active
|
||||||
values. Generally, unused bits should be set to 1.
|
values. Generally, unused bits should be set to 1.
|
||||||
|
|
||||||
MCS0
|
MCS0
|
||||||
@ -47,14 +47,9 @@ MSB 7 6 5 4 3 2 1 0 LSB
|
|||||||
(or others, depends on MCU model) are held low on POR.
|
(or others, depends on MCU model) are held low on POR.
|
||||||
|
|
||||||
|
|
||||||
MCS3
|
|
||||||
----
|
|
||||||
|
|
||||||
Unused.
|
MCS3 (at index 6!)
|
||||||
|
------------------
|
||||||
|
|
||||||
MCS4
|
|
||||||
----
|
|
||||||
|
|
||||||
MSB 7 6 5 4 3 2 1 0 LSB
|
MSB 7 6 5 4 3 2 1 0 LSB
|
||||||
LVD
|
LVD
|
||||||
|
@ -111,7 +111,31 @@ in set options packet:
|
|||||||
46 B9 6A 00 4B 04 00 00 5A A5 FF FF FF 00 FF FF
|
46 B9 6A 00 4B 04 00 00 5A A5 FF FF FF 00 FF FF
|
||||||
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
||||||
00 00 FF A8 FF EE FF E0 FF FD 03 FF FF FF FF FF
|
00 00 FF A8 FF EE FF E0 FF FD 03 FF FF FF FF FF
|
||||||
|
^^
|
||||||
|
MCSP
|
||||||
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
||||||
FF FD FF FF FF 75 BF F7 BC 9F 3A 80 16
|
FF FD FF FF FF 75 BF F7 BC 9F 3A 80 16
|
||||||
^^
|
^^
|
||||||
MCSY
|
MCSY
|
||||||
|
|
||||||
|
password setting
|
||||||
|
|
||||||
|
the password is sent with packet type 0x07 and checked before erase with packet type 0x05. setting the password uses two fields.
|
||||||
|
index 22 of the option block encodes the password length in bytes (MCSP, see above). bit 3 in MCS3 decides whether the password
|
||||||
|
will be checked. if the bit is set, no password check occurs. if it is reset, a password check occurs.
|
||||||
|
|
||||||
|
quick dump from USB-ISP packets:
|
||||||
|
|
||||||
|
set: foobar
|
||||||
|
0000 ff ff ff 00 ff ff 00 05 ff ff ff ff ff ff ff 07 ................
|
||||||
|
0010 ff ff ff ff ff ff ff 07 ff 06 01 ff 6e ff 36 58 ............n.6X
|
||||||
|
0020 ff 00 ff f5 03 ff ff 0c ff ff ff ff ff ff ff 07 ................
|
||||||
|
0030 ff ff ff ff ff ff ff 07 ff ff ff ff ff ff ec 1a ................
|
||||||
|
0040 ff ff ff 99 7f f7 bc 38 9f 61 .......8.a
|
||||||
|
|
||||||
|
reset:
|
||||||
|
0000 ff ff ff 00 ff ff 00 05 ff ff ff ff ff ff ff 07 ................
|
||||||
|
0010 ff ff ff ff ff ff ff 07 ff 00 01 ff 6e ff 36 5e ............n.6^
|
||||||
|
0020 ff 00 ff fd 03 ff ff 04 ff ff ff ff ff ff ff 07 ................
|
||||||
|
0030 ff ff ff ff ff ff ff 07 ff ff ff ff ff ff ec 1a ................
|
||||||
|
0040 ff ff ff 99 7f f7 bc 38 9f 61 .......8.a
|
||||||
|
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
|
||||||
|
|
35
doc/usb15-protocol.txt
Normal file
35
doc/usb15-protocol.txt
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
STC15 series USB ISP protocol
|
||||||
|
=============================
|
||||||
|
|
||||||
|
- 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 arbitrary size are used for writes
|
||||||
|
|
||||||
|
- packets from MCU
|
||||||
|
always start with 0x46 0xb9, similar to serial protocols
|
||||||
|
third byte is packet length
|
||||||
|
followed by data bytes
|
||||||
|
8 bit checksum at the end, looks like 8 bit modular subtraction
|
||||||
|
|
||||||
|
- packet types
|
||||||
|
most likely derived from the serial protocol, at least partially
|
||||||
|
|
||||||
|
info packet
|
||||||
|
- same as with serial protocol
|
||||||
|
|
||||||
|
option packet
|
||||||
|
- generally same as with serial protocol, some header stuff omitted
|
||||||
|
|
||||||
|
- 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 inverted modular sum
|
||||||
|
|
||||||
|
- option packet
|
||||||
|
wIndex is 0
|
||||||
|
wValue is 0xa55a
|
||||||
|
bRequest is 4
|
||||||
|
seems to use the same checksumming scheme
|
||||||
|
|
@ -1 +1 @@
|
|||||||
__version__ = "1.0"
|
__version__ = "1.3"
|
||||||
|
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())
|
@ -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":
|
||||||
@ -109,9 +111,9 @@ class StcGal:
|
|||||||
bindata = bindata[0:code_size]
|
bindata = bindata[0:code_size]
|
||||||
bindata += eedata
|
bindata += eedata
|
||||||
|
|
||||||
# pad to 256 byte boundary
|
# pad to 512 byte boundary
|
||||||
if len(bindata) % 256:
|
if len(bindata) % 512:
|
||||||
bindata += bytes(256 - len(bindata) % 256)
|
bindata += b'\xff' * (512 - len(bindata) % 512)
|
||||||
|
|
||||||
if self.opts.option: self.emit_options(self.opts.option)
|
if self.opts.option: self.emit_options(self.opts.option)
|
||||||
|
|
||||||
@ -190,11 +192,11 @@ 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("-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)
|
||||||
|
@ -839,28 +839,28 @@ class MCUModelDatabase:
|
|||||||
MCUModel(name='STC12C5420', magic=0xe014, total=32768, code=20480, eeprom=12288),
|
MCUModel(name='STC12C5420', magic=0xe014, total=32768, code=20480, eeprom=12288),
|
||||||
MCUModel(name='STC12C5424', magic=0xe018, total=32768, code=24576, eeprom=12288),
|
MCUModel(name='STC12C5424', magic=0xe018, total=32768, code=24576, eeprom=12288),
|
||||||
MCUModel(name='STC12C5428', magic=0xe01c, total=32768, code=28672, eeprom=12288),
|
MCUModel(name='STC12C5428', magic=0xe01c, total=32768, code=28672, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5401AD', magic=0xe0e1, total=32768, code=1024, eeprom=22016),
|
MCUModel(name='STC12LE5401AD', magic=0xe0e1, total=32768, code=1024, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5402AD', magic=0xe0e2, total=32768, code=2048, eeprom=20992),
|
MCUModel(name='STC12LE5402AD', magic=0xe0e2, total=32768, code=2048, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5404AD', magic=0xe0e4, total=32768, code=4096, eeprom=18944),
|
MCUModel(name='STC12LE5404AD', magic=0xe0e4, total=32768, code=4096, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5406AD', magic=0xe0e6, total=32768, code=6144, eeprom=16896),
|
MCUModel(name='STC12LE5406AD', magic=0xe0e6, total=32768, code=6144, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5408AD', magic=0xe0e8, total=32768, code=8192, eeprom=10752),
|
MCUModel(name='STC12LE5408AD', magic=0xe0e8, total=32768, code=8192, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5410AD', magic=0xe0ea, total=32768, code=10240, eeprom=4608),
|
MCUModel(name='STC12LE5410AD', magic=0xe0ea, total=32768, code=10240, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5412AD', magic=0xe0ec, total=32768, code=12288, eeprom=11776),
|
MCUModel(name='STC12LE5412AD', magic=0xe0ec, total=32768, code=12288, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5416AD', magic=0xe0f0, total=32768, code=16384, eeprom=12288),
|
MCUModel(name='STC12LE5416AD', magic=0xe0f0, total=32768, code=16384, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5420AD', magic=0xe0f4, total=32768, code=20480, eeprom=8192),
|
MCUModel(name='STC12LE5420AD', magic=0xe0f4, total=32768, code=20480, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5424AD', magic=0xe0f8, total=32768, code=24576, eeprom=4096),
|
MCUModel(name='STC12LE5424AD', magic=0xe0f8, total=32768, code=24576, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5428AD', magic=0xe0fc, total=32768, code=28672, eeprom=0),
|
MCUModel(name='STC12LE5428AD', magic=0xe0fc, total=32768, code=28672, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5401', magic=0xe081, total=32768, code=1024, eeprom=22016),
|
MCUModel(name='STC12LE5401', magic=0xe081, total=32768, code=1024, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5402', magic=0xe082, total=32768, code=2048, eeprom=20992),
|
MCUModel(name='STC12LE5402', magic=0xe082, total=32768, code=2048, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5404', magic=0xe084, total=32768, code=4096, eeprom=18944),
|
MCUModel(name='STC12LE5404', magic=0xe084, total=32768, code=4096, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5406', magic=0xe086, total=32768, code=6144, eeprom=16896),
|
MCUModel(name='STC12LE5406', magic=0xe086, total=32768, code=6144, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5408', magic=0xe088, total=32768, code=8192, eeprom=10752),
|
MCUModel(name='STC12LE5408', magic=0xe088, total=32768, code=8192, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5410', magic=0xe08a, total=32768, code=10240, eeprom=4608),
|
MCUModel(name='STC12LE5410', magic=0xe08a, total=32768, code=10240, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5412', magic=0xe08c, total=32768, code=12288, eeprom=11776),
|
MCUModel(name='STC12LE5412', magic=0xe08c, total=32768, code=12288, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5416', magic=0xe090, total=32768, code=16384, eeprom=12288),
|
MCUModel(name='STC12LE5416', magic=0xe090, total=32768, code=16384, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5420', magic=0xe094, total=32768, code=20480, eeprom=8192),
|
MCUModel(name='STC12LE5420', magic=0xe094, total=32768, code=20480, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5424', magic=0xe098, total=32768, code=24576, eeprom=4096),
|
MCUModel(name='STC12LE5424', magic=0xe098, total=32768, code=24576, eeprom=12288),
|
||||||
MCUModel(name='STC12LE5428', magic=0xe09c, total=32768, code=28672, eeprom=0),
|
MCUModel(name='STC12LE5428', magic=0xe09c, total=32768, code=28672, eeprom=12288),
|
||||||
MCUModel(name='STC12C1052AD', magic=0xf211, total=8192, code=1024, eeprom=5120),
|
MCUModel(name='STC12C1052AD', magic=0xf211, total=8192, code=1024, eeprom=5120),
|
||||||
MCUModel(name='STC12C2052AD', magic=0xf212, total=8192, code=2048, eeprom=4096),
|
MCUModel(name='STC12C2052AD', magic=0xf212, total=8192, code=2048, eeprom=4096),
|
||||||
MCUModel(name='STC12C3052AD', magic=0xf213, total=8192, code=3072, eeprom=3072),
|
MCUModel(name='STC12C3052AD', magic=0xf213, total=8192, code=3072, eeprom=3072),
|
||||||
|
608
stcgal/options.py
Normal file
608
stcgal/options.py
Normal file
@ -0,0 +1,608 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2013-2016 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 struct
|
||||||
|
from stcgal.utils import Utils
|
||||||
|
|
||||||
|
class BaseOption:
|
||||||
|
def print(self):
|
||||||
|
print("Target options:")
|
||||||
|
for name, get_func, _ in self.options:
|
||||||
|
print(" %s=%s" % (name, get_func()))
|
||||||
|
|
||||||
|
def set_option(self, name, value):
|
||||||
|
for opt, _, set_func in self.options:
|
||||||
|
if opt == name:
|
||||||
|
print("Option %s=%s" % (name, value))
|
||||||
|
set_func(value)
|
||||||
|
return
|
||||||
|
raise ValueError("unknown")
|
||||||
|
|
||||||
|
def get_option(self, name):
|
||||||
|
for opt, get_func, _ in self.options:
|
||||||
|
if opt == name:
|
||||||
|
return get_func(name)
|
||||||
|
raise ValueError("unknown")
|
||||||
|
|
||||||
|
def get_msr(self):
|
||||||
|
return bytes(self.msr)
|
||||||
|
|
||||||
|
|
||||||
|
class Stc89Option(BaseOption):
|
||||||
|
"""Manipulation STC89 series option byte"""
|
||||||
|
|
||||||
|
def __init__(self, msr):
|
||||||
|
self.msr = msr
|
||||||
|
self.options = (
|
||||||
|
("cpu_6t_enabled", self.get_t6, self.set_t6),
|
||||||
|
("bsl_pindetect_enabled", self.get_pindetect, self.set_pindetect),
|
||||||
|
("eeprom_erase_enabled", self.get_ee_erase, self.set_ee_erase),
|
||||||
|
("clock_gain", self.get_clock_gain, self.set_clock_gain),
|
||||||
|
("ale_enabled", self.get_ale, self.set_ale),
|
||||||
|
("xram_enabled", self.get_xram, self.set_xram),
|
||||||
|
("watchdog_por_enabled", self.get_watchdog, self.set_watchdog),
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_msr(self):
|
||||||
|
return self.msr
|
||||||
|
|
||||||
|
def get_t6(self):
|
||||||
|
return not bool(self.msr & 1)
|
||||||
|
|
||||||
|
def set_t6(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr &= 0xfe
|
||||||
|
self.msr |= 0x01 if not bool(val) else 0x00
|
||||||
|
|
||||||
|
def get_pindetect(self):
|
||||||
|
return not bool(self.msr & 4)
|
||||||
|
|
||||||
|
def set_pindetect(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr &= 0xfb
|
||||||
|
self.msr |= 0x04 if not bool(val) else 0x00
|
||||||
|
|
||||||
|
def get_ee_erase(self):
|
||||||
|
return not bool(self.msr & 8)
|
||||||
|
|
||||||
|
def set_ee_erase(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr &= 0xf7
|
||||||
|
self.msr |= 0x08 if not bool(val) else 0x00
|
||||||
|
|
||||||
|
def get_clock_gain(self):
|
||||||
|
gain = bool(self.msr & 16)
|
||||||
|
return "high" if gain else "low"
|
||||||
|
|
||||||
|
def set_clock_gain(self, val):
|
||||||
|
gains = {"low": 0, "high": 0x10}
|
||||||
|
if val not in gains.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(gains.keys()))
|
||||||
|
self.msr &= 0xef
|
||||||
|
self.msr |= gains[val]
|
||||||
|
|
||||||
|
def get_ale(self):
|
||||||
|
return bool(self.msr & 32)
|
||||||
|
|
||||||
|
def set_ale(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr &= 0xdf
|
||||||
|
self.msr |= 0x20 if bool(val) else 0x00
|
||||||
|
|
||||||
|
def get_xram(self):
|
||||||
|
return bool(self.msr & 64)
|
||||||
|
|
||||||
|
def set_xram(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr &= 0xbf
|
||||||
|
self.msr |= 0x40 if bool(val) else 0x00
|
||||||
|
|
||||||
|
def get_watchdog(self):
|
||||||
|
return not bool(self.msr & 128)
|
||||||
|
|
||||||
|
def set_watchdog(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr &= 0x7f
|
||||||
|
self.msr |= 0x80 if not bool(val) else 0x00
|
||||||
|
|
||||||
|
|
||||||
|
class Stc12AOption(BaseOption):
|
||||||
|
"""Manipulate STC12A series option bytes"""
|
||||||
|
|
||||||
|
def __init__(self, msr):
|
||||||
|
assert len(msr) == 4
|
||||||
|
self.msr = bytearray(msr)
|
||||||
|
|
||||||
|
"""list of options and their handlers"""
|
||||||
|
self.options = (
|
||||||
|
("low_voltage_reset", self.get_low_voltage_detect, self.set_low_voltage_detect),
|
||||||
|
("clock_source", self.get_clock_source, self.set_clock_source),
|
||||||
|
("watchdog_por_enabled", self.get_watchdog, self.set_watchdog),
|
||||||
|
("watchdog_stop_idle", self.get_watchdog_idle, self.set_watchdog_idle),
|
||||||
|
("watchdog_prescale", self.get_watchdog_prescale, self.set_watchdog_prescale),
|
||||||
|
("eeprom_erase_enabled", self.get_ee_erase, self.set_ee_erase),
|
||||||
|
("bsl_pindetect_enabled", self.get_pindetect, self.set_pindetect),
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_low_voltage_detect(self):
|
||||||
|
lvd = bool(self.msr[3] & 64)
|
||||||
|
return "high" if not lvd else "low"
|
||||||
|
|
||||||
|
def set_low_voltage_detect(self, val):
|
||||||
|
lvds = {"low": 1, "high": 0}
|
||||||
|
if val not in lvds.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(sources.keys()))
|
||||||
|
self.msr[3] &= 0xbf
|
||||||
|
self.msr[3] |= lvds[val] << 6
|
||||||
|
|
||||||
|
def get_clock_source(self):
|
||||||
|
source = bool(self.msr[0] & 2)
|
||||||
|
return "external" if source else "internal"
|
||||||
|
|
||||||
|
def set_clock_source(self, val):
|
||||||
|
sources = {"internal": 0, "external": 1}
|
||||||
|
if val not in sources.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(sources.keys()))
|
||||||
|
self.msr[0] &= 0xfd
|
||||||
|
self.msr[0] |= sources[val] << 1
|
||||||
|
|
||||||
|
def get_watchdog(self):
|
||||||
|
return not bool(self.msr[1] & 32)
|
||||||
|
|
||||||
|
def set_watchdog(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[1] &= 0xdf
|
||||||
|
self.msr[1] |= 0x20 if not val else 0x00
|
||||||
|
|
||||||
|
def get_watchdog_idle(self):
|
||||||
|
return not bool(self.msr[1] & 8)
|
||||||
|
|
||||||
|
def set_watchdog_idle(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[1] &= 0xf7
|
||||||
|
self.msr[1] |= 0x08 if not val else 0x00
|
||||||
|
|
||||||
|
def get_watchdog_prescale(self):
|
||||||
|
return 2 ** (((self.msr[1]) & 0x07) + 1)
|
||||||
|
|
||||||
|
def set_watchdog_prescale(self, val):
|
||||||
|
val = Utils.to_int(val)
|
||||||
|
wd_vals = {2: 0, 4: 1, 8: 2, 16: 3, 32: 4, 64: 5, 128: 6, 256: 7}
|
||||||
|
if val not in wd_vals.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(wd_vals.keys()))
|
||||||
|
self.msr[1] &= 0xf8
|
||||||
|
self.msr[1] |= wd_vals[val]
|
||||||
|
|
||||||
|
def get_ee_erase(self):
|
||||||
|
return not bool(self.msr[2] & 2)
|
||||||
|
|
||||||
|
def set_ee_erase(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[2] &= 0xfd
|
||||||
|
self.msr[2] |= 0x02 if not val else 0x00
|
||||||
|
|
||||||
|
def get_pindetect(self):
|
||||||
|
return not bool(self.msr[2] & 1)
|
||||||
|
|
||||||
|
def set_pindetect(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[2] &= 0xfe
|
||||||
|
self.msr[2] |= 0x01 if not val else 0x00
|
||||||
|
|
||||||
|
|
||||||
|
class Stc12Option(BaseOption):
|
||||||
|
"""Manipulate STC10/11/12 series option bytes"""
|
||||||
|
|
||||||
|
def __init__(self, msr):
|
||||||
|
assert len(msr) == 4
|
||||||
|
self.msr = bytearray(msr)
|
||||||
|
|
||||||
|
"""list of options and their handlers"""
|
||||||
|
self.options = (
|
||||||
|
("reset_pin_enabled", self.get_reset_pin_enabled, self.set_reset_pin_enabled),
|
||||||
|
("low_voltage_reset", self.get_low_voltage_detect, self.set_low_voltage_detect),
|
||||||
|
("oscillator_stable_delay", self.get_osc_stable_delay, self.set_osc_stable_delay),
|
||||||
|
("por_reset_delay", self.get_por_delay, self.set_por_delay),
|
||||||
|
("clock_gain", self.get_clock_gain, self.set_clock_gain),
|
||||||
|
("clock_source", self.get_clock_source, self.set_clock_source),
|
||||||
|
("watchdog_por_enabled", self.get_watchdog, self.set_watchdog),
|
||||||
|
("watchdog_stop_idle", self.get_watchdog_idle, self.set_watchdog_idle),
|
||||||
|
("watchdog_prescale", self.get_watchdog_prescale, self.set_watchdog_prescale),
|
||||||
|
("eeprom_erase_enabled", self.get_ee_erase, self.set_ee_erase),
|
||||||
|
("bsl_pindetect_enabled", self.get_pindetect, self.set_pindetect),
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_reset_pin_enabled(self):
|
||||||
|
return bool(self.msr[0] & 1)
|
||||||
|
|
||||||
|
def set_reset_pin_enabled(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[0] &= 0xfe
|
||||||
|
self.msr[0] |= 0x01 if bool(val) else 0x00
|
||||||
|
|
||||||
|
def get_low_voltage_detect(self):
|
||||||
|
return not bool(self.msr[0] & 64)
|
||||||
|
|
||||||
|
def set_low_voltage_detect(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[0] &= 0xbf
|
||||||
|
self.msr[0] |= 0x40 if not val else 0x00
|
||||||
|
|
||||||
|
def get_osc_stable_delay(self):
|
||||||
|
return 2 ** (((self.msr[0] >> 4) & 0x03) + 12)
|
||||||
|
|
||||||
|
def set_osc_stable_delay(self, val):
|
||||||
|
val = Utils.to_int(val)
|
||||||
|
osc_vals = {4096: 0, 8192: 1, 16384: 2, 32768: 3}
|
||||||
|
if val not in osc_vals.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(osc_vals.keys()))
|
||||||
|
self.msr[0] &= 0xcf
|
||||||
|
self.msr[0] |= osc_vals[val] << 4
|
||||||
|
|
||||||
|
def get_por_delay(self):
|
||||||
|
delay = not bool(self.msr[1] & 128)
|
||||||
|
return "long" if delay else "short"
|
||||||
|
|
||||||
|
def set_por_delay(self, val):
|
||||||
|
delays = {"short": 1, "long": 0}
|
||||||
|
if val not in delays.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(delays.keys()))
|
||||||
|
self.msr[1] &= 0x7f
|
||||||
|
self.msr[1] |= delays[val] << 7
|
||||||
|
|
||||||
|
def get_clock_gain(self):
|
||||||
|
gain = bool(self.msr[1] & 64)
|
||||||
|
return "high" if gain else "low"
|
||||||
|
|
||||||
|
def set_clock_gain(self, val):
|
||||||
|
gains = {"low": 0, "high": 1}
|
||||||
|
if val not in gains.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(gains.keys()))
|
||||||
|
self.msr[1] &= 0xbf
|
||||||
|
self.msr[1] |= gains[val] << 6
|
||||||
|
|
||||||
|
def get_clock_source(self):
|
||||||
|
source = bool(self.msr[1] & 2)
|
||||||
|
return "external" if source else "internal"
|
||||||
|
|
||||||
|
def set_clock_source(self, val):
|
||||||
|
sources = {"internal": 0, "external": 1}
|
||||||
|
if val not in sources.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(sources.keys()))
|
||||||
|
self.msr[1] &= 0xfd
|
||||||
|
self.msr[1] |= sources[val] << 1
|
||||||
|
|
||||||
|
def get_watchdog(self):
|
||||||
|
return not bool(self.msr[2] & 32)
|
||||||
|
|
||||||
|
def set_watchdog(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[2] &= 0xdf
|
||||||
|
self.msr[2] |= 0x20 if not val else 0x00
|
||||||
|
|
||||||
|
def get_watchdog_idle(self):
|
||||||
|
return not bool(self.msr[2] & 8)
|
||||||
|
|
||||||
|
def set_watchdog_idle(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[2] &= 0xf7
|
||||||
|
self.msr[2] |= 0x08 if not val else 0x00
|
||||||
|
|
||||||
|
def get_watchdog_prescale(self):
|
||||||
|
return 2 ** (((self.msr[2]) & 0x07) + 1)
|
||||||
|
|
||||||
|
def set_watchdog_prescale(self, val):
|
||||||
|
val = Utils.to_int(val)
|
||||||
|
wd_vals = {2: 0, 4: 1, 8: 2, 16: 3, 32: 4, 64: 5, 128: 6, 256: 7}
|
||||||
|
if val not in wd_vals.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(wd_vals.keys()))
|
||||||
|
self.msr[2] &= 0xf8
|
||||||
|
self.msr[2] |= wd_vals[val]
|
||||||
|
|
||||||
|
def get_ee_erase(self):
|
||||||
|
return not bool(self.msr[3] & 2)
|
||||||
|
|
||||||
|
def set_ee_erase(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[3] &= 0xfd
|
||||||
|
self.msr[3] |= 0x02 if not val else 0x00
|
||||||
|
|
||||||
|
def get_pindetect(self):
|
||||||
|
return not bool(self.msr[3] & 1)
|
||||||
|
|
||||||
|
def set_pindetect(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[3] &= 0xfe
|
||||||
|
self.msr[3] |= 0x01 if not val else 0x00
|
||||||
|
|
||||||
|
|
||||||
|
class Stc15AOption(BaseOption):
|
||||||
|
def __init__(self, msr):
|
||||||
|
assert len(msr) == 13
|
||||||
|
self.msr = bytearray(msr)
|
||||||
|
|
||||||
|
self.options = (
|
||||||
|
("reset_pin_enabled", self.get_reset_pin_enabled, self.set_reset_pin_enabled),
|
||||||
|
("watchdog_por_enabled", self.get_watchdog, self.set_watchdog),
|
||||||
|
("watchdog_stop_idle", self.get_watchdog_idle, self.set_watchdog_idle),
|
||||||
|
("watchdog_prescale", self.get_watchdog_prescale, self.set_watchdog_prescale),
|
||||||
|
("low_voltage_reset", self.get_lvrs, self.set_lvrs),
|
||||||
|
("low_voltage_threshold", self.get_low_voltage, self.set_low_voltage),
|
||||||
|
("eeprom_lvd_inhibit", self.get_eeprom_lvd, self.set_eeprom_lvd),
|
||||||
|
("eeprom_erase_enabled", self.get_ee_erase, self.set_ee_erase),
|
||||||
|
("bsl_pindetect_enabled", self.get_pindetect, self.set_pindetect),
|
||||||
|
)
|
||||||
|
|
||||||
|
def set_trim(self, val):
|
||||||
|
self.msr[3:5] = struct.pack(">H", val)
|
||||||
|
|
||||||
|
def get_reset_pin_enabled(self):
|
||||||
|
return bool(self.msr[0] & 16)
|
||||||
|
|
||||||
|
def set_reset_pin_enabled(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[0] &= 0xef
|
||||||
|
self.msr[0] |= 0x10 if bool(val) else 0x00
|
||||||
|
|
||||||
|
def get_watchdog(self):
|
||||||
|
return not bool(self.msr[2] & 32)
|
||||||
|
|
||||||
|
def set_watchdog(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[2] &= 0xdf
|
||||||
|
self.msr[2] |= 0x20 if not val else 0x00
|
||||||
|
|
||||||
|
def get_watchdog_idle(self):
|
||||||
|
return not bool(self.msr[2] & 8)
|
||||||
|
|
||||||
|
def set_watchdog_idle(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[2] &= 0xf7
|
||||||
|
self.msr[2] |= 0x08 if not val else 0x00
|
||||||
|
|
||||||
|
def get_watchdog_prescale(self):
|
||||||
|
return 2 ** (((self.msr[2]) & 0x07) + 1)
|
||||||
|
|
||||||
|
def set_watchdog_prescale(self, val):
|
||||||
|
val = Utils.to_int(val)
|
||||||
|
wd_vals = {2: 0, 4: 1, 8: 2, 16: 3, 32: 4, 64: 5, 128: 6, 256: 7}
|
||||||
|
if val not in wd_vals.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(wd_vals.keys()))
|
||||||
|
self.msr[2] &= 0xf8
|
||||||
|
self.msr[2] |= wd_vals[val]
|
||||||
|
|
||||||
|
def get_lvrs(self):
|
||||||
|
return bool(self.msr[1] & 64)
|
||||||
|
|
||||||
|
def set_lvrs(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[1] &= 0xbf
|
||||||
|
self.msr[1] |= 0x40 if val else 0x00
|
||||||
|
|
||||||
|
def get_eeprom_lvd(self):
|
||||||
|
return bool(self.msr[1] & 128)
|
||||||
|
|
||||||
|
def set_eeprom_lvd(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[1] &= 0x7f
|
||||||
|
self.msr[1] |= 0x80 if val else 0x00
|
||||||
|
|
||||||
|
def get_low_voltage(self):
|
||||||
|
return self.msr[1] & 0x07
|
||||||
|
|
||||||
|
def set_low_voltage(self, val):
|
||||||
|
val = Utils.to_int(val)
|
||||||
|
if val not in range(0, 8):
|
||||||
|
raise ValueError("must be one of %s" % list(range(0, 8)))
|
||||||
|
self.msr[1] &= 0xf8
|
||||||
|
self.msr[1] |= val
|
||||||
|
|
||||||
|
def get_ee_erase(self):
|
||||||
|
return not bool(self.msr[12] & 2)
|
||||||
|
|
||||||
|
def set_ee_erase(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[12] &= 0xfd
|
||||||
|
self.msr[12] |= 0x02 if not val else 0x00
|
||||||
|
|
||||||
|
def get_pindetect(self):
|
||||||
|
return not bool(self.msr[12] & 1)
|
||||||
|
|
||||||
|
def set_pindetect(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[12] &= 0xfe
|
||||||
|
self.msr[12] |= 0x01 if not val else 0x00
|
||||||
|
|
||||||
|
|
||||||
|
class Stc15Option(BaseOption):
|
||||||
|
def __init__(self, msr):
|
||||||
|
assert len(msr) >= 4
|
||||||
|
self.msr = bytearray(msr)
|
||||||
|
|
||||||
|
self.options = (
|
||||||
|
("reset_pin_enabled", self.get_reset_pin_enabled, self.set_reset_pin_enabled),
|
||||||
|
("clock_source", self.get_clock_source, self.set_clock_source),
|
||||||
|
("clock_gain", self.get_clock_gain, self.set_clock_gain),
|
||||||
|
("watchdog_por_enabled", self.get_watchdog, self.set_watchdog),
|
||||||
|
("watchdog_stop_idle", self.get_watchdog_idle, self.set_watchdog_idle),
|
||||||
|
("watchdog_prescale", self.get_watchdog_prescale, self.set_watchdog_prescale),
|
||||||
|
("low_voltage_reset", self.get_lvrs, self.set_lvrs),
|
||||||
|
("low_voltage_threshold", self.get_low_voltage, self.set_low_voltage),
|
||||||
|
("eeprom_lvd_inhibit", self.get_eeprom_lvd, self.set_eeprom_lvd),
|
||||||
|
("eeprom_erase_enabled", self.get_ee_erase, self.set_ee_erase),
|
||||||
|
("bsl_pindetect_enabled", self.get_pindetect, self.set_pindetect),
|
||||||
|
("por_reset_delay", self.get_por_delay, self.set_por_delay),
|
||||||
|
("rstout_por_state", self.get_p33_state, self.set_p33_state),
|
||||||
|
("uart2_passthrough", self.get_uart_passthrough, self.set_uart_passthrough),
|
||||||
|
("uart2_pin_mode", self.get_uart_pin_mode, self.set_uart_pin_mode),
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(msr) > 4:
|
||||||
|
self.options += ("cpu_core_voltage", self.get_core_voltage, self.set_core_voltage),
|
||||||
|
|
||||||
|
def get_reset_pin_enabled(self):
|
||||||
|
return not bool(self.msr[2] & 16)
|
||||||
|
|
||||||
|
def set_reset_pin_enabled(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[2] &= 0xef
|
||||||
|
self.msr[2] |= 0x10 if not bool(val) else 0x00
|
||||||
|
|
||||||
|
def get_clock_source(self):
|
||||||
|
source = bool(self.msr[2] & 0x01)
|
||||||
|
return "internal" if source else "external"
|
||||||
|
|
||||||
|
def set_clock_source(self, val):
|
||||||
|
sources = {"internal": 1, "external": 0}
|
||||||
|
if val not in sources.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(sources.keys()))
|
||||||
|
self.msr[2] &= 0xfe
|
||||||
|
self.msr[2] |= sources[val]
|
||||||
|
|
||||||
|
def get_clock_gain(self):
|
||||||
|
gain = bool(self.msr[2] & 0x02)
|
||||||
|
return "high" if gain else "low"
|
||||||
|
|
||||||
|
def set_clock_gain(self, val):
|
||||||
|
gains = {"low": 0, "high": 1}
|
||||||
|
if val not in gains.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(gains.keys()))
|
||||||
|
self.msr[2] &= 0xfd
|
||||||
|
self.msr[2] |= gains[val] << 1
|
||||||
|
|
||||||
|
def get_watchdog(self):
|
||||||
|
return not bool(self.msr[0] & 32)
|
||||||
|
|
||||||
|
def set_watchdog(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[0] &= 0xdf
|
||||||
|
self.msr[0] |= 0x20 if not val else 0x00
|
||||||
|
|
||||||
|
def get_watchdog_idle(self):
|
||||||
|
return not bool(self.msr[0] & 8)
|
||||||
|
|
||||||
|
def set_watchdog_idle(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[0] &= 0xf7
|
||||||
|
self.msr[0] |= 0x08 if not val else 0x00
|
||||||
|
|
||||||
|
def get_watchdog_prescale(self):
|
||||||
|
return 2 ** (((self.msr[0]) & 0x07) + 1)
|
||||||
|
|
||||||
|
def set_watchdog_prescale(self, val):
|
||||||
|
val = Utils.to_int(val)
|
||||||
|
wd_vals = {2: 0, 4: 1, 8: 2, 16: 3, 32: 4, 64: 5, 128: 6, 256: 7}
|
||||||
|
if val not in wd_vals.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(wd_vals.keys()))
|
||||||
|
self.msr[0] &= 0xf8
|
||||||
|
self.msr[0] |= wd_vals[val]
|
||||||
|
|
||||||
|
def get_lvrs(self):
|
||||||
|
return not bool(self.msr[1] & 64)
|
||||||
|
|
||||||
|
def set_lvrs(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[1] &= 0xbf
|
||||||
|
self.msr[1] |= 0x40 if not val else 0x00
|
||||||
|
|
||||||
|
def get_eeprom_lvd(self):
|
||||||
|
return bool(self.msr[1] & 128)
|
||||||
|
|
||||||
|
def set_eeprom_lvd(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[1] &= 0x7f
|
||||||
|
self.msr[1] |= 0x80 if val else 0x00
|
||||||
|
|
||||||
|
def get_low_voltage(self):
|
||||||
|
return self.msr[1] & 0x07
|
||||||
|
|
||||||
|
def set_low_voltage(self, val):
|
||||||
|
val = Utils.to_int(val)
|
||||||
|
if val not in range(0, 8):
|
||||||
|
raise ValueError("must be one of %s" % list(range(0, 8)))
|
||||||
|
self.msr[1] &= 0xf8
|
||||||
|
self.msr[1] |= val
|
||||||
|
|
||||||
|
def get_ee_erase(self):
|
||||||
|
return bool(self.msr[3] & 2)
|
||||||
|
|
||||||
|
def set_ee_erase(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[3] &= 0xfd
|
||||||
|
self.msr[3] |= 0x02 if val else 0x00
|
||||||
|
|
||||||
|
def get_pindetect(self):
|
||||||
|
return not bool(self.msr[3] & 1)
|
||||||
|
|
||||||
|
def set_pindetect(self, val):
|
||||||
|
val = Utils.to_bool(val);
|
||||||
|
self.msr[3] &= 0xfe
|
||||||
|
self.msr[3] |= 0x01 if not val else 0x00
|
||||||
|
|
||||||
|
def get_por_delay(self):
|
||||||
|
delay = bool(self.msr[2] & 128)
|
||||||
|
return "long" if delay else "short"
|
||||||
|
|
||||||
|
def set_por_delay(self, val):
|
||||||
|
delays = {"short": 0, "long": 1}
|
||||||
|
if val not in delays.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(delays.keys()))
|
||||||
|
self.msr[2] &= 0x7f
|
||||||
|
self.msr[2] |= delays[val] << 7
|
||||||
|
|
||||||
|
def get_p33_state(self):
|
||||||
|
return "high" if self.msr[2] & 0x08 else "low"
|
||||||
|
|
||||||
|
def set_p33_state(self, val):
|
||||||
|
val = Utils.to_bool(val)
|
||||||
|
self.msr[2] &= 0xf7
|
||||||
|
self.msr[2] |= 0x08 if val else 0x00
|
||||||
|
|
||||||
|
def get_uart_passthrough(self):
|
||||||
|
return bool(self.msr[2] & 0x40)
|
||||||
|
|
||||||
|
def set_uart_passthrough(self, val):
|
||||||
|
val = Utils.to_bool(val)
|
||||||
|
self.msr[2] &= 0xbf
|
||||||
|
self.msr[2] |= 0x40 if val else 0x00
|
||||||
|
|
||||||
|
def get_uart_pin_mode(self):
|
||||||
|
return "push-pull" if bool(self.msr[2] & 0x20) else "normal"
|
||||||
|
|
||||||
|
def set_uart_pin_mode(self, val):
|
||||||
|
delays = {"normal": 0, "push-pull": 1}
|
||||||
|
if val not in delays.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(delays.keys()))
|
||||||
|
self.msr[2] &= 0xdf
|
||||||
|
self.msr[2] |= 0x20 if val else 0x00
|
||||||
|
|
||||||
|
def get_core_voltage(self):
|
||||||
|
if self.msr[4] == 0xea: return "low"
|
||||||
|
elif self.msr[4] == 0xf7: return "mid"
|
||||||
|
elif self.msr[4] == 0xfd: return "high"
|
||||||
|
else: return "unknown"
|
||||||
|
|
||||||
|
def set_core_voltage(self, val):
|
||||||
|
volt_vals = {"low": 0xea, "mid": 0xf7, "high": 0xfd}
|
||||||
|
if val not in volt_vals.keys():
|
||||||
|
raise ValueError("must be one of %s" % list(volt_vals.keys()))
|
||||||
|
self.msr[4] = volt_vals[val]
|
@ -21,11 +21,12 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
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
|
||||||
from stcgal.utils import Utils
|
from stcgal.utils import Utils
|
||||||
|
from stcgal.options import *
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -45,588 +46,6 @@ class StcProtocolException(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BaseOption:
|
|
||||||
def print(self):
|
|
||||||
print("Target options:")
|
|
||||||
for name, get_func, _ in self.options:
|
|
||||||
print(" %s=%s" % (name, get_func()))
|
|
||||||
|
|
||||||
def set_option(self, name, value):
|
|
||||||
for opt, _, set_func in self.options:
|
|
||||||
if opt == name:
|
|
||||||
print("Option %s=%s" % (name, value))
|
|
||||||
set_func(value)
|
|
||||||
return
|
|
||||||
raise ValueError("unknown")
|
|
||||||
|
|
||||||
def get_option(self, name):
|
|
||||||
for opt, get_func, _ in self.options:
|
|
||||||
if opt == name:
|
|
||||||
return get_func(name)
|
|
||||||
raise ValueError("unknown")
|
|
||||||
|
|
||||||
def get_msr(self):
|
|
||||||
return bytes(self.msr)
|
|
||||||
|
|
||||||
|
|
||||||
class Stc89Option(BaseOption):
|
|
||||||
"""Manipulation STC89 series option byte"""
|
|
||||||
|
|
||||||
def __init__(self, msr):
|
|
||||||
self.msr = msr
|
|
||||||
self.options = (
|
|
||||||
("cpu_6t_enabled", self.get_t6, self.set_t6),
|
|
||||||
("bsl_pindetect_enabled", self.get_pindetect, self.set_pindetect),
|
|
||||||
("eeprom_erase_enabled", self.get_ee_erase, self.set_ee_erase),
|
|
||||||
("clock_gain", self.get_clock_gain, self.set_clock_gain),
|
|
||||||
("ale_enabled", self.get_ale, self.set_ale),
|
|
||||||
("xram_enabled", self.get_xram, self.set_xram),
|
|
||||||
("watchdog_por_enabled", self.get_watchdog, self.set_watchdog),
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_msr(self):
|
|
||||||
return self.msr
|
|
||||||
|
|
||||||
def get_t6(self):
|
|
||||||
return not bool(self.msr & 1)
|
|
||||||
|
|
||||||
def set_t6(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr &= 0xfe
|
|
||||||
self.msr |= 0x01 if not bool(val) else 0x00
|
|
||||||
|
|
||||||
def get_pindetect(self):
|
|
||||||
return not bool(self.msr & 4)
|
|
||||||
|
|
||||||
def set_pindetect(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr &= 0xfb
|
|
||||||
self.msr |= 0x04 if not bool(val) else 0x00
|
|
||||||
|
|
||||||
def get_ee_erase(self):
|
|
||||||
return not bool(self.msr & 8)
|
|
||||||
|
|
||||||
def set_ee_erase(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr &= 0xf7
|
|
||||||
self.msr |= 0x08 if not bool(val) else 0x00
|
|
||||||
|
|
||||||
def get_clock_gain(self):
|
|
||||||
gain = bool(self.msr & 16)
|
|
||||||
return "high" if gain else "low"
|
|
||||||
|
|
||||||
def set_clock_gain(self, val):
|
|
||||||
gains = {"low": 0, "high": 0x10}
|
|
||||||
if val not in gains.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(gains.keys()))
|
|
||||||
self.msr &= 0xef
|
|
||||||
self.msr |= gains[val]
|
|
||||||
|
|
||||||
def get_ale(self):
|
|
||||||
return bool(self.msr & 32)
|
|
||||||
|
|
||||||
def set_ale(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr &= 0xdf
|
|
||||||
self.msr |= 0x20 if bool(val) else 0x00
|
|
||||||
|
|
||||||
def get_xram(self):
|
|
||||||
return bool(self.msr & 64)
|
|
||||||
|
|
||||||
def set_xram(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr &= 0xbf
|
|
||||||
self.msr |= 0x40 if bool(val) else 0x00
|
|
||||||
|
|
||||||
def get_watchdog(self):
|
|
||||||
return not bool(self.msr & 128)
|
|
||||||
|
|
||||||
def set_watchdog(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr &= 0x7f
|
|
||||||
self.msr |= 0x80 if not bool(val) else 0x00
|
|
||||||
|
|
||||||
|
|
||||||
class Stc12AOption(BaseOption):
|
|
||||||
"""Manipulate STC12A series option bytes"""
|
|
||||||
|
|
||||||
def __init__(self, msr):
|
|
||||||
assert len(msr) == 5
|
|
||||||
self.msr = bytearray(msr)
|
|
||||||
|
|
||||||
"""list of options and their handlers"""
|
|
||||||
self.options = (
|
|
||||||
("low_voltage_reset", self.get_low_voltage_detect, self.set_low_voltage_detect),
|
|
||||||
("clock_source", self.get_clock_source, self.set_clock_source),
|
|
||||||
("watchdog_por_enabled", self.get_watchdog, self.set_watchdog),
|
|
||||||
("watchdog_stop_idle", self.get_watchdog_idle, self.set_watchdog_idle),
|
|
||||||
("watchdog_prescale", self.get_watchdog_prescale, self.set_watchdog_prescale),
|
|
||||||
("eeprom_erase_enabled", self.get_ee_erase, self.set_ee_erase),
|
|
||||||
("bsl_pindetect_enabled", self.get_pindetect, self.set_pindetect),
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_low_voltage_detect(self):
|
|
||||||
return not bool(self.msr[4] & 64)
|
|
||||||
|
|
||||||
def set_low_voltage_detect(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[4] &= 0xbf
|
|
||||||
self.msr[4] |= 0x40 if not val else 0x00
|
|
||||||
|
|
||||||
def get_clock_source(self):
|
|
||||||
source = bool(self.msr[0] & 2)
|
|
||||||
return "external" if source else "internal"
|
|
||||||
|
|
||||||
def set_clock_source(self, val):
|
|
||||||
sources = {"internal": 0, "external": 1}
|
|
||||||
if val not in sources.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(sources.keys()))
|
|
||||||
self.msr[0] &= 0xfd
|
|
||||||
self.msr[0] |= sources[val] << 1
|
|
||||||
|
|
||||||
def get_watchdog(self):
|
|
||||||
return not bool(self.msr[1] & 32)
|
|
||||||
|
|
||||||
def set_watchdog(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[1] &= 0xdf
|
|
||||||
self.msr[1] |= 0x20 if not val else 0x00
|
|
||||||
|
|
||||||
def get_watchdog_idle(self):
|
|
||||||
return not bool(self.msr[1] & 8)
|
|
||||||
|
|
||||||
def set_watchdog_idle(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[1] &= 0xf7
|
|
||||||
self.msr[1] |= 0x08 if not val else 0x00
|
|
||||||
|
|
||||||
def get_watchdog_prescale(self):
|
|
||||||
return 2 ** (((self.msr[1]) & 0x07) + 1)
|
|
||||||
|
|
||||||
def set_watchdog_prescale(self, val):
|
|
||||||
val = Utils.to_int(val)
|
|
||||||
wd_vals = {2: 0, 4: 1, 8: 2, 16: 3, 32: 4, 64: 5, 128: 6, 256: 7}
|
|
||||||
if val not in wd_vals.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(wd_vals.keys()))
|
|
||||||
self.msr[1] &= 0xf8
|
|
||||||
self.msr[1] |= wd_vals[val]
|
|
||||||
|
|
||||||
def get_ee_erase(self):
|
|
||||||
return not bool(self.msr[2] & 2)
|
|
||||||
|
|
||||||
def set_ee_erase(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[2] &= 0xfd
|
|
||||||
self.msr[2] |= 0x02 if not val else 0x00
|
|
||||||
|
|
||||||
def get_pindetect(self):
|
|
||||||
return not bool(self.msr[2] & 1)
|
|
||||||
|
|
||||||
def set_pindetect(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[2] &= 0xfe
|
|
||||||
self.msr[2] |= 0x01 if not val else 0x00
|
|
||||||
|
|
||||||
|
|
||||||
class Stc12Option(BaseOption):
|
|
||||||
"""Manipulate STC10/11/12 series option bytes"""
|
|
||||||
|
|
||||||
def __init__(self, msr):
|
|
||||||
assert len(msr) == 4
|
|
||||||
self.msr = bytearray(msr)
|
|
||||||
|
|
||||||
"""list of options and their handlers"""
|
|
||||||
self.options = (
|
|
||||||
("reset_pin_enabled", self.get_reset_pin_enabled, self.set_reset_pin_enabled),
|
|
||||||
("low_voltage_reset", self.get_low_voltage_detect, self.set_low_voltage_detect),
|
|
||||||
("oscillator_stable_delay", self.get_osc_stable_delay, self.set_osc_stable_delay),
|
|
||||||
("por_reset_delay", self.get_por_delay, self.set_por_delay),
|
|
||||||
("clock_gain", self.get_clock_gain, self.set_clock_gain),
|
|
||||||
("clock_source", self.get_clock_source, self.set_clock_source),
|
|
||||||
("watchdog_por_enabled", self.get_watchdog, self.set_watchdog),
|
|
||||||
("watchdog_stop_idle", self.get_watchdog_idle, self.set_watchdog_idle),
|
|
||||||
("watchdog_prescale", self.get_watchdog_prescale, self.set_watchdog_prescale),
|
|
||||||
("eeprom_erase_enabled", self.get_ee_erase, self.set_ee_erase),
|
|
||||||
("bsl_pindetect_enabled", self.get_pindetect, self.set_pindetect),
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_reset_pin_enabled(self):
|
|
||||||
return bool(self.msr[0] & 1)
|
|
||||||
|
|
||||||
def set_reset_pin_enabled(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[0] &= 0xfe
|
|
||||||
self.msr[0] |= 0x01 if bool(val) else 0x00
|
|
||||||
|
|
||||||
def get_low_voltage_detect(self):
|
|
||||||
return not bool(self.msr[0] & 64)
|
|
||||||
|
|
||||||
def set_low_voltage_detect(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[0] &= 0xbf
|
|
||||||
self.msr[0] |= 0x40 if not val else 0x00
|
|
||||||
|
|
||||||
def get_osc_stable_delay(self):
|
|
||||||
return 2 ** (((self.msr[0] >> 4) & 0x03) + 12)
|
|
||||||
|
|
||||||
def set_osc_stable_delay(self, val):
|
|
||||||
val = Utils.to_int(val)
|
|
||||||
osc_vals = {4096: 0, 8192: 1, 16384: 2, 32768: 3}
|
|
||||||
if val not in osc_vals.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(osc_vals.keys()))
|
|
||||||
self.msr[0] &= 0xcf
|
|
||||||
self.msr[0] |= osc_vals[val] << 4
|
|
||||||
|
|
||||||
def get_por_delay(self):
|
|
||||||
delay = not bool(self.msr[1] & 128)
|
|
||||||
return "long" if delay else "short"
|
|
||||||
|
|
||||||
def set_por_delay(self, val):
|
|
||||||
delays = {"short": 1, "long": 0}
|
|
||||||
if val not in delays.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(delays.keys()))
|
|
||||||
self.msr[1] &= 0x7f
|
|
||||||
self.msr[1] |= delays[val] << 7
|
|
||||||
|
|
||||||
def get_clock_gain(self):
|
|
||||||
gain = bool(self.msr[1] & 64)
|
|
||||||
return "high" if gain else "low"
|
|
||||||
|
|
||||||
def set_clock_gain(self, val):
|
|
||||||
gains = {"low": 0, "high": 1}
|
|
||||||
if val not in gains.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(gains.keys()))
|
|
||||||
self.msr[1] &= 0xbf
|
|
||||||
self.msr[1] |= gains[val] << 6
|
|
||||||
|
|
||||||
def get_clock_source(self):
|
|
||||||
source = bool(self.msr[1] & 2)
|
|
||||||
return "external" if source else "internal"
|
|
||||||
|
|
||||||
def set_clock_source(self, val):
|
|
||||||
sources = {"internal": 0, "external": 1}
|
|
||||||
if val not in sources.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(sources.keys()))
|
|
||||||
self.msr[1] &= 0xfd
|
|
||||||
self.msr[1] |= sources[val] << 1
|
|
||||||
|
|
||||||
def get_watchdog(self):
|
|
||||||
return not bool(self.msr[2] & 32)
|
|
||||||
|
|
||||||
def set_watchdog(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[2] &= 0xdf
|
|
||||||
self.msr[2] |= 0x20 if not val else 0x00
|
|
||||||
|
|
||||||
def get_watchdog_idle(self):
|
|
||||||
return not bool(self.msr[2] & 8)
|
|
||||||
|
|
||||||
def set_watchdog_idle(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[2] &= 0xf7
|
|
||||||
self.msr[2] |= 0x08 if not val else 0x00
|
|
||||||
|
|
||||||
def get_watchdog_prescale(self):
|
|
||||||
return 2 ** (((self.msr[2]) & 0x07) + 1)
|
|
||||||
|
|
||||||
def set_watchdog_prescale(self, val):
|
|
||||||
val = Utils.to_int(val)
|
|
||||||
wd_vals = {2: 0, 4: 1, 8: 2, 16: 3, 32: 4, 64: 5, 128: 6, 256: 7}
|
|
||||||
if val not in wd_vals.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(wd_vals.keys()))
|
|
||||||
self.msr[2] &= 0xf8
|
|
||||||
self.msr[2] |= wd_vals[val]
|
|
||||||
|
|
||||||
def get_ee_erase(self):
|
|
||||||
return not bool(self.msr[3] & 2)
|
|
||||||
|
|
||||||
def set_ee_erase(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[3] &= 0xfd
|
|
||||||
self.msr[3] |= 0x02 if not val else 0x00
|
|
||||||
|
|
||||||
def get_pindetect(self):
|
|
||||||
return not bool(self.msr[3] & 1)
|
|
||||||
|
|
||||||
def set_pindetect(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[3] &= 0xfe
|
|
||||||
self.msr[3] |= 0x01 if not val else 0x00
|
|
||||||
|
|
||||||
|
|
||||||
class Stc15AOption(BaseOption):
|
|
||||||
def __init__(self, msr):
|
|
||||||
assert len(msr) == 13
|
|
||||||
self.msr = bytearray(msr)
|
|
||||||
|
|
||||||
self.options = (
|
|
||||||
("reset_pin_enabled", self.get_reset_pin_enabled, self.set_reset_pin_enabled),
|
|
||||||
("watchdog_por_enabled", self.get_watchdog, self.set_watchdog),
|
|
||||||
("watchdog_stop_idle", self.get_watchdog_idle, self.set_watchdog_idle),
|
|
||||||
("watchdog_prescale", self.get_watchdog_prescale, self.set_watchdog_prescale),
|
|
||||||
("low_voltage_reset", self.get_lvrs, self.set_lvrs),
|
|
||||||
("low_voltage_threshold", self.get_low_voltage, self.set_low_voltage),
|
|
||||||
("eeprom_lvd_inhibit", self.get_eeprom_lvd, self.set_eeprom_lvd),
|
|
||||||
("eeprom_erase_enabled", self.get_ee_erase, self.set_ee_erase),
|
|
||||||
("bsl_pindetect_enabled", self.get_pindetect, self.set_pindetect),
|
|
||||||
)
|
|
||||||
|
|
||||||
def set_trim(self, val):
|
|
||||||
self.msr[3:5] = struct.pack(">H", val)
|
|
||||||
|
|
||||||
def get_reset_pin_enabled(self):
|
|
||||||
return bool(self.msr[0] & 16)
|
|
||||||
|
|
||||||
def set_reset_pin_enabled(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[0] &= 0xef
|
|
||||||
self.msr[0] |= 0x10 if bool(val) else 0x00
|
|
||||||
|
|
||||||
def get_watchdog(self):
|
|
||||||
return not bool(self.msr[2] & 32)
|
|
||||||
|
|
||||||
def set_watchdog(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[2] &= 0xdf
|
|
||||||
self.msr[2] |= 0x20 if not val else 0x00
|
|
||||||
|
|
||||||
def get_watchdog_idle(self):
|
|
||||||
return not bool(self.msr[2] & 8)
|
|
||||||
|
|
||||||
def set_watchdog_idle(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[2] &= 0xf7
|
|
||||||
self.msr[2] |= 0x08 if not val else 0x00
|
|
||||||
|
|
||||||
def get_watchdog_prescale(self):
|
|
||||||
return 2 ** (((self.msr[2]) & 0x07) + 1)
|
|
||||||
|
|
||||||
def set_watchdog_prescale(self, val):
|
|
||||||
val = Utils.to_int(val)
|
|
||||||
wd_vals = {2: 0, 4: 1, 8: 2, 16: 3, 32: 4, 64: 5, 128: 6, 256: 7}
|
|
||||||
if val not in wd_vals.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(wd_vals.keys()))
|
|
||||||
self.msr[2] &= 0xf8
|
|
||||||
self.msr[2] |= wd_vals[val]
|
|
||||||
|
|
||||||
def get_lvrs(self):
|
|
||||||
return bool(self.msr[1] & 64)
|
|
||||||
|
|
||||||
def set_lvrs(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[1] &= 0xbf
|
|
||||||
self.msr[1] |= 0x40 if val else 0x00
|
|
||||||
|
|
||||||
def get_eeprom_lvd(self):
|
|
||||||
return bool(self.msr[1] & 128)
|
|
||||||
|
|
||||||
def set_eeprom_lvd(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[1] &= 0x7f
|
|
||||||
self.msr[1] |= 0x80 if val else 0x00
|
|
||||||
|
|
||||||
def get_low_voltage(self):
|
|
||||||
return self.msr[1] & 0x07
|
|
||||||
|
|
||||||
def set_low_voltage(self, val):
|
|
||||||
val = Utils.to_int(val)
|
|
||||||
if val not in range(0, 8):
|
|
||||||
raise ValueError("must be one of %s" % list(range(0, 8)))
|
|
||||||
self.msr[1] &= 0xf8
|
|
||||||
self.msr[1] |= val
|
|
||||||
|
|
||||||
def get_ee_erase(self):
|
|
||||||
return not bool(self.msr[12] & 2)
|
|
||||||
|
|
||||||
def set_ee_erase(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[12] &= 0xfd
|
|
||||||
self.msr[12] |= 0x02 if not val else 0x00
|
|
||||||
|
|
||||||
def get_pindetect(self):
|
|
||||||
return not bool(self.msr[12] & 1)
|
|
||||||
|
|
||||||
def set_pindetect(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[12] &= 0xfe
|
|
||||||
self.msr[12] |= 0x01 if not val else 0x00
|
|
||||||
|
|
||||||
|
|
||||||
class Stc15Option(BaseOption):
|
|
||||||
def __init__(self, msr):
|
|
||||||
assert len(msr) >= 4
|
|
||||||
self.msr = bytearray(msr)
|
|
||||||
|
|
||||||
self.options = (
|
|
||||||
("reset_pin_enabled", self.get_reset_pin_enabled, self.set_reset_pin_enabled),
|
|
||||||
("clock_source", self.get_clock_source, self.set_clock_source),
|
|
||||||
("clock_gain", self.get_clock_gain, self.set_clock_gain),
|
|
||||||
("watchdog_por_enabled", self.get_watchdog, self.set_watchdog),
|
|
||||||
("watchdog_stop_idle", self.get_watchdog_idle, self.set_watchdog_idle),
|
|
||||||
("watchdog_prescale", self.get_watchdog_prescale, self.set_watchdog_prescale),
|
|
||||||
("low_voltage_reset", self.get_lvrs, self.set_lvrs),
|
|
||||||
("low_voltage_threshold", self.get_low_voltage, self.set_low_voltage),
|
|
||||||
("eeprom_lvd_inhibit", self.get_eeprom_lvd, self.set_eeprom_lvd),
|
|
||||||
("eeprom_erase_enabled", self.get_ee_erase, self.set_ee_erase),
|
|
||||||
("bsl_pindetect_enabled", self.get_pindetect, self.set_pindetect),
|
|
||||||
("por_reset_delay", self.get_por_delay, self.set_por_delay),
|
|
||||||
("rstout_por_state", self.get_p33_state, self.set_p33_state),
|
|
||||||
("uart2_passthrough", self.get_uart_passthrough, self.set_uart_passthrough),
|
|
||||||
("uart2_pin_mode", self.get_uart_pin_mode, self.set_uart_pin_mode),
|
|
||||||
)
|
|
||||||
|
|
||||||
if len(msr) > 4:
|
|
||||||
self.options += ("cpu_core_voltage", self.get_core_voltage, self.set_core_voltage),
|
|
||||||
|
|
||||||
def get_reset_pin_enabled(self):
|
|
||||||
return not bool(self.msr[2] & 16)
|
|
||||||
|
|
||||||
def set_reset_pin_enabled(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[2] &= 0xef
|
|
||||||
self.msr[2] |= 0x10 if not bool(val) else 0x00
|
|
||||||
|
|
||||||
def get_clock_source(self):
|
|
||||||
source = bool(self.msr[2] & 0x01)
|
|
||||||
return "internal" if source else "external"
|
|
||||||
|
|
||||||
def set_clock_source(self, val):
|
|
||||||
sources = {"internal": 1, "external": 0}
|
|
||||||
if val not in sources.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(sources.keys()))
|
|
||||||
self.msr[2] &= 0xfe
|
|
||||||
self.msr[2] |= sources[val]
|
|
||||||
|
|
||||||
def get_clock_gain(self):
|
|
||||||
gain = bool(self.msr[2] & 0x02)
|
|
||||||
return "high" if gain else "low"
|
|
||||||
|
|
||||||
def set_clock_gain(self, val):
|
|
||||||
gains = {"low": 0, "high": 1}
|
|
||||||
if val not in gains.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(gains.keys()))
|
|
||||||
self.msr[2] &= 0xfd
|
|
||||||
self.msr[2] |= gains[val] << 1
|
|
||||||
|
|
||||||
def get_watchdog(self):
|
|
||||||
return not bool(self.msr[0] & 32)
|
|
||||||
|
|
||||||
def set_watchdog(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[0] &= 0xdf
|
|
||||||
self.msr[0] |= 0x20 if not val else 0x00
|
|
||||||
|
|
||||||
def get_watchdog_idle(self):
|
|
||||||
return not bool(self.msr[0] & 8)
|
|
||||||
|
|
||||||
def set_watchdog_idle(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[0] &= 0xf7
|
|
||||||
self.msr[0] |= 0x08 if not val else 0x00
|
|
||||||
|
|
||||||
def get_watchdog_prescale(self):
|
|
||||||
return 2 ** (((self.msr[0]) & 0x07) + 1)
|
|
||||||
|
|
||||||
def set_watchdog_prescale(self, val):
|
|
||||||
val = Utils.to_int(val)
|
|
||||||
wd_vals = {2: 0, 4: 1, 8: 2, 16: 3, 32: 4, 64: 5, 128: 6, 256: 7}
|
|
||||||
if val not in wd_vals.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(wd_vals.keys()))
|
|
||||||
self.msr[0] &= 0xf8
|
|
||||||
self.msr[0] |= wd_vals[val]
|
|
||||||
|
|
||||||
def get_lvrs(self):
|
|
||||||
return not bool(self.msr[1] & 64)
|
|
||||||
|
|
||||||
def set_lvrs(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[1] &= 0xbf
|
|
||||||
self.msr[1] |= 0x40 if not val else 0x00
|
|
||||||
|
|
||||||
def get_eeprom_lvd(self):
|
|
||||||
return bool(self.msr[1] & 128)
|
|
||||||
|
|
||||||
def set_eeprom_lvd(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[1] &= 0x7f
|
|
||||||
self.msr[1] |= 0x80 if val else 0x00
|
|
||||||
|
|
||||||
def get_low_voltage(self):
|
|
||||||
return self.msr[1] & 0x07
|
|
||||||
|
|
||||||
def set_low_voltage(self, val):
|
|
||||||
val = Utils.to_int(val)
|
|
||||||
if val not in range(0, 8):
|
|
||||||
raise ValueError("must be one of %s" % list(range(0, 8)))
|
|
||||||
self.msr[1] &= 0xf8
|
|
||||||
self.msr[1] |= val
|
|
||||||
|
|
||||||
def get_ee_erase(self):
|
|
||||||
return bool(self.msr[3] & 2)
|
|
||||||
|
|
||||||
def set_ee_erase(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[3] &= 0xfd
|
|
||||||
self.msr[3] |= 0x02 if val else 0x00
|
|
||||||
|
|
||||||
def get_pindetect(self):
|
|
||||||
return not bool(self.msr[3] & 1)
|
|
||||||
|
|
||||||
def set_pindetect(self, val):
|
|
||||||
val = Utils.to_bool(val);
|
|
||||||
self.msr[3] &= 0xfe
|
|
||||||
self.msr[3] |= 0x01 if not val else 0x00
|
|
||||||
|
|
||||||
def get_por_delay(self):
|
|
||||||
delay = bool(self.msr[2] & 128)
|
|
||||||
return "long" if delay else "short"
|
|
||||||
|
|
||||||
def set_por_delay(self, val):
|
|
||||||
delays = {"short": 0, "long": 1}
|
|
||||||
if val not in delays.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(delays.keys()))
|
|
||||||
self.msr[2] &= 0x7f
|
|
||||||
self.msr[2] |= delays[val] << 7
|
|
||||||
|
|
||||||
def get_p33_state(self):
|
|
||||||
return "high" if self.msr[2] & 0x08 else "low"
|
|
||||||
|
|
||||||
def set_p33_state(self, val):
|
|
||||||
val = Utils.to_bool(val)
|
|
||||||
self.msr[2] &= 0xf7
|
|
||||||
self.msr[2] |= 0x08 if val else 0x00
|
|
||||||
|
|
||||||
def get_uart_passthrough(self):
|
|
||||||
return bool(self.msr[2] & 0x40)
|
|
||||||
|
|
||||||
def set_uart_passthrough(self, val):
|
|
||||||
val = Utils.to_bool(val)
|
|
||||||
self.msr[2] &= 0xbf
|
|
||||||
self.msr[2] |= 0x40 if val else 0x00
|
|
||||||
|
|
||||||
def get_uart_pin_mode(self):
|
|
||||||
return "push-pull" if bool(self.msr[2] & 0x20) else "normal"
|
|
||||||
|
|
||||||
def set_uart_pin_mode(self, val):
|
|
||||||
delays = {"normal": 0, "push-pull": 1}
|
|
||||||
if val not in delays.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(delays.keys()))
|
|
||||||
self.msr[2] &= 0xdf
|
|
||||||
self.msr[2] |= 0x20 if val else 0x00
|
|
||||||
|
|
||||||
def get_core_voltage(self):
|
|
||||||
if self.msr[4] == 0xea: return "low"
|
|
||||||
elif self.msr[4] == 0xf7: return "mid"
|
|
||||||
elif self.msr[4] == 0xfd: return "high"
|
|
||||||
else: return "unknown"
|
|
||||||
|
|
||||||
def set_core_voltage(self, val):
|
|
||||||
volt_vals = {"low": 0xea, "mid": 0xf7, "high": 0xfd}
|
|
||||||
if val not in volt_vals.keys():
|
|
||||||
raise ValueError("must be one of %s" % list(volt_vals.keys()))
|
|
||||||
self.msr[4] = volt_vals[val]
|
|
||||||
|
|
||||||
|
|
||||||
class StcBaseProtocol:
|
class StcBaseProtocol:
|
||||||
"""Basic functionality for STC BSL protocols"""
|
"""Basic functionality for STC BSL protocols"""
|
||||||
|
|
||||||
@ -695,7 +114,11 @@ class StcBaseProtocol:
|
|||||||
|
|
||||||
# read and check frame start magic
|
# read and check frame start magic
|
||||||
packet = bytes()
|
packet = bytes()
|
||||||
packet += self.read_bytes_safe(1)
|
# XXX: skip extraneous 0xFE byte?
|
||||||
|
leading = self.read_bytes_safe(1)
|
||||||
|
if leading == 0xfe:
|
||||||
|
leading = self.read_bytes_safe(1)
|
||||||
|
packet += leading
|
||||||
# Some (?) BSL versions don't send a frame start with the status
|
# Some (?) BSL versions don't send a frame start with the status
|
||||||
# packet. Let's be liberal and accept that always, just in case.
|
# packet. Let's be liberal and accept that always, just in case.
|
||||||
if packet[0] == self.PACKET_MCU[0]:
|
if packet[0] == self.PACKET_MCU[0]:
|
||||||
@ -775,6 +198,7 @@ class StcBaseProtocol:
|
|||||||
|
|
||||||
protocol_database = [("stc89", "STC(89|90)(C|LE)\d"),
|
protocol_database = [("stc89", "STC(89|90)(C|LE)\d"),
|
||||||
("stc12a", "STC12(C|LE)\d052"),
|
("stc12a", "STC12(C|LE)\d052"),
|
||||||
|
("stc12b", "STC12(C|LE)(52|56)"),
|
||||||
("stc12", "(STC|IAP)(10|11|12)\D"),
|
("stc12", "(STC|IAP)(10|11|12)\D"),
|
||||||
("stc15a", "(STC|IAP)15[FL][01]0\d(E|EA|)$"),
|
("stc15a", "(STC|IAP)15[FL][01]0\d(E|EA|)$"),
|
||||||
("stc15", "(STC|IAP|IRC)15\D")]
|
("stc15", "(STC|IAP|IRC)15\D")]
|
||||||
@ -1012,6 +436,7 @@ class Stc89Protocol(StcBaseProtocol):
|
|||||||
|
|
||||||
# check new baudrate
|
# check new baudrate
|
||||||
print("Switching to %d baud: " % self.baud_transfer, end="")
|
print("Switching to %d baud: " % self.baud_transfer, end="")
|
||||||
|
sys.stdout.flush()
|
||||||
brt, brt_csum, iap, delay = self.calculate_baud()
|
brt, brt_csum, iap, delay = self.calculate_baud()
|
||||||
print("checking ", end="")
|
print("checking ", end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
@ -1109,7 +534,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
|
||||||
@ -1130,6 +585,8 @@ class Stc12AProtocol(Stc89Protocol):
|
|||||||
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.
|
||||||
|
|
||||||
@ -1160,7 +617,7 @@ class Stc12AProtocol(Stc89Protocol):
|
|||||||
"""Initialize options"""
|
"""Initialize options"""
|
||||||
|
|
||||||
# create option state
|
# create option state
|
||||||
self.options = Stc12AOption(status_packet[23:28])
|
self.options = Stc12AOption(status_packet[23:26] + status_packet[29:30])
|
||||||
self.options.print()
|
self.options.print()
|
||||||
|
|
||||||
def handshake(self):
|
def handshake(self):
|
||||||
@ -1228,23 +685,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()
|
||||||
|
# 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],
|
packet = bytes([0x8d, msr[0], msr[1], msr[2], msr[3],
|
||||||
msr[4]])
|
0xff, 0xff, 0xff, 0xff, msr[3], 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
|
||||||
|
|
||||||
packet += struct.pack(">I", int(self.mcu_clock_hz))
|
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")
|
||||||
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
|
||||||
@ -1306,6 +774,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.
|
||||||
|
|
||||||
@ -1336,7 +806,7 @@ class Stc12Protocol(StcBaseProtocol):
|
|||||||
"""Initialize options"""
|
"""Initialize options"""
|
||||||
|
|
||||||
# create option state
|
# create option state
|
||||||
self.options = Stc12Option(status_packet[23:27])
|
self.options = Stc12Option(status_packet[23:26] + status_packet[27:28])
|
||||||
self.options.print()
|
self.options.print()
|
||||||
|
|
||||||
def handshake(self):
|
def handshake(self):
|
||||||
@ -1425,8 +895,6 @@ class Stc12Protocol(StcBaseProtocol):
|
|||||||
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")
|
||||||
@ -1441,26 +909,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()
|
|
||||||
packet = bytes([0x8d, msr[0], msr[1], msr[2], msr[3],
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 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):
|
||||||
@ -1836,7 +1297,7 @@ 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)
|
||||||
@ -1997,12 +1458,6 @@ class StcUsb15Protocol(Stc15Protocol):
|
|||||||
"""PID of STC devices"""
|
"""PID of STC devices"""
|
||||||
USB_PID = 0x4312
|
USB_PID = 0x4312
|
||||||
|
|
||||||
"""Control transfer from host to device"""
|
|
||||||
USB_HOST2DEV = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_RECIPIENT_DEVICE | usb.util.CTRL_OUT
|
|
||||||
|
|
||||||
"""Control transfer from device to host"""
|
|
||||||
USB_DEV2HOST = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_RECIPIENT_DEVICE | usb.util.CTRL_IN
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# XXX: this is really ugly!
|
# XXX: this is really ugly!
|
||||||
Stc15Protocol.__init__(self, "", 0, 0, 0)
|
Stc15Protocol.__init__(self, "", 0, 0, 0)
|
||||||
@ -2016,7 +1471,8 @@ class StcUsb15Protocol(Stc15Protocol):
|
|||||||
def read_packet(self):
|
def read_packet(self):
|
||||||
"""Read a packet from the MCU"""
|
"""Read a packet from the MCU"""
|
||||||
|
|
||||||
packet = self.dev.ctrl_transfer(self.USB_DEV2HOST, 0, 0, 0, 132).tobytes()
|
dev2host = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_RECIPIENT_DEVICE | usb.util.CTRL_IN
|
||||||
|
packet = self.dev.ctrl_transfer(dev2host, 0, 0, 0, 132).tobytes()
|
||||||
if len(packet) < 5 or packet[0] != 0x46 or packet[1] != 0xb9:
|
if len(packet) < 5 or packet[0] != 0x46 or packet[1] != 0xb9:
|
||||||
self.dump_packet(packet)
|
self.dump_packet(packet)
|
||||||
raise StcFramingException("incorrect frame start")
|
raise StcFramingException("incorrect frame start")
|
||||||
@ -2049,7 +1505,8 @@ class StcUsb15Protocol(Stc15Protocol):
|
|||||||
i += 7
|
i += 7
|
||||||
|
|
||||||
self.dump_packet(chunks, request, value, index, receive=False)
|
self.dump_packet(chunks, request, value, index, receive=False)
|
||||||
self.dev.ctrl_transfer(self.USB_HOST2DEV, request, value, index, chunks);
|
host2dev = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_RECIPIENT_DEVICE | usb.util.CTRL_OUT
|
||||||
|
self.dev.ctrl_transfer(host2dev, request, value, index, chunks);
|
||||||
|
|
||||||
def connect(self, autoreset=False):
|
def connect(self, autoreset=False):
|
||||||
"""Connect to USB device and read info packet"""
|
"""Connect to USB device and read info packet"""
|
||||||
@ -2069,9 +1526,15 @@ class StcUsb15Protocol(Stc15Protocol):
|
|||||||
if self.dev:
|
if self.dev:
|
||||||
self.dev.set_configuration()
|
self.dev.set_configuration()
|
||||||
self.status_packet = self.read_packet()
|
self.status_packet = self.read_packet()
|
||||||
else:
|
if len(self.status_packet) < 38:
|
||||||
|
self.status_packet = None
|
||||||
|
raise StcFramingException
|
||||||
|
else: raise StcFramingException
|
||||||
|
except StcFramingException:
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
except (StcFramingException, usb.core.USBError): pass
|
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")
|
||||||
|
Reference in New Issue
Block a user