7 Commits

Author SHA1 Message Date
b4c7f34d39 stc15: fix RC oscillator baudrate switch packet
It looks like it wasn't correct. The last value sent is probably
supposed to be the trim value for the chosen trim frequency.

Addresses grigorig/stcgal#16.
2016-06-09 16:15:09 +02:00
65a7759647 stc12+: drop checksum verification for flashing
It's not needed on STC12 and up. All transfers are error checked with
parity and a 16-bit modular sum already. STC15 dropped the verification
checksum on the protocol level, it's not sent with the write status
packet, which is a testament to this not being needed.

Some parts store the UID in the last bytes of flash memory and this
verification actually caused incorrect verification failures because
of the verification, which apparently read the UID on verification
readback.

Fixes grigorig/stcgal#15.
2016-05-28 11:25:44 +02:00
8ad77586d4 Update version to 1.2 2016-05-20 03:22:24 +02:00
276c696fa4 frontend: enable protocol autodetection by default
It seems to work rather well after some extended testing. Also clean
up and update the protocol documentation while at it.
2016-05-20 02:59:35 +02:00
26ef34991b usb15: abort if permission denied
Don't ignore permission denied when looking for a suitable USB device.
Otherwise users don't notice what the problem is, stcgal will just
keep waiting on the prompt.
2016-05-20 02:55:23 +02:00
f90fe4152b Add STC12B protocol variant
This is just like STC12, but with the STC12A option packet. Used by
STC12xx52 series, STC12xx56 series and possibly others.

Fixes grigorig/stcgal#14.
2016-05-20 02:54:57 +02:00
d6ef028dc7 Extract mix-ins for STC12 and STC12A options
This simplifies code down the line. No functional change intended.
2016-05-20 02:44:50 +02:00
6 changed files with 96 additions and 63 deletions

View File

@ -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``` STC89/90 series
* ```stc12a``` STC12Cx052AD and possibly others
* ```stc12``` Most STC10/11/12 series (default)
* ```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,

7
debian/changelog vendored
View File

@ -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
View File

@ -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

View File

@ -1 +1 @@
__version__ = "1.0"
__version__ = "1.2"

View File

@ -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":
@ -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)

View File

@ -21,7 +21,7 @@
#
import serial
import sys, os, time, struct, re
import sys, os, time, struct, re, errno
import argparse
import collections
from stcgal.models import MCUModelDatabase
@ -194,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")]
@ -529,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
@ -650,37 +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()
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])
# 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))
self.write_packet(packet)
response = self.read_packet()
if response[0] != 0x80:
if response[0] != 0x50:
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")
# 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
@ -742,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.
@ -861,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")
@ -877,28 +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()
# 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))
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):
@ -1274,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)
@ -1507,7 +1526,11 @@ class StcUsb15Protocol(Stc15Protocol):
self.status_packet = None
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()
print("done")