# Update Mboot or MicroPython from a .dfu.gz file on the board's filesystem # MIT license; Copyright (c) 2019-2020 Damien P. George from micropython import const import struct, time import uzlib, machine, stm # Constants to be used with update_mpy VFS_FAT = 1 VFS_LFS1 = 2 VFS_LFS2 = 3 # Constants for creating mboot elements. _ELEM_TYPE_END = const(1) _ELEM_TYPE_MOUNT = const(2) _ELEM_TYPE_FSLOAD = const(3) _ELEM_TYPE_STATUS = const(4) FLASH_KEY1 = 0x45670123 FLASH_KEY2 = 0xCDEF89AB def check_mem_contains(addr, buf): mem8 = stm.mem8 r = range(len(buf)) for off in r: if mem8[addr + off] != buf[off]: return False return True def check_mem_erased(addr, size): mem16 = stm.mem16 r = range(0, size, 2) for off in r: if mem16[addr + off] != 0xFFFF: return False return True def dfu_read(filename): f = open(filename, "rb") hdr = f.read(3) f.seek(0) if hdr == b"Dfu": pass elif hdr == b"\x1f\x8b\x08": f = uzlib.DecompIO(f, 16 + 15) else: print("Invalid firmware", filename) return None elems = [] hdr = f.read(11) sig, ver, size, num_targ = struct.unpack("<5sBIB", hdr) file_offset = 11 for i in range(num_targ): hdr = f.read(274) sig, alt, has_name, name, t_size, num_elem = struct.unpack("<6sBi255sII", hdr) file_offset += 274 file_offset_t = file_offset for j in range(num_elem): hdr = f.read(8) addr, e_size = struct.unpack(" 16 * 1024 and not check_mem_erased(mboot_addr + 16 * 1024, 16 * 1024): flash_erase_sector(1) flash_write(mboot_addr, mboot_fw) flash_lock() machine.enable_irq(irq) print("New Mboot programmed.") if check_mem_contains(mboot_addr, mboot_fw): print("Verification of new Mboot succeeded.") else: print("Verification of new Mboot FAILED! Try rerunning.") print("Programming finished, can now reset or turn off.") def _create_element(kind, body): return bytes([kind, len(body)]) + body def update_mpy(filename, fs_base, fs_len, fs_type=VFS_FAT, fs_blocksize=0, status_addr=None): # Check firmware is of .dfu or .dfu.gz type try: with open(filename, "rb") as f: hdr = uzlib.DecompIO(f, 16 + 15).read(6) except Exception: with open(filename, "rb") as f: hdr = f.read(6) if hdr != b"DfuSe\x01": print("Firmware must be a .dfu(.gz) file.") return if fs_type in (VFS_LFS1, VFS_LFS2) and not fs_blocksize: raise Exception("littlefs requires fs_blocksize parameter") mount_point = 1 elems = _create_element( _ELEM_TYPE_MOUNT, struct.pack("