Merge pull request #80 from grigorig/pr64

Added protocol stc89a (BSL 7.2.5c) PR#64
This commit is contained in:
area-8051 2023-06-01 18:37:26 +02:00 committed by GitHub
commit a6b791b089
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 316 additions and 0 deletions

View 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

View File

@ -26,6 +26,7 @@ import stcgal
import serial import serial
from stcgal.utils import BaudType from stcgal.utils import BaudType
from stcgal.protocols import Stc89Protocol from stcgal.protocols import Stc89Protocol
from stcgal.protocols import Stc89AProtocol
from stcgal.protocols import Stc12AProtocol from stcgal.protocols import Stc12AProtocol
from stcgal.protocols import Stc12BProtocol from stcgal.protocols import Stc12BProtocol
from stcgal.protocols import Stc12Protocol from stcgal.protocols import Stc12Protocol
@ -52,6 +53,8 @@ class StcGal:
"""Initialize protocol backend""" """Initialize protocol backend"""
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 == "stc89a":
self.protocol = Stc89AProtocol(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": elif opts.protocol == "stc12b":

View File

@ -628,6 +628,239 @@ class Stc89Protocol(StcBaseProtocol):
print("done") 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: class Stc12AOptionsMixIn:
def program_options(self): def program_options(self):
print("Setting options: ", end="") print("Setting options: ", end="")