Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
af153a89e7 |
95
README.md
95
README.md
@ -4,16 +4,15 @@ stcgal - STC MCU ISP flash tool
|
|||||||
stcgal is a command line flash programming tool for STC MCU Ltd. [1]
|
stcgal is a command line flash programming tool for STC MCU Ltd. [1]
|
||||||
8051 compatible microcontrollers. The name was inspired by avrdude [2].
|
8051 compatible microcontrollers. The name was inspired by avrdude [2].
|
||||||
|
|
||||||
STC microcontrollers have an UART/USB based boot strap loader (BSL). It
|
STC microcontrollers have a UART based boot strap loader (BSL). It
|
||||||
utilizes a packet-based protocol to flash the code memory and IAP
|
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
|
memory over a serial link. This is referred to as in-system programming (ISP).
|
||||||
(ISP). The BSL is also used to configure various (fuse-like) device
|
The BSL is also used to configure various (fuse-like) device
|
||||||
options. Unfortunately, this protocol is not publicly documented and
|
options. Unfortunately, this protocol is not publicly documented and
|
||||||
STC only provide a (crude) Windows GUI application for programming.
|
STC only provide a (crude) Windows GUI 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;
|
||||||
software; it supports a wide range of MCUs, it is very portable and
|
it supports a wide range of MCUs, it is very portable and suitable for automation.
|
||||||
suitable for automation.
|
|
||||||
|
|
||||||
[1] http://stcmcu.com/
|
[1] http://stcmcu.com/
|
||||||
[2] http://www.nongnu.org/avrdude/
|
[2] http://www.nongnu.org/avrdude/
|
||||||
@ -25,33 +24,24 @@ 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/6.6C)
|
* STC89C52RC (BSL version: 4.3C)
|
||||||
* STC90C52RC (BSL version: 4.3C)
|
|
||||||
* STC89C54RD+ (BSL version: 4.3C)
|
|
||||||
* STC12C2052 (BSL version: 5.8D)
|
|
||||||
* STC12C2052AD (BSL version: 5.8D)
|
* STC12C2052AD (BSL version: 5.8D)
|
||||||
* STC12C5608AD (BSL version: 6.0G)
|
* STC12C5A60S2 (BSL version: 6.2I)
|
||||||
* STC12C5A16S2 (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)
|
|
||||||
* STC11F08XE (BSL version: 6.5M)
|
* STC11F08XE (BSL version: 6.5M)
|
||||||
* STC12C5204AD (BSL version: 6.6H)
|
|
||||||
* STC15F104E (BSL version: 6.7Q)
|
* STC15F104E (BSL version: 6.7Q)
|
||||||
* STC15F204EA (BSL version: 6.7R)
|
* STC15F204EA (BSL version: 6.7R)
|
||||||
* STC15L104W (BSL version: 7.1.4Q)
|
* STC15L104W (BSL version: 7.1Q)
|
||||||
* STC15F104W (BSL version: 7.1.4Q)
|
* IAP15F2K61S2 (BSL version: 7.1S)
|
||||||
* IAP15F2K61S2 (BSL version: 7.1.4S)
|
|
||||||
* STC15L2K16S2 (BSL version: 7.2.4S)
|
* STC15L2K16S2 (BSL version: 7.2.4S)
|
||||||
* STC15W408AS (BSL version: 7.2.4T)
|
* STC15W408AS (BSL version: 7.2.4T)
|
||||||
* STC15W4K56S4 (BSL version: 7.3.4T, UART and USB mode)
|
* STC15W4K56S4 (BSL version: 7.3.4T)
|
||||||
|
|
||||||
Compatibility reports, both negative and positive, are welcome.
|
More compatibility testing is going to happen soon.
|
||||||
|
|
||||||
Features
|
Features
|
||||||
--------
|
--------
|
||||||
|
|
||||||
* UART and USB BSL support
|
|
||||||
* Display part info
|
* Display part info
|
||||||
* Determine operating frequency
|
* Determine operating frequency
|
||||||
* Program flash memory
|
* Program flash memory
|
||||||
@ -59,14 +49,11 @@ Features
|
|||||||
* Set device options
|
* Set device options
|
||||||
* Read unique device ID (STC 10/11/12/15)
|
* Read unique device ID (STC 10/11/12/15)
|
||||||
* Trim RC oscillator frequency (STC 15)
|
* Trim RC oscillator frequency (STC 15)
|
||||||
* Automatic power-cycling with DTR toggle
|
|
||||||
* Automatic UART protocol detection
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
|
||||||
stcgal requires Python 3.2 (or later) and pySerial. USB support is
|
stcgal requires Python 3.2 (or later) and pySerial. You can run stcgal
|
||||||
optional and requires pyusb 1.0.0b2 or later. You can run stcgal
|
|
||||||
directly with the included ```stcgal.py``` script. The recommended
|
directly with the included ```stcgal.py``` script. The recommended
|
||||||
method for permanent installation is to use Python's setuptools. Run
|
method for permanent installation is to use Python's setuptools. Run
|
||||||
```./setup.py build``` to build and ```sudo ./setup.py install```
|
```./setup.py build``` to build and ```sudo ./setup.py install```
|
||||||
@ -79,27 +66,24 @@ Usage
|
|||||||
Call stcgal with ```-h``` for usage information.
|
Call stcgal with ```-h``` for usage information.
|
||||||
|
|
||||||
```
|
```
|
||||||
usage: stcgal.py [-h] [-a] [-P {stc89,stc12a,stc12,stc15a,stc15,auto}]
|
usage: stcgal.py [-h] [-P {stc89,stc12a,stc12,stc15a,stc15}] [-p PORT]
|
||||||
[-p PORT] [-b BAUD] [-l HANDSHAKE] [-o OPTION] [-t TRIM] [-D]
|
[-b BAUD] [-l HANDSHAKE] [-o OPTION] [-t TRIM] [-D]
|
||||||
[code_image] [eeprom_image]
|
[code_binary] [eeprom_binary]
|
||||||
|
|
||||||
stcgal 1.0 - an STC MCU ISP flash tool
|
stcgal 1.0 - an STC MCU ISP flash tool
|
||||||
(C) 2014-2015 Grigori Goronzy
|
|
||||||
https://github.com/grigorig/stcgal
|
|
||||||
|
|
||||||
positional arguments:
|
positional arguments:
|
||||||
code_image code segment file to flash (BIN/HEX)
|
code_binary code segment binary file to flash
|
||||||
eeprom_image eeprom segment file to flash (BIN/HEX)
|
eeprom_binary eeprom segment binary file to flash
|
||||||
|
|
||||||
optional arguments:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
-a, --autoreset cycle power automatically by asserting DTR
|
-P {stc89,stc12a,stc12,stc15a,stc15}, --protocol {stc89,stc12a,stc12,stc15a,stc15}
|
||||||
-P {stc89,stc12a,stc12,stc15a,stc15,auto}, --protocol {stc89,stc12a,stc12,stc15a,stc15,auto}
|
|
||||||
protocol version
|
protocol version
|
||||||
-p PORT, --port PORT serial port device
|
-p PORT, --port PORT serial port device
|
||||||
-b BAUD, --baud BAUD transfer baud rate (default: 19200)
|
-b BAUD, --baud BAUD transfer baud rate (default: 19200)
|
||||||
-l HANDSHAKE, --handshake HANDSHAKE
|
-l HANDSHAKE, --handshake HANDSHAKE
|
||||||
handshake baud rate (default: 2400)
|
handshake baud rate (default: 1200)
|
||||||
-o OPTION, --option OPTION
|
-o OPTION, --option OPTION
|
||||||
set option (can be used multiple times)
|
set option (can be used multiple times)
|
||||||
-t TRIM, --trim TRIM RC oscillator frequency in kHz (STC15 series only)
|
-t TRIM, --trim TRIM RC oscillator frequency in kHz (STC15 series only)
|
||||||
@ -111,18 +95,14 @@ 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. By default
|
BSL. The protocol must be specified with the ```-P``` flag. Here's
|
||||||
UART protocol autodetection is used. The mapping between protocols
|
the general mapping between protocols and MCU series:
|
||||||
and MCU series is as follows:
|
|
||||||
|
|
||||||
* ```stc89``` STC89/90 series
|
* ```stc89``` STC 89/90 series
|
||||||
* ```stc12a``` STC12x052 series and possibly others
|
* ```stc12a``` STC12Cx052AD and possibly others
|
||||||
* ```stc12b``` STC12x52 series, STC12x56 series and possibly others
|
|
||||||
* ```stc12``` Most STC10/11/12 series
|
* ```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
|
|
||||||
* ```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,
|
||||||
@ -241,9 +221,7 @@ 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``` | low/high | STC12A/STC12 | Low-voltage reset level (low: ~3.3V, high: ~3.7V)
|
```low_voltage_reset ``` | true/false | STC12A+ | Low-voltage reset (brownout)
|
||||||
```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.
|
||||||
@ -266,31 +244,6 @@ device options. Use the ```-t``` flag to request trimming to a certain
|
|||||||
value. Generally, frequencies between 4 and 35 MHz can be achieved. If
|
value. Generally, frequencies between 4 and 35 MHz can be achieved. If
|
||||||
trimming fails, stcgal will abort.
|
trimming fails, stcgal will abort.
|
||||||
|
|
||||||
### Automatic power-cycling
|
|
||||||
|
|
||||||
STC's microcontrollers require a power-on reset to invoke the bootloader,
|
|
||||||
which can be inconvenient. stcgal can use the DTR control signal of a
|
|
||||||
serial interface to automate this. The DTR signal is asserted for
|
|
||||||
approximately 500 ms when the autoreset feature is enabled with the
|
|
||||||
```-a``` flag. This requires external circuitry to actually switch the
|
|
||||||
power. In some cases, when the microcontroller draws only little power,
|
|
||||||
it is possible to directly supply power from the DTR signal, however.
|
|
||||||
|
|
||||||
### Exit status
|
|
||||||
|
|
||||||
The exit status is 0 if no error occured while executing stcgal. Any
|
|
||||||
error, such as a protocol error or I/O error, results in an exit
|
|
||||||
status of 1. If the the user aborted stcgal by pressing CTRL-C,
|
|
||||||
that results in an exit status of 2.
|
|
||||||
|
|
||||||
### USB support
|
|
||||||
|
|
||||||
STC15W4 series have an USB-based BSL that can be optionally
|
|
||||||
used. USB support in stcgal is experimental and might change in the
|
|
||||||
future. USB mode is enabled by using the ```usb15``` protocol. The
|
|
||||||
port (```-p```) flag as well as the baudrate options are ignored for
|
|
||||||
the USB protocol. RC frequency trimming is not supported.
|
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
13
debian/changelog
vendored
13
debian/changelog
vendored
@ -1,16 +1,3 @@
|
|||||||
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.
|
stcgal is a command line flash programming tool for STC MCU Ltd. 8051
|
||||||
8051 compatible microcontrollers. The name was inspired by avrdude.
|
compatible microcontrollers. The name was inspired by avrdude.
|
||||||
.
|
.
|
||||||
STC microcontrollers have an UART/USB based boot strap loader (BSL). It
|
STC microcontrollers have a UART based boot strap loader (BSL). It
|
||||||
utilizes a packet-based protocol to flash the code memory and IAP
|
utilizes a packet-based protocol to flash the code memory and
|
||||||
memory over a serial link. This is referred to as in-system programming
|
IAP memory over a serial link. This is referred to as in-system
|
||||||
(ISP). The BSL is also used to configure various (fuse-like) device
|
programming (ISP). The BSL is also used to configure various
|
||||||
options. Unfortunately, this protocol is not publicly documented and
|
(fuse-like) device options. Unfortunately, this protocol is not
|
||||||
STC only provide a (crude) Windows GUI application for programming.
|
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
|
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
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# This curious script dumps all model info from STC-ISP.
|
# This curious script dumps all model info from STC-ISP.
|
||||||
# Data is directly read from the binary.
|
# Data is directly read from the binary.
|
||||||
# Offsets are for stc-isp-15xx-v6.85K.exe, sha1sum aa66e4c1ab49de27369b83c954a7c202acce0950
|
# Offsets are for STC-ISP 6.85I, sha1sum a1a625d6c491fe98d0286ebac0a8d78b94dca81d
|
||||||
|
|
||||||
MCU_TABLE_OFFSET = 0x00064550
|
MCU_TABLE_OFFSET = 0x00063550
|
||||||
MCU_TABLE_SIZE = 941
|
MCU_TABLE_SIZE = 914
|
||||||
MCU_RECORD_SIZE = 32
|
MCU_RECORD_SIZE = 32
|
||||||
MCU_NAMES_OFFSET = 0x0007e80c
|
MCU_NAMES_OFFSET = 0x0007d708
|
||||||
MCU_NAMES_PTR_OFFSET = 0x0047e80c
|
MCU_NAMES_PTR_OFFSET = 0x0047d708
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
@ -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")
|
||||||
|
|
||||||
# TODO: With some MCUs, the amount of available EEPROM depends on the BSL version.
|
# XXX: 1 KB are reserved one *some* MCUs for some reason
|
||||||
# Generally, newer BSLs free up a KB of additional EEPROM. Currently, always the
|
#if ee_size > 0 and not name_str.startswith("IAP"):
|
||||||
# maximum amount (with newer BSL) is reported.
|
# ee_size -= 1024
|
||||||
|
|
||||||
# STC12x54xx always have 12 KB eeprom
|
# STC12C54xx always have 12 KB eeprom
|
||||||
if name_str.startswith("STC12C54") or name_str.startswith("STC12LE54"):
|
if name_str.startswith("STC12C54"):
|
||||||
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 7 MCS bytes have active
|
In STC12A series, the first 4 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,9 +47,14 @@ 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
|
||||||
|
----
|
||||||
|
|
||||||
MCS3 (at index 6!)
|
Unused.
|
||||||
------------------
|
|
||||||
|
|
||||||
|
MCS4
|
||||||
|
----
|
||||||
|
|
||||||
MSB 7 6 5 4 3 2 1 0 LSB
|
MSB 7 6 5 4 3 2 1 0 LSB
|
||||||
LVD
|
LVD
|
||||||
|
@ -111,31 +111,7 @@ 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
|
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
24
setup.py
24
setup.py
@ -1,25 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
#
|
|
||||||
# Copyright (c) 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 stcgal
|
import stcgal
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
@ -29,9 +8,6 @@ setup(
|
|||||||
version = stcgal.__version__,
|
version = stcgal.__version__,
|
||||||
packages = find_packages(exclude=["doc"]),
|
packages = find_packages(exclude=["doc"]),
|
||||||
install_requires = ["pyserial"],
|
install_requires = ["pyserial"],
|
||||||
extras_require = {
|
|
||||||
"usb": ["pyusb>=1.0.0"]
|
|
||||||
},
|
|
||||||
entry_points = {
|
entry_points = {
|
||||||
"console_scripts": [
|
"console_scripts": [
|
||||||
"stcgal = stcgal.frontend:cli",
|
"stcgal = stcgal.frontend:cli",
|
||||||
|
@ -1 +1 @@
|
|||||||
__version__ = "1.3"
|
__version__ = "1.0"
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
#
|
|
||||||
# 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())
|
|
@ -32,25 +32,18 @@ class StcGal:
|
|||||||
|
|
||||||
def __init__(self, opts):
|
def __init__(self, opts):
|
||||||
self.opts = opts
|
self.opts = opts
|
||||||
|
|
||||||
if opts.protocol == "stc89":
|
if opts.protocol == "stc89":
|
||||||
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":
|
||||||
self.protocol = Stc15AProtocol(opts.port, opts.handshake, opts.baud,
|
self.protocol = Stc15AProtocol(opts.port, opts.handshake, opts.baud,
|
||||||
round(opts.trim * 1000))
|
round(opts.trim * 1000))
|
||||||
elif opts.protocol == "stc15":
|
else:
|
||||||
self.protocol = Stc15Protocol(opts.port, opts.handshake, opts.baud,
|
self.protocol = Stc15Protocol(opts.port, opts.handshake, opts.baud,
|
||||||
round(opts.trim * 1000))
|
round(opts.trim * 1000))
|
||||||
elif opts.protocol == "usb15":
|
|
||||||
self.protocol = StcUsb15Protocol()
|
|
||||||
else:
|
|
||||||
self.protocol = StcBaseProtocol(opts.port, opts.handshake, opts.baud)
|
|
||||||
|
|
||||||
self.protocol.debug = opts.debug
|
self.protocol.debug = opts.debug
|
||||||
|
|
||||||
@ -111,9 +104,9 @@ class StcGal:
|
|||||||
bindata = bindata[0:code_size]
|
bindata = bindata[0:code_size]
|
||||||
bindata += eedata
|
bindata += eedata
|
||||||
|
|
||||||
# pad to 512 byte boundary
|
# pad to 256 byte boundary
|
||||||
if len(bindata) % 512:
|
if len(bindata) % 256:
|
||||||
bindata += b'\xff' * (512 - len(bindata) % 512)
|
bindata += bytes(256 - len(bindata) % 256)
|
||||||
|
|
||||||
if self.opts.option: self.emit_options(self.opts.option)
|
if self.opts.option: self.emit_options(self.opts.option)
|
||||||
|
|
||||||
@ -124,21 +117,7 @@ class StcGal:
|
|||||||
self.protocol.disconnect()
|
self.protocol.disconnect()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try: self.protocol.connect()
|
||||||
self.protocol.connect(autoreset=self.opts.autoreset)
|
|
||||||
|
|
||||||
if self.opts.protocol == "auto":
|
|
||||||
if not self.protocol.protocol_name:
|
|
||||||
raise StcProtocolException("cannot detect protocol")
|
|
||||||
base_protocol = self.protocol
|
|
||||||
self.opts.protocol = self.protocol.protocol_name
|
|
||||||
print("Protocol detected: %s" % self.opts.protocol)
|
|
||||||
# recreate self.protocol with proper protocol class
|
|
||||||
self.__init__(self.opts)
|
|
||||||
else:
|
|
||||||
base_protocol = None
|
|
||||||
|
|
||||||
self.protocol.initialize(base_protocol)
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sys.stdout.flush();
|
sys.stdout.flush();
|
||||||
print("interrupted")
|
print("interrupted")
|
||||||
@ -152,10 +131,6 @@ class StcGal:
|
|||||||
sys.stdout.flush();
|
sys.stdout.flush();
|
||||||
print("Serial port error: %s" % e, file=sys.stderr)
|
print("Serial port error: %s" % e, file=sys.stderr)
|
||||||
return 1
|
return 1
|
||||||
except IOError as e:
|
|
||||||
sys.stdout.flush();
|
|
||||||
print("I/O error: %s" % e, file=sys.stderr)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if self.opts.code_image:
|
if self.opts.code_image:
|
||||||
@ -192,19 +167,18 @@ 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-2017 Grigori Goronzy\nhttps://github.com/grigorig/stcgal" %stcgal.__version__)
|
description="stcgal %s - an STC MCU ISP flash tool\n(C) 2014-2015 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("-P", "--protocol", help="protocol version", choices=["stc89", "stc12a", "stc12", "stc15a", "stc15"], 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: 1200)", type=BaudType(), default=1200)
|
||||||
parser.add_argument("-o", "--option", help="set option (can be used multiple times)", action="append")
|
parser.add_argument("-o", "--option", help="set option (can be used multiple times)", action="append")
|
||||||
parser.add_argument("-t", "--trim", help="RC oscillator frequency in kHz (STC15 series only)", type=float, default=0.0)
|
parser.add_argument("-t", "--trim", help="RC oscillator frequency in kHz (STC15 series only)", type=float, default=0.0)
|
||||||
parser.add_argument("-D", "--debug", help="enable debug output", action="store_true")
|
parser.add_argument("-D", "--debug", help="enable debug output", action="store_true")
|
||||||
opts = parser.parse_args()
|
opts = parser.parse_args()
|
||||||
|
|
||||||
# run programmer
|
# run programmer
|
||||||
gal = StcGal(opts)
|
gal = StcGal(opts)
|
||||||
return gal.run()
|
return gal.run()
|
||||||
|
@ -32,38 +32,14 @@ class MCUModelDatabase:
|
|||||||
MCUModel = collections.namedtuple("MCUModel", ["name", "magic", "total", "code", "eeprom"])
|
MCUModel = collections.namedtuple("MCUModel", ["name", "magic", "total", "code", "eeprom"])
|
||||||
|
|
||||||
models = (
|
models = (
|
||||||
MCUModel(name='STC8F8K08S4A10', magic=0xf611, total=65536, code=8192, eeprom=57344),
|
MCUModel(name='STC15H4K08S4', magic=0xf601, total=65536, code=8192, eeprom=0),
|
||||||
MCUModel(name='STC8F8K16S4A10', magic=0xf612, total=65536, code=16384, eeprom=49152),
|
MCUModel(name='STC15H4K16S4', magic=0xf602, total=65536, code=16384, eeprom=0),
|
||||||
MCUModel(name='STC8F8K24S4A10', magic=0xf613, total=65536, code=24576, eeprom=40960),
|
MCUModel(name='STC15H4K24S4', magic=0xf603, total=65536, code=24576, eeprom=0),
|
||||||
MCUModel(name='STC8F8K32S4A10', magic=0xf614, total=65536, code=32768, eeprom=32768),
|
MCUModel(name='STC15H4K32S4', magic=0xf604, total=65536, code=32768, eeprom=0),
|
||||||
MCUModel(name='STC8F8K40S4A10', magic=0xf615, total=65536, code=40960, eeprom=24576),
|
MCUModel(name='STC15H4K40S4', magic=0xf605, total=65536, code=40960, eeprom=0),
|
||||||
MCUModel(name='STC8F8K48S4A10', magic=0xf616, total=65536, code=49152, eeprom=16384),
|
MCUModel(name='STC15H4K48S4', magic=0xf606, total=65536, code=49152, eeprom=0),
|
||||||
MCUModel(name='STC8F8K56S4A10', magic=0xf617, total=65536, code=57344, eeprom=8192),
|
MCUModel(name='STC15H4K56S4', magic=0xf607, total=65536, code=57344, eeprom=0),
|
||||||
MCUModel(name='STC8F8K64S4A10', magic=0xf618, total=65536, code=65024, eeprom=512),
|
MCUModel(name='STC15H4K64S4', magic=0xf608, total=65536, code=65024, eeprom=0),
|
||||||
MCUModel(name='STC8A8K08S4A12', magic=0xf621, total=65536, code=8192, eeprom=57344),
|
|
||||||
MCUModel(name='STC8A8K16S4A12', magic=0xf622, total=65536, code=16384, eeprom=49152),
|
|
||||||
MCUModel(name='STC8A8K24S4A12', magic=0xf623, total=65536, code=24576, eeprom=40960),
|
|
||||||
MCUModel(name='STC8A8K32S4A12', magic=0xf624, total=65536, code=32768, eeprom=32768),
|
|
||||||
MCUModel(name='STC8A8K40S4A12', magic=0xf625, total=65536, code=40960, eeprom=24576),
|
|
||||||
MCUModel(name='STC8A8K48S4A12', magic=0xf626, total=65536, code=49152, eeprom=16384),
|
|
||||||
MCUModel(name='STC8A8K56S4A12', magic=0xf627, total=65536, code=57344, eeprom=8192),
|
|
||||||
MCUModel(name='STC8A8K64S4A12', magic=0xf628, total=65536, code=65024, eeprom=512),
|
|
||||||
MCUModel(name='STC8F2K08S4', magic=0xf631, total=65536, code=8192, eeprom=57344),
|
|
||||||
MCUModel(name='STC8F2K16S4', magic=0xf632, total=65536, code=16384, eeprom=49152),
|
|
||||||
MCUModel(name='STC8F2K24S4', magic=0xf633, total=65536, code=24576, eeprom=40960),
|
|
||||||
MCUModel(name='STC8F2K32S4', magic=0xf634, total=65536, code=32768, eeprom=32768),
|
|
||||||
MCUModel(name='STC8F2K40S4', magic=0xf635, total=65536, code=40960, eeprom=24576),
|
|
||||||
MCUModel(name='STC8F2K48S4', magic=0xf636, total=65536, code=49152, eeprom=16384),
|
|
||||||
MCUModel(name='STC8F2K56S4', magic=0xf637, total=65536, code=57344, eeprom=8192),
|
|
||||||
MCUModel(name='STC8F2K64S4', magic=0xf638, total=65536, code=65024, eeprom=512),
|
|
||||||
MCUModel(name='STC15H4K08S4', magic=0xf601, total=65536, code=8192, eeprom=57344),
|
|
||||||
MCUModel(name='STC15H4K16S4', magic=0xf602, total=65536, code=16384, eeprom=49152),
|
|
||||||
MCUModel(name='STC15H4K24S4', magic=0xf603, total=65536, code=24576, eeprom=40960),
|
|
||||||
MCUModel(name='STC15H4K32S4', magic=0xf604, total=65536, code=32768, eeprom=32768),
|
|
||||||
MCUModel(name='STC15H4K40S4', magic=0xf605, total=65536, code=40960, eeprom=24576),
|
|
||||||
MCUModel(name='STC15H4K48S4', magic=0xf606, total=65536, code=49152, eeprom=16384),
|
|
||||||
MCUModel(name='STC15H4K56S4', magic=0xf607, total=65536, code=57344, eeprom=8192),
|
|
||||||
MCUModel(name='STC15H4K64S4', magic=0xf608, total=65536, code=65024, eeprom=512),
|
|
||||||
MCUModel(name='STC15F2K08S2', magic=0xf401, total=65536, code=8192, eeprom=54272),
|
MCUModel(name='STC15F2K08S2', magic=0xf401, total=65536, code=8192, eeprom=54272),
|
||||||
MCUModel(name='STC15F2K16S2', magic=0xf402, total=65536, code=16384, eeprom=46080),
|
MCUModel(name='STC15F2K16S2', magic=0xf402, total=65536, code=16384, eeprom=46080),
|
||||||
MCUModel(name='STC15F2K24S2', magic=0xf403, total=65536, code=24576, eeprom=37888),
|
MCUModel(name='STC15F2K24S2', magic=0xf403, total=65536, code=24576, eeprom=37888),
|
||||||
@ -233,9 +209,6 @@ class MCUModelDatabase:
|
|||||||
MCUModel(name='STC15W1K08PWM', magic=0xf52d, total=65536, code=8192, eeprom=52224),
|
MCUModel(name='STC15W1K08PWM', magic=0xf52d, total=65536, code=8192, eeprom=52224),
|
||||||
MCUModel(name='STC15W1K16PWM', magic=0xf52e, total=65536, code=16384, eeprom=44032),
|
MCUModel(name='STC15W1K16PWM', magic=0xf52e, total=65536, code=16384, eeprom=44032),
|
||||||
MCUModel(name='STC15W1K20S', magic=0xf52f, total=65536, code=20480, eeprom=39936),
|
MCUModel(name='STC15W1K20S', magic=0xf52f, total=65536, code=20480, eeprom=39936),
|
||||||
MCUModel(name='STC15W1K20AS', magic=0xf534, total=65536, code=20480, eeprom=39936),
|
|
||||||
MCUModel(name='STC15W1K32AS', magic=0xf535, total=65536, code=32768, eeprom=27648),
|
|
||||||
MCUModel(name='STC15W1K48AS', magic=0xf536, total=65536, code=49152, eeprom=11264),
|
|
||||||
MCUModel(name='STC15W2K32S2', magic=0xf530, total=65536, code=32768, eeprom=27648),
|
MCUModel(name='STC15W2K32S2', magic=0xf530, total=65536, code=32768, eeprom=27648),
|
||||||
MCUModel(name='STC15W2K48S2', magic=0xf531, total=65536, code=49152, eeprom=11264),
|
MCUModel(name='STC15W2K48S2', magic=0xf531, total=65536, code=49152, eeprom=11264),
|
||||||
MCUModel(name='STC15W2K32AS', magic=0xf532, total=65536, code=32768, eeprom=27648),
|
MCUModel(name='STC15W2K32AS', magic=0xf532, total=65536, code=32768, eeprom=27648),
|
||||||
@ -839,28 +812,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=12288),
|
MCUModel(name='STC12LE5401AD', magic=0xe0e1, total=32768, code=1024, eeprom=22016),
|
||||||
MCUModel(name='STC12LE5402AD', magic=0xe0e2, total=32768, code=2048, eeprom=12288),
|
MCUModel(name='STC12LE5402AD', magic=0xe0e2, total=32768, code=2048, eeprom=20992),
|
||||||
MCUModel(name='STC12LE5404AD', magic=0xe0e4, total=32768, code=4096, eeprom=12288),
|
MCUModel(name='STC12LE5404AD', magic=0xe0e4, total=32768, code=4096, eeprom=18944),
|
||||||
MCUModel(name='STC12LE5406AD', magic=0xe0e6, total=32768, code=6144, eeprom=12288),
|
MCUModel(name='STC12LE5406AD', magic=0xe0e6, total=32768, code=6144, eeprom=16896),
|
||||||
MCUModel(name='STC12LE5408AD', magic=0xe0e8, total=32768, code=8192, eeprom=12288),
|
MCUModel(name='STC12LE5408AD', magic=0xe0e8, total=32768, code=8192, eeprom=10752),
|
||||||
MCUModel(name='STC12LE5410AD', magic=0xe0ea, total=32768, code=10240, eeprom=12288),
|
MCUModel(name='STC12LE5410AD', magic=0xe0ea, total=32768, code=10240, eeprom=4608),
|
||||||
MCUModel(name='STC12LE5412AD', magic=0xe0ec, total=32768, code=12288, eeprom=12288),
|
MCUModel(name='STC12LE5412AD', magic=0xe0ec, total=32768, code=12288, eeprom=11776),
|
||||||
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=12288),
|
MCUModel(name='STC12LE5420AD', magic=0xe0f4, total=32768, code=20480, eeprom=8192),
|
||||||
MCUModel(name='STC12LE5424AD', magic=0xe0f8, total=32768, code=24576, eeprom=12288),
|
MCUModel(name='STC12LE5424AD', magic=0xe0f8, total=32768, code=24576, eeprom=4096),
|
||||||
MCUModel(name='STC12LE5428AD', magic=0xe0fc, total=32768, code=28672, eeprom=12288),
|
MCUModel(name='STC12LE5428AD', magic=0xe0fc, total=32768, code=28672, eeprom=0),
|
||||||
MCUModel(name='STC12LE5401', magic=0xe081, total=32768, code=1024, eeprom=12288),
|
MCUModel(name='STC12LE5401', magic=0xe081, total=32768, code=1024, eeprom=22016),
|
||||||
MCUModel(name='STC12LE5402', magic=0xe082, total=32768, code=2048, eeprom=12288),
|
MCUModel(name='STC12LE5402', magic=0xe082, total=32768, code=2048, eeprom=20992),
|
||||||
MCUModel(name='STC12LE5404', magic=0xe084, total=32768, code=4096, eeprom=12288),
|
MCUModel(name='STC12LE5404', magic=0xe084, total=32768, code=4096, eeprom=18944),
|
||||||
MCUModel(name='STC12LE5406', magic=0xe086, total=32768, code=6144, eeprom=12288),
|
MCUModel(name='STC12LE5406', magic=0xe086, total=32768, code=6144, eeprom=16896),
|
||||||
MCUModel(name='STC12LE5408', magic=0xe088, total=32768, code=8192, eeprom=12288),
|
MCUModel(name='STC12LE5408', magic=0xe088, total=32768, code=8192, eeprom=10752),
|
||||||
MCUModel(name='STC12LE5410', magic=0xe08a, total=32768, code=10240, eeprom=12288),
|
MCUModel(name='STC12LE5410', magic=0xe08a, total=32768, code=10240, eeprom=4608),
|
||||||
MCUModel(name='STC12LE5412', magic=0xe08c, total=32768, code=12288, eeprom=12288),
|
MCUModel(name='STC12LE5412', magic=0xe08c, total=32768, code=12288, eeprom=11776),
|
||||||
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=12288),
|
MCUModel(name='STC12LE5420', magic=0xe094, total=32768, code=20480, eeprom=8192),
|
||||||
MCUModel(name='STC12LE5424', magic=0xe098, total=32768, code=24576, eeprom=12288),
|
MCUModel(name='STC12LE5424', magic=0xe098, total=32768, code=24576, eeprom=4096),
|
||||||
MCUModel(name='STC12LE5428', magic=0xe09c, total=32768, code=28672, eeprom=12288),
|
MCUModel(name='STC12LE5428', magic=0xe09c, total=32768, code=28672, eeprom=0),
|
||||||
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),
|
||||||
|
@ -1,608 +0,0 @@
|
|||||||
#
|
|
||||||
# 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]
|
|
1283
stcgal/protocols.py
1283
stcgal/protocols.py
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user