diff --git a/README.md b/README.md index d6bb384..83af352 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,7 @@ protocols and MCU series is as follows: * ```stc89``` STC 89/90 series * ```stc12a``` STC12Cx052AD and possibly others +* ```stc12b``` STC12x52xx series, STC12x56xx series and possibly others * ```stc12``` Most STC10/11/12 series (default) * ```stc15a``` STC15x104E and STC15x204E(A) series * ```stc15``` Most STC15 series diff --git a/stcgal/frontend.py b/stcgal/frontend.py index 286c66f..83058a1 100644 --- a/stcgal/frontend.py +++ b/stcgal/frontend.py @@ -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", choices=["stc89", "stc12a", "stc12b", "stc12", "stc15a", "stc15", "usb15", "auto"], default="stc12") 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) diff --git a/stcgal/protocols.py b/stcgal/protocols.py index 22493b5..5e728a9 100644 --- a/stcgal/protocols.py +++ b/stcgal/protocols.py @@ -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. @@ -877,28 +907,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):