diff --git a/host/scripts/app/swim.lua b/host/scripts/app/swim.lua index 037d646..507a9f6 100644 --- a/host/scripts/app/swim.lua +++ b/host/scripts/app/swim.lua @@ -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 diff --git a/host/scripts/inlretro.lua b/host/scripts/inlretro.lua index eb057a1..3223b0a 100644 --- a/host/scripts/inlretro.lua +++ b/host/scripts/inlretro.lua @@ -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")