b3230814a8
This is the IAP flash memory block size, and the BSL apparently expects erase to be done aligned to 512 byte.
187 lines
5.1 KiB
Plaintext
187 lines
5.1 KiB
Plaintext
STC10/11/12 reverse engineering
|
|
|
|
Initialisation/Synchronisation
|
|
------------------------------
|
|
|
|
Send a constant stream of 0x7f bytes, and wait for an initial response
|
|
by the MCU.
|
|
|
|
Basic frame format
|
|
------------------
|
|
|
|
M0 M1 DR L0 L1 D0 ... Dn C0 C1 ME
|
|
|
|
M0 := 0x46
|
|
M1 := 0xb9
|
|
DR := 0x6a if host2mcu else 0x68
|
|
L := 16 bit big endian packet length, counted from DR to ME
|
|
C := 16 big endian modular sum from DR to Dn
|
|
ME := 0x16
|
|
|
|
D0..Dn is the packet payload
|
|
|
|
In most cases, the first byte of the payload marks the type of packet
|
|
or type of command. Responses by the MCU often use this type to tell
|
|
the programmer software which kind of command should follow. For
|
|
instance, after the baudrate handshake, the MCU replies with a
|
|
type 0x84 packet, and 0x84 is used for "erase" command packets from
|
|
the host.
|
|
|
|
Fun fact: The start marker (0x46, 0xb9) interpreted as UTF-16 is the
|
|
Unicode character U+46B9, which is an unusual CJK ideograph (䚹)
|
|
which translates as "to prepare" or "all ready" into English. How
|
|
fitting! This might not be a coincidence.
|
|
|
|
Packets host2mcu
|
|
----------------
|
|
|
|
1. Initiate baudrate handshake
|
|
|
|
Payload: 0x50, 0x07, 0x00, 0x36, 0x01, ID0, ID1
|
|
^ is 0x00 with current STC software and 11F08XE, what gives?
|
|
|
|
ID0 = MCU ID, byte 1
|
|
ID1 = MCU ID, byte 2
|
|
|
|
2. Test baudrate setting
|
|
|
|
Payload: 0x8f, 0xc0, brt, 0x3f, brt_csum, delay, iap
|
|
|
|
brt := MCU baudrate timer compare
|
|
brt_csum := (2 * (256 - brt)) & 0xff
|
|
delay := delay after baudrate change (0x40 seems to be fine),
|
|
STC software always seems to use 0xa0
|
|
iap := MCU IAP wait state register value
|
|
|
|
3. Switch to baudrate setting
|
|
|
|
Payload: 0x8e, 0xc0, brt, 0x3f, brt_csum, delay, iap
|
|
^ current STC software *omits* this here!
|
|
Almost the same as the test packet.
|
|
|
|
4. Erase flash memory
|
|
|
|
Payload: 0x84, 0xff, 0x00, blks, 0x00, 0x00, size,
|
|
^ no idea what that is for, current STC software uses 0x00
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x80, ..., 0x0e
|
|
|
|
blks := 256 byte blocks to clear
|
|
size := total number of 256 byte blocks (size of flash memory)
|
|
|
|
The 0x80..0x0e sequence seems to be some kind of magic code
|
|
to stop flaky connections and the like from erasing the flash
|
|
by accident.
|
|
|
|
"size" specifies the number of flash memory blocks. if blks > size,
|
|
eeprom will be erased.
|
|
|
|
Note that while erase size is specified in 256 byte blocks, the IAP
|
|
memory actually has 512 bytes physical erase block size, and the BSL
|
|
expects 512 byte aligned erase commands!
|
|
|
|
5. Program flash memory
|
|
|
|
Payload: 0x00, 0x00, 0x00, addr0, addr1, size0, size1, D0, ..., Dn
|
|
|
|
addr0, addr1 := big-endian 16 bit address
|
|
size0, size1 := big-endian 16 bit block size, always 128
|
|
D0...Dn := block data
|
|
|
|
Current STC software always seems to write at least 4 128 byte blocks
|
|
for some reason. Data is zero-padded.
|
|
|
|
Current STC software always writes a sequential set of memory. Since
|
|
flash and eeprom are essentially the same, any free space between
|
|
flash to be written and eeprom to be written is padded with zeros,
|
|
and then the whole batch is sent at once.
|
|
|
|
6. Finish flash programming
|
|
|
|
Payload: 0x69, 0x00, 0x00, 0x36, 0x01, ID0, ID1
|
|
^ kSTC-ISP uses 0x07
|
|
|
|
This should be sent after all flash programming is done. I am not
|
|
entirely sure why, though. Programming also works without it.
|
|
|
|
7. Set options
|
|
|
|
Payload: 0x8d, MS0, ..., MS15, CLK0, CLK1, CLK2, CLK3
|
|
|
|
MS0...MS15 := configuration registers specific to MCU model,
|
|
not documented here.
|
|
|
|
CLK0...CLK3 := 32 bit big endian measured clock, in Hz
|
|
|
|
8. Reset MCU
|
|
|
|
Payload: 0x82
|
|
|
|
|
|
Packets mcu2host
|
|
----------------
|
|
|
|
1. Info packet
|
|
|
|
Payload: 0x50, SYNC00, SYNC01, ..., SYNC70, SYNC71,
|
|
V1, V2, 0x00, ID0, ID1, 0x8c,
|
|
MS0, ..., MS7,
|
|
UID0, ..., UID6,
|
|
unknown bytes follow
|
|
|
|
SYNC* := sequence of 8 16-bit big-endian counter values, recorded
|
|
from the initial 0x7f sync sequence. this can be used to
|
|
determine the MCU clock frequency.
|
|
|
|
V1 := version number, two digits packed BCD.
|
|
V2 := stepping, one ASCII character.
|
|
ID0 := MCU model ID, byte 1
|
|
ID1 := MCU model ID, byte 2
|
|
UID0...UID6 := 7 bytes of unique id
|
|
|
|
UID is only sent by some BSL versions, others send zero bytes.
|
|
|
|
2. Acknowledge baudrate handshake start
|
|
|
|
Payload: 0x8f
|
|
|
|
This means the programming software should erase the flash memory as
|
|
the next step.
|
|
|
|
3. Acknowledge baudrate test
|
|
|
|
Payload: request packet payload with some pad byte appended to payload
|
|
|
|
4. Acknowledge baudrate switch
|
|
|
|
Payload: request packet payload with some pad byte appended to payload, and
|
|
first payload byte changed to 0x84
|
|
|
|
5. Acknowledge erase
|
|
|
|
Payload: 0x00, [UID0, ..., UID6]
|
|
|
|
The UID is optional, not sent by all BSL versions.
|
|
|
|
6. Acknowledge block write
|
|
|
|
Payload: 0x00, csum
|
|
|
|
csum := 8 bit modular sum of flash block data
|
|
|
|
7. Acknowledge finish flash writing
|
|
|
|
Payload: 0x8d
|
|
|
|
This means the programming software should set options as the next
|
|
step.
|
|
|
|
8. Acknowledge set options
|
|
|
|
Payload: 0x50, MS0, ..., MS4, 0x03, 0xff, V1, V2, MS0, ..., MS7,
|
|
UID0, ..., UID6,
|
|
unknown bytes follow
|
|
|
|
Some of the model-specific bytes are repeated twice (MS0-MS4).
|