243 lines
7.3 KiB
Lua
243 lines
7.3 KiB
Lua
|
|
-- create the module's table
|
|
local fwupdate = {}
|
|
|
|
-- import required modules
|
|
local dict = require "scripts.app.dict"
|
|
local help = require "scripts.app.help"
|
|
|
|
-- file constants
|
|
|
|
-- local functions
|
|
|
|
|
|
local function erase_main()
|
|
|
|
--dict.fwupdate("ERASE_1KB_PAGE", 2) --page 0 & 1 (first 2KByte) are forbidden
|
|
--dict.fwupdate("ERASE_1KB_PAGE", 3) --this is redundant for RB (aligns C6 to RB when done with above)
|
|
--dict.fwupdate("ERASE_1KB_PAGE", 4) --0x0800_1000 - 0x0800_17FF
|
|
--dict.fwupdate("ERASE_1KB_PAGE", 5) --redundant RB
|
|
--dict.fwupdate("ERASE_1KB_PAGE", 6) --0x0800_1800 - 0x0800_1FFF
|
|
--dict.fwupdate("ERASE_1KB_PAGE", 7)
|
|
--dict.fwupdate("ERASE_1KB_PAGE", 8) --0x0800_2000 - 0x0800_27FF
|
|
--dict.fwupdate("ERASE_1KB_PAGE", 9)
|
|
|
|
curpage = 2 --skip the first pages
|
|
rv = dict.fwupdate("GET_FLASH_ADDR")
|
|
print("flash addr:", string.format("%X", rv) )
|
|
|
|
while (curpage<32) do
|
|
-- while (curpage<128) do --RB has 128KB but last 96KB isn't used (yet)
|
|
if(curpage%4 ==0) then
|
|
print("erasing page:", curpage)
|
|
end
|
|
dict.fwupdate("ERASE_1KB_PAGE", curpage)
|
|
|
|
--rv = dict.fwupdate("GET_FLASH_ADDR")
|
|
--print("flash addr:", string.format("%X", rv) )
|
|
|
|
curpage = curpage+1
|
|
end
|
|
|
|
end
|
|
|
|
--skip is used because there is a ram pointer that often varies between builds
|
|
--we're never going back to main so this mismatch is allowed
|
|
local function update_firmware(newbuild, skip, forceup)
|
|
|
|
local error = false
|
|
|
|
|
|
--open new file first, don't bother continuing if can't find it.
|
|
file = assert(io.open(newbuild, "rb"))
|
|
|
|
--TODO REPORT build time stamp so can be certain it was a build just made if desired
|
|
|
|
--TODO read the fwupdater & app version from the provided file
|
|
--compare to current device and determine if they're compatible
|
|
--test let's tinker with SRAM
|
|
dict.bootload("SET_PTR_HI", 0x0800)
|
|
dict.bootload("SET_PTR_LO", 0x0800) --application version 0x08000800 "AV00"
|
|
local av = dict.bootload("RD_PTR_OFFSET")
|
|
local ver = dict.bootload("RD_PTR_OFFSET",1)
|
|
local avstring = string.format("%s%s%s%s", string.char(av&0x00FF), string.char(av>>8),
|
|
string.char(ver&0x00FF), string.char(ver>>8))
|
|
|
|
if avstring == "AV00" then
|
|
print("application version:", avstring)
|
|
else
|
|
print("app version", avstring, "unknown, may need to update to firmware v2.3 or later using STmicro dfuse")
|
|
end
|
|
|
|
|
|
--verify the first 2KByte match, don't continue if not..
|
|
--use the bootload dictionary to complete this
|
|
--want to wait to enter firmware updater
|
|
|
|
--set bootloader 16bit pointer to start of flash
|
|
dict.bootload("SET_PTR_HI", 0x0800)
|
|
dict.bootload("SET_PTR_LO", 0x0000)
|
|
local offset = 0 --first read has no offset
|
|
|
|
--advance the file past first 2KByte
|
|
local buffsize = 1
|
|
local byte, data
|
|
local byte_num = 0
|
|
local readdata
|
|
local data_l
|
|
|
|
print("Verifing first 2KByte of updater..")
|
|
while byte_num < (2*1024) do
|
|
|
|
--read next byte from the file and convert to binary
|
|
--gotta be a better way to read a half word (16bits) at a time but don't care right now...
|
|
byte_str = file:read(buffsize)
|
|
if byte_str then
|
|
data_l = string.unpack("B", byte_str, 1)
|
|
else
|
|
--should only have to make this check for lower byte
|
|
--binary file should be even
|
|
print("There's a problem, file provided is smaller than 2KB fwupdater..")
|
|
--TODO test this
|
|
error = true
|
|
break
|
|
end
|
|
byte_str = file:read(buffsize)
|
|
data = string.unpack("B", byte_str, 1)
|
|
data = (data<<8)+data_l
|
|
|
|
if (true) then
|
|
--both these options work, but the later is limited to reading 64KByte space
|
|
readdata = dict.bootload("RD_PTR_OFF_UP", offset)
|
|
--readdata = dict.bootload("RD_PTR_OFFSET", byte_num>>1) --shift by one 16bit read
|
|
|
|
-- print("read data:", string.format("%X", readdata) )
|
|
if readdata ~= data then
|
|
print("\n\nUnable to verify byte number", help.hex(byte_num),
|
|
" to flash expected:", help.hex(data), "was:", help.hex(readdata))
|
|
if forceup then
|
|
print("continuing anyway because force update was set...")
|
|
elseif byte_num == skip then
|
|
print("there was an expected mismatch at byte:", help.hex(byte_num))
|
|
else
|
|
print("\n\nPROBLEM! with firmware updater verification exiting")
|
|
print("exiting because it's not safe to proceed...")
|
|
print("no changes to device flash were made\n\n")
|
|
error = true
|
|
break
|
|
end
|
|
--else
|
|
-- print("verified byte number", help.hex(byte_num),
|
|
-- " of flash ", help.hex(data), help.hex(readdata))
|
|
end
|
|
end
|
|
|
|
offset = 1 --this is zero for first byte, but one for all others..
|
|
byte_num = byte_num + 2
|
|
end
|
|
|
|
if (not error) then
|
|
print("\nSuccessfully verified first 2KB of provided file")
|
|
print("matches the device's firmware updater section\n")
|
|
end
|
|
|
|
--enter fwupdate mode
|
|
dict.bootload("PREP_FWUPDATE")
|
|
|
|
--now the device will only respond to FWUPDATE dictionary commands
|
|
|
|
--erase 30KByte of application code
|
|
if (not error) then
|
|
erase_main()
|
|
end
|
|
|
|
--Set FLASH->AR to beginging of application section
|
|
--this can be done be re-erasing it..
|
|
--maybe we could have skipped page 2 in erase_main
|
|
--or have erase_main count down..
|
|
if (not error) then
|
|
dict.fwupdate("ERASE_1KB_PAGE", 2)
|
|
print("flash addr:", help.hex(dict.fwupdate("GET_FLASH_ADDR")))
|
|
print("\n");
|
|
end
|
|
|
|
|
|
offset = 0 --first write has no offset
|
|
|
|
if (not error) then
|
|
print("Updating device main application flash..")
|
|
while byte_num < (32*1024) do
|
|
|
|
--read next byte from the file and convert to binary
|
|
--gotta be a better way to read a half word (16bits) at a time but don't care right now...
|
|
byte_str = file:read(buffsize)
|
|
if byte_str then
|
|
data_l = string.unpack("B", byte_str, 1)
|
|
else
|
|
--should only have to make this check for lower byte
|
|
--binary file should be even
|
|
print("end of file")
|
|
break
|
|
end
|
|
byte_str = file:read(buffsize)
|
|
data = string.unpack("B", byte_str, 1)
|
|
data = (data<<8)+data_l
|
|
|
|
if( (byte_num % (4*1024)) == 0 ) then
|
|
print("flashing KB", byte_num/1024)
|
|
end
|
|
|
|
--print("writting:", string.format("%X", data), "addr:", string.format("%X", byte_num))
|
|
|
|
--write the data
|
|
dict.fwupdate("WR_HWORD", data, offset)
|
|
|
|
if (true) then
|
|
readdata = dict.fwupdate("READ_FLASH", byte_num, 0x00)
|
|
-- print("read data:", string.format("%X", readdata) )
|
|
if readdata ~= data then
|
|
print("\n\nERROR!!!! flashing byte number", help.hex(byte_num),
|
|
" to flash expected:", help.hex(data), "was:", help.hex(readdata))
|
|
print("exiting before causing more damage...\n\n")
|
|
error = true
|
|
break
|
|
--else
|
|
-- print("verified byte number", help.hex(byte_num),
|
|
-- " to flash ", help.hex(data), help.hex(readdata))
|
|
end
|
|
end
|
|
|
|
offset = 1 --this is zero for first write, but one for all others..
|
|
byte_num = byte_num + 2
|
|
end
|
|
end
|
|
|
|
if (not error) then
|
|
print("\nSuccessfully updated the device firmware!")
|
|
end
|
|
|
|
--close file
|
|
assert(file:close())
|
|
|
|
print("\n\n DONE, Reseting device \n\n IGNORE the errors that comes next.. \n\n")
|
|
|
|
--TODO maybe don't reset if we got an error, allow for correction while fwupdate still has control..?
|
|
dict.fwupdate("RESET_DEVICE")
|
|
|
|
--write build to flash
|
|
|
|
print("updated") --this doesn't print because reset errored us out..
|
|
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
|
|
fwupdate.update_firmware = update_firmware
|
|
|
|
-- return the module's table
|
|
return fwupdate
|