micropython/ports/stm32/boards/LEGO_HUB_NO6/appupdate.py

62 wiersze
2.2 KiB
Python

# Application firmware update function for LEGO_HUB_NO6.
# MIT license; Copyright (c) 2022-2024 Damien P. George
from micropython import const
import random, struct, machine, fwupdate, spiflash, pyb
_IOCTL_BLOCK_COUNT = const(4)
_IOCTL_BLOCK_SIZE = const(5)
# Mboot addresses the external SPI flash at this location.
_MBOOT_SPIFLASH_BASE_ADDR = 0x80000000
# The raw filesystem is in the first 1MiB of external SPI flash,
# but skip the first and last flash sectors.
_RAW_FILESYSTEM_ADDR = const(4 * 1024)
_RAW_FILESYSTEM_LEN = const(1016 * 1024)
def _copy_file_to_raw_filesystem(filename, flash, block):
block_count = flash.ioctl(_IOCTL_BLOCK_COUNT, 0)
block_size = flash.ioctl(_IOCTL_BLOCK_SIZE, 0)
buf = bytearray(block_size)
with open(filename, "rb") as file:
while True:
n = file.readinto(buf)
if not n:
break
flash.writeblocks(block, buf)
block += 1
if block >= block_count:
print("|", end="")
block = 0
print(".", end="")
print()
def update_app(filename):
print(f"Updating application firmware from {filename}")
# We can't use pyb.Flash() because we need to write to the "reserved" 1M area.
flash = spiflash.SPIFlash(start=_RAW_FILESYSTEM_ADDR, len=_RAW_FILESYSTEM_LEN)
# Partition the raw filesystem into two segments for wear levelling.
block_count = flash.ioctl(_IOCTL_BLOCK_COUNT, 0)
block_size = flash.ioctl(_IOCTL_BLOCK_SIZE, 0)
block_start = random.randrange(0, block_count)
print(f"Raw filesystem block layout: 0 .. {block_start} .. {block_count}")
# Copy the file to the special raw filesystem.
_copy_file_to_raw_filesystem(filename, flash, block_start)
# Enter mboot with a request to do a filesystem-load update.
# Note: the filename doesn't mean anything here, but still needs to be non-empty.
fwupdate.update_mpy(
filename,
fs_type=fwupdate.VFS_RAW,
fs_base=_MBOOT_SPIFLASH_BASE_ADDR + _RAW_FILESYSTEM_ADDR + block_start * block_size,
fs_len=(block_count - block_start) * block_size,
fs_base2=_MBOOT_SPIFLASH_BASE_ADDR + _RAW_FILESYSTEM_ADDR,
fs_len2=block_start * block_size,
)