Compare commits
18 Commits
usbisp
...
stc15-baud
Author | SHA1 | Date | |
---|---|---|---|
b4c7f34d39 | |||
65a7759647 | |||
8ad77586d4 | |||
276c696fa4 | |||
26ef34991b | |||
f90fe4152b | |||
d6ef028dc7 | |||
979d7f513f | |||
fce2f01232 | |||
854f36100b | |||
92f4def11a | |||
6c0af88551 | |||
366a3a5bd3 | |||
c046e886e3 | |||
7ba95eab68 | |||
61a4fa0e4f | |||
da5f6678c5 | |||
a8f141584d |
19
README.md
19
README.md
@ -111,17 +111,18 @@ Most importantly, ```-p``` sets the serial port to be used for programming.
|
||||
### Protocols
|
||||
|
||||
STC MCUs use a variety of related but incompatible protocols for the
|
||||
BSL. The protocol can be specified with the ```-P``` flag. Optionally,
|
||||
experimental protocol autodetection can be used. The mapping between
|
||||
protocols and MCU series is as follows:
|
||||
BSL. The protocol can be specified with the ```-P``` flag. By default
|
||||
UART protocol autodetection is used. The mapping between protocols
|
||||
and MCU series is as follows:
|
||||
|
||||
* ```stc89``` STC 89/90 series
|
||||
* ```stc12a``` STC12Cx052AD and possibly others
|
||||
* ```stc12``` Most STC10/11/12 series (default)
|
||||
* ```stc89``` STC89/90 series
|
||||
* ```stc12a``` STC12x052 series and possibly others
|
||||
* ```stc12b``` STC12x52 series, STC12x56 series and possibly others
|
||||
* ```stc12``` Most STC10/11/12 series
|
||||
* ```stc15a``` STC15x104E and STC15x204E(A) series
|
||||
* ```stc15``` Most STC15 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 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
|
||||
```xram_enabled``` | true/false | STC89 only | Use internal XRAM (STC89 only)
|
||||
```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
|
||||
```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.
|
||||
|
7
debian/changelog
vendored
7
debian/changelog
vendored
@ -1,3 +1,10 @@
|
||||
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
|
||||
|
||||
* Initial Debianized Release
|
||||
|
18
debian/control
vendored
18
debian/control
vendored
@ -10,17 +10,17 @@ X-Python3-Version: >= 3.2
|
||||
Package: stcgal
|
||||
Architecture: all
|
||||
Depends: ${misc:Depends}, python3, python3-serial
|
||||
Recommends: python3-usb (>= 1.0.0~b2)
|
||||
Description: STC MCU ISP flash tool
|
||||
stcgal is a command line flash programming tool for STC MCU Ltd. 8051
|
||||
compatible microcontrollers. The name was inspired by avrdude.
|
||||
stcgal is a command line flash programming tool for STC MCU Ltd.
|
||||
8051 compatible microcontrollers. The name was inspired by avrdude.
|
||||
.
|
||||
STC microcontrollers have a UART based boot strap loader (BSL). It
|
||||
utilizes a packet-based protocol to flash the code memory and
|
||||
IAP memory over a serial link. This is referred to as in-system
|
||||
programming (ISP). The BSL is also used to configure various
|
||||
(fuse-like) device options. Unfortunately, this protocol is not
|
||||
publicly documented and STC only provide a (crude) Windows GUI
|
||||
application for programming.
|
||||
STC microcontrollers have an UART/USB based boot strap loader (BSL). It
|
||||
utilizes a packet-based protocol to flash the code memory and IAP
|
||||
memory over a serial link. This is referred to as in-system programming
|
||||
(ISP). The BSL is also used to configure various (fuse-like) device
|
||||
options. Unfortunately, this protocol is not publicly documented and
|
||||
STC only provide a (crude) Windows GUI application for programming.
|
||||
.
|
||||
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
|
||||
|
@ -25,12 +25,12 @@ for i in range(MCU_TABLE_SIZE):
|
||||
inp.seek(mcu_name_offset)
|
||||
name_str = inp.read(16).split(b'\00')[0].decode("ascii")
|
||||
|
||||
# XXX: 1 KB are reserved one *some* MCUs for some reason
|
||||
#if ee_size > 0 and not name_str.startswith("IAP"):
|
||||
# ee_size -= 1024
|
||||
# TODO: With some MCUs, the amount of available EEPROM depends on the BSL version.
|
||||
# Generally, newer BSLs free up a KB of additional EEPROM. Currently, always the
|
||||
# maximum amount (with newer BSL) is reported.
|
||||
|
||||
# STC12C54xx always have 12 KB eeprom
|
||||
if name_str.startswith("STC12C54"):
|
||||
# STC12x54xx always have 12 KB eeprom
|
||||
if name_str.startswith("STC12C54") or name_str.startswith("STC12LE54"):
|
||||
ee_size = 12 * 1024
|
||||
|
||||
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,
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
MCS3
|
||||
----
|
||||
|
||||
Unused.
|
||||
|
||||
|
||||
MCS4
|
||||
----
|
||||
MCS3 (at index 6!)
|
||||
------------------
|
||||
|
||||
MSB 7 6 5 4 3 2 1 0 LSB
|
||||
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
|
||||
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
|
||||
^^
|
||||
MCSP
|
||||
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
|
||||
^^
|
||||
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
|
||||
|
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.2"
|
||||
|
@ -37,6 +37,8 @@ class StcGal:
|
||||
self.protocol = Stc89Protocol(opts.port, opts.handshake, opts.baud)
|
||||
elif opts.protocol == "stc12a":
|
||||
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":
|
||||
self.protocol = Stc12Protocol(opts.port, opts.handshake, opts.baud)
|
||||
elif opts.protocol == "stc15a":
|
||||
@ -109,9 +111,9 @@ class StcGal:
|
||||
bindata = bindata[0:code_size]
|
||||
bindata += eedata
|
||||
|
||||
# pad to 256 byte boundary
|
||||
if len(bindata) % 256:
|
||||
bindata += bytes(256 - len(bindata) % 256)
|
||||
# pad to 512 byte boundary
|
||||
if len(bindata) % 512:
|
||||
bindata += b'\xff' * (512 - len(bindata) % 512)
|
||||
|
||||
if self.opts.option: self.emit_options(self.opts.option)
|
||||
|
||||
@ -194,7 +196,7 @@ def cli():
|
||||
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("-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("-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)
|
||||
|
@ -839,28 +839,28 @@ class MCUModelDatabase:
|
||||
MCUModel(name='STC12C5420', magic=0xe014, total=32768, code=20480, 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='STC12LE5401AD', magic=0xe0e1, total=32768, code=1024, eeprom=22016),
|
||||
MCUModel(name='STC12LE5402AD', magic=0xe0e2, total=32768, code=2048, eeprom=20992),
|
||||
MCUModel(name='STC12LE5404AD', magic=0xe0e4, total=32768, code=4096, eeprom=18944),
|
||||
MCUModel(name='STC12LE5406AD', magic=0xe0e6, total=32768, code=6144, eeprom=16896),
|
||||
MCUModel(name='STC12LE5408AD', magic=0xe0e8, total=32768, code=8192, eeprom=10752),
|
||||
MCUModel(name='STC12LE5410AD', magic=0xe0ea, total=32768, code=10240, eeprom=4608),
|
||||
MCUModel(name='STC12LE5412AD', magic=0xe0ec, total=32768, code=12288, eeprom=11776),
|
||||
MCUModel(name='STC12LE5401AD', magic=0xe0e1, total=32768, code=1024, eeprom=12288),
|
||||
MCUModel(name='STC12LE5402AD', magic=0xe0e2, total=32768, code=2048, eeprom=12288),
|
||||
MCUModel(name='STC12LE5404AD', magic=0xe0e4, total=32768, code=4096, eeprom=12288),
|
||||
MCUModel(name='STC12LE5406AD', magic=0xe0e6, total=32768, code=6144, eeprom=12288),
|
||||
MCUModel(name='STC12LE5408AD', magic=0xe0e8, total=32768, code=8192, eeprom=12288),
|
||||
MCUModel(name='STC12LE5410AD', magic=0xe0ea, total=32768, code=10240, eeprom=12288),
|
||||
MCUModel(name='STC12LE5412AD', magic=0xe0ec, total=32768, code=12288, 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='STC12LE5424AD', magic=0xe0f8, total=32768, code=24576, eeprom=4096),
|
||||
MCUModel(name='STC12LE5428AD', magic=0xe0fc, total=32768, code=28672, eeprom=0),
|
||||
MCUModel(name='STC12LE5401', magic=0xe081, total=32768, code=1024, eeprom=22016),
|
||||
MCUModel(name='STC12LE5402', magic=0xe082, total=32768, code=2048, eeprom=20992),
|
||||
MCUModel(name='STC12LE5404', magic=0xe084, total=32768, code=4096, eeprom=18944),
|
||||
MCUModel(name='STC12LE5406', magic=0xe086, total=32768, code=6144, eeprom=16896),
|
||||
MCUModel(name='STC12LE5408', magic=0xe088, total=32768, code=8192, eeprom=10752),
|
||||
MCUModel(name='STC12LE5410', magic=0xe08a, total=32768, code=10240, eeprom=4608),
|
||||
MCUModel(name='STC12LE5412', magic=0xe08c, total=32768, code=12288, eeprom=11776),
|
||||
MCUModel(name='STC12LE5420AD', magic=0xe0f4, total=32768, code=20480, eeprom=12288),
|
||||
MCUModel(name='STC12LE5424AD', magic=0xe0f8, total=32768, code=24576, eeprom=12288),
|
||||
MCUModel(name='STC12LE5428AD', magic=0xe0fc, total=32768, code=28672, eeprom=12288),
|
||||
MCUModel(name='STC12LE5401', magic=0xe081, total=32768, code=1024, eeprom=12288),
|
||||
MCUModel(name='STC12LE5402', magic=0xe082, total=32768, code=2048, eeprom=12288),
|
||||
MCUModel(name='STC12LE5404', magic=0xe084, total=32768, code=4096, eeprom=12288),
|
||||
MCUModel(name='STC12LE5406', magic=0xe086, total=32768, code=6144, eeprom=12288),
|
||||
MCUModel(name='STC12LE5408', magic=0xe088, total=32768, code=8192, eeprom=12288),
|
||||
MCUModel(name='STC12LE5410', magic=0xe08a, total=32768, code=10240, eeprom=12288),
|
||||
MCUModel(name='STC12LE5412', magic=0xe08c, total=32768, code=12288, 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='STC12LE5424', magic=0xe098, total=32768, code=24576, eeprom=4096),
|
||||
MCUModel(name='STC12LE5428', magic=0xe09c, total=32768, code=28672, eeprom=0),
|
||||
MCUModel(name='STC12LE5420', magic=0xe094, total=32768, code=20480, eeprom=12288),
|
||||
MCUModel(name='STC12LE5424', magic=0xe098, total=32768, code=24576, eeprom=12288),
|
||||
MCUModel(name='STC12LE5428', magic=0xe09c, total=32768, code=28672, eeprom=12288),
|
||||
MCUModel(name='STC12C1052AD', magic=0xf211, total=8192, code=1024, eeprom=5120),
|
||||
MCUModel(name='STC12C2052AD', magic=0xf212, total=8192, code=2048, eeprom=4096),
|
||||
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 sys, os, time, struct, re
|
||||
import sys, os, time, struct, re, errno
|
||||
import argparse
|
||||
import collections
|
||||
from stcgal.models import MCUModelDatabase
|
||||
from stcgal.utils import Utils
|
||||
from stcgal.options import *
|
||||
import functools
|
||||
|
||||
try:
|
||||
@ -45,588 +46,6 @@ class StcProtocolException(Exception):
|
||||
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:
|
||||
"""Basic functionality for STC BSL protocols"""
|
||||
|
||||
@ -775,6 +194,7 @@ class StcBaseProtocol:
|
||||
|
||||
protocol_database = [("stc89", "STC(89|90)(C|LE)\d"),
|
||||
("stc12a", "STC12(C|LE)\d052"),
|
||||
("stc12b", "STC12(C|LE)(52|56)"),
|
||||
("stc12", "(STC|IAP)(10|11|12)\D"),
|
||||
("stc15a", "(STC|IAP)15[FL][01]0\d(E|EA|)$"),
|
||||
("stc15", "(STC|IAP|IRC)15\D")]
|
||||
@ -1012,6 +432,7 @@ class Stc89Protocol(StcBaseProtocol):
|
||||
|
||||
# check new baudrate
|
||||
print("Switching to %d baud: " % self.baud_transfer, end="")
|
||||
sys.stdout.flush()
|
||||
brt, brt_csum, iap, delay = self.calculate_baud()
|
||||
print("checking ", end="")
|
||||
sys.stdout.flush()
|
||||
@ -1109,7 +530,37 @@ class Stc89Protocol(StcBaseProtocol):
|
||||
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"""
|
||||
ERASE_COUNTDOWN = 0x0d
|
||||
@ -1130,6 +581,8 @@ class Stc12AProtocol(Stc89Protocol):
|
||||
self.mcu_bsl_version = "%d.%d%s" % (bl_version >> 4, bl_version & 0x0f,
|
||||
chr(bl_stepping))
|
||||
|
||||
self.bsl_version = bl_version
|
||||
|
||||
def calculate_baud(self):
|
||||
"""Calculate MCU baudrate setting.
|
||||
|
||||
@ -1160,7 +613,7 @@ class Stc12AProtocol(Stc89Protocol):
|
||||
"""Initialize options"""
|
||||
|
||||
# create option state
|
||||
self.options = Stc12AOption(status_packet[23:28])
|
||||
self.options = Stc12AOption(status_packet[23:26] + status_packet[29:30])
|
||||
self.options.print()
|
||||
|
||||
def handshake(self):
|
||||
@ -1228,23 +681,34 @@ class Stc12AProtocol(Stc89Protocol):
|
||||
raise StcProtocolException("incorrect magic in erase packet")
|
||||
print("done")
|
||||
|
||||
|
||||
class Stc12OptionsMixIn:
|
||||
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],
|
||||
msr[4]])
|
||||
0xff, 0xff, 0xff, 0xff, msr[3], 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
|
||||
|
||||
packet += struct.pack(">I", int(self.mcu_clock_hz))
|
||||
self.write_packet(packet)
|
||||
response = self.read_packet()
|
||||
if response[0] != 0x80:
|
||||
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
|
||||
if not self.uid:
|
||||
self.uid = response[18:25]
|
||||
|
||||
class Stc12Protocol(StcBaseProtocol):
|
||||
"""Protocol handler for STC 10/11/12 series"""
|
||||
print("Target UID: %s" % Utils.hexstr(self.uid))
|
||||
|
||||
|
||||
class Stc12BaseProtocol(StcBaseProtocol):
|
||||
"""Base class for STC 10/11/12 series protocol handlers"""
|
||||
|
||||
"""block size for programming flash"""
|
||||
PROGRAM_BLOCKSIZE = 128
|
||||
@ -1306,6 +770,8 @@ class Stc12Protocol(StcBaseProtocol):
|
||||
self.mcu_bsl_version = "%d.%d%s" % (bl_version >> 4, bl_version & 0x0f,
|
||||
chr(bl_stepping))
|
||||
|
||||
self.bsl_version = bl_version
|
||||
|
||||
def calculate_baud(self):
|
||||
"""Calculate MCU baudrate setting.
|
||||
|
||||
@ -1336,7 +802,7 @@ class Stc12Protocol(StcBaseProtocol):
|
||||
"""Initialize options"""
|
||||
|
||||
# create option state
|
||||
self.options = Stc12Option(status_packet[23:27])
|
||||
self.options = Stc12Option(status_packet[23:26] + status_packet[27:28])
|
||||
self.options.print()
|
||||
|
||||
def handshake(self):
|
||||
@ -1425,8 +891,6 @@ class Stc12Protocol(StcBaseProtocol):
|
||||
response = self.read_packet()
|
||||
if response[0] != 0x00:
|
||||
raise StcProtocolException("incorrect magic in write packet")
|
||||
elif response[1] != csum:
|
||||
raise StcProtocolException("verification checksum mismatch")
|
||||
print(".", end="")
|
||||
sys.stdout.flush()
|
||||
print(" done")
|
||||
@ -1441,26 +905,19 @@ class Stc12Protocol(StcBaseProtocol):
|
||||
raise StcProtocolException("incorrect magic in finish packet")
|
||||
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))
|
||||
self.write_packet(packet)
|
||||
response = self.read_packet()
|
||||
if response[0] != 0x50:
|
||||
raise StcProtocolException("incorrect magic in option packet")
|
||||
print("done")
|
||||
class Stc12Protocol(Stc12OptionsMixIn, Stc12BaseProtocol):
|
||||
"""STC 10/11/12 series protocol handler"""
|
||||
|
||||
# If UID wasn't sent with erase acknowledge, it should be in this packet
|
||||
if not self.uid:
|
||||
self.uid = response[18:25]
|
||||
def __init__(self, port, handshake, baud):
|
||||
Stc12BaseProtocol.__init__(self, port, handshake, baud)
|
||||
|
||||
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):
|
||||
@ -1836,7 +1293,7 @@ class Stc15Protocol(Stc15AProtocol):
|
||||
# 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
|
||||
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)
|
||||
packet += bytes([iap_wait])
|
||||
self.write_packet(packet)
|
||||
@ -1997,12 +1454,6 @@ class StcUsb15Protocol(Stc15Protocol):
|
||||
"""PID of STC devices"""
|
||||
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):
|
||||
# XXX: this is really ugly!
|
||||
Stc15Protocol.__init__(self, "", 0, 0, 0)
|
||||
@ -2016,7 +1467,8 @@ class StcUsb15Protocol(Stc15Protocol):
|
||||
def read_packet(self):
|
||||
"""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:
|
||||
self.dump_packet(packet)
|
||||
raise StcFramingException("incorrect frame start")
|
||||
@ -2049,7 +1501,8 @@ class StcUsb15Protocol(Stc15Protocol):
|
||||
i += 7
|
||||
|
||||
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):
|
||||
"""Connect to USB device and read info packet"""
|
||||
@ -2069,9 +1522,15 @@ class StcUsb15Protocol(Stc15Protocol):
|
||||
if self.dev:
|
||||
self.dev.set_configuration()
|
||||
self.status_packet = self.read_packet()
|
||||
else:
|
||||
time.sleep(0.5)
|
||||
except (StcFramingException, usb.core.USBError): pass
|
||||
if len(self.status_packet) < 38:
|
||||
self.status_packet = None
|
||||
raise StcFramingException
|
||||
else: raise StcFramingException
|
||||
except StcFramingException:
|
||||
time.sleep(0.5)
|
||||
except usb.core.USBError as err:
|
||||
if err.errno == errno.EACCES:
|
||||
raise IOError(err.strerror)
|
||||
|
||||
self.initialize_model()
|
||||
print("done")
|
||||
|
Reference in New Issue
Block a user