620 lines
17 KiB
Lua
620 lines
17 KiB
Lua
|
|
-- create the module's table
|
|
local swim = {}
|
|
|
|
-- import required modules
|
|
local dict = require "scripts.app.dict"
|
|
--local buffers = require "scripts.app.buffers"
|
|
|
|
-- file constants
|
|
-- firmware assembly return error code definitions
|
|
--.equ NO_RESP, 0xFF device didn't appear to respond
|
|
--.equ ACK, 0x01 transfer successful
|
|
--.equ NAK, 0x00 device couldn't complete operation
|
|
--.equ HERR, 0x0E header error
|
|
--.equ PERR, 0x09 pairity error
|
|
local ECODE = {}
|
|
ECODE.NORESP = 0xFF
|
|
ECODE.ACK = 0x01
|
|
ECODE.NAK = 0x00
|
|
ECODE.PERR = 0x0E
|
|
ECODE.HERR = 0x09
|
|
--local NRESP = 0xFF
|
|
--local ACK = 0x01
|
|
--local NAK = 0x00
|
|
--local PERR = 0x0E
|
|
--local HERR = 0x09
|
|
|
|
local cur_CSR = 0x00
|
|
local SWIM_CSR = 0x7F80
|
|
--local DEF_MAX_NAK = 8
|
|
local DEF_MAX_NAK = 12 --8 wasn't enough especially for long strings of 0x00 -> 0xff or vice versa
|
|
|
|
-- local functions
|
|
local function get_key_for_value( t, value )
|
|
for k,v in pairs(t) do
|
|
if v==value then
|
|
return k
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function system_reset( debug )
|
|
|
|
--TODO if cur_CSR has bit 2 set, SWIM must be reactivated
|
|
|
|
if dict.swim("SWIM_SRST") ~= ECODE.ACK then
|
|
if debug then print("ERROR unable to reset STM8 core") end
|
|
else
|
|
-- print("reset stm8 core")
|
|
end
|
|
end
|
|
|
|
local function reset_swim()
|
|
--print("resetting SWIM")
|
|
dict.swim("SWIM_RESET")
|
|
|
|
-- wotf(SWIM_CSR, cur_CSR)
|
|
--must rewrite current value of SWIM_CSR register as HIGHSPEED is cleared during SWIM RESET
|
|
dict.swim("WOTF", SWIM_CSR, cur_CSR)
|
|
end
|
|
|
|
|
|
local function rotf(addr, hspeed, debug)
|
|
|
|
local result = ECODE.NAK
|
|
local data
|
|
local tries = 5
|
|
local resets = 3
|
|
|
|
local opcode = "ROTF"
|
|
if hspeed then
|
|
opcode = "ROTF_HS"
|
|
end
|
|
|
|
while result ~= "ACK" and tries > 0 do
|
|
result, data = dict.swim(opcode, addr)
|
|
--convert the value to the key string
|
|
result = get_key_for_value( ECODE, result)
|
|
if debug then print("rotf", string.format(" %X: %X, result ", addr, data), result) end
|
|
if result == "NORESP" then
|
|
reset_swim()
|
|
end
|
|
tries = tries - 1
|
|
if tries == 0 then
|
|
print("ERROR max tries exceeded")
|
|
reset_swim()
|
|
resets = resets - 1
|
|
if resets > 0 then
|
|
tries = 5
|
|
end
|
|
end
|
|
end
|
|
|
|
--return the result of the final transfer
|
|
return result, data
|
|
end
|
|
|
|
local function wotf(addr, data, hspeed, debug, maxnaks)
|
|
|
|
local result = ECODE.NAK
|
|
local tries = DEF_MAX_NAK
|
|
local resets = 3
|
|
|
|
--allow calling function to increase max allowed NAKs
|
|
if maxnaks then
|
|
tries = maxnaks
|
|
end
|
|
|
|
local opcode = "WOTF"
|
|
if hspeed then
|
|
opcode = "WOTF_HS"
|
|
end
|
|
|
|
while result ~= "ACK" and tries >= 0 do
|
|
result = dict.swim(opcode, addr, data)
|
|
result = get_key_for_value( ECODE, result)
|
|
if debug then print("wotf", string.format(" %X: %X, result ", addr, data), result) end
|
|
if result == "NORESP" then
|
|
reset_swim()
|
|
end
|
|
tries = tries - 1
|
|
if tries < 0 then
|
|
print("ERROR max tries exceeded, resetting stm8")
|
|
reset_swim()
|
|
resets = resets - 1
|
|
if resets > 0 then
|
|
tries = 5
|
|
print(" FAIL! max resets exceeded!!!!!")
|
|
end
|
|
end
|
|
end
|
|
|
|
--return the result of the final transfer
|
|
return result
|
|
end
|
|
|
|
local function stop_and_reset()
|
|
|
|
--switch to low speed if was in high
|
|
dict.swim("SWIM_RESET")
|
|
|
|
--set bit 2 so SWIM module is also reset on system reset
|
|
cur_CSR = 0xA4
|
|
-- wotf(SWIM_CSR, cur_CSR)
|
|
--must rewrite current value of SWIM_CSR register as HIGHSPEED is cleared during SWIM RESET
|
|
wotf(SWIM_CSR, cur_CSR)
|
|
|
|
--print("resetting SWIM")
|
|
dict.swim("SWIM_SRST")
|
|
end
|
|
|
|
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
|
|
|
|
local function unlock_flash(hspeed)
|
|
--write 0x56 then 0xae in
|
|
--flash_pukr (0x00 5062)(3)
|
|
wotf(0x5062, 0x56, hspeed)
|
|
wotf(0x5062, 0xAE, hspeed)
|
|
end
|
|
|
|
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("wotf :", dict.swim("WOTF_HS", 0x8028, 0x49))
|
|
--print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x8028)))
|
|
|
|
--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
|
|
rotf(0x0000, true, true)
|
|
wotf(0x0000, 0x00, true, true)
|
|
rotf(0x0000, true, true)
|
|
wotf(0x0000, 0xFF, true, true)
|
|
rotf(0x0000, true, true)
|
|
wotf(0x0000, 0xA5, true, true)
|
|
rotf(0x0000, true, true)
|
|
wotf(0x0000, 0xC3, true, true)
|
|
rotf(0x0000, true, 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!
|
|
-- 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!
|
|
-- 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
|
|
-- --lock flash/eeprom
|
|
-- lock_flash_eeprom(true)
|
|
-- --read it back
|
|
|
|
-- print("READ BACK DATA")
|
|
-- local byte_addr = 0x0200
|
|
-- while byte_addr < 0x0280 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
|
|
-- print("wotf LED PA_CR1:", dict.swim("WOTF", 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", 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", 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!
|
|
|
|
|
|
--holds SWIM pin low for 16usec+ to reset SWIM comms incase of error
|
|
-- dict.swim("SWIM_RESET")
|
|
|
|
--reset the chip, if bit2 set in CSR the SWIM exits active mode with this reset
|
|
-- print("wotf SRST:", dict.swim("SWIM_SRST"))
|
|
--SWIM is now inactive chip is executing it's program code
|
|
|
|
--indicate to logic analyzer that test sequence above is complete
|
|
-- dict.pinport("CTL_SET_LO", "EXP0")
|
|
-- dict.io("IO_RESET")
|
|
|
|
end
|
|
|
|
|
|
local function read_stack()
|
|
|
|
--STM8 stack starts at $0200 which is where the CIC version
|
|
--and other special data is placed starting with v2.0
|
|
local stack_start = 0x0200
|
|
-- local last_char = 73 --73 end of copyright
|
|
local last_char = 74 --mirroring bit
|
|
local ack
|
|
local data = {}
|
|
|
|
--read
|
|
for i = 0, last_char do
|
|
ack, data[i+1] = rotf(stack_start+i, true, false)
|
|
end
|
|
|
|
print("\n")
|
|
|
|
local j = 1
|
|
while data[j] do
|
|
io.write(string.char(data[j]))
|
|
--io.write("B-",j,"=",data[j], " ")
|
|
j = j+1
|
|
end
|
|
print("\n")
|
|
|
|
-- print("rotf :", string.format("%X %X", dict.swim("ROTF_HS", 0x0000)))
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
local function start( debug, noreset )
|
|
|
|
--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
|
|
if debug then print("Successfully established SWIM comms") end
|
|
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")
|
|
--optionally reset core below, but not of much use since a ROP enabled device
|
|
--will reset once SWIM comms initiate rotf/wotf
|
|
--if(noreset ~= true) then
|
|
-- if debug then print("RESETTING STM8 CPU") end
|
|
-- system_reset( true )
|
|
--else
|
|
-- if debug then print("STM8 CPU WASN'T reset during activation") end
|
|
--end
|
|
|
|
--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
|
|
--TODO if this bit is enabled bunch of other code here needs updated to re-establish SWIM
|
|
--via this routine when system is reset
|
|
-- 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 disable_ROP_erase(debug)
|
|
|
|
local toprint = nil-- debug
|
|
local maxnak = 20
|
|
|
|
if debug then print("disabling ROP and erasing STM8 CIC") 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
|
|
if debug then print("enabling optn byte writes") end
|
|
wotf(0x505B, 0x80, true, toprint, maxnak)
|
|
wotf(0x505C, 0x7F, true, toprint, maxnak)
|
|
|
|
--enable READ OUT PROTECTION
|
|
--0x4800 Read-out protection (ROP)
|
|
--0x00 by default, set to 0xAA to prevent reading out flash & eeprom
|
|
if debug then print("reading ROP byte") end
|
|
if debug then rotf(0x4800, true, debug) end
|
|
if debug then print("clearing ROP byte") end
|
|
wotf(0x4800, 0x00, true, toprint, maxnak)
|
|
--after clearing ROP, system must be reset
|
|
--getting error that option bytes aren't complimentary
|
|
--seems they get completely erased and we should now flash them
|
|
--to be complimentary
|
|
--go ahead and write proper "erased" complimentary data prior to system reset
|
|
|
|
--option bytes seem to take awhile to write, increase max
|
|
if debug then print("writing compliment option bytes") end
|
|
--ROP wotf(0x4800, 0x00, true, toprint)
|
|
wotf(0x4801, 0x00, true, toprint, maxnak)
|
|
wotf(0x4802, 0xFF, true, toprint, maxnak)
|
|
wotf(0x4803, 0x00, true, toprint, maxnak)
|
|
wotf(0x4804, 0xFF, true, toprint, maxnak)
|
|
wotf(0x4805, 0x00, true, toprint, maxnak)
|
|
wotf(0x4806, 0xFF, true, toprint, maxnak)
|
|
wotf(0x4807, 0x00, true, toprint, maxnak)
|
|
wotf(0x4808, 0xFF, true, toprint, maxnak)
|
|
wotf(0x4809, 0x00, true, toprint, maxnak)
|
|
wotf(0x480A, 0xFF, true, toprint, maxnak)
|
|
|
|
--disable option byte writing
|
|
if debug then print("disabling option byte writting") end
|
|
wotf(0x505B, 0x00, true, toprint, maxnak)
|
|
wotf(0x505C, 0xFF, true, toprint, maxnak)
|
|
|
|
if debug then print("locking eeprom") end
|
|
lock_flash_eeprom(true)
|
|
|
|
-- if debug then print("read back option bytes")
|
|
-- rotf(0x4800, true, true)
|
|
-- rotf(0x4801, true, true)
|
|
-- rotf(0x4802, true, true)
|
|
-- rotf(0x4803, true, true)
|
|
-- rotf(0x4804, true, true)
|
|
-- rotf(0x4805, true, true)
|
|
-- rotf(0x4806, true, true)
|
|
-- rotf(0x4807, true, true)
|
|
-- rotf(0x4808, true, true)
|
|
-- rotf(0x4809, true, true)
|
|
-- rotf(0x480A, true, true)
|
|
-- end
|
|
|
|
--need to reset the chip to reload option bytes
|
|
--after clearing ROP, system must be reset
|
|
if debug then print("resetting STM8") end
|
|
system_reset( false )
|
|
--TODO swim may need re-established if SWIM_CSR RST bit is set
|
|
-- start()
|
|
|
|
if debug then print("done erasing chip, ROP disabled") end
|
|
end
|
|
|
|
local function write_optn_bytes(rop, debug)
|
|
|
|
local maxnak = 20
|
|
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, maxnak)
|
|
wotf(0x505C, 0x7F, true, toprint, maxnak)
|
|
|
|
--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, maxnak)
|
|
wotf(0x4804, 0xFE, true, toprint, maxnak)
|
|
print("optn byte write enabled")
|
|
|
|
--enable READ OUT PROTECTION
|
|
--0x4800 Read-out protection (ROP)
|
|
--0x00 by default, set to 0xAA to prevent reading out flash & eeprom
|
|
if rop then
|
|
wotf(0x4800, 0xAA, true, toprint, maxnak)
|
|
print("Read out Protection enabled")
|
|
else
|
|
print("Read out Protection isn't enabled, CIC code can be stolen!")
|
|
end
|
|
|
|
--disable option byte writing
|
|
wotf(0x505B, 0x00, true, toprint, maxnak)
|
|
wotf(0x505C, 0xFF, true, toprint, maxnak)
|
|
print("optn byte write disabled")
|
|
|
|
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
|
|
|
|
local function snes_v3_prgm(debug)
|
|
--dict.pinport("CTL_IP_PU", "SNES_RST")
|
|
--reset_swim()
|
|
-- print("curCSR", cur_CSR)
|
|
--start()
|
|
-- print("curCSR", cur_CSR)
|
|
--SNES v3 boards route Flash /OE to STM8 pin 3 PD6
|
|
|
|
--(PD_ODR,0x500f);
|
|
--(PD_IDR,0x5010);
|
|
--(PD_DDR,0x5011);
|
|
--(PD_CR1,0x5012);
|
|
--(PD_CR2,0x5013);
|
|
|
|
wotf(0x5012, 0x40, true, debug) --PD6 is input with pullup, if changed to output via DDR it will be push pull
|
|
wotf(0x5011, 0x40, true, debug) --PD6 is push-pull output now
|
|
wotf(0x500F, 0x40, true, debug) --PD6 high, program mode
|
|
end
|
|
|
|
local function snes_v3_play(debug)
|
|
--dict.pinport("CTL_IP_PU", "SNES_RST")
|
|
--reset_swim()
|
|
--start()
|
|
wotf(0x5012, 0x40, true, debug) --PD6 is input with pullup, if changed to output via DDR it will be push pull
|
|
wotf(0x5011, 0x40, true, debug) --PD6 is push-pull output now
|
|
wotf(0x500F, 0x00, true, debug) --PD6 low, play mode
|
|
end
|
|
|
|
-- global variables so other modules can use them
|
|
|
|
|
|
-- call functions desired to run when script is called/imported
|
|
|
|
|
|
-- functions other modules are able to call
|
|
swim.start = start
|
|
swim.write_flash = write_flash
|
|
swim.write_optn_bytes = write_optn_bytes
|
|
swim.disable_ROP_erase = disable_ROP_erase
|
|
swim.printCSR = printCSR
|
|
swim.wotf = wotf
|
|
swim.rotf = rotf
|
|
swim.swim_test = swim_test
|
|
swim.read_stack = read_stack
|
|
swim.snes_v3_prgm = snes_v3_prgm
|
|
swim.snes_v3_play = snes_v3_play
|
|
swim.stop_and_reset = stop_and_reset
|
|
|
|
-- return the module's table
|
|
return swim
|