Successfully flashing STM8 CIC via SWIM!

currently flashes binary file to flash and sets option byte for TIM1
TODO program ROP byte!
next up to control flash /OE pin via SWIM instead of EXP0
This commit is contained in:
Paul Molloy 2017-10-22 22:57:03 -05:00
parent 0dd8828744
commit 235e1649f1
2 changed files with 263 additions and 164 deletions

View File

@ -38,12 +38,19 @@ local function get_key_for_value( t, value )
return nil
end
local function stm8_system_reset()
--if cur_CSR has bit 2 set, SWIM must be reactivated
local function system_reset()
--TODO if cur_CSR has bit 2 set, SWIM must be reactivated
if dict.swim("SWIM_SRST") ~= ECODE.ACK then
print("ERROR unable to reset STM8 core")
else
-- print("reset stm8 core")
end
end
local function reset_swim()
print("resetting SWIM")
--print("resetting SWIM")
dict.swim("SWIM_RESET")
-- wotf(SWIM_CSR, cur_CSR)
@ -51,7 +58,7 @@ local function reset_swim()
dict.swim("WOTF", SWIM_CSR, cur_CSR)
end
local function rotf(addr, hspeed, num)
local function rotf(addr, hspeed, debug)
local result = ECODE.NAK
local data
@ -67,7 +74,7 @@ local function rotf(addr, hspeed, num)
result, data = dict.swim(opcode, addr)
--convert the value to the key string
result = get_key_for_value( ECODE, result)
print("rotf", string.format(" %X: %X, result ", addr, data), result)
if debug then print("rotf", string.format(" %X: %X, result ", addr, data), result) end
if result == "NORESP" then
reset_swim()
end
@ -81,12 +88,15 @@ local function rotf(addr, hspeed, num)
end
end
end
--return the result of the final transfer
return result, data
end
local function wotf(addr, data, hspeed, num)
local function wotf(addr, data, hspeed, debug)
local result = ECODE.NAK
local tries = 5
local tries = 8
local resets = 3
local opcode = "WOTF"
@ -97,8 +107,7 @@ local function wotf(addr, data, hspeed, num)
while result ~= "ACK" and tries > 0 do
result = dict.swim(opcode, addr, data)
result = get_key_for_value( ECODE, result)
print("wotf", string.format(" %X: %X, result ", addr, data), result)
tries = tries - 1
if debug then print("wotf", string.format(" %X: %X, result ", addr, data), result) end
if result == "NORESP" then
reset_swim()
end
@ -110,194 +119,133 @@ local function wotf(addr, data, hspeed, num)
tries = 5
end
end
tries = tries - 1
end
--return the result of the final transfer
return result
end
local function start()
local function unlock_eeprom(hspeed)
--Write 0xAE then 56h in
--FLASH_DUKR (0x00 5064)(1)(2)
wotf(0x5064, 0xAE, hspeed)
wotf(0x5064, 0x56, hspeed)
end
dict.io("IO_RESET")
local function unlock_flash(hspeed)
--write 0x56 then 0xae in
--flash_pukr (0x00 5062)(3)
wotf(0x5062, 0x56, hspeed)
wotf(0x5062, 0xAE, hspeed)
end
dict.io("SNES_INIT")
dict.io("SWIM_INIT", "SWIM_ON_EXP0")
dict.swim("SWIM_ACTIVATE")
--holds SWIM pin low for 16usec+ to reset SWIM comms incase of error
--also verifies that device has SWIM active
dict.swim("SWIM_RESET")
--write 0A0h to SWIM_CSR
--bit 5: allows entire memory range to be read & swim reset to be accessed
--bit 7: masks internal reset sources (like WDT..?)
--print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF", 0x7F80)))
-- print("wotf SWIM_CSR:", dict.swim("WOTF", 0x7F80, 0xA0))
cur_CSR = 0xA0
wotf(SWIM_CSR, cur_CSR)
--print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF", 0x7F80)))
--read SWIM_CSR
--dict.swim("SWIM_RESET")
--print("wotf SRST:", dict.swim("SWIM_SRST"))
--print("wotf SWIM_CSR:", dict.swim("WOTF", 0x7F80, 0xA0))
--now the SRST command is available, whole memory range available, and internal resets disabled
--by default there is now a breakpoint set at reset vector
--reset the STM8 core
print("wotf SRST:", dict.swim("SWIM_SRST"))
--the STM8 core is now stalled @ reset vector
--can read/write to any address on STM8 core
--if CIC ROP bit is set, we can only r/w to periph & SRAM
--bit 2: SWIM is reset (exits active mode) when chip reset
--this forces successful SWIM entry on each execution of script
-- print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF", 0x7F80)))
--print("wotf SWIM_CSR:", dict.swim("WOTF", 0x7F80, 0xA4))
-- cur_CSR = cur_CSR | 0x04
-- wotf(SWIM_CSR, cur_CSR)
-- print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF", 0x7F80)))
wotf(0x0000, 0x00)
rotf(0x0000)
rotf(0x0000)
rotf(0x0000)
rotf(0x0000)
rotf(0x0000)
rotf(0x0000)
rotf(0x0000)
rotf(0x0000)
rotf(0x0000)
rotf(0x0000)
rotf(0x0000)
rotf(0x0000)
print("switch to HS")
--bit 4: SWIM HIGH SPEED (set for high speed) SWIM RESET will set back to low speed
--print("wotf SWIM_CSR:", dict.swim("WOTF", 0x7F80, 0xB4))
cur_CSR = cur_CSR | 0x10
wotf(SWIM_CSR, cur_CSR)
-- print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF_HS", 0x7F80)))
--print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF_HS", 0x7F80)))
local function lock_flash_eeprom(hspeed)
--lock eeprom:
--Reset bit 3 (DUL)
--in FLASH_IAPSR (0x00 505F)
--lock flash:
--Reset bit 1 (PUL)
--in FLASH_IAPSR (0x00 505F)
--just lock em both
wotf(0x505F, 0x00, hspeed)
end
local function swim_test()
--print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x8028)))
--print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x8029)))
--print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x802A)))
--print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x802B)))
--print("wotf :", dict.swim("WOTF_HS", 0x8028, 0x49))
--print("wotf :", dict.swim("WOTF_HS", 0x8029, 0x4E))
--print("wotf :", dict.swim("WOTF_HS", 0x802A, 0x4C))
--print("wotf :", dict.swim("WOTF_HS", 0x802B, 0x20))
--print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x8028)))
--print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x8029)))
--print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x802A)))
--print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x802B)))
--read then write to SRAM
-- print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x0000)))
--print("wotf :", dict.swim("WOTF_HS", 0x0000, 0x00))
--high speed now, enable flag with true
wotf(0x0000, 0x00, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
rotf(0x0000, true)
wotf(0x0000, 0xEE, true)
rotf(0x0000, true)
wotf(0x0000, 0xAA, true)
rotf(0x0000, true)
wotf(0x0000, 0x55, true)
rotf(0x0000, true)
-- wotf(0x0000, 0x00, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- rotf(0x0000, true)
-- wotf(0x0000, 0xEE, true)
-- rotf(0x0000, true)
-- wotf(0x0000, 0xAA, true)
-- rotf(0x0000, true)
-- wotf(0x0000, 0x55, true)
-- rotf(0x0000, true)
-- print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x0000)))
--read then write to eeprom
-- print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x4000)))
--
-- --need to unlock the eeprom first!
-- --need to unlock the eeprom first!
unlock_eeprom(true)
-- --Write 0xAE then 56h in
-- --FLASH_DUKR (0x00 5064)(1)(2)
-- print("wotf :", dict.swim("WOTF_HS", 0x5064, 0xAE))
-- print("wotf :", dict.swim("WOTF_HS", 0x5064, 0x56))
-- --write data
rotf(0x4000, true)
wotf(0x4000, 0xDE, true)
wotf(0x4001, 0xAD, true)
wotf(0x4002, 0xBE, true)
wotf(0x4003, 0xEF, true)
-- print("wotf :", dict.swim("WOTF_HS", 0x4000, 0x00))
--
-- --lock eeprom
-- --Reset bit 3 (DUL)
lock_flash_eeprom(true)
-- --in FLASH_IAPSR (0x00 505F)
-- print("wotf :", dict.swim("WOTF_HS", 0x505F, 0x00))
--
-- print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x4000)))
rotf(0x4000, true)
rotf(0x4001, true)
rotf(0x4002, true)
rotf(0x4003, true)
--read then write to flash
-- print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x8028)))
--need to unlock the flash first!
--Write 0x56 then 0xAE in
--FLASH_PUKR (0x00 5062)(3)
-- print("wotf :", dict.swim("WOTF_HS", 0x5062, 0x56))
-- print("wotf :", dict.swim("WOTF_HS", 0x5062, 0xAE))
-- --write data
-- byte = 0x8028
-- data = 0x12
-- while byte < 0x8030 do
-- while (dict.swim("WOTF_HS", byte, data) ~= 1) do
-- print("woft nak ", byte)
-- end
--
-- byte = byte + 1
unlock_flash(true)
--write data
print("WRITE DATA")
local byte_addr = 0x8028
local data = 0xFF
while byte_addr < 0x8030 do
wotf(byte_addr, data, true, true)
byte_addr = byte_addr + 1
-- data = data + 0x11
--
-- end
-- print("wotf 28:", dict.swim("WOTF_HS", 0x8028, 0xEE))
-- print("wotf 29:", dict.swim("WOTF_HS", 0x8029, 0x11))
-- print("wotf 2A:", dict.swim("WOTF_HS", 0x802A, 0x22))
-- print("wotf 2B:", dict.swim("WOTF_HS", 0x802B, 0x33))
-- print("wotf 2C:", dict.swim("WOTF_HS", 0x802C, 0x44))
-- print("wotf 2D:", dict.swim("WOTF_HS", 0x802D, 0x55))
-- print("wotf 2E:", dict.swim("WOTF_HS", 0x802E, 0x66))
-- print("wotf 2F:", dict.swim("WOTF_HS", 0x802F, 0x77))
--lock flash
--Reset bit 1 (PUL)
-- --in FLASH_IAPSR (0x00 505F)
-- print("wotf :", dict.swim("WOTF_HS", 0x505F, 0x00))
--
-- print("rotf 28 :", string.format("%X %X", dict.swim("ROTF_HS", 0x8028)))
-- print("rotf 29 :", string.format("%X %X", dict.swim("ROTF_HS", 0x8029)))
-- print("rotf 2A :", string.format("%X %X", dict.swim("ROTF_HS", 0x802A)))
-- print("rotf 2B :", string.format("%X %X", dict.swim("ROTF_HS", 0x802B)))
-- print("rotf 2C :", string.format("%X %X", dict.swim("ROTF_HS", 0x802C)))
-- print("rotf 2D :", string.format("%X %X", dict.swim("ROTF_HS", 0x802D)))
-- print("rotf 2E :", string.format("%X %X", dict.swim("ROTF_HS", 0x802E)))
-- print("rotf 2F :", string.format("%X %X", dict.swim("ROTF_HS", 0x802F)))
--
--
-- --print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF", 0x7F80)))
--print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF", 0x7F80)))
--print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF", 0x7F80)))
--print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF", 0x7F80)))
--print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF", 0x7F80)))
end
--lock flash/eeprom
lock_flash_eeprom(true)
--read it back
print("READ BACK DATA")
local byte_addr = 0x8028
while byte_addr < 0x8030 do
rotf(byte_addr, true, true)
byte_addr = byte_addr + 1
end
--test by blinking LED via periph register access
--v2 board has LED on hi_lo_sel PA2
@ -309,13 +257,13 @@ local function start()
-- print("wotf LED PA_ODR:", dict.swim("WOTF", 0x5000, 0x04)) --PA2 output set LED ON!
-- print("wotf LED PA_ODR:", dict.swim("WOTF", 0x5000, 0x00)) --PA2 output set LED OFF!
--HIGH SPEED
print("wotf LED PA_CR1:", dict.swim("WOTF_HS", 0x5003, 0xFF)) --default is input w/o pullup, now pullups enabled
--LED should be dimly lit
--set pin to pushpull
print("wotf LED PA_DDR:", dict.swim("WOTF_HS", 0x5002, 0x04)) --PA2 is output CR1 set above makes pushpull
--LED is push/pull, ODR default to 0, so LED OFF
print("wotf LED PA_ODR:", dict.swim("WOTF_HS", 0x5000, 0x04)) --PA2 output set LED ON!
print("wotf LED PA_ODR:", dict.swim("WOTF_HS", 0x5000, 0x00)) --PA2 output set LED OFF!
-- print("wotf LED PA_CR1:", dict.swim("WOTF_HS", 0x5003, 0xFF)) --default is input w/o pullup, now pullups enabled
-- --LED should be dimly lit
-- --set pin to pushpull
-- print("wotf LED PA_DDR:", dict.swim("WOTF_HS", 0x5002, 0x04)) --PA2 is output CR1 set above makes pushpull
-- --LED is push/pull, ODR default to 0, so LED OFF
-- print("wotf LED PA_ODR:", dict.swim("WOTF_HS", 0x5000, 0x04)) --PA2 output set LED ON!
-- print("wotf LED PA_ODR:", dict.swim("WOTF_HS", 0x5000, 0x00)) --PA2 output set LED OFF!
--holds SWIM pin low for 16usec+ to reset SWIM comms incase of error
@ -332,6 +280,132 @@ local function start()
end
local function start()
dict.io("IO_RESET")
dict.io("SNES_INIT")
dict.io("SWIM_INIT", "SWIM_ON_EXP0")
dict.swim("SWIM_ACTIVATE")
--holds SWIM pin low for 16usec+ to reset SWIM comms incase of error
--also verifies that device has SWIM active
dict.swim("SWIM_RESET")
--write 0A0h to SWIM_CSR
--bit 5: allows entire memory range to be read & swim reset to be accessed
--bit 7: masks internal reset sources (like WDT..?)
cur_CSR = 0xA0
if wotf(SWIM_CSR, cur_CSR) == "ACK" then
print("Successfully established SWIM comms")
else
print("Unable to establish SWIM comms")
return false
end
--read SWIM_CSR
--dict.swim("SWIM_RESET")
--print("wotf SRST:", dict.swim("SWIM_SRST"))
--print("wotf SWIM_CSR:", dict.swim("WOTF", 0x7F80, 0xA0))
--now the SRST command is available, whole memory range available, and internal resets disabled
--by default there is now a breakpoint set at reset vector
--reset the STM8 core
-- dict.swim("SWIM_SRST")
system_reset()
--the STM8 core is now stalled @ reset vector
--can read/write to any address on STM8 core
--if CIC ROP bit is set, we can only r/w to periph & SRAM
--bit 2: SWIM is reset (exits active mode) when chip reset
--this forces successful SWIM entry on each execution of script
-- cur_CSR = cur_CSR | 0x04
-- wotf(SWIM_CSR, cur_CSR)
--print("switch to HS")
--bit 4: SWIM HIGH SPEED (set for high speed) SWIM RESET will set back to low speed
--print("wotf SWIM_CSR:", dict.swim("WOTF", 0x7F80, 0xB4))
cur_CSR = cur_CSR | 0x10
wotf(SWIM_CSR, cur_CSR)
-- swim_test()
return true
end
local function printCSR()
print(cur_CSR)
end
local function write_optn_bytes(debug)
local toprint = nil--debug
if debug then print("programming option bytes") end
unlock_eeprom(true)
--FLASH_CR2 and FLASH_NCR2 must be enabled to permit option byte writing
--DEF_8BIT_REG_AT(FLASH_CR2,0x505b); default 0x00
--DEF_8BIT_REG_AT(FLASH_NCR2,0x505c); default 0xFF
--BIT 7: OPT/NOPT
wotf(0x505B, 0x80, true, toprint)
wotf(0x505C, 0x7F, true, toprint)
--need to enable AFR0 for TIM1 timer input pins
--AFR0 Alternate function remapping option 0(2)
--0: AFR0 remapping option inactive: Default alternate functions(1)
--1: Port C5 alternate function = TIM2_CH1; port C6 alternate function =
--TIM1_CH1; port C7 alternate function = TIM1_CH2.
--0x4803 Alternate function remapping (AFR)
-- OPT2 AFR7 AFR6 AFR5 AFR4 AFR3 AFR2 AFR1 AFR0 0x00
--0x4804 NOPT2 NAFR7 NAFR6 NAFR5 NAFR4 NAFR3 NAFR2 NAFR1 NAFR0 0xFF
if debug then print("ENABLING AFR0 for TIM1") end
wotf(0x4803, 0x01, true, toprint)
wotf(0x4804, 0xFE, true, toprint)
--disable option byte writing
wotf(0x505B, 0x00, true, toprint)
wotf(0x505C, 0xFF, true, toprint)
lock_flash_eeprom(true)
if debug then print("done with option byte programming") end
end
local function write_flash(file, debug)
unlock_flash(true)
local toprint = debug
local buff_size = 1
local byte_num = 0
local readdata = 0
local readresult = 0
print("Programming STM8 CIC flash")
for byte in file:lines(buff_size) do
local data = string.unpack("B", byte, 1)
-- print(data)
wotf(0x8000+byte_num, data, true, toprint)
--wotf(0x8000+byte_num, 0xFF, true, true)
readresult, readdata = rotf(0x8000+byte_num, true, toprint )
if readdata ~= data then
print("ERROR flashing byte number", byte_num, "to STM8 CIC", data, readdata)
end
--if byte_num == 0x4C0 then
--if byte_num == 0x020 then
----if byte_num == 0x1FFF then
-- return
--end
byte_num = byte_num + 1
end
print("Done with STM8 CIC flash")
lock_flash_eeprom(true)
end
-- global variables so other modules can use them
@ -340,6 +414,9 @@ end
-- functions other modules are able to call
swim.start = start
swim.write_flash = write_flash
swim.write_optn_bytes = write_optn_bytes
swim.printCSR = printCSR
swim.wotf = wotf
swim.rotf = rotf

View File

@ -100,7 +100,29 @@ function main ()
elseif cart_console == "SNES" then
swim.start()
if swim.start() then
--SWIM is now established and running at HIGH SPEED
--swim.printCSR()
--check if ROP set, allow clearing ROP and erasing CIC
--open CIC file
local cic_file = assert(io.open("SNESCIC.bin", "rb"))
--write CIC file
swim.write_flash( cic_file )
--close CIC file
assert(cic_file:close())
--write option bytes
swim.write_optn_bytes( true )
--set ROP byte
else
print("ERROR problem with STM8 CIC")
end
dict.io("IO_RESET")
dict.io("SNES_INIT")