Compare commits
7 Commits
stc12b
...
stc15-baud
Author | SHA1 | Date | |
---|---|---|---|
b4c7f34d39 | |||
65a7759647 | |||
8ad77586d4 | |||
276c696fa4 | |||
26ef34991b | |||
f90fe4152b | |||
d6ef028dc7 |
13
README.md
13
README.md
@ -111,17 +111,18 @@ Most importantly, ```-p``` sets the serial port to be used for programming.
|
|||||||
### Protocols
|
### Protocols
|
||||||
|
|
||||||
STC MCUs use a variety of related but incompatible protocols for the
|
STC MCUs use a variety of related but incompatible protocols for the
|
||||||
BSL. The protocol can be specified with the ```-P``` flag. Optionally,
|
BSL. The protocol can be specified with the ```-P``` flag. By default
|
||||||
experimental protocol autodetection can be used. The mapping between
|
UART protocol autodetection is used. The mapping between protocols
|
||||||
protocols and MCU series is as follows:
|
and MCU series is as follows:
|
||||||
|
|
||||||
* ```stc89``` STC89/90 series
|
* ```stc89``` STC89/90 series
|
||||||
* ```stc12a``` STC12Cx052AD and possibly others
|
* ```stc12a``` STC12x052 series and possibly others
|
||||||
* ```stc12``` Most STC10/11/12 series (default)
|
* ```stc12b``` STC12x52 series, STC12x56 series and possibly others
|
||||||
|
* ```stc12``` Most STC10/11/12 series
|
||||||
* ```stc15a``` STC15x104E and STC15x204E(A) series
|
* ```stc15a``` STC15x104E and STC15x204E(A) series
|
||||||
* ```stc15``` Most STC15 series
|
* ```stc15``` Most STC15 series
|
||||||
* ```usb15``` USB support on STC15W4 series
|
* ```usb15``` USB support on STC15W4 series
|
||||||
* ```auto``` Automatic detection of UART based protocols
|
* ```auto``` Automatic detection of UART based protocols (default)
|
||||||
|
|
||||||
The text files in the doc/ subdirectory provide an overview over
|
The text files in the doc/ subdirectory provide an overview over
|
||||||
the reverse engineered protocols used by the BSLs. For more details,
|
the reverse engineered protocols used by the BSLs. For more details,
|
||||||
|
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
|
stcgal (1.0git) unstable; urgency=low
|
||||||
|
|
||||||
* Initial Debianized Release
|
* Initial Debianized Release
|
||||||
|
18
debian/control
vendored
18
debian/control
vendored
@ -10,17 +10,17 @@ X-Python3-Version: >= 3.2
|
|||||||
Package: stcgal
|
Package: stcgal
|
||||||
Architecture: all
|
Architecture: all
|
||||||
Depends: ${misc:Depends}, python3, python3-serial
|
Depends: ${misc:Depends}, python3, python3-serial
|
||||||
|
Recommends: python3-usb (>= 1.0.0~b2)
|
||||||
Description: STC MCU ISP flash tool
|
Description: STC MCU ISP flash tool
|
||||||
stcgal is a command line flash programming tool for STC MCU Ltd. 8051
|
stcgal is a command line flash programming tool for STC MCU Ltd.
|
||||||
compatible microcontrollers. The name was inspired by avrdude.
|
8051 compatible microcontrollers. The name was inspired by avrdude.
|
||||||
.
|
.
|
||||||
STC microcontrollers have a UART based boot strap loader (BSL). It
|
STC microcontrollers have an UART/USB based boot strap loader (BSL). It
|
||||||
utilizes a packet-based protocol to flash the code memory and
|
utilizes a packet-based protocol to flash the code memory and IAP
|
||||||
IAP memory over a serial link. This is referred to as in-system
|
memory over a serial link. This is referred to as in-system programming
|
||||||
programming (ISP). The BSL is also used to configure various
|
(ISP). The BSL is also used to configure various (fuse-like) device
|
||||||
(fuse-like) device options. Unfortunately, this protocol is not
|
options. Unfortunately, this protocol is not publicly documented and
|
||||||
publicly documented and STC only provide a (crude) Windows GUI
|
STC only provide a (crude) Windows GUI application for programming.
|
||||||
application for programming.
|
|
||||||
.
|
.
|
||||||
stcgal is a full-featured Open Source replacement for STC's Windows
|
stcgal is a full-featured Open Source replacement for STC's Windows
|
||||||
software; it supports a wide range of MCUs, it is very portable and
|
software; it supports a wide range of MCUs, it is very portable and
|
||||||
|
@ -1 +1 @@
|
|||||||
__version__ = "1.0"
|
__version__ = "1.2"
|
||||||
|
@ -37,6 +37,8 @@ class StcGal:
|
|||||||
self.protocol = Stc89Protocol(opts.port, opts.handshake, opts.baud)
|
self.protocol = Stc89Protocol(opts.port, opts.handshake, opts.baud)
|
||||||
elif opts.protocol == "stc12a":
|
elif opts.protocol == "stc12a":
|
||||||
self.protocol = Stc12AProtocol(opts.port, opts.handshake, opts.baud)
|
self.protocol = Stc12AProtocol(opts.port, opts.handshake, opts.baud)
|
||||||
|
elif opts.protocol == "stc12b":
|
||||||
|
self.protocol = Stc12BProtocol(opts.port, opts.handshake, opts.baud)
|
||||||
elif opts.protocol == "stc12":
|
elif opts.protocol == "stc12":
|
||||||
self.protocol = Stc12Protocol(opts.port, opts.handshake, opts.baud)
|
self.protocol = Stc12Protocol(opts.port, opts.handshake, opts.baud)
|
||||||
elif opts.protocol == "stc15a":
|
elif opts.protocol == "stc15a":
|
||||||
@ -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("code_image", help="code segment file to flash (BIN/HEX)", type=argparse.FileType("rb"), nargs='?')
|
||||||
parser.add_argument("eeprom_image", help="eeprom segment file to flash (BIN/HEX)", type=argparse.FileType("rb"), nargs='?')
|
parser.add_argument("eeprom_image", help="eeprom segment file to flash (BIN/HEX)", type=argparse.FileType("rb"), nargs='?')
|
||||||
parser.add_argument("-a", "--autoreset", help="cycle power automatically by asserting DTR", action="store_true")
|
parser.add_argument("-a", "--autoreset", help="cycle power automatically by asserting DTR", action="store_true")
|
||||||
parser.add_argument("-P", "--protocol", help="protocol version", choices=["stc89", "stc12a", "stc12", "stc15a", "stc15", "usb15", "auto"], default="stc12")
|
parser.add_argument("-P", "--protocol", help="protocol version (default: auto)", choices=["stc89", "stc12a", "stc12b", "stc12", "stc15a", "stc15", "usb15", "auto"], default="auto")
|
||||||
parser.add_argument("-p", "--port", help="serial port device", default="/dev/ttyUSB0")
|
parser.add_argument("-p", "--port", help="serial port device", default="/dev/ttyUSB0")
|
||||||
parser.add_argument("-b", "--baud", help="transfer baud rate (default: 19200)", type=BaudType(), default=19200)
|
parser.add_argument("-b", "--baud", help="transfer baud rate (default: 19200)", type=BaudType(), default=19200)
|
||||||
parser.add_argument("-l", "--handshake", help="handshake baud rate (default: 2400)", type=BaudType(), default=2400)
|
parser.add_argument("-l", "--handshake", help="handshake baud rate (default: 2400)", type=BaudType(), default=2400)
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import serial
|
import serial
|
||||||
import sys, os, time, struct, re
|
import sys, os, time, struct, re, errno
|
||||||
import argparse
|
import argparse
|
||||||
import collections
|
import collections
|
||||||
from stcgal.models import MCUModelDatabase
|
from stcgal.models import MCUModelDatabase
|
||||||
@ -194,6 +194,7 @@ class StcBaseProtocol:
|
|||||||
|
|
||||||
protocol_database = [("stc89", "STC(89|90)(C|LE)\d"),
|
protocol_database = [("stc89", "STC(89|90)(C|LE)\d"),
|
||||||
("stc12a", "STC12(C|LE)\d052"),
|
("stc12a", "STC12(C|LE)\d052"),
|
||||||
|
("stc12b", "STC12(C|LE)(52|56)"),
|
||||||
("stc12", "(STC|IAP)(10|11|12)\D"),
|
("stc12", "(STC|IAP)(10|11|12)\D"),
|
||||||
("stc15a", "(STC|IAP)15[FL][01]0\d(E|EA|)$"),
|
("stc15a", "(STC|IAP)15[FL][01]0\d(E|EA|)$"),
|
||||||
("stc15", "(STC|IAP|IRC)15\D")]
|
("stc15", "(STC|IAP|IRC)15\D")]
|
||||||
@ -529,7 +530,37 @@ class Stc89Protocol(StcBaseProtocol):
|
|||||||
print("done")
|
print("done")
|
||||||
|
|
||||||
|
|
||||||
class Stc12AProtocol(Stc89Protocol):
|
class Stc12AOptionsMixIn:
|
||||||
|
def program_options(self):
|
||||||
|
print("Setting options: ", end="")
|
||||||
|
sys.stdout.flush()
|
||||||
|
msr = self.options.get_msr()
|
||||||
|
packet = bytes([0x8d, msr[0], msr[1], msr[2], 0xff, msr[3]])
|
||||||
|
packet += struct.pack(">I", int(self.mcu_clock_hz))
|
||||||
|
packet += bytes([msr[3]])
|
||||||
|
packet += bytes([0xff, msr[0], msr[1], 0xff, 0xff, 0xff, 0xff, msr[2]])
|
||||||
|
packet += bytes([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
|
||||||
|
packet += struct.pack(">I", int(self.mcu_clock_hz))
|
||||||
|
packet += bytes([0xff, 0xff, 0xff])
|
||||||
|
|
||||||
|
self.write_packet(packet)
|
||||||
|
response = self.read_packet()
|
||||||
|
if response[0] != 0x80:
|
||||||
|
raise StcProtocolException("incorrect magic in option packet")
|
||||||
|
|
||||||
|
# XXX: this is done by STC-ISP on newer parts. not sure why, but let's
|
||||||
|
# just replicate it, just to be sure.
|
||||||
|
if self.bsl_version >= 0x66:
|
||||||
|
packet = bytes([0x50])
|
||||||
|
self.write_packet(packet)
|
||||||
|
response = self.read_packet()
|
||||||
|
if response[0] != 0x10:
|
||||||
|
raise StcProtocolException("incorrect magic in option packet")
|
||||||
|
|
||||||
|
print("done")
|
||||||
|
|
||||||
|
|
||||||
|
class Stc12AProtocol(Stc12AOptionsMixIn, Stc89Protocol):
|
||||||
|
|
||||||
"""countdown value for flash erase"""
|
"""countdown value for flash erase"""
|
||||||
ERASE_COUNTDOWN = 0x0d
|
ERASE_COUNTDOWN = 0x0d
|
||||||
@ -650,37 +681,34 @@ class Stc12AProtocol(Stc89Protocol):
|
|||||||
raise StcProtocolException("incorrect magic in erase packet")
|
raise StcProtocolException("incorrect magic in erase packet")
|
||||||
print("done")
|
print("done")
|
||||||
|
|
||||||
|
|
||||||
|
class Stc12OptionsMixIn:
|
||||||
def program_options(self):
|
def program_options(self):
|
||||||
print("Setting options: ", end="")
|
print("Setting options: ", end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
msr = self.options.get_msr()
|
msr = self.options.get_msr()
|
||||||
packet = bytes([0x8d, msr[0], msr[1], msr[2], 0xff, msr[3]])
|
# XXX: it's not 100% clear if the index of msr[3] is consistent
|
||||||
packet += struct.pack(">I", int(self.mcu_clock_hz))
|
# between devices, so write it to both indices.
|
||||||
packet += bytes([msr[3]])
|
packet = bytes([0x8d, msr[0], msr[1], msr[2], msr[3],
|
||||||
packet += bytes([0xff, msr[0], msr[1], 0xff, 0xff, 0xff, 0xff, msr[2]])
|
0xff, 0xff, 0xff, 0xff, msr[3], 0xff,
|
||||||
packet += bytes([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
|
||||||
packet += struct.pack(">I", int(self.mcu_clock_hz))
|
|
||||||
packet += bytes([0xff, 0xff, 0xff])
|
|
||||||
|
|
||||||
|
packet += struct.pack(">I", int(self.mcu_clock_hz))
|
||||||
self.write_packet(packet)
|
self.write_packet(packet)
|
||||||
response = self.read_packet()
|
response = self.read_packet()
|
||||||
if response[0] != 0x80:
|
if response[0] != 0x50:
|
||||||
raise StcProtocolException("incorrect magic in option packet")
|
raise StcProtocolException("incorrect magic in option packet")
|
||||||
|
|
||||||
# XXX: this is done by STC-ISP on newer parts. not sure why, but let's
|
|
||||||
# just replicate it, just to be sure.
|
|
||||||
if self.bsl_version >= 0x66:
|
|
||||||
packet = bytes([0x50])
|
|
||||||
self.write_packet(packet)
|
|
||||||
response = self.read_packet()
|
|
||||||
if response[0] != 0x10:
|
|
||||||
raise StcProtocolException("incorrect magic in option packet")
|
|
||||||
|
|
||||||
print("done")
|
print("done")
|
||||||
|
|
||||||
|
# If UID wasn't sent with erase acknowledge, it should be in this packet
|
||||||
|
if not self.uid:
|
||||||
|
self.uid = response[18:25]
|
||||||
|
|
||||||
class Stc12Protocol(StcBaseProtocol):
|
print("Target UID: %s" % Utils.hexstr(self.uid))
|
||||||
"""Protocol handler for STC 10/11/12 series"""
|
|
||||||
|
|
||||||
|
class Stc12BaseProtocol(StcBaseProtocol):
|
||||||
|
"""Base class for STC 10/11/12 series protocol handlers"""
|
||||||
|
|
||||||
"""block size for programming flash"""
|
"""block size for programming flash"""
|
||||||
PROGRAM_BLOCKSIZE = 128
|
PROGRAM_BLOCKSIZE = 128
|
||||||
@ -742,6 +770,8 @@ class Stc12Protocol(StcBaseProtocol):
|
|||||||
self.mcu_bsl_version = "%d.%d%s" % (bl_version >> 4, bl_version & 0x0f,
|
self.mcu_bsl_version = "%d.%d%s" % (bl_version >> 4, bl_version & 0x0f,
|
||||||
chr(bl_stepping))
|
chr(bl_stepping))
|
||||||
|
|
||||||
|
self.bsl_version = bl_version
|
||||||
|
|
||||||
def calculate_baud(self):
|
def calculate_baud(self):
|
||||||
"""Calculate MCU baudrate setting.
|
"""Calculate MCU baudrate setting.
|
||||||
|
|
||||||
@ -861,8 +891,6 @@ class Stc12Protocol(StcBaseProtocol):
|
|||||||
response = self.read_packet()
|
response = self.read_packet()
|
||||||
if response[0] != 0x00:
|
if response[0] != 0x00:
|
||||||
raise StcProtocolException("incorrect magic in write packet")
|
raise StcProtocolException("incorrect magic in write packet")
|
||||||
elif response[1] != csum:
|
|
||||||
raise StcProtocolException("verification checksum mismatch")
|
|
||||||
print(".", end="")
|
print(".", end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
print(" done")
|
print(" done")
|
||||||
@ -877,28 +905,19 @@ class Stc12Protocol(StcBaseProtocol):
|
|||||||
raise StcProtocolException("incorrect magic in finish packet")
|
raise StcProtocolException("incorrect magic in finish packet")
|
||||||
print("done")
|
print("done")
|
||||||
|
|
||||||
def program_options(self):
|
|
||||||
print("Setting options: ", end="")
|
|
||||||
sys.stdout.flush()
|
|
||||||
msr = self.options.get_msr()
|
|
||||||
# XXX: it's not 100% clear if the index of msr[3] is consistent
|
|
||||||
# between devices, so write it to both indices.
|
|
||||||
packet = bytes([0x8d, msr[0], msr[1], msr[2], msr[3],
|
|
||||||
0xff, 0xff, 0xff, 0xff, msr[3], 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
|
|
||||||
|
|
||||||
packet += struct.pack(">I", int(self.mcu_clock_hz))
|
class Stc12Protocol(Stc12OptionsMixIn, Stc12BaseProtocol):
|
||||||
self.write_packet(packet)
|
"""STC 10/11/12 series protocol handler"""
|
||||||
response = self.read_packet()
|
|
||||||
if response[0] != 0x50:
|
|
||||||
raise StcProtocolException("incorrect magic in option packet")
|
|
||||||
print("done")
|
|
||||||
|
|
||||||
# If UID wasn't sent with erase acknowledge, it should be in this packet
|
def __init__(self, port, handshake, baud):
|
||||||
if not self.uid:
|
Stc12BaseProtocol.__init__(self, port, handshake, baud)
|
||||||
self.uid = response[18:25]
|
|
||||||
|
|
||||||
print("Target UID: %s" % Utils.hexstr(self.uid))
|
|
||||||
|
class Stc12BProtocol(Stc12AOptionsMixIn, Stc12BaseProtocol):
|
||||||
|
"""STC 10/11/12 variant protocol handler"""
|
||||||
|
|
||||||
|
def __init__(self, port, handshake, baud):
|
||||||
|
Stc12BaseProtocol.__init__(self, port, handshake, baud)
|
||||||
|
|
||||||
|
|
||||||
class Stc15AProtocol(Stc12Protocol):
|
class Stc15AProtocol(Stc12Protocol):
|
||||||
@ -1274,7 +1293,7 @@ class Stc15Protocol(Stc15AProtocol):
|
|||||||
# This is a bit of a hack, but it works.
|
# This is a bit of a hack, but it works.
|
||||||
bauds = self.baud_transfer if (self.mcu_magic >> 8) == 0xf2 else self.baud_transfer * 4
|
bauds = self.baud_transfer if (self.mcu_magic >> 8) == 0xf2 else self.baud_transfer * 4
|
||||||
packet += struct.pack(">H", int(65535 - program_speed / bauds))
|
packet += struct.pack(">H", int(65535 - program_speed / bauds))
|
||||||
packet += struct.pack(">H", int(65535 - (program_speed / bauds) * 1.5))
|
packet += bytes(user_trim)
|
||||||
iap_wait = self.get_iap_delay(program_speed)
|
iap_wait = self.get_iap_delay(program_speed)
|
||||||
packet += bytes([iap_wait])
|
packet += bytes([iap_wait])
|
||||||
self.write_packet(packet)
|
self.write_packet(packet)
|
||||||
@ -1507,7 +1526,11 @@ class StcUsb15Protocol(Stc15Protocol):
|
|||||||
self.status_packet = None
|
self.status_packet = None
|
||||||
raise StcFramingException
|
raise StcFramingException
|
||||||
else: raise StcFramingException
|
else: raise StcFramingException
|
||||||
except (StcFramingException, usb.core.USBError): time.sleep(0.5)
|
except StcFramingException:
|
||||||
|
time.sleep(0.5)
|
||||||
|
except usb.core.USBError as err:
|
||||||
|
if err.errno == errno.EACCES:
|
||||||
|
raise IOError(err.strerror)
|
||||||
|
|
||||||
self.initialize_model()
|
self.initialize_model()
|
||||||
print("done")
|
print("done")
|
||||||
|
Reference in New Issue
Block a user