diff --git a/tasmota/berry/zigbee/tubezb_cc2652_flasher.be b/tasmota/berry/zigbee/tubezb_cc2652_flasher.be new file mode 100644 index 000000000..f96d7b8a6 --- /dev/null +++ b/tasmota/berry/zigbee/tubezb_cc2652_flasher.be @@ -0,0 +1,176 @@ + +################################################################################# +# +# class `sonoff_zb_pro_flasher` +# +################################################################################# + +class tubezb_cc2652_flasher + static CCFG_address = 0x057FD8 + static CCFG_reference = 0xC5FE0FC5 # DIO 15 for BSL + + ################################################################################# + # 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 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) + # import string + + # check than sz is a multiple of 4 + if (sz % 4 != 0) + import string + raise "value_error", string.format("size of payload is not a mutliple of 4: 0x%06X", addr) + end + + # print(string.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 + import string + raise "value_error", string.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 tubezb_cc2652_flasher() + + +#- +# Flash local firmware + +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") + +-# diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_7_0_statemachine.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_7_0_statemachine.ino index 34e97ec14..08211a1d0 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_7_0_statemachine.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_7_0_statemachine.ino @@ -473,7 +473,7 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = { ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredCoord) ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) // set any failure to ABORT ZI_SEND(ZBS_STARTUPFROMAPP) // start coordinator - ZI_WAIT_RECV(5000, ZBR_STARTUPFROMAPP) // wait for sync ack of command + ZI_WAIT_RECV(10000, ZBR_STARTUPFROMAPP) // wait for sync ack of command ZI_WAIT_UNTIL_FUNC(20000, AREQ_STARTUPFROMAPP, &ZNP_ReceiveStateChange) // wait for async message that coordinator started, max 20s ZI_GOTO(ZIGBEE_LABEL_COORD_STARTED) @@ -493,7 +493,7 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = { ZI_WAIT_RECV(2000, ZBR_W_BDB_CHANN_OK) // all is good, we can start ZI_SEND(ZBS_BDB_START_COMMIS) // start coordinator - ZI_WAIT_RECV(5000, ZBR_BDB_START_COMMIS) // wait for sync ack of command + ZI_WAIT_RECV(10000, ZBR_BDB_START_COMMIS) // wait for sync ack of command ZI_WAIT_UNTIL_FUNC(20000, AREQ_STARTUPFROMAPP, &ZNP_ReceiveStateChange) // wait for async message that coordinator started, max 20s // ======================================================================