Tasmota/tasmota/berry/zigbee/sonoff_zb_pro_flasher.be

179 lines
5.7 KiB
Plaintext

#################################################################################
#
# class `sonoff_zb_pro_flasher`
#
#################################################################################
class sonoff_zb_pro_flasher
static CCFG_address = 0x057FD8
static CCFG_reference = 0xC5FE08C5
#################################################################################
# Flashing from Intel HEX files
#################################################################################
var filename # filename of hex file
var f # file object
var file_checked # was the file already parsed. It cannot be flashed if not previously parsed and validated
var file_validated # was the file already validated. It cannot be flashed if not previously parsed and validated
var file_hex # intelhex object
var flasher # low-level flasher object (cc2652_flasher instance)
def init()
self.file_checked = false
self.file_validated = false
end
def load(filename)
import intelhex
if type(filename) != 'string' raise "value_error", "invalid file name" end
self.filename = filename
self.file_hex = intelhex(filename) # prepare the parser object
self.file_checked = false
self.file_validated = false
end
#################################################################################
# check that the HEX file is valid
# parse it completely once, and verify some values
#################################################################################
def check()
self.file_hex.parse(/ -> self._check_pre(),
/ address, len, data, offset -> self._check_cb(address, len, data, offset),
/ -> self._check_post()
)
end
#################################################################################
# Flash the firmware to the device
#
#################################################################################
def flash()
if !self.file_checked
print("FLH: firmware not checked, use `cc.check()`")
raise "flash_error", "firmware not checked"
end
if !self.file_validated
print("FLH: firmware not validated, use `cc.check()`")
raise "flash_error", "firmware not validated"
end
import cc2652_flasher # this stops zigbee and configures serial
self.flasher = cc2652_flasher
try
self.file_hex.parse(/ -> self._flash_pre(),
/ address, len, data, offset -> self._flash_cb(address, len, data, offset),
/ -> self._flash_post()
)
except .. as e, m
self.file_checked = false
self.file_validated = false
raise e, m
end
end
#################################################################################
# Dump firmware to local file
#
#################################################################################
def dump_to_file(filename)
import cc2652_flasher # this stops zigbee and configures serial
self.flasher = cc2652_flasher
print("FLH: Dump started (takes 3 minutes during which Tasmota is unresponsive)")
self.flasher.start()
self.flasher.ping()
self.flasher.flash_dump_to_file(filename, 0x000000, 0x58000)
print("FLH: Dump completed")
end
#################################################################################
# low-level
#################################################################################
def _flash_pre()
print("FLH: Flashing started (takes 5-8 minutes during which Tasmota is unresponsive)")
self.flasher.start()
self.flasher.ping()
# erase flash
self.flasher.flash_erase()
end
def _flash_post()
print("FLH: Flashing completed: OK")
var flash_crc = self.flasher.cmd_crc32(0x0,0x30000)
print("FLH: Flash crc32 0x000000 - 0x2FFFF = " + str(flash_crc));
# tasmota.log("FLH: Verification of HEX file OK", 2)
end
def _flash_cb(addr, sz, data, offset)
var payload = data[offset .. offset + sz - 1]
# final check
if size(payload) != sz raise "flash_error", "incomplete payload" end
self.flasher.flash_write(addr, payload)
end
# start verification (log only)
def _check_pre()
print("FLH: Starting verification of HEX file")
# tasmota.log("FLH: Starting verification of HEX file", 2)
end
# don't flash so ignore data
# check CCFG at location 0x57FD8 (4 bytes)
def _check_cb(addr, sz, data, offset)
# check than sz is a multiple of 4
if (sz % 4 != 0)
raise "value_error", format("size of payload is not a mutliple of 4: 0x%06X", addr)
end
# print(format("> addr=0x%06X sz=0x%02X data=%s", addr, sz, data[offset..offset+sz-1]))
var CCFG = self.CCFG_address
if addr <= CCFG && addr+sz > CCFG+4
# we have CCFG in the buffer
var ccfg_bytes = data.get(4 + CCFG - addr, 4)
if ccfg_bytes != self.CCFG_reference
raise "value_error", format("incorrect CCFG, BSL is not set to DIO_8 LOW (0x%08X expected 0x%08X)", ccfg_bytes, self.CCFG_reference) end
self.file_validated = true # if we are here, it means that the file looks correct
end
end
def _check_post()
print("FLH: Verification of HEX file OK")
# tasmota.log("FLH: Verification of HEX file OK", 2)
self.file_checked = true
end
end
return sonoff_zb_pro_flasher()
#-
# Flash local firmware
import sonoff_zb_pro_flasher as cc
cc.load("SonoffZBPro_coord_20230507.hex")
cc.check()
cc.flash()
import sonoff_zb_pro_flasher as cc
cc.load("SonoffZBPro_coord_20220219.hex")
cc.check()
cc.flash()
-#
#-
# Dump local firmware
import sonoff_zb_pro_flasher as cc
cc.dump_to_file("SonoffZBPro_dump.bin")
-#