Added protocol stc89a (BSL 7.2.5c) PR#64
This commit is contained in:
parent
f41ae5679f
commit
4894e8f219
80
doc/reverse-engineering/stc89a-c52rc.txt
Normal file
80
doc/reverse-engineering/stc89a-c52rc.txt
Normal file
@ -0,0 +1,80 @@
|
||||
001046: Read (UP): 2021-01-09 15:37:44.9125552 +0.0085328
|
||||
46 b9 68 00 29 50 fd 84 1e 11 4d 05 8e 96 27 7c F.h.)P....M...'|
|
||||
^
|
||||
cpu_6t
|
||||
04 47 01 7f 40 81 72 43 00 f0 51 05 80 00 ff ff .G..@.rC..Q.....
|
||||
^ ^ ^ ^
|
||||
freq_counte | | |
|
||||
bl_version |
|
||||
bl_stepping |
|
||||
bl_minor
|
||||
|
||||
|
||||
ff ff 38 20 20 02 19 60 0d a0 16 ..8 ..`...
|
||||
|
||||
|
||||
001057: Write (DOWN): 2021-01-09 15:37:44.9814096 +0.0129872
|
||||
46 b9 6a 00 0a 01 ff fd 82 02 f3 16 F.j.........
|
||||
^
|
||||
handshake
|
||||
|
||||
|
||||
001072: Read (UP): 2021-01-09 15:37:45.0836096 +0.0115168
|
||||
46 b9 68 00 07 01 00 70 16 F.h....p.
|
||||
|
||||
001113: Write (DOWN): 2021-01-09 15:37:45.1352048 +0.0171904
|
||||
46 b9 6a 00 0b 05 00 00 46 b9 01 79 16 F.j.....F..y.
|
||||
^
|
||||
ping-pong
|
||||
|
||||
|
||||
001116: Read (UP): 2021-01-09 15:37:45.1392768 +0.0017200
|
||||
46 b9 68 00 07 05 00 74 16 F.h....t.
|
||||
|
||||
|
||||
001127: Write (DOWN): 2021-01-09 15:37:45.1502464 +0.0109472
|
||||
46 b9 6a 00 0b 03 00 00 46 b9 01 77 16 F.j.....F..w.
|
||||
^
|
||||
erase_flash ?
|
||||
|
||||
|
||||
001170: Read (UP): 2021-01-09 15:37:45.4729040 +0.0099696
|
||||
46 b9 68 00 0e 03 f0 51 c5 f2 06 7c 14 04 07 16 F.h....Q...|....
|
||||
^
|
||||
mcu id
|
||||
|
||||
|
||||
001181: Write (DOWN): 2021-01-09 15:37:45.4791856 +0.0062576
|
||||
46 b9 6a 00 8b 32 00 00 46 b9 02 00 08 12 00 3f F.j..2..F......?
|
||||
^ ^
|
||||
write address
|
||||
write data
|
||||
80 fe 75 81 07 12 00 4c e5 82 60 03 02 00 03 e4 ..u....L..`.....
|
||||
78 ff f6 d8 fd 02 00 03 ae 82 af 83 8e 04 8f 05 x...............
|
||||
1e be ff 01 1f ec 4d 60 0f 7c 90 7d 01 1c bc ff ......M`.|.}....
|
||||
01 1d ec 4d 70 f7 80 e4 22 90 03 e8 12 00 1e e5 ...Mp...".......
|
||||
80 f4 f5 80 80 f3 75 82 00 22 ff ff ff ff ff ff ......u.."......
|
||||
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 ff ff ff ff ff ff ff ff ff 52 f9 16 ..........R..
|
||||
|
||||
|
||||
001188: Read (UP): 2021-01-09 15:37:45.5301744 +0.0047088
|
||||
46 b9 68 00 08 02 54 00 c6 16 F.h...T...
|
||||
^
|
||||
write done
|
||||
|
||||
|
||||
001199: Write (DOWN): 2021-01-09 15:37:45.5575264 +0.0273248
|
||||
46 b9 6a 00 0c 04 00 00 46 b9 fd 02 76 16 F.j.....F...v.
|
||||
^
|
||||
write msr
|
||||
|
||||
|
||||
001202: Read (UP): 2021-01-09 15:37:45.5625296 +0.0018304
|
||||
46 b9 68 00 08 04 54 00 c8 16 F.h...T...
|
||||
unknown
|
||||
|
||||
001213: Write (DOWN): 2021-01-09 15:37:45.5712992 +0.0087472
|
||||
46 b9 6a 00 07 ff 01 70 16 F.j....p.
|
||||
unknown
|
@ -26,6 +26,7 @@ import stcgal
|
||||
import serial
|
||||
from stcgal.utils import BaudType
|
||||
from stcgal.protocols import Stc89Protocol
|
||||
from stcgal.protocols import Stc89AProtocol
|
||||
from stcgal.protocols import Stc12AProtocol
|
||||
from stcgal.protocols import Stc12BProtocol
|
||||
from stcgal.protocols import Stc12Protocol
|
||||
@ -52,6 +53,8 @@ class StcGal:
|
||||
"""Initialize protocol backend"""
|
||||
if opts.protocol == "stc89":
|
||||
self.protocol = Stc89Protocol(opts.port, opts.handshake, opts.baud)
|
||||
elif opts.protocol == "stc89a":
|
||||
self.protocol = Stc89AProtocol(opts.port, opts.handshake, opts.baud)
|
||||
elif opts.protocol == "stc12a":
|
||||
self.protocol = Stc12AProtocol(opts.port, opts.handshake, opts.baud)
|
||||
elif opts.protocol == "stc12b":
|
||||
|
@ -628,6 +628,239 @@ class Stc89Protocol(StcBaseProtocol):
|
||||
print("done")
|
||||
|
||||
|
||||
class Stc89AProtocol(StcBaseProtocol):
|
||||
"""Protocol handler for STC 89/90 series"""
|
||||
|
||||
PARITY = serial.PARITY_NONE
|
||||
"""Parity configuration - these don't use any parity"""
|
||||
|
||||
PROGRAM_BLOCKSIZE = 128
|
||||
"""block size for programming flash"""
|
||||
|
||||
def __init__(self, port, baud_handshake, baud_transfer):
|
||||
StcBaseProtocol.__init__(self, port, baud_handshake, baud_transfer)
|
||||
|
||||
self.cpu_6t = None
|
||||
|
||||
def extract_payload(self, packet):
|
||||
"""Verify the checksum of packet and return its payload"""
|
||||
|
||||
packet_csum = packet[-2] + (packet[-3] << 8)
|
||||
calc_csum = sum(packet[2:-3]) & 0xffff
|
||||
if packet_csum != calc_csum:
|
||||
self.dump_packet(packet)
|
||||
raise StcFramingException("packet checksum mismatch")
|
||||
|
||||
payload = StcBaseProtocol.extract_payload(self, packet)
|
||||
return payload[:-1]
|
||||
|
||||
def write_packet(self, packet_data):
|
||||
"""Send packet to MCU.
|
||||
|
||||
Constructs a packet with supplied payload and sends it to the MCU.
|
||||
"""
|
||||
|
||||
# frame start and direction magic
|
||||
packet = bytes()
|
||||
packet += self.PACKET_START
|
||||
packet += self.PACKET_HOST
|
||||
|
||||
# packet length and payload
|
||||
packet += struct.pack(">H", len(packet_data) + 6)
|
||||
packet += packet_data
|
||||
|
||||
# checksum and end code
|
||||
packet += struct.pack(">H", sum(packet[2:]) & 0xffff)
|
||||
packet += self.PACKET_END
|
||||
|
||||
self.dump_packet(packet, receive=False)
|
||||
self.ser.write(packet)
|
||||
self.ser.flush()
|
||||
|
||||
def get_status_packet(self):
|
||||
"""Read and decode status packet"""
|
||||
|
||||
status_packet = self.read_packet()
|
||||
if status_packet[0] != 0x50:
|
||||
raise StcProtocolException("incorrect magic in status packet" + str(status_packet[0]))
|
||||
return status_packet
|
||||
|
||||
def initialize_options(self, status_packet):
|
||||
"""Initialize options"""
|
||||
|
||||
if len(status_packet) < 20:
|
||||
raise StcProtocolException("invalid options in status packet")
|
||||
self.options = Stc89Option(status_packet[1])
|
||||
self.options.print()
|
||||
|
||||
self.ser.parity = "E"
|
||||
|
||||
def calculate_baud(self):
|
||||
"""Calculate MCU baudrate setting.
|
||||
|
||||
Calculate appropriate baudrate settings for the MCU's UART,
|
||||
according to clock frequency and requested baud rate.
|
||||
"""
|
||||
|
||||
# timing is different in 6T mode
|
||||
sample_rate = 32 #if self.cpu_6t else 32
|
||||
# baudrate is directly controlled by programming the MCU's BRT register
|
||||
brt = 65536 - round((self.mcu_clock_hz) / (self.baud_transfer * sample_rate))
|
||||
|
||||
baud_actual = (self.mcu_clock_hz) / (sample_rate * (65536 - brt))
|
||||
baud_error = (abs(self.baud_transfer - baud_actual) * 100.0) / self.baud_transfer
|
||||
if baud_error > 5.0:
|
||||
print("WARNING: baudrate error is %.2f%%. You may need to set a slower rate." %
|
||||
baud_error, file=sys.stderr)
|
||||
|
||||
# IAP wait states (according to datasheet(s))
|
||||
iap_wait = 0x80
|
||||
if self.mcu_clock_hz < 10E6: iap_wait = 0x83
|
||||
elif self.mcu_clock_hz < 30E6: iap_wait = 0x82
|
||||
elif self.mcu_clock_hz < 50E6: iap_wait = 0x81
|
||||
|
||||
# MCU delay after switching baud rates
|
||||
delay = 0xa0
|
||||
|
||||
return brt, iap_wait
|
||||
|
||||
def initialize_status(self, status_packet):
|
||||
"""Decode status packet and store basic MCU info"""
|
||||
|
||||
self.cpu_6t = not bool(status_packet[1] & 1)
|
||||
|
||||
freq_counter = struct.unpack(">H", status_packet[13:15])[0]
|
||||
self.mcu_clock_hz = (12 * freq_counter * self.baud_handshake)
|
||||
|
||||
bl_version, bl_stepping = struct.unpack("BB", status_packet[17:19])
|
||||
bl_minor = status_packet[22] & 0x0f
|
||||
self.mcu_bsl_version = "%d.%d.%d%s" % (bl_version >> 4, bl_version & 0x0f,
|
||||
bl_minor, chr(bl_stepping))
|
||||
|
||||
def handshake(self):
|
||||
"""Switch to transfer baudrate
|
||||
|
||||
Switches to transfer baudrate and verifies that the setting works with
|
||||
a ping-pong exchange of packets."""
|
||||
|
||||
# check new baudrate
|
||||
print("Switching to %d baud: " % self.baud_transfer, end="")
|
||||
sys.stdout.flush()
|
||||
brt,iap = self.calculate_baud()
|
||||
print("checking ", end="")
|
||||
sys.stdout.flush()
|
||||
packet = bytes([0x01])
|
||||
packet += struct.pack(">H", brt)
|
||||
packet += bytes([iap])
|
||||
self.write_packet(packet)
|
||||
time.sleep(0.2)
|
||||
print(self.baud_transfer)
|
||||
response = self.read_packet()
|
||||
|
||||
if response[0] != 0x01:
|
||||
raise StcProtocolException("incorrect magic in handshake packet")
|
||||
|
||||
self.ser.baudrate = self.baud_transfer
|
||||
|
||||
# ping-pong test
|
||||
print("testing ", end="")
|
||||
sys.stdout.flush()
|
||||
packet = bytes([0x05, 0x00, 0x00, 0x46, 0xB9])
|
||||
self.write_packet(packet)
|
||||
response = self.read_packet()
|
||||
if response[0] != 0x05:
|
||||
raise StcProtocolException("incorrect magic in handshake packet")
|
||||
|
||||
print("done")
|
||||
|
||||
def reset_device(self, resetcmd=False):
|
||||
if not resetcmd:
|
||||
print("Cycling power: ", end="")
|
||||
sys.stdout.flush()
|
||||
self.ser.setDTR(False)
|
||||
time.sleep(0.5)
|
||||
self.ser.setDTR(True)
|
||||
print("done")
|
||||
else:
|
||||
print("Cycling power via shell cmd: " + resetcmd)
|
||||
os.system(resetcmd)
|
||||
|
||||
print("Waiting for MCU: ", end="")
|
||||
sys.stdout.flush()
|
||||
|
||||
def erase_flash(self, erase_size, _):
|
||||
"""Erase the MCU's flash memory.
|
||||
|
||||
Erase the flash memory with a block-erase command.
|
||||
flash_size is ignored; not used on STC 89 series.
|
||||
"""
|
||||
|
||||
print("Erasing All blocks: ", end="")
|
||||
sys.stdout.flush()
|
||||
packet = bytes([0x03, 0x00, 0x00, 0x46, 0xB9])
|
||||
self.write_packet(packet)
|
||||
response = self.read_packet()
|
||||
if response[0] != 0x03:
|
||||
raise StcProtocolException("incorrect magic in erase packet")
|
||||
|
||||
print("MCU ID: {:x}{:x}{:x}{:x}{:x}{:x}{:x}".format(response[1],response[2],response[3]
|
||||
,response[4],response[5],response[6],response[7]))
|
||||
|
||||
print("done")
|
||||
|
||||
def program_flash(self, data):
|
||||
"""Program the MCU's flash memory.
|
||||
|
||||
Write data into flash memory, using the PROGRAM_BLOCKSIZE
|
||||
as the block size (depends on MCU's RAM size).
|
||||
"""
|
||||
p = 0
|
||||
|
||||
for i in range(0, len(data), self.PROGRAM_BLOCKSIZE):
|
||||
packet = bytes(3)
|
||||
if p == 0:
|
||||
packet = bytes([0x22,0x00,0x00])
|
||||
else:
|
||||
packet = bytes([0x02])
|
||||
packet += int(128 * p).to_bytes(length=2, byteorder='big', signed=True)
|
||||
|
||||
|
||||
p = p + 1
|
||||
packet += bytes([0x46, 0xB9])
|
||||
packet += data[i:i+self.PROGRAM_BLOCKSIZE]
|
||||
|
||||
self.write_packet(packet)
|
||||
|
||||
response = self.read_packet()
|
||||
if len(response) < 1 or response[0] != 0x02:
|
||||
raise StcProtocolException("incorrect magic in write packet")
|
||||
|
||||
self.progress_cb(i, self.PROGRAM_BLOCKSIZE, len(data))
|
||||
self.progress_cb(len(data), self.PROGRAM_BLOCKSIZE, len(data))
|
||||
|
||||
def program_options(self):
|
||||
"""Program option byte into flash"""
|
||||
|
||||
print("Setting options: ")
|
||||
sys.stdout.flush()
|
||||
msr = self.options.get_msr()
|
||||
packet = bytes([0x04,0x00,0x00,0x46,0xB9, msr])
|
||||
self.write_packet(packet)
|
||||
response = self.read_packet()
|
||||
if response[0] != 0x04:
|
||||
raise StcProtocolException("incorrect magic in option packet")
|
||||
print("done")
|
||||
|
||||
def disconnect(self):
|
||||
"""Disconnect from MCU"""
|
||||
|
||||
# reset mcu
|
||||
packet = bytes([0xFF])
|
||||
self.write_packet(packet)
|
||||
self.ser.close()
|
||||
print("Disconnected!")
|
||||
|
||||
|
||||
class Stc12AOptionsMixIn:
|
||||
def program_options(self):
|
||||
print("Setting options: ", end="")
|
||||
|
Loading…
Reference in New Issue
Block a user