From ed7c169c893609c44cc9441cc091dee5a05b4f0a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 3 Jan 2025 11:53:00 +1100 Subject: [PATCH 01/33] py/objarray: Add MP_DEFINE_MEMORYVIEW_OBJ convenience macro. Signed-off-by: Damien George --- py/objarray.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/py/objarray.h b/py/objarray.h index 4a0e8a983fe77..bb7a514b97913 100644 --- a/py/objarray.h +++ b/py/objarray.h @@ -53,6 +53,10 @@ typedef struct _mp_obj_array_t { } mp_obj_array_t; #if MICROPY_PY_BUILTINS_MEMORYVIEW + +#define MP_DEFINE_MEMORYVIEW_OBJ(obj_name, typecode, offset, len, ptr) \ + mp_obj_array_t obj_name = {{&mp_type_memoryview}, (typecode), (offset), (len), (ptr)} + static inline void mp_obj_memoryview_init(mp_obj_array_t *self, size_t typecode, size_t offset, size_t len, void *items) { self->base.type = &mp_type_memoryview; self->typecode = typecode; @@ -60,6 +64,7 @@ static inline void mp_obj_memoryview_init(mp_obj_array_t *self, size_t typecode, self->len = len; self->items = items; } + #endif #if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY From 6c25351e090bb6de1cc0823f7a2ea7c75bef8726 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 15 Nov 2024 12:57:34 +1100 Subject: [PATCH 02/33] extmod/modvfs: Add rom_ioctl function. Signed-off-by: Damien George --- extmod/modvfs.c | 5 +++++ extmod/vfs.h | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/extmod/modvfs.c b/extmod/modvfs.c index df422365b75ef..2730e8cbc97d4 100644 --- a/extmod/modvfs.c +++ b/extmod/modvfs.c @@ -38,6 +38,10 @@ #error "MICROPY_PY_VFS requires MICROPY_VFS" #endif +#if MICROPY_VFS_ROM +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_rom_ioctl_obj, 1, 4, mp_vfs_rom_ioctl); +#endif + static const mp_rom_map_elem_t vfs_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_vfs) }, @@ -53,6 +57,7 @@ static const mp_rom_map_elem_t vfs_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) }, #endif #if MICROPY_VFS_ROM + { MP_ROM_QSTR(MP_QSTR_rom_ioctl), MP_ROM_PTR(&mp_vfs_rom_ioctl_obj) }, { MP_ROM_QSTR(MP_QSTR_VfsRom), MP_ROM_PTR(&mp_type_vfs_rom) }, #endif #if MICROPY_VFS_POSIX diff --git a/extmod/vfs.h b/extmod/vfs.h index 626e25a351123..543b2a8808f26 100644 --- a/extmod/vfs.h +++ b/extmod/vfs.h @@ -52,6 +52,13 @@ #define MP_BLOCKDEV_IOCTL_BLOCK_SIZE (5) #define MP_BLOCKDEV_IOCTL_BLOCK_ERASE (6) +// Constants for vfs.rom_ioctl() function. +#define MP_VFS_ROM_IOCTL_GET_NUMBER_OF_SEGMENTS (1) // rom_ioctl(1) +#define MP_VFS_ROM_IOCTL_GET_SEGMENT (2) // rom_ioctl(2, ) +#define MP_VFS_ROM_IOCTL_WRITE_PREPARE (3) // rom_ioctl(3, , ) +#define MP_VFS_ROM_IOCTL_WRITE (4) // rom_ioctl(4, , , ) +#define MP_VFS_ROM_IOCTL_WRITE_COMPLETE (5) // rom_ioctl(5, ) + // At the moment the VFS protocol just has import_stat, but could be extended to other methods typedef struct _mp_vfs_proto_t { mp_import_stat_t (*import_stat)(void *self, const char *path); @@ -122,4 +129,9 @@ MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_rmdir_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_stat_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_statvfs_obj); +#if MICROPY_VFS_ROM +// A port must define this. +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args); +#endif + #endif // MICROPY_INCLUDED_EXTMOD_VFS_H From e8d746ce99b63f642d9fee4806fca2c7f66687ac Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 4 Mar 2022 10:56:27 +1100 Subject: [PATCH 03/33] unix: Implement rom_ioctl. Signed-off-by: Damien George --- ports/unix/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ports/unix/main.c b/ports/unix/main.c index 58fa3ff589a55..53a5a2309f55b 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -45,6 +45,7 @@ #include "py/gc.h" #include "py/objstr.h" #include "py/cstack.h" +#include "py/mperrno.h" #include "py/mphal.h" #include "py/mpthread.h" #include "extmod/misc.h" @@ -803,3 +804,7 @@ void nlr_jump_fail(void *val) { fprintf(stderr, "FATAL: uncaught NLR %p\n", val); exit(1); } + +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); +} From 7cc96ed9c59dc700b049f674e87ebdc3972165a5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 18 Dec 2024 11:42:41 +1100 Subject: [PATCH 04/33] qemu/main: Implement rom_ioctl. Signed-off-by: Damien George --- ports/qemu/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/qemu/main.c b/ports/qemu/main.c index 75c6fe4cdc0d8..bcb62d51dd057 100644 --- a/ports/qemu/main.c +++ b/ports/qemu/main.c @@ -77,3 +77,7 @@ void nlr_jump_fail(void *val) { mp_printf(&mp_plat_print, "uncaught NLR\n"); exit(1); } + +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); +} From a24afb483a0bfb60d4adac77e5b5a172abb021f6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 4 Mar 2022 10:57:46 +1100 Subject: [PATCH 05/33] tools/mpremote: Add "romfs build" and "romfs deploy". tools/mpremote: Implement compilation .py to .mpy. Signed-off-by: Damien George --- tools/mpremote/mpremote/commands.py | 90 +++++++++++++++++ tools/mpremote/mpremote/main.py | 18 ++++ tools/mpremote/mpremote/romfs.py | 148 ++++++++++++++++++++++++++++ 3 files changed, 256 insertions(+) create mode 100644 tools/mpremote/mpremote/romfs.py diff --git a/tools/mpremote/mpremote/commands.py b/tools/mpremote/mpremote/commands.py index f86befd080349..578c5b9d0709c 100644 --- a/tools/mpremote/mpremote/commands.py +++ b/tools/mpremote/mpremote/commands.py @@ -7,6 +7,7 @@ from .transport import TransportError, stdout_write_bytes from .transport_serial import SerialTransport +from .romfs import make_romfs class CommandError(Exception): @@ -478,3 +479,92 @@ def do_rtc(state, args): state.transport.exec("machine.RTC().datetime({})".format(timetuple)) else: print(state.transport.eval("machine.RTC().datetime()")) + + +def _do_romfs_build(state, args): + state.did_action() + + input_directory = args.path[0] + output_file = input_directory + ".romfs" + romfs = make_romfs(input_directory, mpy_cross=args.mpy) + print(f"Image size is {len(romfs)} bytes") + with open(output_file, "wb") as f: + f.write(romfs) + + +def _do_romfs_deploy(state, args): + rom_id = 0 + + state.ensure_raw_repl() + state.did_action() + + # Read in or create the romfs filesystem. + romfs_filename = args.path[0] + if romfs_filename.endswith(".romfs"): + with open(romfs_filename, "rb") as f: + romfs = f.read() + else: + romfs = make_romfs(romfs_filename, mpy_cross=args.mpy) + print(f"Image size is {len(romfs)} bytes") + + # Detect the romfs and get its associated device. + state.transport.exec("import vfs") + state.transport.exec(f"import vfs;dev=vfs.rom_ioctl(2,{rom_id})") + has_object = state.transport.eval("hasattr(dev,'ioctl')") + if has_object: + rom_block_count = state.transport.eval("dev.ioctl(4,0)") + rom_block_size = state.transport.eval("dev.ioctl(5,0)") + rom_size = rom_block_count * rom_block_size + print( + f"ROM partition has size {rom_size} bytes ({rom_block_count} blocks of {rom_block_size} bytes each)" + ) + else: + rom_size = state.transport.eval("len(dev)") + print(f"ROM partition has size {rom_size} bytes") + + # Check if romfs will fit on the target device. + if len(romfs) > rom_size: + print("ROMFS partition is too small for image") + sys.exit(1) + + # Prepare ROM for writing. + print("Preparing ROM for writing") + chunk_size = 4096 + if has_object: + for offset in range(0, len(romfs), rom_block_size): + state.transport.exec(f"dev.ioctl(6,{offset // rom_block_size})") + chunk_size = min(chunk_size, rom_block_size) + else: + rom_min_write = state.transport.eval(f"vfs.rom_ioctl(3,{rom_id},{len(romfs)})") + chunk_size = max(chunk_size, rom_min_write) + + # Deploy the romfs filesystem to the device. + state.transport.exec(f"buf=bytearray({chunk_size})") + for offset in range(0, len(romfs), chunk_size): + romfs_chunk = romfs[offset : offset + chunk_size] + state.transport.exec(f"buf[:{len(romfs_chunk)}]=" + repr(romfs_chunk)) + print(f"\rWriting at offset {offset}", end="") + if has_object: + state.transport.exec( + f"dev.writeblocks({offset // rom_block_size},buf,{offset % rom_block_size})" + ) + else: + state.transport.exec(f"vfs.rom_ioctl(4,{rom_id},{offset},buf)") + + # Complete writing. + if has_object: + pass + else: + state.transport.eval(f"vfs.rom_ioctl(5,{rom_id})") + + print() + print("ROMFS image deployed") + + +def do_romfs(state, args): + if args.command[0] == "build": + _do_romfs_build(state, args) + elif args.command[0] == "deploy": + _do_romfs_deploy(state, args) + else: + raise CommandError(f"romfs: '{args.command[0]}' is not a command") diff --git a/tools/mpremote/mpremote/main.py b/tools/mpremote/mpremote/main.py index e6e397020fe85..abdf8aa44672a 100644 --- a/tools/mpremote/mpremote/main.py +++ b/tools/mpremote/mpremote/main.py @@ -36,6 +36,7 @@ do_resume, do_rtc, do_soft_reset, + do_romfs, ) from .mip import do_mip from .repl import do_repl @@ -228,6 +229,14 @@ def argparse_mip(): return cmd_parser +def argparse_romfs(): + cmd_parser = argparse.ArgumentParser(description="manage romfs") + _bool_flag(cmd_parser, "mpy", "m", True, "download as compiled .mpy files (default)") + cmd_parser.add_argument("command", nargs=1, help="romfs command (e.g. build, deploy)") + cmd_parser.add_argument("path", nargs=1, help="path to directory to deploy") + return cmd_parser + + def argparse_none(description): return lambda: argparse.ArgumentParser(description=description) @@ -302,6 +311,15 @@ def argparse_none(description): do_version, argparse_none("print version and exit"), ), + # separate commands for each step: + # manifest -> directory -> romfs -> device + # then can have shortcuts that do everything at once + # can have auto-mpy-cross + # no need to do the first step (manifest) now + "romfs": ( + do_romfs, + argparse_romfs, + ), } # Additional commands aliases. diff --git a/tools/mpremote/mpremote/romfs.py b/tools/mpremote/mpremote/romfs.py new file mode 100644 index 0000000000000..ae781a36dfe62 --- /dev/null +++ b/tools/mpremote/mpremote/romfs.py @@ -0,0 +1,148 @@ +# MIT license; Copyright (c) 2022 Damien P. George + +import struct, sys, os + +try: + from mpy_cross import run as mpy_cross_run +except ImportError: + mpy_cross_run = None + + +class VfsRomWriter: + ROMFS_HEADER = b"\xd2\xcd\x31" + + ROMFS_RECORD_KIND_UNUSED = 0 + ROMFS_RECORD_KIND_PADDING = 1 + ROMFS_RECORD_KIND_DATA_VERBATIM = 2 + ROMFS_RECORD_KIND_DATA_POINTER = 3 + ROMFS_RECORD_KIND_DIRECTORY = 4 + ROMFS_RECORD_KIND_FILE = 5 + + def __init__(self): + self._dir_stack = [(None, bytearray())] + + def _encode_uint(self, value): + encoded = [value & 0x7F] + value >>= 7 + while value != 0: + encoded.insert(0, 0x80 | (value & 0x7F)) + value >>= 7 + return bytes(encoded) + + def _pack(self, kind, payload): + return self._encode_uint(kind) + self._encode_uint(len(payload)) + payload + + def _extend(self, data): + buf = self._dir_stack[-1][1] + buf.extend(data) + return len(buf) + + def finalise(self): + _, data = self._dir_stack.pop() + encoded_kind = VfsRomWriter.ROMFS_HEADER + encoded_len = self._encode_uint(len(data)) + if (len(encoded_kind) + len(encoded_len) + len(data)) % 2 == 1: + encoded_len = b"\x80" + encoded_len + data = encoded_kind + encoded_len + data + return data + + def opendir(self, dirname): + self._dir_stack.append((dirname, bytearray())) + + def closedir(self): + dirname, dirdata = self._dir_stack.pop() + dirdata = self._encode_uint(len(dirname)) + bytes(dirname, "ascii") + dirdata + self._extend(self._pack(VfsRomWriter.ROMFS_RECORD_KIND_DIRECTORY, dirdata)) + + def mkdata(self, data): + assert len(self._dir_stack) == 1 + return self._extend(self._pack(VfsRomWriter.ROMFS_RECORD_KIND_DATA_VERBATIM, data)) - len( + data + ) + + def mkfile(self, filename, filedata): + filename = bytes(filename, "ascii") + payload = self._encode_uint(len(filename)) + payload += filename + if isinstance(filedata, tuple): + sub_payload = self._encode_uint(filedata[0]) + sub_payload += self._encode_uint(filedata[1]) + payload += self._pack(VfsRomWriter.ROMFS_RECORD_KIND_DATA_POINTER, sub_payload) + else: + payload += self._pack(VfsRomWriter.ROMFS_RECORD_KIND_DATA_VERBATIM, filedata) + self._dir_stack[-1][1].extend(self._pack(VfsRomWriter.ROMFS_RECORD_KIND_FILE, payload)) + + +def copy_recursively(vfs, src_dir, print_prefix, mpy_cross): + assert src_dir.endswith("/") + DIR = 1 << 14 + mpy_cross_missed = 0 + dir_contents = sorted(os.listdir(src_dir)) + for name in dir_contents: + src_name = src_dir + name + st = os.stat(src_name) + + if name == dir_contents[-1]: + # Last entry in the directory listing. + print_entry = "\\--" + print_recurse = " " + else: + # Not the last entry in the directory listing. + print_entry = "|--" + print_recurse = "| " + + if st[0] & DIR: + # A directory, enter it and copy its contents recursively. + print(print_prefix + print_entry, name + "/") + vfs.opendir(name) + mpy_cross_missed += copy_recursively( + vfs, src_name + "/", print_prefix + print_recurse, mpy_cross + ) + vfs.closedir() + else: + # A file. + did_mpy = False + name_extra = "" + if mpy_cross and name.endswith(".py"): + name_mpy = name[:-3] + ".mpy" + src_name_mpy = src_dir + name_mpy + if not os.path.isfile(src_name_mpy): + if mpy_cross_run is not None: + did_mpy = True + proc = mpy_cross_run(src_name) + proc.wait() + else: + mpy_cross_missed += 1 + if did_mpy: + name_extra = " -> .mpy" + print(print_prefix + print_entry, name + name_extra) + if did_mpy: + name = name_mpy + src_name = src_name_mpy + with open(src_name, "rb") as src: + vfs.mkfile(name, src.read()) + if did_mpy: + os.remove(src_name_mpy) + return mpy_cross_missed + + +def make_romfs(src_dir, *, mpy_cross): + if not src_dir.endswith("/"): + src_dir += "/" + + vfs = VfsRomWriter() + + # Build the filesystem recursively. + print("Building romfs filesystem, source directory: {}".format(src_dir)) + print("/") + try: + mpy_cross_missed = copy_recursively(vfs, src_dir, "", mpy_cross) + except OSError as er: + print("Error: OSError {}".format(er), file=sys.stderr) + sys.exit(1) + + if mpy_cross_missed: + print("Warning: `mpy_cross` module not found, .py files were not precompiled") + mpy_cross = False + + return vfs.finalise() From b6f9f090db80a58ba668202fd83ad593938ea9e7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 16 Jan 2025 12:56:20 +1100 Subject: [PATCH 06/33] tools/mpremote: Add "romfs query" subcommand. Signed-off-by: Damien George --- tools/mpremote/mpremote/commands.py | 32 +++++++++++++++++++++++++++-- tools/mpremote/mpremote/main.py | 4 ++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/tools/mpremote/mpremote/commands.py b/tools/mpremote/mpremote/commands.py index 578c5b9d0709c..f03596202421e 100644 --- a/tools/mpremote/mpremote/commands.py +++ b/tools/mpremote/mpremote/commands.py @@ -481,6 +481,33 @@ def do_rtc(state, args): print(state.transport.eval("machine.RTC().datetime()")) +def _do_romfs_query(state, args): + state.ensure_raw_repl() + state.did_action() + + # Detect the romfs and get its associated device. + state.transport.exec("import vfs") + num_rom_partitions = state.transport.eval("hasattr(vfs, 'rom_ioctl') and vfs.rom_ioctl(1)") + if num_rom_partitions is False: + print("No ROM partitions available") + return + + for rom_id in range(num_rom_partitions): + state.transport.exec(f"dev=vfs.rom_ioctl(2,{rom_id})") + has_object = state.transport.eval("hasattr(dev,'ioctl')") + if has_object: + rom_block_count = state.transport.eval("dev.ioctl(4,0)") + rom_block_size = state.transport.eval("dev.ioctl(5,0)") + rom_size = rom_block_count * rom_block_size + print( + f"ROM{rom_id} partition has size {rom_size} bytes ({rom_block_count} blocks of {rom_block_size} bytes each)" + ) + else: + rom_size = state.transport.eval("len(dev)") + print(f"ROM{rom_id} partition has size {rom_size} bytes") + print("Contents:", state.transport.eval("bytes(memoryview(dev)[:8]).hex(':')"), "...") + + def _do_romfs_build(state, args): state.did_action() @@ -508,7 +535,6 @@ def _do_romfs_deploy(state, args): print(f"Image size is {len(romfs)} bytes") # Detect the romfs and get its associated device. - state.transport.exec("import vfs") state.transport.exec(f"import vfs;dev=vfs.rom_ioctl(2,{rom_id})") has_object = state.transport.eval("hasattr(dev,'ioctl')") if has_object: @@ -562,7 +588,9 @@ def _do_romfs_deploy(state, args): def do_romfs(state, args): - if args.command[0] == "build": + if args.command[0] == "query": + _do_romfs_query(state, args) + elif args.command[0] == "build": _do_romfs_build(state, args) elif args.command[0] == "deploy": _do_romfs_deploy(state, args) diff --git a/tools/mpremote/mpremote/main.py b/tools/mpremote/mpremote/main.py index abdf8aa44672a..6130cb6200614 100644 --- a/tools/mpremote/mpremote/main.py +++ b/tools/mpremote/mpremote/main.py @@ -232,8 +232,8 @@ def argparse_mip(): def argparse_romfs(): cmd_parser = argparse.ArgumentParser(description="manage romfs") _bool_flag(cmd_parser, "mpy", "m", True, "download as compiled .mpy files (default)") - cmd_parser.add_argument("command", nargs=1, help="romfs command (e.g. build, deploy)") - cmd_parser.add_argument("path", nargs=1, help="path to directory to deploy") + cmd_parser.add_argument("command", nargs=1, help="romfs command (e.g. query, build, deploy)") + cmd_parser.add_argument("path", nargs="*", help="path to directory to deploy") return cmd_parser From 75af92d9cf79b09d6d912de02187916db54c3938 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 4 Mar 2022 10:56:50 +1100 Subject: [PATCH 07/33] stm32: Enable VfsRom. Signed-off-by: Damien George --- ports/stm32/boardctrl.h | 6 + .../boards/NUCLEO_F091RC/mpconfigboard.mk | 2 +- ports/stm32/boards/PYBD_SF2/f722_qspi.ld | 10 +- ports/stm32/boards/PYBD_SF2/mpconfigboard.h | 1 + ports/stm32/boards/PYBD_SF6/f767.ld | 6 +- ports/stm32/boards/_boot.py | 10 ++ ports/stm32/boards/manifest.py | 1 + ports/stm32/boards/manifest_minimal.py | 1 + ports/stm32/boards/stm32f091xc.ld | 6 +- ports/stm32/boards/stm32f405.ld | 6 +- ports/stm32/mpconfigboard_common.h | 6 + ports/stm32/storage.c | 143 ++++++++++++++++++ 12 files changed, 193 insertions(+), 5 deletions(-) create mode 100644 ports/stm32/boards/_boot.py create mode 100644 ports/stm32/boards/manifest_minimal.py diff --git a/ports/stm32/boardctrl.h b/ports/stm32/boardctrl.h index 8f4ce30eff80a..bddef85f764d6 100644 --- a/ports/stm32/boardctrl.h +++ b/ports/stm32/boardctrl.h @@ -61,6 +61,12 @@ #define MICROPY_BOARD_TOP_SOFT_RESET_LOOP boardctrl_top_soft_reset_loop #endif +#ifndef MICROPY_BOARD_FROZEN_BOOT_FILE +#if MICROPY_VFS_ROM +#define MICROPY_BOARD_FROZEN_BOOT_FILE "_boot.py" +#endif +#endif + #ifndef MICROPY_BOARD_RUN_BOOT_PY #define MICROPY_BOARD_RUN_BOOT_PY boardctrl_run_boot_py #endif diff --git a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk index 193ed793f6fc0..d8187824830f0 100644 --- a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk @@ -9,7 +9,7 @@ MICROPY_VFS_LFS1 ?= 1 MICROPY_HW_ENABLE_ISR_UART_FLASH_FUNCS_IN_RAM = 1 # Don't include default frozen modules because MCU is tight on flash space -FROZEN_MANIFEST ?= +FROZEN_MANIFEST ?= boards/manifest_minimal.py # LTO reduces final binary size, may be slower to build depending on gcc version and hardware LTO ?= 1 diff --git a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld index 70d7f9cc4b8e4..876f918d79f75 100644 --- a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld +++ b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld @@ -19,7 +19,8 @@ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K - FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 480K /* sectors 2-7 */ + FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 352K /* sectors 2-6 */ + FLASH_ROMFS (rx): ORIGIN = 0x08060000, LENGTH = 128K /* sector 7 */ FLASH_EXT (rx) : ORIGIN = 0x90000000, LENGTH = 2048K /* external QSPI */ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 256K /* DTCM+SRAM1+SRAM2 */ } @@ -39,6 +40,9 @@ _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; +_micropy_hw_romfs_start = ORIGIN(FLASH_ROMFS); +_micropy_hw_romfs_size = LENGTH(FLASH_ROMFS); + /* Define output sections */ SECTIONS { @@ -50,6 +54,10 @@ SECTIONS *lib/mynewt-nimble/*(.text* .rodata*) *lib/cyw43-driver/*(.rodata.w4343*_combined) *drivers/cyw43/*(.rodata.cyw43_btfw_*) + *lib/oofatfs/*(.text* .rodata*) + *lib/littlefs/*(.text* .rodata*) + *lib/lwip/*(.text* .rodata*) + *extmod/*(.text* .rodata*) . = ALIGN(4); } >FLASH_EXT } diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h index f0ef67e77e604..c55fc85e0d592 100644 --- a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h @@ -27,6 +27,7 @@ #define MICROPY_HW_BOARD_NAME "PYBD-SF2W" #define MICROPY_HW_MCU_NAME "STM32F722IEK" +#define MICROPY_VFS_ROM (1) #define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "PYBD" #define MICROPY_PY_PYB_LEGACY (1) diff --git a/ports/stm32/boards/PYBD_SF6/f767.ld b/ports/stm32/boards/PYBD_SF6/f767.ld index 4262a48a9962c..fd3f4051c58ad 100644 --- a/ports/stm32/boards/PYBD_SF6/f767.ld +++ b/ports/stm32/boards/PYBD_SF6/f767.ld @@ -17,7 +17,8 @@ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K - FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 2016K /* sectors 1-11 3x32K 1*128K 7*256K */ + FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 1504K /* sectors 1-9 3x32K 1*128K 5*256K */ + FLASH_ROMFS (rx): ORIGIN = 0x08180000, LENGTH = 512K /* sectors 10-11 2*256k */ FLASH_EXT (rx) : ORIGIN = 0x90000000, LENGTH = 2048K /* external QSPI */ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 512K /* DTCM=128k, SRAM1=368K, SRAM2=16K */ } @@ -37,4 +38,7 @@ _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; +_micropy_hw_romfs_start = ORIGIN(FLASH_ROMFS); +_micropy_hw_romfs_size = LENGTH(FLASH_ROMFS); + INCLUDE common_bl.ld diff --git a/ports/stm32/boards/_boot.py b/ports/stm32/boards/_boot.py new file mode 100644 index 0000000000000..3a7345f80cb94 --- /dev/null +++ b/ports/stm32/boards/_boot.py @@ -0,0 +1,10 @@ +import sys, vfs + +try: + vfs.mount(vfs.VfsRom(vfs.rom_ioctl(2)), "/rom") + # Note: this won't execute boot.py/main.py because the cwd is still /flash. + sys.path.insert(0, "/rom") +except: + pass + +del sys, vfs diff --git a/ports/stm32/boards/manifest.py b/ports/stm32/boards/manifest.py index 4f38179713ea6..7e4d1821351eb 100644 --- a/ports/stm32/boards/manifest.py +++ b/ports/stm32/boards/manifest.py @@ -1,3 +1,4 @@ +freeze(".", "_boot.py", opt=3) include("$(MPY_DIR)/extmod/asyncio") require("dht") diff --git a/ports/stm32/boards/manifest_minimal.py b/ports/stm32/boards/manifest_minimal.py new file mode 100644 index 0000000000000..ec2408e1074aa --- /dev/null +++ b/ports/stm32/boards/manifest_minimal.py @@ -0,0 +1 @@ +freeze(".", "_boot.py", opt=3) diff --git a/ports/stm32/boards/stm32f091xc.ld b/ports/stm32/boards/stm32f091xc.ld index a8f0d3316ebf6..e7ae96ec4dd64 100644 --- a/ports/stm32/boards/stm32f091xc.ld +++ b/ports/stm32/boards/stm32f091xc.ld @@ -5,7 +5,8 @@ /* Specify the memory areas */ MEMORY { - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 236K /* sectors 0-117 */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 226K /* sectors 0-112 */ + FLASH_ROMFS (rx): ORIGIN = 0x08036000, LENGTH = 10K /* sectors 113-117 */ FLASH_FS (r) : ORIGIN = 0x0803B000, LENGTH = 20K /* sectors 118-127 */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K } @@ -32,3 +33,6 @@ _heap_end = _sstack; _micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); + +_micropy_hw_romfs_start = ORIGIN(FLASH_ROMFS); +_micropy_hw_romfs_size = LENGTH(FLASH_ROMFS); diff --git a/ports/stm32/boards/stm32f405.ld b/ports/stm32/boards/stm32f405.ld index 792558b6371e0..430ecc125e9d0 100644 --- a/ports/stm32/boards/stm32f405.ld +++ b/ports/stm32/boards/stm32f405.ld @@ -8,7 +8,8 @@ MEMORY FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K /* entire flash */ FLASH_START (rx): ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */ FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 112K /* sectors 1,2,3,4 are for filesystem */ - FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 896K /* sectors 5,6,7,8,9,10,11 */ + FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 640K /* sectors 5,6,7,8,9 */ + FLASH_ROMFS (rx): ORIGIN = 0x080c0000, LENGTH = 256K /* sectors 10,11 */ CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K } @@ -33,3 +34,6 @@ _micropy_hw_internal_flash_storage_ram_cache_start = ORIGIN(CCMRAM); _micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(CCMRAM) + LENGTH(CCMRAM); _micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); + +_micropy_hw_romfs_start = ORIGIN(FLASH_ROMFS); +_micropy_hw_romfs_size = LENGTH(FLASH_ROMFS); diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 4ce0a75b87e2b..07e79aea3ec5e 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -32,6 +32,12 @@ /*****************************************************************************/ // Feature settings with defaults +#ifndef MICROPY_VFS_ROM +#if defined(STM32F091xC) || defined(STM32F405xx) +#define MICROPY_VFS_ROM (1) +#endif +#endif + // Whether to include the stm module #ifndef MICROPY_PY_STM #define MICROPY_PY_STM (1) diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index a6594fd4d98c9..a946773d5c1f9 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -24,10 +24,12 @@ * THE SOFTWARE. */ +#include "py/objarray.h" #include "py/runtime.h" #include "py/mperrno.h" #include "extmod/vfs_fat.h" +#include "flash.h" #include "systick.h" #include "led.h" #include "storage.h" @@ -231,6 +233,9 @@ int storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_bl // // Expose the flash as an object with the block protocol. +// If VfsRom is enabled then make pyb.Flash objects support raw internal flash. +#define PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH (MICROPY_VFS_ROM) + #ifdef MICROPY_HW_BDEV_SPIFLASH_EXTENDED // Board defined an external SPI flash for use with extended block protocol #define MICROPY_HW_BDEV_BLOCKSIZE_EXT (MP_SPIFLASH_ERASE_BLOCK_SIZE) @@ -264,6 +269,9 @@ typedef struct _pyb_flash_obj_t { uint32_t start; // in bytes uint32_t len; // in bytes bool use_native_block_size; + #if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH + bool is_raw_internal_flash; + #endif } pyb_flash_obj_t; // This Flash object represents the entire available flash, with emulated partition table at start @@ -289,6 +297,7 @@ static mp_obj_t pyb_flash_make_new(const mp_obj_type_t *type, size_t n_args, siz { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -322,12 +331,32 @@ static mp_obj_t pyb_flash_make_new(const mp_obj_type_t *type, size_t n_args, siz return MP_OBJ_FROM_PTR(self); } +#if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH +static mp_int_t pyb_flash_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { + pyb_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->is_raw_internal_flash && flags == MP_BUFFER_READ) { + bufinfo->buf = (void *)self->start; + bufinfo->len = self->len; + bufinfo->typecode = 'B'; + return 0; + } else { + // Unsupported. + return 1; + } +} +#endif + static mp_obj_t pyb_flash_readblocks(size_t n_args, const mp_obj_t *args) { pyb_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]); uint32_t block_num = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE); mp_uint_t ret = -MP_EIO; + #if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH + if (self->is_raw_internal_flash) { + // Read from raw flash is not implemented. + } else + #endif if (n_args == 3) { // Cast self->start to signed in case it's pyb_flash_obj with negative start block_num += FLASH_PART1_START_BLOCK + (int32_t)self->start / FLASH_BLOCK_SIZE; @@ -355,6 +384,15 @@ static mp_obj_t pyb_flash_writeblocks(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); mp_uint_t ret = -MP_EIO; + #if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH + if (self->is_raw_internal_flash) { + uint32_t sector_size = 0; + flash_get_sector_info(self->start, NULL, §or_size); + uint32_t offset = n_args == 3 ? 0 : mp_obj_get_int(args[3]); + uint32_t dest = self->start + block_num * sector_size + offset; + ret = flash_write(dest, bufinfo.buf, bufinfo.len / 4); + } else + #endif if (n_args == 3) { // Cast self->start to signed in case it's pyb_flash_obj with negative start block_num += FLASH_PART1_START_BLOCK + (int32_t)self->start / FLASH_BLOCK_SIZE; @@ -379,6 +417,12 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_flash_writeblocks_obj, 3, 4, pyb_ static mp_obj_t pyb_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { pyb_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t cmd = mp_obj_get_int(cmd_in); + #if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH + uint32_t sector_size = 0; + if (self->is_raw_internal_flash) { + flash_get_sector_info(self->start, NULL, §or_size); + } + #endif switch (cmd) { case MP_BLOCKDEV_IOCTL_INIT: { mp_int_t ret = 0; @@ -403,6 +447,12 @@ static mp_obj_t pyb_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_ case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: { mp_int_t n; + #if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH + if (self->is_raw_internal_flash) { + // Get number of sectors of internal flash. + n = self->len / sector_size; + } else + #endif if (self == &pyb_flash_obj) { // Get true size n = storage_get_block_count(); @@ -416,6 +466,12 @@ static mp_obj_t pyb_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_ case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: { mp_int_t n = FLASH_BLOCK_SIZE; + #if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH + if (self->is_raw_internal_flash) { + // Get actual sector size of internal flash. + n = sector_size; + } else + #endif if (self->use_native_block_size) { n = MICROPY_HW_BDEV_BLOCKSIZE_EXT; } @@ -424,6 +480,13 @@ static mp_obj_t pyb_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_ case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: { int ret = 0; + #if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH + if (self->is_raw_internal_flash) { + uint32_t dest = self->start + mp_obj_get_int(arg_in) * sector_size; + ret = flash_erase(dest); + return MP_OBJ_NEW_SMALL_INT(ret); + } + #endif #if defined(MICROPY_HW_BDEV_ERASEBLOCKS_EXT) if (self->use_native_block_size) { mp_int_t block_num = self->start / MICROPY_HW_BDEV_BLOCKSIZE_EXT + mp_obj_get_int(arg_in); @@ -448,12 +511,19 @@ static const mp_rom_map_elem_t pyb_flash_locals_dict_table[] = { static MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table); +#if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH +#define PYB_FLASH_GET_BUFFER buffer, pyb_flash_get_buffer, +#else +#define PYB_FLASH_GET_BUFFER +#endif + MP_DEFINE_CONST_OBJ_TYPE( pyb_flash_type, MP_QSTR_Flash, MP_TYPE_FLAG_NONE, make_new, pyb_flash_make_new, print, pyb_flash_print, + PYB_FLASH_GET_BUFFER locals_dict, &pyb_flash_locals_dict ); @@ -475,3 +545,76 @@ void pyb_flash_init_vfs(fs_user_mount_t *vfs) { } #endif + +/******************************************************************************/ +// romfs partition + +#if MICROPY_VFS_ROM + +#define MICROPY_HW_ROMFS_BASE (uintptr_t)(&_micropy_hw_romfs_start) +#define MICROPY_HW_ROMFS_BYTES (uintptr_t)(&_micropy_hw_romfs_size) + +extern uint8_t _micropy_hw_romfs_start; +extern uint8_t _micropy_hw_romfs_size; + +#if MICROPY_HW_ENABLE_STORAGE +static const pyb_flash_obj_t romfs_obj = { + .base = { &pyb_flash_type }, + .start = MICROPY_HW_ROMFS_BASE, + .len = MICROPY_HW_ROMFS_BYTES, + .use_native_block_size = false, + .is_raw_internal_flash = true, +}; +#else +static const MP_DEFINE_MEMORYVIEW_OBJ(romfs_obj, 'B', 0, MICROPY_HW_ROMFS_BYTES, (void *)MICROPY_HW_ROMFS_BASE); +#endif + +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { + switch (mp_obj_get_int(args[0])) { + case MP_VFS_ROM_IOCTL_GET_NUMBER_OF_SEGMENTS: + return MP_OBJ_NEW_SMALL_INT(1); + + case MP_VFS_ROM_IOCTL_GET_SEGMENT: + return MP_OBJ_FROM_PTR(&romfs_obj); + + #if !MICROPY_HW_ENABLE_STORAGE + + case MP_VFS_ROM_IOCTL_WRITE_PREPARE: { + // Erase sectors in given range. + if (n_args < 3) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + uint32_t dest = MICROPY_HW_ROMFS_BASE; + uint32_t dest_max = dest + mp_obj_get_int(args[2]); + while (dest < dest_max) { + int ret = flash_erase(dest); + if (ret < 0) { + return MP_OBJ_NEW_SMALL_INT(ret); + } + uint32_t sector_size = 0; + flash_get_sector_info(dest, NULL, §or_size); + dest += sector_size; + } + return MP_OBJ_NEW_SMALL_INT(16); + } + + case MP_VFS_ROM_IOCTL_WRITE: { + // Write data to flash. + if (n_args < 4) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + uint32_t dest = MICROPY_HW_ROMFS_BASE + mp_obj_get_int(args[2]); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); + int ret = flash_write(dest, bufinfo.buf, bufinfo.len / 4); + return MP_OBJ_NEW_SMALL_INT(ret); + } + + #endif + + default: + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } +} + +#endif // MICROPY_VFS_ROM From 1c1e38d264962e4aa85e62a9d92bbc0965736ac1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 3 Jan 2025 15:08:41 +1100 Subject: [PATCH 08/33] stm32: Disable machine.Pin legacy on NUCLEO_F091RC. Signed-off-by: Damien George --- ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h index 6a9ac02714fb7..0f108e4ae38ed 100644 --- a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h @@ -11,6 +11,7 @@ #define MICROPY_PY_NETWORK (0) #define MICROPY_PY_STM (0) #define MICROPY_PY_PYB_LEGACY (0) +#define MICROPY_PY_MACHINE_PIN_LEGACY (0) #define MICROPY_PY_HEAPQ (0) #define MICROPY_PY_FRAMEBUF (0) From bde499b5baaf64894d63ab68b6421aea8e8fe2c6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 3 Jan 2025 15:29:56 +1100 Subject: [PATCH 09/33] stm32: Increase size of NUCLEO_F091RC ROM partition. Signed-off-by: Damien George --- ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h | 1 + ports/stm32/boards/stm32f091xc.ld | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h index 0f108e4ae38ed..f137ad09a6133 100644 --- a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h @@ -6,6 +6,7 @@ #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_OPT_COMPUTED_GOTO (0) +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_SOCKET (0) #define MICROPY_PY_NETWORK (0) diff --git a/ports/stm32/boards/stm32f091xc.ld b/ports/stm32/boards/stm32f091xc.ld index e7ae96ec4dd64..f1c6ecd2c03a3 100644 --- a/ports/stm32/boards/stm32f091xc.ld +++ b/ports/stm32/boards/stm32f091xc.ld @@ -5,8 +5,8 @@ /* Specify the memory areas */ MEMORY { - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 226K /* sectors 0-112 */ - FLASH_ROMFS (rx): ORIGIN = 0x08036000, LENGTH = 10K /* sectors 113-117 */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 224K /* sectors 0-111 */ + FLASH_ROMFS (rx): ORIGIN = 0x08038000, LENGTH = 12K /* sectors 112-117 */ FLASH_FS (r) : ORIGIN = 0x0803B000, LENGTH = 20K /* sectors 118-127 */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K } From 82ed2fc08f2632f4cb7af3e6f0b5ba8efc3fb6f5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 16 Jan 2025 12:57:56 +1100 Subject: [PATCH 10/33] stm32: Rework ROM partition support. Now supports both internal flash and external QSPI-mapped flash. Signed-off-by: Damien George --- ports/stm32/Makefile | 1 + .../ADAFRUIT_F405_EXPRESS/mpconfigboard.h | 4 + .../stm32/boards/LEGO_HUB_NO6/mpconfigboard.h | 4 + .../stm32/boards/LEGO_HUB_NO6/stm32f413xg.ld | 8 +- .../stm32/boards/LEGO_HUB_NO7/mpconfigboard.h | 4 + .../boards/NUCLEO_F091RC/mpconfigboard.h | 4 + ports/stm32/boards/PYBD_SF2/f722_qspi.ld | 15 +- ports/stm32/boards/PYBD_SF2/mpconfigboard.h | 6 +- ports/stm32/boards/PYBD_SF6/f767.ld | 7 +- ports/stm32/boards/PYBD_SF6/mpconfigboard.h | 5 + ports/stm32/boards/PYBV10/mpconfigboard.h | 4 + ports/stm32/boards/PYBV11/mpconfigboard.h | 4 + ports/stm32/boards/_boot.py | 2 +- ports/stm32/boards/stm32f091xc.ld | 8 +- ports/stm32/boards/stm32f405.ld | 5 +- ports/stm32/mpconfigboard_common.h | 26 ++- ports/stm32/mpconfigport.h | 3 + ports/stm32/qspi.c | 2 - ports/stm32/qspi.h | 7 + ports/stm32/romfs.c | 161 ++++++++++++++++++ ports/stm32/storage.c | 141 --------------- 21 files changed, 250 insertions(+), 171 deletions(-) create mode 100644 ports/stm32/romfs.c diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index a9612f1a5792e..d75a898448714 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -287,6 +287,7 @@ SRC_C += \ rtc.c \ flash.c \ flashbdev.c \ + romfs.c \ spibdev.c \ storage.c \ sdcard.c \ diff --git a/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h b/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h index c573f942a0a13..f8c426b4d00ae 100644 --- a/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h +++ b/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h @@ -25,6 +25,10 @@ #define MICROPY_HW_RTC_USE_US (0) #define MICROPY_HW_RTC_USE_CALOUT (1) +// ROMFS config +#define MICROPY_HW_ROMFS_ENABLE_INTERNAL_FLASH (1) +#define MICROPY_HW_ROMFS_ENABLE_PART1 (1) + // External SPI Flash config #if !MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE diff --git a/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h b/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h index 9878b1533eedb..e038bc2325ea2 100644 --- a/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h +++ b/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h @@ -32,6 +32,10 @@ // For 2.7 to 3.6 V, 75 to 100 MHz: 3 wait states. #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_3 +// ROMFS config +#define MICROPY_HW_ROMFS_ENABLE_INTERNAL_FLASH (1) +#define MICROPY_HW_ROMFS_ENABLE_PART1 (1) + // UART buses // Bluetooth HCI #define MICROPY_HW_UART2_CTS (pyb_pin_BT_CTS) diff --git a/ports/stm32/boards/LEGO_HUB_NO6/stm32f413xg.ld b/ports/stm32/boards/LEGO_HUB_NO6/stm32f413xg.ld index d3c43a6948316..5e516c01bf92d 100644 --- a/ports/stm32/boards/LEGO_HUB_NO6/stm32f413xg.ld +++ b/ports/stm32/boards/LEGO_HUB_NO6/stm32f413xg.ld @@ -3,11 +3,11 @@ */ /* Specify the memory areas */ -/* FLASH_FS2 is placed before FLASH_TEXT to support 1MB and 1.5MB FLASH with common code in flashbdev.c */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K /* entire flash */ - FLASH_APP (rx) : ORIGIN = 0x08010000, LENGTH = 976K + FLASH_APP (rx) : ORIGIN = 0x08010000, LENGTH = 448K + FLASH_ROMFS (rx): ORIGIN = 0x08080000, LENGTH = 256K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K /* SRAM1 + SRAM2 */ } @@ -25,3 +25,7 @@ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; + +/* ROMFS location */ +_micropy_hw_romfs_part1_start = ORIGIN(FLASH_ROMFS); +_micropy_hw_romfs_part1_size = LENGTH(FLASH_ROMFS); diff --git a/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h b/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h index 3615225e51b6b..b07c7cea9171e 100644 --- a/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h +++ b/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h @@ -32,6 +32,10 @@ // For 2.7 to 3.6 V, 75 to 100 MHz: 3 wait states. #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_3 +// ROMFS config +#define MICROPY_HW_ROMFS_ENABLE_INTERNAL_FLASH (1) +#define MICROPY_HW_ROMFS_ENABLE_PART1 (1) + // UART buses // Bluetooth HCI #define MICROPY_HW_UART2_CTS (pyb_pin_BT_CTS) diff --git a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h index f137ad09a6133..00f31b5628168 100644 --- a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h @@ -34,6 +34,10 @@ // The board has an external 32kHz crystal #define MICROPY_HW_RTC_USE_LSE (1) +// ROMFS config +#define MICROPY_HW_ROMFS_ENABLE_INTERNAL_FLASH (1) +#define MICROPY_HW_ROMFS_ENABLE_PART1 (1) + // UART config #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) diff --git a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld index 876f918d79f75..5efefde358cc8 100644 --- a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld +++ b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld @@ -19,9 +19,9 @@ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K - FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 352K /* sectors 2-6 */ - FLASH_ROMFS (rx): ORIGIN = 0x08060000, LENGTH = 128K /* sector 7 */ - FLASH_EXT (rx) : ORIGIN = 0x90000000, LENGTH = 2048K /* external QSPI */ + FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 480K /* sectors 2-7 */ + FLASH_EXT (rx) : ORIGIN = 0x90000000, LENGTH = 1024K /* external QSPI */ + FLASH_ROMFS (rx): ORIGIN = 0x90100000, LENGTH = 512K /* external QSPI */ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 256K /* DTCM+SRAM1+SRAM2 */ } @@ -40,8 +40,9 @@ _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; -_micropy_hw_romfs_start = ORIGIN(FLASH_ROMFS); -_micropy_hw_romfs_size = LENGTH(FLASH_ROMFS); +/* ROMFS location */ +_micropy_hw_romfs_part1_start = ORIGIN(FLASH_ROMFS); +_micropy_hw_romfs_part1_size = LENGTH(FLASH_ROMFS); /* Define output sections */ SECTIONS @@ -54,10 +55,6 @@ SECTIONS *lib/mynewt-nimble/*(.text* .rodata*) *lib/cyw43-driver/*(.rodata.w4343*_combined) *drivers/cyw43/*(.rodata.cyw43_btfw_*) - *lib/oofatfs/*(.text* .rodata*) - *lib/littlefs/*(.text* .rodata*) - *lib/lwip/*(.text* .rodata*) - *extmod/*(.text* .rodata*) . = ALIGN(4); } >FLASH_EXT } diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h index c55fc85e0d592..e8923bf9b66e5 100644 --- a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h @@ -27,7 +27,6 @@ #define MICROPY_HW_BOARD_NAME "PYBD-SF2W" #define MICROPY_HW_MCU_NAME "STM32F722IEK" -#define MICROPY_VFS_ROM (1) #define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "PYBD" #define MICROPY_PY_PYB_LEGACY (1) @@ -65,6 +64,11 @@ void board_sleep(int value); #define MICROPY_HW_RTC_USE_US (1) #define MICROPY_HW_RTC_USE_CALOUT (1) +// ROMFS config +#define MICROPY_HW_ROMFS_ENABLE_EXTERNAL_QSPI (1) +#define MICROPY_HW_ROMFS_QSPI_SPIFLASH_OBJ (&spi_bdev2.spiflash) +#define MICROPY_HW_ROMFS_ENABLE_PART1 (1) + // SPI flash #1, for R/W storage #define MICROPY_HW_SOFTQSPI_SCK_LOW(self) (GPIOE->BSRR = (0x10000 << 11)) #define MICROPY_HW_SOFTQSPI_SCK_HIGH(self) (GPIOE->BSRR = (1 << 11)) diff --git a/ports/stm32/boards/PYBD_SF6/f767.ld b/ports/stm32/boards/PYBD_SF6/f767.ld index fd3f4051c58ad..e130efd6608fa 100644 --- a/ports/stm32/boards/PYBD_SF6/f767.ld +++ b/ports/stm32/boards/PYBD_SF6/f767.ld @@ -18,8 +18,8 @@ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 1504K /* sectors 1-9 3x32K 1*128K 5*256K */ - FLASH_ROMFS (rx): ORIGIN = 0x08180000, LENGTH = 512K /* sectors 10-11 2*256k */ FLASH_EXT (rx) : ORIGIN = 0x90000000, LENGTH = 2048K /* external QSPI */ + FLASH_ROMFS (rx): ORIGIN = 0x90000000, LENGTH = 1024K /* external QSPI */ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 512K /* DTCM=128k, SRAM1=368K, SRAM2=16K */ } @@ -38,7 +38,8 @@ _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; -_micropy_hw_romfs_start = ORIGIN(FLASH_ROMFS); -_micropy_hw_romfs_size = LENGTH(FLASH_ROMFS); +/* ROMFS location */ +_micropy_hw_romfs_part1_start = ORIGIN(FLASH_ROMFS); +_micropy_hw_romfs_part1_size = LENGTH(FLASH_ROMFS); INCLUDE common_bl.ld diff --git a/ports/stm32/boards/PYBD_SF6/mpconfigboard.h b/ports/stm32/boards/PYBD_SF6/mpconfigboard.h index 8c11d7b2eec96..526a111177987 100644 --- a/ports/stm32/boards/PYBD_SF6/mpconfigboard.h +++ b/ports/stm32/boards/PYBD_SF6/mpconfigboard.h @@ -45,6 +45,11 @@ #define MICROPY_HW_CLK_PLLQ (6) #define MICROPY_HW_FLASH_LATENCY (FLASH_LATENCY_4) +// ROMFS config +#define MICROPY_HW_ROMFS_ENABLE_EXTERNAL_QSPI (1) +#define MICROPY_HW_ROMFS_QSPI_SPIFLASH_OBJ (&spi_bdev2.spiflash) +#define MICROPY_HW_ROMFS_ENABLE_PART1 (1) + // Extra UART config #define MICROPY_HW_UART7_TX (pyb_pin_W16) #define MICROPY_HW_UART7_RX (pyb_pin_W22B) diff --git a/ports/stm32/boards/PYBV10/mpconfigboard.h b/ports/stm32/boards/PYBV10/mpconfigboard.h index 6219862be4957..b9216c70ff1fa 100644 --- a/ports/stm32/boards/PYBV10/mpconfigboard.h +++ b/ports/stm32/boards/PYBV10/mpconfigboard.h @@ -24,6 +24,10 @@ #define MICROPY_HW_RTC_USE_US (0) #define MICROPY_HW_RTC_USE_CALOUT (1) +// ROMFS config +#define MICROPY_HW_ROMFS_ENABLE_INTERNAL_FLASH (1) +#define MICROPY_HW_ROMFS_ENABLE_PART1 (1) + // UART config #define MICROPY_HW_UART1_NAME "XB" #define MICROPY_HW_UART1_TX (pin_B6) diff --git a/ports/stm32/boards/PYBV11/mpconfigboard.h b/ports/stm32/boards/PYBV11/mpconfigboard.h index c8f660c8fbb86..2b96ff974b7f2 100644 --- a/ports/stm32/boards/PYBV11/mpconfigboard.h +++ b/ports/stm32/boards/PYBV11/mpconfigboard.h @@ -24,6 +24,10 @@ #define MICROPY_HW_RTC_USE_US (0) #define MICROPY_HW_RTC_USE_CALOUT (1) +// ROMFS config +#define MICROPY_HW_ROMFS_ENABLE_INTERNAL_FLASH (1) +#define MICROPY_HW_ROMFS_ENABLE_PART1 (1) + // UART config #define MICROPY_HW_UART1_NAME "XB" #define MICROPY_HW_UART1_TX (pin_B6) diff --git a/ports/stm32/boards/_boot.py b/ports/stm32/boards/_boot.py index 3a7345f80cb94..be65bff646ad0 100644 --- a/ports/stm32/boards/_boot.py +++ b/ports/stm32/boards/_boot.py @@ -1,7 +1,7 @@ import sys, vfs try: - vfs.mount(vfs.VfsRom(vfs.rom_ioctl(2)), "/rom") + vfs.mount(vfs.VfsRom(vfs.rom_ioctl(2, 0)), "/rom") # Note: this won't execute boot.py/main.py because the cwd is still /flash. sys.path.insert(0, "/rom") except: diff --git a/ports/stm32/boards/stm32f091xc.ld b/ports/stm32/boards/stm32f091xc.ld index f1c6ecd2c03a3..0f0fedaf3067a 100644 --- a/ports/stm32/boards/stm32f091xc.ld +++ b/ports/stm32/boards/stm32f091xc.ld @@ -5,8 +5,8 @@ /* Specify the memory areas */ MEMORY { - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 224K /* sectors 0-111 */ - FLASH_ROMFS (rx): ORIGIN = 0x08038000, LENGTH = 12K /* sectors 112-117 */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 226K /* sectors 0-112 */ + FLASH_ROMFS (rx): ORIGIN = 0x08038800, LENGTH = 10K /* sectors 113-117 */ FLASH_FS (r) : ORIGIN = 0x0803B000, LENGTH = 20K /* sectors 118-127 */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K } @@ -34,5 +34,5 @@ _heap_end = _sstack; _micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); -_micropy_hw_romfs_start = ORIGIN(FLASH_ROMFS); -_micropy_hw_romfs_size = LENGTH(FLASH_ROMFS); +_micropy_hw_romfs_part1_start = ORIGIN(FLASH_ROMFS); +_micropy_hw_romfs_part1_size = LENGTH(FLASH_ROMFS); diff --git a/ports/stm32/boards/stm32f405.ld b/ports/stm32/boards/stm32f405.ld index 430ecc125e9d0..98039f3e56d7b 100644 --- a/ports/stm32/boards/stm32f405.ld +++ b/ports/stm32/boards/stm32f405.ld @@ -35,5 +35,6 @@ _micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(CCMRAM) + LENGTH(CCMRA _micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); -_micropy_hw_romfs_start = ORIGIN(FLASH_ROMFS); -_micropy_hw_romfs_size = LENGTH(FLASH_ROMFS); +/* ROMFS location */ +_micropy_hw_romfs_part1_start = ORIGIN(FLASH_ROMFS); +_micropy_hw_romfs_part1_size = LENGTH(FLASH_ROMFS); diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 07e79aea3ec5e..2a650077f3a45 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -32,12 +32,6 @@ /*****************************************************************************/ // Feature settings with defaults -#ifndef MICROPY_VFS_ROM -#if defined(STM32F091xC) || defined(STM32F405xx) -#define MICROPY_VFS_ROM (1) -#endif -#endif - // Whether to include the stm module #ifndef MICROPY_PY_STM #define MICROPY_PY_STM (1) @@ -73,6 +67,26 @@ #define MICROPY_HW_ENTER_BOOTLOADER_VIA_RESET (1) #endif +// Whether to enable ROMFS on the internal flash. +#ifndef MICROPY_HW_ROMFS_ENABLE_INTERNAL_FLASH +#define MICROPY_HW_ROMFS_ENABLE_INTERNAL_FLASH (0) +#endif + +// Whether to enable ROMFS on external QSPI flash. +#ifndef MICROPY_HW_ROMFS_ENABLE_EXTERNAL_QSPI +#define MICROPY_HW_ROMFS_ENABLE_EXTERNAL_QSPI (0) +#endif + +// Whether to enable ROMFS partition 1. +#ifndef MICROPY_HW_ROMFS_ENABLE_PART1 +#define MICROPY_HW_ROMFS_ENABLE_PART1 (0) +#endif + +// Whether to enable ROMFS partition 2. +#ifndef MICROPY_HW_ROMFS_ENABLE_PART2 +#define MICROPY_HW_ROMFS_ENABLE_PART2 (0) +#endif + // Whether to enable storage on the internal flash of the MCU #ifndef MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (1) diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 2b57446ee8233..da86fa641623a 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -79,6 +79,9 @@ #define MICROPY_SCHEDULER_STATIC_NODES (1) #define MICROPY_SCHEDULER_DEPTH (8) #define MICROPY_VFS (1) +#ifndef MICROPY_VFS_ROM +#define MICROPY_VFS_ROM (MICROPY_HW_ROMFS_ENABLE_INTERNAL_FLASH || MICROPY_HW_ROMFS_ENABLE_EXTERNAL_QSPI) +#endif // control over Python builtins #ifndef MICROPY_PY_BUILTINS_HELP_TEXT diff --git a/ports/stm32/qspi.c b/ports/stm32/qspi.c index 98364db41d4fb..34359a1ccf838 100644 --- a/ports/stm32/qspi.c +++ b/ports/stm32/qspi.c @@ -34,8 +34,6 @@ #if defined(MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2) -#define QSPI_MAP_ADDR (0x90000000) - #ifndef MICROPY_HW_QSPI_PRESCALER #define MICROPY_HW_QSPI_PRESCALER 3 // F_CLK = F_AHB/3 (72MHz when CPU is 216MHz) #endif diff --git a/ports/stm32/qspi.h b/ports/stm32/qspi.h index c774b12582be6..6fe91168cfdba 100644 --- a/ports/stm32/qspi.h +++ b/ports/stm32/qspi.h @@ -28,9 +28,16 @@ #include "drivers/bus/qspi.h" +#define QSPI_MAP_ADDR (0x90000000) +#define QSPI_MAP_ADDR_MAX (0xa0000000) + extern const mp_qspi_proto_t qspi_proto; void qspi_init(void); void qspi_memory_map(void); +static inline bool qspi_is_valid_addr(uint32_t addr) { + return QSPI_MAP_ADDR <= addr && addr < QSPI_MAP_ADDR_MAX; +} + #endif // MICROPY_INCLUDED_STM32_QSPI_H diff --git a/ports/stm32/romfs.c b/ports/stm32/romfs.c new file mode 100644 index 0000000000000..5bee9f548b6eb --- /dev/null +++ b/ports/stm32/romfs.c @@ -0,0 +1,161 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2025 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/obj.h" +#include "py/objarray.h" +#include "py/mperrno.h" +#include "extmod/vfs.h" +#include "drivers/memory/spiflash.h" + +#include "flash.h" +#include "qspi.h" +#include "storage.h" + +#if MICROPY_VFS_ROM + +#if MICROPY_HW_ROMFS_ENABLE_PART1 && !defined(MICROPY_HW_ROMFS_PART1_START) +#define MICROPY_HW_ROMFS_PART1_START (uintptr_t)(&_micropy_hw_romfs_part1_start) +#define MICROPY_HW_ROMFS_PART1_SIZE (uintptr_t)(&_micropy_hw_romfs_part1_size) +extern uint8_t _micropy_hw_romfs_part1_start; +extern uint8_t _micropy_hw_romfs_part1_size; +#endif + +#if MICROPY_HW_ROMFS_ENABLE_PART2 && !defined(MICROPY_HW_ROMFS_PART2_START) +#define MICROPY_HW_ROMFS_PART2_START (uintptr_t)(&_micropy_hw_romfs_part2_start) +#define MICROPY_HW_ROMFS_PART2_SIZE (uintptr_t)(&_micropy_hw_romfs_part2_size) +extern uint8_t _micropy_hw_romfs_part2_start; +extern uint8_t _micropy_hw_romfs_part2_size; +#endif + +#define ROMFS_MEMORYVIEW(base, size) {{&mp_type_memoryview}, 'B', 0, (size), (void *)(base)} + +static const mp_obj_array_t romfs_obj_table[] = { + #if MICROPY_HW_ROMFS_ENABLE_PART1 + ROMFS_MEMORYVIEW(MICROPY_HW_ROMFS_PART1_START, MICROPY_HW_ROMFS_PART1_SIZE), + #endif + #if MICROPY_HW_ROMFS_ENABLE_PART2 + ROMFS_MEMORYVIEW(MICROPY_HW_ROMFS_PART2_START, MICROPY_HW_ROMFS_PART2_SIZE), + #endif +}; + +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { + mp_int_t cmd = mp_obj_get_int(args[0]); + if (cmd == MP_VFS_ROM_IOCTL_GET_NUMBER_OF_SEGMENTS) { + return MP_OBJ_NEW_SMALL_INT(MP_ARRAY_SIZE(romfs_obj_table)); + } + + if (n_args < 2) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + + mp_int_t romfs_id = mp_obj_get_int(args[1]); + if (!(0 <= romfs_id && romfs_id < MP_ARRAY_SIZE(romfs_obj_table))) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + + const mp_obj_array_t *romfs_obj = &romfs_obj_table[romfs_id]; + uintptr_t romfs_base = (uintptr_t)romfs_obj->items; + uintptr_t romfs_len = romfs_obj->len; + + if (cmd == MP_VFS_ROM_IOCTL_GET_SEGMENT) { + // Return the ROMFS memoryview object. + return MP_OBJ_FROM_PTR(romfs_obj); + } + + if (cmd == MP_VFS_ROM_IOCTL_WRITE_PREPARE) { + // Erase sectors in given range. + if (n_args < 3) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + uint32_t dest = romfs_base; + uint32_t dest_max = dest + mp_obj_get_int(args[2]); + if (dest_max > romfs_base + romfs_len) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + + #if MICROPY_HW_ROMFS_ENABLE_INTERNAL_FLASH + if (flash_is_valid_addr(dest)) { + while (dest < dest_max) { + int ret = flash_erase(dest); + if (ret < 0) { + return MP_OBJ_NEW_SMALL_INT(ret); + } + uint32_t sector_size = 0; + flash_get_sector_info(dest, NULL, §or_size); + dest += sector_size; + } + return MP_OBJ_NEW_SMALL_INT(16); + } + #endif + + #if MICROPY_HW_ROMFS_ENABLE_EXTERNAL_QSPI + if (qspi_is_valid_addr(dest)) { + dest -= QSPI_MAP_ADDR; + dest_max -= QSPI_MAP_ADDR; + while (dest < dest_max) { + int ret = mp_spiflash_erase_block(MICROPY_HW_ROMFS_QSPI_SPIFLASH_OBJ, dest); + if (ret < 0) { + return MP_OBJ_NEW_SMALL_INT(ret); + } + dest += MP_SPIFLASH_ERASE_BLOCK_SIZE; + } + return MP_OBJ_NEW_SMALL_INT(4); + } + #endif + } + + if (cmd == MP_VFS_ROM_IOCTL_WRITE) { + // Write data to flash. + if (n_args < 4) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + uint32_t dest = romfs_base + mp_obj_get_int(args[2]); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); + if (dest + bufinfo.len > romfs_base + romfs_len) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + + #if MICROPY_HW_ROMFS_ENABLE_INTERNAL_FLASH + if (flash_is_valid_addr(dest)) { + int ret = flash_write(dest, bufinfo.buf, bufinfo.len / 4); + return MP_OBJ_NEW_SMALL_INT(ret); + } + #endif + + #if MICROPY_HW_ROMFS_ENABLE_EXTERNAL_QSPI + if (qspi_is_valid_addr(dest)) { + dest -= QSPI_MAP_ADDR; + int ret = mp_spiflash_write(MICROPY_HW_ROMFS_QSPI_SPIFLASH_OBJ, dest, bufinfo.len, bufinfo.buf); + return MP_OBJ_NEW_SMALL_INT(ret); + } + #endif + } + + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); +} + +#endif // MICROPY_VFS_ROM diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index a946773d5c1f9..7625bd223f0cd 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -24,7 +24,6 @@ * THE SOFTWARE. */ -#include "py/objarray.h" #include "py/runtime.h" #include "py/mperrno.h" #include "extmod/vfs_fat.h" @@ -233,9 +232,6 @@ int storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_bl // // Expose the flash as an object with the block protocol. -// If VfsRom is enabled then make pyb.Flash objects support raw internal flash. -#define PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH (MICROPY_VFS_ROM) - #ifdef MICROPY_HW_BDEV_SPIFLASH_EXTENDED // Board defined an external SPI flash for use with extended block protocol #define MICROPY_HW_BDEV_BLOCKSIZE_EXT (MP_SPIFLASH_ERASE_BLOCK_SIZE) @@ -269,9 +265,6 @@ typedef struct _pyb_flash_obj_t { uint32_t start; // in bytes uint32_t len; // in bytes bool use_native_block_size; - #if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH - bool is_raw_internal_flash; - #endif } pyb_flash_obj_t; // This Flash object represents the entire available flash, with emulated partition table at start @@ -331,32 +324,12 @@ static mp_obj_t pyb_flash_make_new(const mp_obj_type_t *type, size_t n_args, siz return MP_OBJ_FROM_PTR(self); } -#if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH -static mp_int_t pyb_flash_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { - pyb_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->is_raw_internal_flash && flags == MP_BUFFER_READ) { - bufinfo->buf = (void *)self->start; - bufinfo->len = self->len; - bufinfo->typecode = 'B'; - return 0; - } else { - // Unsupported. - return 1; - } -} -#endif - static mp_obj_t pyb_flash_readblocks(size_t n_args, const mp_obj_t *args) { pyb_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]); uint32_t block_num = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE); mp_uint_t ret = -MP_EIO; - #if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH - if (self->is_raw_internal_flash) { - // Read from raw flash is not implemented. - } else - #endif if (n_args == 3) { // Cast self->start to signed in case it's pyb_flash_obj with negative start block_num += FLASH_PART1_START_BLOCK + (int32_t)self->start / FLASH_BLOCK_SIZE; @@ -384,15 +357,6 @@ static mp_obj_t pyb_flash_writeblocks(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); mp_uint_t ret = -MP_EIO; - #if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH - if (self->is_raw_internal_flash) { - uint32_t sector_size = 0; - flash_get_sector_info(self->start, NULL, §or_size); - uint32_t offset = n_args == 3 ? 0 : mp_obj_get_int(args[3]); - uint32_t dest = self->start + block_num * sector_size + offset; - ret = flash_write(dest, bufinfo.buf, bufinfo.len / 4); - } else - #endif if (n_args == 3) { // Cast self->start to signed in case it's pyb_flash_obj with negative start block_num += FLASH_PART1_START_BLOCK + (int32_t)self->start / FLASH_BLOCK_SIZE; @@ -417,12 +381,6 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_flash_writeblocks_obj, 3, 4, pyb_ static mp_obj_t pyb_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { pyb_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t cmd = mp_obj_get_int(cmd_in); - #if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH - uint32_t sector_size = 0; - if (self->is_raw_internal_flash) { - flash_get_sector_info(self->start, NULL, §or_size); - } - #endif switch (cmd) { case MP_BLOCKDEV_IOCTL_INIT: { mp_int_t ret = 0; @@ -447,12 +405,6 @@ static mp_obj_t pyb_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_ case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: { mp_int_t n; - #if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH - if (self->is_raw_internal_flash) { - // Get number of sectors of internal flash. - n = self->len / sector_size; - } else - #endif if (self == &pyb_flash_obj) { // Get true size n = storage_get_block_count(); @@ -466,12 +418,6 @@ static mp_obj_t pyb_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_ case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: { mp_int_t n = FLASH_BLOCK_SIZE; - #if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH - if (self->is_raw_internal_flash) { - // Get actual sector size of internal flash. - n = sector_size; - } else - #endif if (self->use_native_block_size) { n = MICROPY_HW_BDEV_BLOCKSIZE_EXT; } @@ -480,13 +426,6 @@ static mp_obj_t pyb_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_ case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: { int ret = 0; - #if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH - if (self->is_raw_internal_flash) { - uint32_t dest = self->start + mp_obj_get_int(arg_in) * sector_size; - ret = flash_erase(dest); - return MP_OBJ_NEW_SMALL_INT(ret); - } - #endif #if defined(MICROPY_HW_BDEV_ERASEBLOCKS_EXT) if (self->use_native_block_size) { mp_int_t block_num = self->start / MICROPY_HW_BDEV_BLOCKSIZE_EXT + mp_obj_get_int(arg_in); @@ -511,19 +450,12 @@ static const mp_rom_map_elem_t pyb_flash_locals_dict_table[] = { static MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table); -#if PYB_FLASH_ENABLE_RAW_INTERNAL_FLASH -#define PYB_FLASH_GET_BUFFER buffer, pyb_flash_get_buffer, -#else -#define PYB_FLASH_GET_BUFFER -#endif - MP_DEFINE_CONST_OBJ_TYPE( pyb_flash_type, MP_QSTR_Flash, MP_TYPE_FLAG_NONE, make_new, pyb_flash_make_new, print, pyb_flash_print, - PYB_FLASH_GET_BUFFER locals_dict, &pyb_flash_locals_dict ); @@ -545,76 +477,3 @@ void pyb_flash_init_vfs(fs_user_mount_t *vfs) { } #endif - -/******************************************************************************/ -// romfs partition - -#if MICROPY_VFS_ROM - -#define MICROPY_HW_ROMFS_BASE (uintptr_t)(&_micropy_hw_romfs_start) -#define MICROPY_HW_ROMFS_BYTES (uintptr_t)(&_micropy_hw_romfs_size) - -extern uint8_t _micropy_hw_romfs_start; -extern uint8_t _micropy_hw_romfs_size; - -#if MICROPY_HW_ENABLE_STORAGE -static const pyb_flash_obj_t romfs_obj = { - .base = { &pyb_flash_type }, - .start = MICROPY_HW_ROMFS_BASE, - .len = MICROPY_HW_ROMFS_BYTES, - .use_native_block_size = false, - .is_raw_internal_flash = true, -}; -#else -static const MP_DEFINE_MEMORYVIEW_OBJ(romfs_obj, 'B', 0, MICROPY_HW_ROMFS_BYTES, (void *)MICROPY_HW_ROMFS_BASE); -#endif - -mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { - switch (mp_obj_get_int(args[0])) { - case MP_VFS_ROM_IOCTL_GET_NUMBER_OF_SEGMENTS: - return MP_OBJ_NEW_SMALL_INT(1); - - case MP_VFS_ROM_IOCTL_GET_SEGMENT: - return MP_OBJ_FROM_PTR(&romfs_obj); - - #if !MICROPY_HW_ENABLE_STORAGE - - case MP_VFS_ROM_IOCTL_WRITE_PREPARE: { - // Erase sectors in given range. - if (n_args < 3) { - return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); - } - uint32_t dest = MICROPY_HW_ROMFS_BASE; - uint32_t dest_max = dest + mp_obj_get_int(args[2]); - while (dest < dest_max) { - int ret = flash_erase(dest); - if (ret < 0) { - return MP_OBJ_NEW_SMALL_INT(ret); - } - uint32_t sector_size = 0; - flash_get_sector_info(dest, NULL, §or_size); - dest += sector_size; - } - return MP_OBJ_NEW_SMALL_INT(16); - } - - case MP_VFS_ROM_IOCTL_WRITE: { - // Write data to flash. - if (n_args < 4) { - return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); - } - uint32_t dest = MICROPY_HW_ROMFS_BASE + mp_obj_get_int(args[2]); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); - int ret = flash_write(dest, bufinfo.buf, bufinfo.len / 4); - return MP_OBJ_NEW_SMALL_INT(ret); - } - - #endif - - default: - return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); - } -} - -#endif // MICROPY_VFS_ROM From 5b56336f1aca1b4d0e8d470968f475516933794b Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 14 Jan 2025 11:34:21 +0100 Subject: [PATCH 11/33] stm32/boards/ARDUINO_GIGA: Enable ROMFS. Signed-off-by: iabdalkader --- ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h | 9 +++++++-- ports/stm32/boards/ARDUINO_GIGA/stm32h747.ld | 6 +++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h b/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h index fdf3128a3606d..b46d3c4b81097 100644 --- a/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h +++ b/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h @@ -32,6 +32,11 @@ typedef unsigned int mp_uint_t; // must be pointer size #define MICROPY_HW_ENTER_BOOTLOADER_VIA_RESET (0) #define MICROPY_HW_TIM_IS_RESERVED(id) (id == 1) +// ROMFS config +#define MICROPY_HW_ROMFS_ENABLE_EXTERNAL_QSPI (1) +#define MICROPY_HW_ROMFS_QSPI_SPIFLASH_OBJ (&spi_bdev.spiflash) +#define MICROPY_HW_ROMFS_ENABLE_PART1 (1) + // Flash storage config #define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1) #define MICROPY_HW_SPIFLASH_SOFT_RESET (1) @@ -125,8 +130,8 @@ void GIGA_board_low_power(int mode); // QSPI flash #1 for storage #define MICROPY_HW_QSPI_PRESCALER (2) // 100MHz #define MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 (27) -// Reserve 1MiB at the end for compatibility with alternate firmware that places WiFi blob here. -#define MICROPY_HW_SPIFLASH_SIZE_BITS (120 * 1024 * 1024) +// Reserve 4MiB for romfs and 1MiB at for WiFi/BT firmware. +#define MICROPY_HW_SPIFLASH_SIZE_BITS (88 * 1024 * 1024) #define MICROPY_HW_QSPIFLASH_CS (pyb_pin_QSPI2_CS) #define MICROPY_HW_QSPIFLASH_SCK (pyb_pin_QSPI2_CLK) #define MICROPY_HW_QSPIFLASH_IO0 (pyb_pin_QSPI2_D0) diff --git a/ports/stm32/boards/ARDUINO_GIGA/stm32h747.ld b/ports/stm32/boards/ARDUINO_GIGA/stm32h747.ld index 793a76b970292..43dda26f07dc3 100644 --- a/ports/stm32/boards/ARDUINO_GIGA/stm32h747.ld +++ b/ports/stm32/boards/ARDUINO_GIGA/stm32h747.ld @@ -13,11 +13,11 @@ MEMORY SRAM3 (xrw) : ORIGIN = 0x30040000, LENGTH = 32K /* SRAM3 D2 */ SRAM4 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K /* SRAM4 D3 */ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K /* Total available flash */ - FLASH_EXT (rx) : ORIGIN = 0x90000000, LENGTH = 16384K /* 16MBs external QSPI flash */ FLASH_BL (rx) : ORIGIN = 0x08000000, LENGTH = 128K /* Arduino bootloader */ FLASH_FS (r) : ORIGIN = 0x08020000, LENGTH = 128K /* filesystem */ FLASH_TEXT (rx) : ORIGIN = 0x08040000, LENGTH = 1280K /* CM7 firmware */ FLASH_CM4 (rx) : ORIGIN = 0x08180000, LENGTH = 512K /* CM4 firmware */ + FLASH_ROMFS (rx) : ORIGIN = 0x90B00000, LENGTH = 4096K /* romfs partition in QSPI flash */ } /* produce a link error if there is not this amount of RAM for these sections */ @@ -44,6 +44,10 @@ _micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(DTCM) + LENGTH(DTCM); _micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); +/* Location of romfs filesystem */ +_micropy_hw_romfs_part1_start = ORIGIN(FLASH_ROMFS); +_micropy_hw_romfs_part1_size = LENGTH(FLASH_ROMFS); + /* OpenAMP shared memory region */ _openamp_shm_region_start = ORIGIN(SRAM4); _openamp_shm_region_end = ORIGIN(SRAM4) + LENGTH(SRAM4); From 90f5af4195b2691f3bf2de603018ae14973b0069 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 14 Jan 2025 11:35:45 +0100 Subject: [PATCH 12/33] stm32/boards/ARDUINO_NICLA_VISION: Enable ROMFS. Signed-off-by: iabdalkader --- ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h | 9 +++++++-- ports/stm32/boards/ARDUINO_NICLA_VISION/stm32h747.ld | 6 +++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h b/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h index 505f8b6890169..d1b9f60b23e33 100644 --- a/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h +++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h @@ -32,6 +32,11 @@ typedef unsigned int mp_uint_t; // must be pointer size #define MICROPY_HW_ENTER_BOOTLOADER_VIA_RESET (0) #define MICROPY_HW_TIM_IS_RESERVED(id) (id == 3) +// ROMFS config +#define MICROPY_HW_ROMFS_ENABLE_EXTERNAL_QSPI (1) +#define MICROPY_HW_ROMFS_QSPI_SPIFLASH_OBJ (&spi_bdev.spiflash) +#define MICROPY_HW_ROMFS_ENABLE_PART1 (1) + // Flash storage config #define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1) #define MICROPY_HW_SPIFLASH_SOFT_RESET (1) @@ -130,8 +135,8 @@ void NICLAV_board_osc_enable(int enable); // QSPI flash for storage #define MICROPY_HW_QSPI_PRESCALER (2) // 100MHz #define MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 (27) -// Reserve 1MiB at the end for compatibility with alternate firmware that places WiFi blob here. -#define MICROPY_HW_SPIFLASH_SIZE_BITS (120 * 1024 * 1024) +// Reserve 4MiB for romfs and 1MiB at for WiFi/BT firmware. +#define MICROPY_HW_SPIFLASH_SIZE_BITS (88 * 1024 * 1024) #define MICROPY_HW_QSPIFLASH_CS (pyb_pin_QSPI2_CS) #define MICROPY_HW_QSPIFLASH_SCK (pyb_pin_QSPI2_CLK) #define MICROPY_HW_QSPIFLASH_IO0 (pyb_pin_QSPI2_D0) diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/stm32h747.ld b/ports/stm32/boards/ARDUINO_NICLA_VISION/stm32h747.ld index 6d6ce279f299c..580f51726dc4d 100644 --- a/ports/stm32/boards/ARDUINO_NICLA_VISION/stm32h747.ld +++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/stm32h747.ld @@ -13,11 +13,11 @@ MEMORY SRAM3 (xrw) : ORIGIN = 0x30040000, LENGTH = 32K /* SRAM3 D2 */ SRAM4 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K /* SRAM4 D3 */ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K /* Total available flash */ - FLASH_EXT (rx) : ORIGIN = 0x90000000, LENGTH = 16384K /* 16MBs external QSPI flash */ FLASH_BL (rx) : ORIGIN = 0x08000000, LENGTH = 128K /* Arduino bootloader */ FLASH_FS (r) : ORIGIN = 0x08020000, LENGTH = 128K /* filesystem */ FLASH_TEXT (rx) : ORIGIN = 0x08040000, LENGTH = 1280K /* CM7 firmware */ FLASH_CM4 (rx) : ORIGIN = 0x08180000, LENGTH = 512K /* CM4 firmware */ + FLASH_ROMFS (rx) : ORIGIN = 0x90B00000, LENGTH = 4096K /* romfs partition in QSPI flash */ } _cm4_ram_start = ORIGIN(SRAM4); @@ -46,6 +46,10 @@ _micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(DTCM) + LENGTH(DTCM); _micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); +/* Location of romfs filesystem */ +_micropy_hw_romfs_part1_start = ORIGIN(FLASH_ROMFS); +_micropy_hw_romfs_part1_size = LENGTH(FLASH_ROMFS); + /* OpenAMP shared memory region */ _openamp_shm_region_start = ORIGIN(SRAM4); _openamp_shm_region_end = ORIGIN(SRAM4) + LENGTH(SRAM4); From e6b2259c782965e71131951093e7d1e45d839695 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 14 Jan 2025 11:36:22 +0100 Subject: [PATCH 13/33] stm32/boards/ARDUINO_PORTENTA_H7: Enable ROMFS. Signed-off-by: iabdalkader --- ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h | 9 +++++++-- ports/stm32/boards/ARDUINO_PORTENTA_H7/stm32h747.ld | 6 +++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h index 900bf18673728..e295dcb82cd4e 100644 --- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h +++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h @@ -32,6 +32,11 @@ typedef unsigned int mp_uint_t; // must be pointer size #define MICROPY_HW_ENTER_BOOTLOADER_VIA_RESET (0) #define MICROPY_HW_TIM_IS_RESERVED(id) (id == 1) +// ROMFS config +#define MICROPY_HW_ROMFS_ENABLE_EXTERNAL_QSPI (1) +#define MICROPY_HW_ROMFS_QSPI_SPIFLASH_OBJ (&spi_bdev.spiflash) +#define MICROPY_HW_ROMFS_ENABLE_PART1 (1) + // Flash storage config #define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1) #define MICROPY_HW_SPIFLASH_SOFT_RESET (1) @@ -129,8 +134,8 @@ void PORTENTA_board_osc_enable(int enable); // QSPI flash #1 for storage #define MICROPY_HW_QSPI_PRESCALER (2) // 100MHz #define MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 (27) -// Reserve 1MiB at the end for compatibility with alternate firmware that places WiFi blob here. -#define MICROPY_HW_SPIFLASH_SIZE_BITS (120 * 1024 * 1024) +// Reserve 4MiB for romfs and 1MiB at for WiFi/BT firmware. +#define MICROPY_HW_SPIFLASH_SIZE_BITS (88 * 1024 * 1024) #define MICROPY_HW_QSPIFLASH_CS (pyb_pin_QSPI2_CS) #define MICROPY_HW_QSPIFLASH_SCK (pyb_pin_QSPI2_CLK) #define MICROPY_HW_QSPIFLASH_IO0 (pyb_pin_QSPI2_D0) diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/stm32h747.ld b/ports/stm32/boards/ARDUINO_PORTENTA_H7/stm32h747.ld index 793a76b970292..43dda26f07dc3 100644 --- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/stm32h747.ld +++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/stm32h747.ld @@ -13,11 +13,11 @@ MEMORY SRAM3 (xrw) : ORIGIN = 0x30040000, LENGTH = 32K /* SRAM3 D2 */ SRAM4 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K /* SRAM4 D3 */ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K /* Total available flash */ - FLASH_EXT (rx) : ORIGIN = 0x90000000, LENGTH = 16384K /* 16MBs external QSPI flash */ FLASH_BL (rx) : ORIGIN = 0x08000000, LENGTH = 128K /* Arduino bootloader */ FLASH_FS (r) : ORIGIN = 0x08020000, LENGTH = 128K /* filesystem */ FLASH_TEXT (rx) : ORIGIN = 0x08040000, LENGTH = 1280K /* CM7 firmware */ FLASH_CM4 (rx) : ORIGIN = 0x08180000, LENGTH = 512K /* CM4 firmware */ + FLASH_ROMFS (rx) : ORIGIN = 0x90B00000, LENGTH = 4096K /* romfs partition in QSPI flash */ } /* produce a link error if there is not this amount of RAM for these sections */ @@ -44,6 +44,10 @@ _micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(DTCM) + LENGTH(DTCM); _micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); +/* Location of romfs filesystem */ +_micropy_hw_romfs_part1_start = ORIGIN(FLASH_ROMFS); +_micropy_hw_romfs_part1_size = LENGTH(FLASH_ROMFS); + /* OpenAMP shared memory region */ _openamp_shm_region_start = ORIGIN(SRAM4); _openamp_shm_region_end = ORIGIN(SRAM4) + LENGTH(SRAM4); From dfcb3413772cae4fe24365bdc101bb51ad0d2488 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 4 Mar 2022 10:57:38 +1100 Subject: [PATCH 14/33] rp2: Enable VfsRom. Signed-off-by: Damien George --- ports/rp2/modules/_boot.py | 9 ++++++++- ports/rp2/mpconfigport.h | 1 + ports/rp2/rp2_flash.c | 39 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/ports/rp2/modules/_boot.py b/ports/rp2/modules/_boot.py index 71cb28d6823bb..772287078806c 100644 --- a/ports/rp2/modules/_boot.py +++ b/ports/rp2/modules/_boot.py @@ -1,6 +1,13 @@ import vfs +import sys import machine, rp2 +# Try to mount the ROMFS. +try: + vfs.mount(vfs.VfsRom(vfs.rom_ioctl(2)), "/rom") + sys.path.insert(0, "/rom") +except: + pass # Try to mount the filesystem, and format the flash if it doesn't exist. # Note: the flash requires the programming size to be aligned to 256 bytes. @@ -12,4 +19,4 @@ fs = vfs.VfsLfs2(bdev, progsize=256) vfs.mount(fs, "/") -del vfs, bdev, fs +del vfs, sys, bdev, fs diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index fe8287ba1d6e5..435e0a7ca14d7 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -170,6 +170,7 @@ #define MICROPY_VFS (1) #define MICROPY_VFS_LFS2 (1) #define MICROPY_VFS_FAT (1) +#define MICROPY_VFS_ROM (1) #define MICROPY_SSL_MBEDTLS (1) #define MICROPY_PY_LWIP_PPP (MICROPY_PY_NETWORK_PPP_LWIP) #define MICROPY_PY_LWIP_SOCK_RAW (MICROPY_PY_LWIP) diff --git a/ports/rp2/rp2_flash.c b/ports/rp2/rp2_flash.c index a487fb1633b21..b71dd4f4f57af 100644 --- a/ports/rp2/rp2_flash.c +++ b/ports/rp2/rp2_flash.c @@ -28,6 +28,7 @@ #include "py/mphal.h" #include "py/runtime.h" +#include "py/mperrno.h" #include "extmod/vfs.h" #include "modrp2.h" #include "hardware/flash.h" @@ -44,6 +45,9 @@ static_assert(MICROPY_HW_FLASH_STORAGE_BYTES % 4096 == 0, "Flash storage size mu #define MICROPY_HW_FLASH_STORAGE_BASE (PICO_FLASH_SIZE_BYTES - MICROPY_HW_FLASH_STORAGE_BYTES) #endif +#define MICROPY_HW_ROMFS_BASE (512 * 1024) // leave 512k for firmware... +#define MICROPY_HW_ROMFS_BYTES (MICROPY_HW_FLASH_STORAGE_BASE - MICROPY_HW_ROMFS_BASE) + static_assert(MICROPY_HW_FLASH_STORAGE_BYTES <= PICO_FLASH_SIZE_BYTES, "MICROPY_HW_FLASH_STORAGE_BYTES too big"); static_assert(MICROPY_HW_FLASH_STORAGE_BASE + MICROPY_HW_FLASH_STORAGE_BYTES <= PICO_FLASH_SIZE_BYTES, "MICROPY_HW_FLASH_STORAGE_BYTES too big"); @@ -59,6 +63,14 @@ static rp2_flash_obj_t rp2_flash_obj = { .flash_size = MICROPY_HW_FLASH_STORAGE_BYTES, }; +#if MICROPY_HW_ROMFS_BYTES > 0 +static rp2_flash_obj_t rp2_flash_romfs_obj = { + .base = { &rp2_flash_type }, + .flash_base = MICROPY_HW_ROMFS_BASE, + .flash_size = MICROPY_HW_ROMFS_BYTES, +}; +#endif + // Tag the flash drive in the binary as readable/writable (but not reformatable) bi_decl(bi_block_device( BINARY_INFO_TAG_MICROPYTHON, @@ -138,6 +150,19 @@ static mp_obj_t rp2_flash_make_new(const mp_obj_type_t *type, size_t n_args, siz return MP_OBJ_FROM_PTR(self); } +static mp_int_t rp2_flash_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { + rp2_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (flags == MP_BUFFER_READ) { + bufinfo->buf = (void *)(XIP_BASE + self->flash_base); + bufinfo->len = self->flash_size; + bufinfo->typecode = 'B'; + return 0; + } else { + // Write unsupported. + return 1; + } +} + static mp_obj_t rp2_flash_readblocks(size_t n_args, const mp_obj_t *args) { rp2_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]); uint32_t offset = mp_obj_get_int(args[1]) * BLOCK_SIZE_BYTES; @@ -218,5 +243,19 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_Flash, MP_TYPE_FLAG_NONE, make_new, rp2_flash_make_new, + buffer, rp2_flash_get_buffer, locals_dict, &rp2_flash_locals_dict ); + +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { + switch (mp_obj_get_int(args[0])) { + #if MICROPY_HW_ROMFS_BYTES > 0 + case MP_VFS_ROM_IOCTL_GET_NUMBER_OF_SEGMENTS: + return MP_OBJ_NEW_SMALL_INT(1); + case MP_VFS_ROM_IOCTL_GET_SEGMENT: + return MP_OBJ_FROM_PTR(&rp2_flash_romfs_obj); + #endif + default: + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } +} From f5827961057c138daa198ef88788249d62851b09 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 23 Nov 2024 22:24:41 +1100 Subject: [PATCH 15/33] rp2/rp2_flash: Allow MICROPY_HW_ROMFS_BYTES to be configurable. Thanks to @robert-hh. Signed-off-by: Damien George --- ports/rp2/rp2_flash.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ports/rp2/rp2_flash.c b/ports/rp2/rp2_flash.c index b71dd4f4f57af..a2a320bad41e0 100644 --- a/ports/rp2/rp2_flash.c +++ b/ports/rp2/rp2_flash.c @@ -45,8 +45,12 @@ static_assert(MICROPY_HW_FLASH_STORAGE_BYTES % 4096 == 0, "Flash storage size mu #define MICROPY_HW_FLASH_STORAGE_BASE (PICO_FLASH_SIZE_BYTES - MICROPY_HW_FLASH_STORAGE_BYTES) #endif -#define MICROPY_HW_ROMFS_BASE (512 * 1024) // leave 512k for firmware... -#define MICROPY_HW_ROMFS_BYTES (MICROPY_HW_FLASH_STORAGE_BASE - MICROPY_HW_ROMFS_BASE) +#ifndef MICROPY_HW_ROMFS_BYTES +#define MICROPY_HW_ROMFS_BYTES (128 * 1024) +#endif + +// Put ROMFS at the upper end of the code space. +#define MICROPY_HW_ROMFS_BASE (MICROPY_HW_FLASH_STORAGE_BASE - MICROPY_HW_ROMFS_BYTES) static_assert(MICROPY_HW_FLASH_STORAGE_BYTES <= PICO_FLASH_SIZE_BYTES, "MICROPY_HW_FLASH_STORAGE_BYTES too big"); static_assert(MICROPY_HW_FLASH_STORAGE_BASE + MICROPY_HW_FLASH_STORAGE_BYTES <= PICO_FLASH_SIZE_BYTES, "MICROPY_HW_FLASH_STORAGE_BYTES too big"); From 2745616fec86b7b7303b544579167842b847e9c5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 3 Mar 2022 18:05:06 +1100 Subject: [PATCH 16/33] esp32: Enable VfsRom. esp32/partitions-4MiB.csv: Reserve 128K for romfs. Signed-off-by: Damien George --- ports/esp32/esp32_partition.c | 72 +++++++++++++++++++++++++++++++++ ports/esp32/modules/_boot.py | 9 +++++ ports/esp32/mpconfigport.h | 1 + ports/esp32/partitions-4MiB.csv | 3 +- 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/ports/esp32/esp32_partition.c b/ports/esp32/esp32_partition.c index 55830a285b0b6..485cbca1a71ad 100644 --- a/ports/esp32/esp32_partition.c +++ b/ports/esp32/esp32_partition.c @@ -53,6 +53,20 @@ typedef struct _esp32_partition_obj_t { uint16_t block_size; } esp32_partition_obj_t; +#if MICROPY_VFS_ROM + +static esp32_partition_obj_t esp32_partition_romfs_obj = { + .base = { .type = NULL }, + .part = NULL, + .cache = NULL, + .block_size = NATIVE_BLOCK_SIZE_BYTES, +}; + +static const void *esp32_partition_romfs_ptr = NULL; +static esp_partition_mmap_handle_t esp32_partition_romfs_handle; + +#endif + static esp32_partition_obj_t *esp32_partition_new(const esp_partition_t *part, uint16_t block_size) { if (part == NULL) { mp_raise_OSError(MP_ENOENT); @@ -114,6 +128,24 @@ static mp_obj_t esp32_partition_make_new(const mp_obj_type_t *type, size_t n_arg return MP_OBJ_FROM_PTR(esp32_partition_new(part, block_size)); } +#if MICROPY_VFS_ROM +static mp_int_t esp32_partition_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { + esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self == &esp32_partition_romfs_obj && flags == MP_BUFFER_READ) { + if (esp32_partition_romfs_ptr == NULL) { + check_esp_err(esp_partition_mmap(self->part, 0, self->part->size, ESP_PARTITION_MMAP_DATA, &esp32_partition_romfs_ptr, &esp32_partition_romfs_handle)); + } + bufinfo->buf = (void *)esp32_partition_romfs_ptr; + bufinfo->len = self->part->size; + bufinfo->typecode = 'B'; + return 0; + } else { + // Unsupported. + return 1; + } +} +#endif + static mp_obj_t esp32_partition_find(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // Parse args enum { ARG_type, ARG_subtype, ARG_label, ARG_block_size }; @@ -284,11 +316,51 @@ static const mp_rom_map_elem_t esp32_partition_locals_dict_table[] = { }; static MP_DEFINE_CONST_DICT(esp32_partition_locals_dict, esp32_partition_locals_dict_table); +#if MICROPY_VFS_ROM +#define ESP32_PARTITION_GET_BUFFER buffer, esp32_partition_get_buffer, +#else +#define ESP32_PARTITION_GET_BUFFER +#endif + MP_DEFINE_CONST_OBJ_TYPE( esp32_partition_type, MP_QSTR_Partition, MP_TYPE_FLAG_NONE, make_new, esp32_partition_make_new, print, esp32_partition_print, + ESP32_PARTITION_GET_BUFFER locals_dict, &esp32_partition_locals_dict ); + +/******************************************************************************/ +// romfs partition + +#if MICROPY_VFS_ROM + +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { + if (esp32_partition_romfs_obj.base.type == NULL) { + esp32_partition_romfs_obj.base.type = &esp32_partition_type; + // Get the romfs partition. + // TODO: number of segments ioctl can be used if there is more than one romfs. + esp_partition_iterator_t iter = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "romfs"); + if (iter != NULL) { + esp32_partition_romfs_obj.part = esp_partition_get(iter); + } + esp_partition_iterator_release(iter); + } + + if (esp32_partition_romfs_obj.part == NULL) { + return MP_OBJ_NEW_SMALL_INT(-MP_ENODEV); + } + + switch (mp_obj_get_int(args[0])) { + case MP_VFS_ROM_IOCTL_GET_NUMBER_OF_SEGMENTS: + return MP_OBJ_NEW_SMALL_INT(1); + case MP_VFS_ROM_IOCTL_GET_SEGMENT: + return MP_OBJ_FROM_PTR(&esp32_partition_romfs_obj); + default: + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } +} + +#endif // MICROPY_VFS_ROM diff --git a/ports/esp32/modules/_boot.py b/ports/esp32/modules/_boot.py index 96af581f38a5c..8c8b4a24bc5ff 100644 --- a/ports/esp32/modules/_boot.py +++ b/ports/esp32/modules/_boot.py @@ -1,7 +1,14 @@ import gc import vfs +import sys from flashbdev import bdev +try: + vfs.mount(vfs.VfsRom(vfs.rom_ioctl(2)), "/rom") + sys.path.insert(0, "/rom") +except: + pass + try: if bdev: vfs.mount(bdev, "/") @@ -11,3 +18,5 @@ inisetup.setup() gc.collect() + +del sys diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index b5b7d63a56333..6488b8f78646f 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -70,6 +70,7 @@ #define MICROPY_USE_INTERNAL_PRINTF (0) // ESP32 SDK requires its own printf #define MICROPY_SCHEDULER_DEPTH (8) #define MICROPY_VFS (1) +#define MICROPY_VFS_ROM (1) // control over Python builtins #define MICROPY_PY_STR_BYTES_CMP_WARN (1) diff --git a/ports/esp32/partitions-4MiB.csv b/ports/esp32/partitions-4MiB.csv index 53f0f167442bc..dd02506e54684 100644 --- a/ports/esp32/partitions-4MiB.csv +++ b/ports/esp32/partitions-4MiB.csv @@ -3,5 +3,6 @@ # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, -factory, app, factory, 0x10000, 0x1F0000, +factory, app, factory, 0x10000, 0x1D0000, +romfs, data, 0x8f, 0x1E0000, 0x20000, vfs, data, fat, 0x200000, 0x200000, From d0c1e6fa96506e3450bb0a615607d7415bd0959e Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 15 Nov 2024 11:18:09 +1100 Subject: [PATCH 17/33] esp8266: Enable VfsRom. Available ROMFS size: - FLASH_512K: 8KiBytes - FLASH_1M: 16KiBytes - FLASH_2M+: 256KiBytes - OTA: 8KiBytes Signed-off-by: Damien George --- ports/esp8266/boards/ESP8266_GENERIC/_boot.py | 9 ++- .../boards/ESP8266_GENERIC/manifest_512kiB.py | 16 ++--- .../boards/ESP8266_GENERIC/mpconfigboard.h | 22 +++--- ports/esp8266/boards/esp8266_1MiB.ld | 6 +- ports/esp8266/boards/esp8266_2MiB.ld | 6 +- ports/esp8266/boards/esp8266_512kiB.ld | 6 +- ports/esp8266/boards/esp8266_common.ld | 4 ++ ports/esp8266/boards/esp8266_ota.ld | 3 +- ports/esp8266/modesp.c | 70 ++++++++++++++++++- ports/esp8266/modules/_boot.py | 10 ++- ports/esp8266/mpconfigport.h | 8 +++ 11 files changed, 133 insertions(+), 27 deletions(-) diff --git a/ports/esp8266/boards/ESP8266_GENERIC/_boot.py b/ports/esp8266/boards/ESP8266_GENERIC/_boot.py index 16da8bc4c3750..048d8a06ec8f7 100644 --- a/ports/esp8266/boards/ESP8266_GENERIC/_boot.py +++ b/ports/esp8266/boards/ESP8266_GENERIC/_boot.py @@ -1,6 +1,13 @@ # Minimal _boot.py for the 512kiB variant. Does not set up a block device or # filesystem. Other variants use esp8266/modules/_boot.py. -import gc +import gc, vfs gc.threshold((gc.mem_free() + gc.mem_alloc()) // 4) + +# Try to mount the ROMFS. +try: + vfs.mount(vfs.VfsRom(vfs.rom_ioctl(2)), "/") +except: + pass + diff --git a/ports/esp8266/boards/ESP8266_GENERIC/manifest_512kiB.py b/ports/esp8266/boards/ESP8266_GENERIC/manifest_512kiB.py index 15f6cffc3f94a..9abaaa746f7c4 100644 --- a/ports/esp8266/boards/ESP8266_GENERIC/manifest_512kiB.py +++ b/ports/esp8266/boards/ESP8266_GENERIC/manifest_512kiB.py @@ -1,9 +1,9 @@ module("_boot.py", opt=3) -module("apa102.py", base_path="$(PORT_DIR)/modules", opt=3) -module("port_diag.py", base_path="$(PORT_DIR)/modules", opt=3) -require("ntptime") -require("dht") -require("onewire") -require("ds18x20") -require("webrepl") -require("neopixel") +# module("apa102.py", base_path="$(PORT_DIR)/modules", opt=3) +# module("port_diag.py", base_path="$(PORT_DIR)/modules", opt=3) +# require("ntptime") +# require("dht") +# require("onewire") +# require("ds18x20") +# require("webrepl") +# require("neopixel") diff --git a/ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.h b/ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.h index 1f679961e8786..1c564f52fb3ca 100644 --- a/ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.h +++ b/ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.h @@ -3,15 +3,11 @@ #define MICROPY_HW_BOARD_NAME "ESP module" #define MICROPY_HW_MCU_NAME "ESP8266" -#define MICROPY_PERSISTENT_CODE_LOAD (1) #define MICROPY_EMIT_XTENSA (1) #define MICROPY_EMIT_INLINE_XTENSA (1) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) -#define MICROPY_READER_VFS (MICROPY_VFS) -#define MICROPY_VFS (1) - #define MICROPY_PY_CRYPTOLIB (1) #elif defined(MICROPY_ESP8266_1M) @@ -19,16 +15,11 @@ #define MICROPY_HW_BOARD_NAME "ESP module (1M)" #define MICROPY_HW_MCU_NAME "ESP8266" -#define MICROPY_PERSISTENT_CODE_LOAD (1) #define MICROPY_EMIT_XTENSA (1) #define MICROPY_EMIT_INLINE_XTENSA (1) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) -#define MICROPY_READER_VFS (MICROPY_VFS) -#define MICROPY_VFS (1) - - #define MICROPY_PY_CRYPTOLIB (1) #elif defined(MICROPY_ESP8266_512K) @@ -46,5 +37,18 @@ #define MICROPY_PY_ASYNCIO (0) #define MICROPY_PY_RE_SUB (0) #define MICROPY_PY_FRAMEBUF (0) +#define MICROPY_PY_HEAPQ (0) + +#define MICROPY_VFS_WRITABLE (0) + +#define MICROPY_PY_ESP_FLASH_FUNCS (0) +#define MICROPY_PY_ESP_EXTRA_FUNCS (0) #endif + +// Configuration common to all variants. + +#define MICROPY_PERSISTENT_CODE_LOAD (1) +#define MICROPY_READER_VFS (MICROPY_VFS) +#define MICROPY_VFS (1) +#define MICROPY_VFS_ROM (1) diff --git a/ports/esp8266/boards/esp8266_1MiB.ld b/ports/esp8266/boards/esp8266_1MiB.ld index 94bc6a229a75b..678013940acdf 100644 --- a/ports/esp8266/boards/esp8266_1MiB.ld +++ b/ports/esp8266/boards/esp8266_1MiB.ld @@ -2,7 +2,8 @@ Flash layout: 0x40200000 36k header + iram/dram init - 0x40209000 572k firmware (irom0) + 0x40209000 556k firmware (irom0) + 0x40294000 16k ROMFS 0x40298000 396k filesystem 0x402fb000 20k SDK parameters */ @@ -12,7 +13,8 @@ MEMORY dport0_0_seg : org = 0x3ff00000, len = 16 dram0_0_seg : org = 0x3ffe8000, len = 80K iram1_0_seg : org = 0x40100000, len = 32K - irom0_0_seg : org = 0x40209000, len = 572K + irom0_0_seg : org = 0x40209000, len = 556K + FLASH_ROMFS : org = 0x40294000, len = 16K } /* define common sections and symbols */ diff --git a/ports/esp8266/boards/esp8266_2MiB.ld b/ports/esp8266/boards/esp8266_2MiB.ld index b5813ce0fb7a4..76cb22de14e37 100644 --- a/ports/esp8266/boards/esp8266_2MiB.ld +++ b/ports/esp8266/boards/esp8266_2MiB.ld @@ -2,7 +2,8 @@ Flash layout: 0x40200000 36k header + iram/dram init - 0x40209000 988k firmware (irom0) + 0x40209000 732k firmware (irom0) + 0x402c0000 256k ROMFS 0x40300000 1M+ filesystem (not memory mapped) */ @@ -11,7 +12,8 @@ MEMORY dport0_0_seg : org = 0x3ff00000, len = 16 dram0_0_seg : org = 0x3ffe8000, len = 80K iram1_0_seg : org = 0x40100000, len = 32K - irom0_0_seg : org = 0x40209000, len = 1M - 36K + irom0_0_seg : org = 0x40209000, len = 1M - 36K - 256K + FLASH_ROMFS : org = 0x402c0000, len = 256K } /* define common sections and symbols */ diff --git a/ports/esp8266/boards/esp8266_512kiB.ld b/ports/esp8266/boards/esp8266_512kiB.ld index c4cc798499df0..24a33fe031c70 100644 --- a/ports/esp8266/boards/esp8266_512kiB.ld +++ b/ports/esp8266/boards/esp8266_512kiB.ld @@ -2,7 +2,8 @@ Flash layout: 0x40200000 36k header + iram/dram init - 0x40209000 456k firmware (irom0) + 0x40209000 448k firmware (irom0) + 0x40279000 8k ROMFS 0x4027b000 20k SDK parameters */ @@ -11,7 +12,8 @@ MEMORY dport0_0_seg : org = 0x3ff00000, len = 16 dram0_0_seg : org = 0x3ffe8000, len = 80K iram1_0_seg : org = 0x40100000, len = 32K - irom0_0_seg : org = 0x40209000, len = 512K - 36K - 20K + irom0_0_seg : org = 0x40209000, len = 512K - 36K - 20K - 8K + FLASH_ROMFS : org = 0x4027a000, len = 8K } /* define common sections and symbols */ diff --git a/ports/esp8266/boards/esp8266_common.ld b/ports/esp8266/boards/esp8266_common.ld index cf4883acc9d20..4c4970045902c 100644 --- a/ports/esp8266/boards/esp8266_common.ld +++ b/ports/esp8266/boards/esp8266_common.ld @@ -3,6 +3,10 @@ /* define the top of RAM */ _heap_end = ORIGIN(dram0_0_seg) + LENGTH(dram0_0_seg); +/* define ROMFS extents */ +_micropy_hw_romfs_start = ORIGIN(FLASH_ROMFS); +_micropy_hw_romfs_size = LENGTH(FLASH_ROMFS); + PHDRS { dport0_0_phdr PT_LOAD; diff --git a/ports/esp8266/boards/esp8266_ota.ld b/ports/esp8266/boards/esp8266_ota.ld index 7fdf6abef00e3..c5ea2d58fa1a7 100644 --- a/ports/esp8266/boards/esp8266_ota.ld +++ b/ports/esp8266/boards/esp8266_ota.ld @@ -6,7 +6,8 @@ MEMORY dram0_0_seg : org = 0x3ffe8000, len = 0x14000 iram1_0_seg : org = 0x40100000, len = 0x8000 /* 0x3c000 is size of bootloader, 0x9000 is size of packed RAM segments */ - irom0_0_seg : org = 0x40200000 + 0x3c000 + 0x9000, len = 0x8f000 + irom0_0_seg : org = 0x40200000 + 0x3c000 + 0x9000, len = 0x8f000 - 8K + FLASH_ROMFS : org = 0x402d2000, len = 8K } /* define common sections and symbols */ diff --git a/ports/esp8266/modesp.c b/ports/esp8266/modesp.c index f303da1a33289..d35b17532f100 100644 --- a/ports/esp8266/modesp.c +++ b/ports/esp8266/modesp.c @@ -164,9 +164,10 @@ static MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size); #define IS_OTA_FIRMWARE() ((*(uint32_t *)0x40200000 & 0xff00) == 0x100) extern byte _firmware_size[]; +extern uint8_t _micropy_hw_romfs_size; static mp_obj_t esp_flash_user_start(void) { - return MP_OBJ_NEW_SMALL_INT((uint32_t)_firmware_size); + return MP_OBJ_NEW_SMALL_INT((uint32_t)_firmware_size + (uint32_t)&_micropy_hw_romfs_size); } static MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_user_start_obj, esp_flash_user_start); @@ -345,21 +346,25 @@ static const mp_rom_map_elem_t esp_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_osdebug), MP_ROM_PTR(&esp_osdebug_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_type), MP_ROM_PTR(&esp_sleep_type_obj) }, { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&esp_deepsleep_obj) }, + #if MICROPY_PY_ESP_FLASH_FUNCS { MP_ROM_QSTR(MP_QSTR_flash_id), MP_ROM_PTR(&esp_flash_id_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_read), MP_ROM_PTR(&esp_flash_read_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_write), MP_ROM_PTR(&esp_flash_write_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_erase), MP_ROM_PTR(&esp_flash_erase_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&esp_flash_size_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_user_start), MP_ROM_PTR(&esp_flash_user_start_obj) }, + #endif #if MICROPY_ESP8266_APA102 { MP_ROM_QSTR(MP_QSTR_apa102_write), MP_ROM_PTR(&esp_apa102_write_obj) }, #endif + #if MICROPY_PY_ESP_EXTRA_FUNCS { MP_ROM_QSTR(MP_QSTR_freemem), MP_ROM_PTR(&esp_freemem_obj) }, { MP_ROM_QSTR(MP_QSTR_meminfo), MP_ROM_PTR(&esp_meminfo_obj) }, { MP_ROM_QSTR(MP_QSTR_check_fw), MP_ROM_PTR(&esp_check_fw_obj) }, { MP_ROM_QSTR(MP_QSTR_malloc), MP_ROM_PTR(&esp_malloc_obj) }, { MP_ROM_QSTR(MP_QSTR_free), MP_ROM_PTR(&esp_free_obj) }, { MP_ROM_QSTR(MP_QSTR_esf_free_bufs), MP_ROM_PTR(&esp_esf_free_bufs_obj) }, + #endif #if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA { MP_ROM_QSTR(MP_QSTR_set_native_code_location), MP_ROM_PTR(&esp_set_native_code_location_obj) }, #endif @@ -379,3 +384,66 @@ const mp_obj_module_t esp_module = { }; MP_REGISTER_MODULE(MP_QSTR_esp, esp_module); + +///// + +#if MICROPY_VFS_ROM + +#include "py/objarray.h" +#include "extmod/vfs.h" + +#define FLASH_MEM_BASE (0x40200000) +#define FLASH_PAGE_SIZE (4096) + +#define MICROPY_HW_ROMFS_BASE (uintptr_t)(&_micropy_hw_romfs_start) +#define MICROPY_HW_ROMFS_BYTES (uintptr_t)(&_micropy_hw_romfs_size) + +#define ROMFS_SPI_FLASH_OFFSET (MICROPY_HW_ROMFS_BASE - FLASH_MEM_BASE) + +extern uint8_t _micropy_hw_romfs_start; +extern uint8_t _micropy_hw_romfs_size; + +static const MP_DEFINE_MEMORYVIEW_OBJ(romfs_obj, 'B', 0, MICROPY_HW_ROMFS_BYTES, (void *)MICROPY_HW_ROMFS_BASE); + +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { + switch (mp_obj_get_int(args[0])) { + case MP_VFS_ROM_IOCTL_GET_NUMBER_OF_SEGMENTS: + return MP_OBJ_NEW_SMALL_INT(1); + + case MP_VFS_ROM_IOCTL_GET_SEGMENT: + return MP_OBJ_FROM_PTR(&romfs_obj); + + case MP_VFS_ROM_IOCTL_WRITE_PREPARE: { + uint32_t dest = ROMFS_SPI_FLASH_OFFSET; + uint32_t dest_max = dest + mp_obj_get_int(args[2]); + while (dest < dest_max) { + ets_loop_iter(); // flash access takes time so run any pending tasks + SpiFlashOpResult res = spi_flash_erase_sector(dest / FLASH_PAGE_SIZE); + ets_loop_iter(); + if (res != SPI_FLASH_RESULT_OK) { + return MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? -MP_ETIMEDOUT : -MP_EIO); + } + dest += FLASH_PAGE_SIZE; + } + return MP_OBJ_NEW_SMALL_INT(4); // minimum write size + } + + case MP_VFS_ROM_IOCTL_WRITE: { + mp_int_t offset = ROMFS_SPI_FLASH_OFFSET + mp_obj_get_int(args[2]); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); + ets_loop_iter(); // flash access takes time so run any pending tasks + SpiFlashOpResult res = spi_flash_write(offset, bufinfo.buf, (bufinfo.len + 3) & ~3); + ets_loop_iter(); + if (res == SPI_FLASH_RESULT_OK) { + return MP_OBJ_NEW_SMALL_INT(0); + } + return MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? -MP_ETIMEDOUT : -MP_EIO); + } + + default: + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } +} + +#endif // MICROPY_VFS_ROM diff --git a/ports/esp8266/modules/_boot.py b/ports/esp8266/modules/_boot.py index 00a0d6550f945..570dd3139e99f 100644 --- a/ports/esp8266/modules/_boot.py +++ b/ports/esp8266/modules/_boot.py @@ -1,9 +1,17 @@ import gc gc.threshold((gc.mem_free() + gc.mem_alloc()) // 4) -import vfs + +import sys, vfs from flashbdev import bdev +# Try to mount the ROMFS. +try: + vfs.mount(vfs.VfsRom(vfs.rom_ioctl(2)), "/rom") + sys.path.insert(0, "/rom") +except: + pass + if bdev: try: vfs.mount(bdev, "/") diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 83d80a7c963f6..e88986b16b55b 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -111,6 +111,14 @@ #define MICROPY_STREAMS_POSIX_API (1) #define MICROPY_MODULE_FROZEN_LEXER mp_lexer_new_from_str32 +#ifndef MICROPY_PY_ESP_FLASH_FUNCS +#define MICROPY_PY_ESP_FLASH_FUNCS (1) +#endif + +#ifndef MICROPY_PY_ESP_EXTRA_FUNCS +#define MICROPY_PY_ESP_EXTRA_FUNCS (1) +#endif + #define MICROPY_FATFS_ENABLE_LFN (1) #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_MAX_SS (4096) From 711615ab51184987b8c5078f6c63357990c6329a Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 21 Nov 2024 17:03:37 +0100 Subject: [PATCH 18/33] mimxrt/mimxrt_flash: Add support for the VfsRom filesystem. The default size is 256k. It can be changed in mpconfigboard.h by defining MICROPY_HW_ROMFS_BYTES to a different value, but it must not be smaller than a single sector. Signed-off-by: robert-hh --- ports/mimxrt/mimxrt_flash.c | 36 +++++++++++++++++++++++++++++++++++ ports/mimxrt/modules/_boot.py | 6 ++++++ ports/mimxrt/mpconfigport.h | 3 +++ 3 files changed, 45 insertions(+) diff --git a/ports/mimxrt/mimxrt_flash.c b/ports/mimxrt/mimxrt_flash.c index fdd48e280bc15..ac5995c33532f 100644 --- a/ports/mimxrt/mimxrt_flash.c +++ b/ports/mimxrt/mimxrt_flash.c @@ -5,6 +5,7 @@ * * Copyright (c) 2020-2021 Damien P. George * Copyright (c) 2021-2023 Philipp Ebensberger + * Copyright (c) 2021-2024 Robert Hammelrath * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,6 +30,7 @@ #include "py/runtime.h" #include "extmod/vfs.h" +#include "py/mperrno.h" #include "modmimxrt.h" #include "flash.h" #include BOARD_FLASH_OPS_HEADER_H @@ -153,3 +155,37 @@ MP_DEFINE_CONST_OBJ_TYPE( make_new, mimxrt_flash_make_new, locals_dict, &mimxrt_flash_locals_dict ); + +#if MICROPY_VFS_ROM + +#ifndef MICROPY_HW_ROMFS_BYTES +#define MICROPY_HW_ROMFS_BYTES (256 * 1024) +#endif +// Put ROMFS at the upper end of the respective code space. +// For machine.mem32 the absolute address is required, for the flash functions +// erase and write the offset to the flash start address. +#define MICROPY_HW_ROMFS_ADDRESS (((uint32_t)&__vfs_start) - MICROPY_HW_ROMFS_BYTES) +#define MICROPY_HW_ROMFS_BASE (MICROPY_HW_FLASH_STORAGE_BASE - MICROPY_HW_ROMFS_BYTES) + +static mimxrt_flash_obj_t mimxrt_flash_romfs_obj = { + .base = { &mimxrt_flash_type }, +}; + +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { + if (MICROPY_HW_ROMFS_BYTES <= 0) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + switch (mp_obj_get_int(args[0])) { + case -1: // request object-based capabilities + mimxrt_flash_romfs_obj.flash_base = MICROPY_HW_ROMFS_BASE; + mimxrt_flash_romfs_obj.flash_size = MICROPY_HW_ROMFS_BYTES; + return MP_OBJ_FROM_PTR(&mimxrt_flash_romfs_obj); + case 0: // number of segments + return MP_OBJ_NEW_SMALL_INT(1); + case 1: // address + return mp_obj_new_int(MICROPY_HW_ROMFS_ADDRESS); + default: + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } +} +#endif // MICROPY_VFS_ROM diff --git a/ports/mimxrt/modules/_boot.py b/ports/mimxrt/modules/_boot.py index fa3b780434a43..74b7f1918e04d 100644 --- a/ports/mimxrt/modules/_boot.py +++ b/ports/mimxrt/modules/_boot.py @@ -8,6 +8,12 @@ import mimxrt from machine import Pin +try: + vfs.mount(vfs.VfsRom(vfs.rom_ioctl(1)), "/rom") + sys.path.insert(0, "/rom") +except: + pass + bdev = mimxrt.Flash() try: fs = vfs.VfsLfs2(bdev, progsize=256) diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h index 7da85f1aee579..4a4a184fde7ca 100644 --- a/ports/mimxrt/mpconfigport.h +++ b/ports/mimxrt/mpconfigport.h @@ -59,6 +59,9 @@ uint32_t trng_random_u32(void); #define MICROPY_SCHEDULER_DEPTH (8) #define MICROPY_SCHEDULER_STATIC_NODES (1) #define MICROPY_VFS (1) +#ifndef MICROPY_VFS_ROM +#define MICROPY_VFS_ROM (1) +#endif // Control over Python builtins #define MICROPY_PY_BUILTINS_HELP_TEXT mimxrt_help_text From b601c9e60a07ca19c651ade25b59860e779696eb Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 19 Nov 2024 08:48:29 +0100 Subject: [PATCH 19/33] samd: Support the VfsRom file system for SAMD21. The VfsRom file system has a size of 15k or 16k and is placed at the upper end of the flash. Implication: - Without SPIFLASH: Reduce the internal LFS file system from 64k to 42k, leaving about 7k headroom for future code changes. Use the object-based capabilities for VfsRom. The VfsRom size is 15k. - With SPIFLASH: Remove the onewire, ds18x20 and dht drivers from frozen bytecode as they can be placed into the vfsRom files when needed. The VfsRom size is 16k. Use the rom_ioctl functions for VfsRom, since the flash devices for the regular file system and VfsRom are different. Signed-off-by: robert-hh --- ports/samd/Makefile | 6 +- .../mpconfigboard.mk | 2 +- .../mpconfigboard.mk | 2 +- .../SAMD21_XPLAINED_PRO/mpconfigboard.mk | 2 +- ports/samd/boards/samd21x18a.ld | 16 ++- ports/samd/mcu/samd21/manifest.py | 3 - ports/samd/mcu/samd21/mpconfigmcu.h | 2 +- ports/samd/mcu/samd21/mpconfigmcu.mk | 7 +- ports/samd/modules/_boot.py | 6 + ports/samd/mpconfigport.h | 3 + ports/samd/samd_flash.c | 109 +++++++++++++++--- ports/samd/samd_soc.c | 4 + 12 files changed, 130 insertions(+), 32 deletions(-) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 005664f178d3c..e7441a6d94970 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -90,7 +90,7 @@ CFLAGS += $(CFLAGS_EXTRA) CFLAGS += -DMICROPY_HW_CODESIZE=$(strip $(subst K,' ', $(MICROPY_HW_CODESIZE))) LDFLAGS += -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref -LDFLAGS += --defsym=_codesize=$(MICROPY_HW_CODESIZE) +LDFLAGS += --defsym=_codesize=$(MICROPY_HW_CODESIZE) --defsym=_vfsromsize=$(MICROPY_HW_VFSROMSIZE) LIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) @@ -103,6 +103,10 @@ CFLAGS += -Os -DNDEBUG LDFLAGS += --gc-sections --print-memory-usage CFLAGS += -fdata-sections -ffunction-sections endif +# Disable VFSROM support if the size was set to 0 +ifeq ($(MICROPY_HW_VFSROMSIZE),0) + CFLAGS += -DMICROPY_VFS_ROM=0 +endif # Flags for optional C++ source code CXXFLAGS += $(filter-out -std=c99,$(CFLAGS)) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.mk index e2895c7c0c2f9..6ea327a650d40 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.mk +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.mk @@ -5,4 +5,4 @@ TEXT0 = 0x2000 # The ?='s allow overriding in mpconfigboard.mk. # MicroPython settings -MICROPY_HW_CODESIZE ?= 248K +MICROPY_HW_CODESIZE ?= 232K diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.mk index e2895c7c0c2f9..6ea327a650d40 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.mk +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.mk @@ -5,4 +5,4 @@ TEXT0 = 0x2000 # The ?='s allow overriding in mpconfigboard.mk. # MicroPython settings -MICROPY_HW_CODESIZE ?= 248K +MICROPY_HW_CODESIZE ?= 232K diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.mk b/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.mk index cc43c22cea588..4e8fb3d4429fb 100644 --- a/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.mk +++ b/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.mk @@ -3,4 +3,4 @@ CMSIS_MCU = SAMD21J18A LD_FILES = boards/samd21x18a.ld sections.ld TEXT0 = 0x2000 -MICROPY_HW_CODESIZE ?= 248K +MICROPY_HW_CODESIZE ?= 232K diff --git a/ports/samd/boards/samd21x18a.ld b/ports/samd/boards/samd21x18a.ld index 3ab051569fb18..7de761b0f6a84 100644 --- a/ports/samd/boards/samd21x18a.ld +++ b/ports/samd/boards/samd21x18a.ld @@ -3,8 +3,8 @@ */ /* -_codesize is defined in mpconfigmcu.mk or mpconfigboard.mk as -MICROPY_HW_CODESIZE and is set in Makefile +_codesize and _vfsromsize are defined in mpconfigmcu.mk or mpconfigboard.mk +as MICROPY_HW_CODESIZE and MICROPY_HW_VFSROMSIZE and are set in Makefile. */ _flashsize = 256K; /* The physical flash size */ @@ -21,8 +21,18 @@ MEMORY _estack = ORIGIN(RAM) + LENGTH(RAM) - 8; _sstack = _estack - 8K; +/* +The VfsROM file system is placed at the end of the flash. +For device with SPI flash the number for _sflash_fs will be 0. +That does not matter since these devices do not use the MCU flash file +system. +*/ + _oflash_fs = ORIGIN(FLASH) + _codesize; -_sflash_fs = _flashsize - _codesize - _bootloader; +_sflash_fs = _flashsize - _codesize - _bootloader - _vfsromsize; + +_oflash_vfsrom = ORIGIN(FLASH) + _flashsize - _vfsromsize - _bootloader; +_sflash_vfsrom = _vfsromsize; _sheap = _ebss; _eheap = _sstack; diff --git a/ports/samd/mcu/samd21/manifest.py b/ports/samd/mcu/samd21/manifest.py index 2a19a843f8a9b..8ad1e38ba099a 100644 --- a/ports/samd/mcu/samd21/manifest.py +++ b/ports/samd/mcu/samd21/manifest.py @@ -1,5 +1,2 @@ include("$(PORT_DIR)/boards/manifest.py") include("$(MPY_DIR)/extmod/asyncio") -require("onewire") -require("ds18x20") -require("dht") diff --git a/ports/samd/mcu/samd21/mpconfigmcu.h b/ports/samd/mcu/samd21/mpconfigmcu.h index 29965f50f63a8..131ee723a9667 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.h +++ b/ports/samd/mcu/samd21/mpconfigmcu.h @@ -2,7 +2,7 @@ #include "samd21.h" #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_BASIC_FEATURES) -#if MICROPY_HW_CODESIZE == 248 +#if MICROPY_HW_CODESIZE == 232 #define SAMD21_EXTRA_FEATURES 1 #else #define SAMD21_EXTRA_FEATURES 0 diff --git a/ports/samd/mcu/samd21/mpconfigmcu.mk b/ports/samd/mcu/samd21/mpconfigmcu.mk index 34209775c2565..cc6058562c4b2 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.mk +++ b/ports/samd/mcu/samd21/mpconfigmcu.mk @@ -4,10 +4,13 @@ CFLAGS_MCU += -DCFG_TUSB_MCU=OPT_MCU_SAMD21 MPY_CROSS_MCU_ARCH = armv6m -MICROPY_HW_CODESIZE ?= 184K +MICROPY_HW_CODESIZE ?= 191K -ifeq ($(MICROPY_HW_CODESIZE), 248K) +ifeq ($(MICROPY_HW_CODESIZE), 232K) FROZEN_MANIFEST ?= mcu/$(MCU_SERIES_LOWER)/manifest.py +MICROPY_HW_VFSROMSIZE ?= 16K +else +MICROPY_HW_VFSROMSIZE ?= 15K endif MICROPY_VFS_LFS1 ?= 1 diff --git a/ports/samd/modules/_boot.py b/ports/samd/modules/_boot.py index f4053e2cddf00..6444dc1d40378 100644 --- a/ports/samd/modules/_boot.py +++ b/ports/samd/modules/_boot.py @@ -3,6 +3,12 @@ import samd import sys +try: + vfs.mount(vfs.VfsRom(vfs.rom_ioctl(1)), "/rom") + sys.path.insert(0, "/rom") +except: + pass + bdev = samd.Flash() # Try to mount the filesystem, and format the flash if it doesn't exist. diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 0b47500bf7e7c..896acd1a00c0c 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -85,6 +85,9 @@ #define MICROPY_PY_OS_INCLUDEFILE "ports/samd/modos.c" #define MICROPY_READER_VFS (1) #define MICROPY_VFS (1) +#ifndef MICROPY_VFS_ROM +#define MICROPY_VFS_ROM (1) +#endif #ifndef MICROPY_PY_MACHINE_ADC #define MICROPY_PY_MACHINE_ADC (1) #endif diff --git a/ports/samd/samd_flash.c b/ports/samd/samd_flash.c index f68bdf140f490..dfcffbfa10349 100644 --- a/ports/samd/samd_flash.c +++ b/ports/samd/samd_flash.c @@ -28,9 +28,10 @@ #include "py/runtime.h" #include "extmod/vfs.h" +#include "py/mperrno.h" #include "samd_soc.h" -#if MICROPY_HW_MCUFLASH +#if MICROPY_HW_MCUFLASH || MICROPY_VFS_ROM // ASF 4 #include "hal_flash.h" @@ -45,7 +46,6 @@ #endif static struct flash_descriptor flash_desc; -static mp_int_t BLOCK_SIZE = VFS_BLOCK_SIZE_BYTES; // Board specific: mpconfigboard.h extern const mp_obj_type_t samd_flash_type; typedef struct _samd_flash_obj_t { @@ -54,8 +54,9 @@ typedef struct _samd_flash_obj_t { uint32_t flash_size; } samd_flash_obj_t; +#if MICROPY_HW_MCUFLASH +static mp_int_t BLOCK_SIZE = VFS_BLOCK_SIZE_BYTES; // Board specific: mpconfigboard.h extern uint8_t _oflash_fs, _sflash_fs; - // Build a Flash storage at top. static samd_flash_obj_t samd_flash_obj = { .base = { &samd_flash_type }, @@ -63,9 +64,18 @@ static samd_flash_obj_t samd_flash_obj = { .flash_size = (uint32_t)&_sflash_fs, // Get from MCU-Specific loader script. }; +static mp_obj_t samd_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + // No args required. bdev=Flash(). Start Addr & Size defined in samd_flash_obj. + mp_arg_check_num(n_args, n_kw, 0, 0, false); + + // Return singleton object. + return MP_OBJ_FROM_PTR(&samd_flash_obj); +} +#endif // MICROPY_HW_MCUFLASH + // Flash init (from cctpy) // Method is needed for when MP starts up in _boot.py -static void samd_flash_init(void) { +void samd_flash_init(void) { #ifdef SAMD51 hri_mclk_set_AHBMASK_NVMCTRL_bit(MCLK); #endif @@ -76,27 +86,19 @@ static void samd_flash_init(void) { flash_init(&flash_desc, NVMCTRL); } -static mp_obj_t samd_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - // No args required. bdev=Flash(). Start Addr & Size defined in samd_flash_obj. - mp_arg_check_num(n_args, n_kw, 0, 0, false); - - samd_flash_init(); - - // Return singleton object. - return MP_OBJ_FROM_PTR(&samd_flash_obj); -} - +#if MICROPY_HW_MCUFLASH // Function for ioctl. static mp_obj_t eraseblock(uint32_t sector_in) { // Destination address aligned with page start to be erased. - uint32_t DEST_ADDR = sector_in; // Number of pages to be erased. - mp_int_t PAGE_SIZE = flash_get_page_size(&flash_desc); // adf4 API call + uint32_t dest_addr = sector_in; // Number of pages to be erased. + mp_int_t page_size = flash_get_page_size(&flash_desc); // adf4 API call - flash_erase(&flash_desc, DEST_ADDR, (BLOCK_SIZE / PAGE_SIZE)); + flash_erase(&flash_desc, dest_addr, (BLOCK_SIZE / page_size)); return mp_const_none; } + static mp_obj_t samd_flash_version(void) { return MP_OBJ_NEW_SMALL_INT(flash_get_version()); } @@ -131,7 +133,7 @@ static mp_obj_t samd_flash_writeblocks(size_t n_args, const mp_obj_t *args) { } // Write data to flash (adf4 API) flash_write(&flash_desc, offset, bufinfo.buf, bufinfo.len); - // TODO check return value + return mp_const_none; } static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(samd_flash_writeblocks_obj, 3, 4, samd_flash_writeblocks); @@ -178,5 +180,74 @@ MP_DEFINE_CONST_OBJ_TYPE( make_new, samd_flash_make_new, locals_dict, &samd_flash_locals_dict ); +#endif -#endif // MICROPY_HW_MCUFLASH +#if MICROPY_VFS_ROM +// +// Uses object-based capabilities for devices using the internal flash +// for the regular file system and ioctl function for devices with +// external flash. +// +extern uint8_t _oflash_vfsrom, _sflash_vfsrom; + +#define MICROPY_HW_ROMFS_BASE ((uint32_t)&_oflash_vfsrom) +#define MICROPY_HW_ROMFS_BYTES ((uint32_t)&_sflash_vfsrom) +#define VFSROM_BLOCK_SIZE (2048) + +#if MICROPY_HW_MCUFLASH +static samd_flash_obj_t samd_flash_romfs_obj = { + .base = { &samd_flash_type }, + .flash_base = MICROPY_HW_ROMFS_BASE, // Get from MCU-Specific loader script. + .flash_size = MICROPY_HW_ROMFS_BYTES, // Get from MCU-Specific loader script. +}; +#endif + +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { + if (MICROPY_HW_ROMFS_BYTES <= 0) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + switch (mp_obj_get_int(args[0])) { + #if MICROPY_HW_MCUFLASH + case -1: // request object-based capabilities + return MP_OBJ_FROM_PTR(&samd_flash_romfs_obj); + #endif + + case 0: // number of segments + return MP_OBJ_NEW_SMALL_INT(1); + case 1: // address + return mp_obj_new_int(MICROPY_HW_ROMFS_BASE); + + #if !MICROPY_HW_MCUFLASH + case 2: // num blocks + return MP_OBJ_NEW_SMALL_INT(MICROPY_HW_ROMFS_BYTES / VFSROM_BLOCK_SIZE); + case 3: // block_size + return MP_OBJ_NEW_SMALL_INT(VFSROM_BLOCK_SIZE); + case 4: { // erase one block at offset address of flash + if (n_args < 2) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + // Erase sector. + uint32_t dest_addr = MICROPY_HW_ROMFS_BASE + mp_obj_get_int(args[1]); + mp_int_t page_size = flash_get_page_size(&flash_desc); // adf4 API call + flash_erase(&flash_desc, dest_addr, (VFSROM_BLOCK_SIZE / page_size)); + return MP_OBJ_NEW_SMALL_INT(0); + } + case 5: { // write to byte offset address in flash + if (n_args < 3) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + uint32_t dest_addr = MICROPY_HW_ROMFS_BASE + mp_obj_get_int(args[1]); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); + // Write data to flash. + flash_write(&flash_desc, dest_addr, bufinfo.buf, bufinfo.len); + return MP_OBJ_NEW_SMALL_INT(0); + } + #endif + default: + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } +} +#endif + +#endif // MICROPY_HW_MCUFLASH || MICROPY_VFS_ROM diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c index e78032513c216..3ec418ff96e17 100644 --- a/ports/samd/samd_soc.c +++ b/ports/samd/samd_soc.c @@ -39,6 +39,7 @@ #include "tusb.h" extern void machine_rtc_start(bool force); +extern void samd_flash_init(void); static void usb_init(void) { // Init USB clock @@ -120,6 +121,9 @@ void samd_init(void) { mp_hal_ticks_cpu_enable(); #endif machine_rtc_start(false); + #if MICROPY_HW_MCUFLASH || MICROPY_VFS_ROM + samd_flash_init(); + #endif } #if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_UART From aa05efb2fe74e41e191f7bd5c28e98403a12ec56 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 20 Nov 2024 21:27:37 +0100 Subject: [PATCH 20/33] samd: Support the VfsRom file system for SAMD51. The VfsRom file system has a size default of 64k for SAMD51x19 and 256K for SAMD51x20. It is placed at the upper end of the flash. Implication: - Without SPIFLASH: Reduce the internal LFS file system from 128k to 64k. - With SPIFLASH: Reduce the code size from 496K to 432K. If that is not sufficient for some boards or configurations, it can be changed for each board or board variant. Signed-off-by: robert-hh --- .../ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk | 5 ++++- .../mpconfigboard.mk | 5 ++++- .../ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk | 5 ++++- ports/samd/boards/MINISAM_M4/mpconfigboard.mk | 5 ++++- .../boards/SEEED_WIO_TERMINAL/mpconfigboard.mk | 5 ++++- .../SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk | 5 ++++- ports/samd/boards/samd51x19a.ld | 16 +++++++++++++--- ports/samd/boards/samd51x20a.ld | 16 +++++++++++++--- ports/samd/mcu/samd51/manifest.py | 3 --- ports/samd/mcu/samd51/mpconfigmcu.h | 8 ++++---- ports/samd/mcu/samd51/mpconfigmcu.mk | 1 + 11 files changed, 55 insertions(+), 19 deletions(-) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk index 6ec2d43dedbd8..73be611309e4a 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk @@ -5,4 +5,7 @@ TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. # MicroPython settings -MICROPY_HW_CODESIZE ?= 496K +# The size of a MCU flash filesystem will be +# 1008k - MICROPY_HW_CODESIZE - MICROPY_HW_VFSROMSIZE +# The default for MICROPY_HW_VFSROMSIZE is 64K +MICROPY_HW_CODESIZE ?= 432K diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk index 740154a6d6825..adc9b1397c3eb 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk @@ -5,4 +5,7 @@ TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. # MicroPython settings -MICROPY_HW_CODESIZE ?= 496K +# The size of a MCU flash filesystem will be +# 1008k - MICROPY_HW_CODESIZE - MICROPY_HW_VFSROMSIZE +# The default for MICROPY_HW_VFSROMSIZE is 64K +MICROPY_HW_CODESIZE ?= 432K diff --git a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk index 43ca5a59cc636..709441b833212 100644 --- a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk +++ b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk @@ -7,4 +7,7 @@ TEXT0 = 0x4000 MICROPY_PY_NETWORK ?= 1 MICROPY_PY_NETWORK_NINAW10 ?= 1 -MICROPY_HW_CODESIZE ?= 496K +# The size of a MCU flash filesystem will be +# 1008k - MICROPY_HW_CODESIZE - MICROPY_HW_VFSROMSIZE +# The default for MICROPY_HW_VFSROMSIZE is 64K +MICROPY_HW_CODESIZE ?= 432K diff --git a/ports/samd/boards/MINISAM_M4/mpconfigboard.mk b/ports/samd/boards/MINISAM_M4/mpconfigboard.mk index 54948627d2b67..eea063fe55433 100644 --- a/ports/samd/boards/MINISAM_M4/mpconfigboard.mk +++ b/ports/samd/boards/MINISAM_M4/mpconfigboard.mk @@ -6,4 +6,7 @@ TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. # MicroPython settings -MICROPY_HW_CODESIZE ?= 496K +# The size of a MCU flash filesystem will be +# 1008k - MICROPY_HW_CODESIZE - MICROPY_HW_VFSROMSIZE +# The default for MICROPY_HW_VFSROMSIZE is 64K +MICROPY_HW_CODESIZE ?= 432K diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.mk b/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.mk index 7bf70ac669566..fd6d4b24516d0 100644 --- a/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.mk +++ b/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.mk @@ -5,4 +5,7 @@ TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. # MicroPython settings -MICROPY_HW_CODESIZE ?= 496K +# The size of a MCU flash filesystem will be +# 1008k - MICROPY_HW_CODESIZE - MICROPY_HW_VFSROMSIZE +# The default for MICROPY_HW_VFSROMSIZE is 64K +MICROPY_HW_CODESIZE ?= 432K diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk index 263e582694495..0af891e263686 100644 --- a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk @@ -5,4 +5,7 @@ TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. # MicroPython settings -MICROPY_HW_CODESIZE ?= 1008K +# The size of a MCU flash filesystem will be +# 1008k - MICROPY_HW_CODESIZE - MICROPY_HW_VFSROMSIZE +MICROPY_HW_CODESIZE ?= 752K +MICROPY_HW_VFSROMSIZE ?= 256K diff --git a/ports/samd/boards/samd51x19a.ld b/ports/samd/boards/samd51x19a.ld index 30bc8e33281fb..45d102da8874c 100644 --- a/ports/samd/boards/samd51x19a.ld +++ b/ports/samd/boards/samd51x19a.ld @@ -3,8 +3,8 @@ */ /* -_codesize is defined in mpconfigmcu.mk or mpconfigboard.mk as -MICROPY_HW_CODESIZE and is set in Makefile +_codesize and _vfsromsize are defined in mpconfigmcu.mk or mpconfigboard.mk +as MICROPY_HW_CODESIZE and MICROPY_HW_VFSROMSIZE and are set in Makefile. */ _flashsize = 512K; /* The physical flash size */ @@ -21,8 +21,18 @@ MEMORY _estack = ORIGIN(RAM) + LENGTH(RAM) - 8; _sstack = _estack - 16K; +/* +The VfsROM file system is placed at the end of the flash. +For device with SPI flash the number for _sflash_fs might be 0. +That does not matter since these devices do not use the MCU flash file +system. +*/ + _oflash_fs = ORIGIN(FLASH) + _codesize; -_sflash_fs = _flashsize - _codesize - _bootloader; +_sflash_fs = _flashsize - _codesize - _bootloader - _vfsromsize; + +_oflash_vfsrom = ORIGIN(FLASH) + _flashsize - _vfsromsize - _bootloader; +_sflash_vfsrom = _vfsromsize; _sheap = _ebss; _eheap = _sstack; diff --git a/ports/samd/boards/samd51x20a.ld b/ports/samd/boards/samd51x20a.ld index 472ab316c6fde..e485a173fcdaa 100644 --- a/ports/samd/boards/samd51x20a.ld +++ b/ports/samd/boards/samd51x20a.ld @@ -3,8 +3,8 @@ */ /* -_codesize is defined in mpconfigmcu.mk or mpconfigboard.mk as -MICROPY_HW_CODESIZE and is set in Makefile +_codesize and _vfsromsize are defined in mpconfigmcu.mk or mpconfigboard.mk +as MICROPY_HW_CODESIZE and MICROPY_HW_VFSROMSIZE and are set in Makefile. */ _flashsize = 1024K; /* The physical flash size */ @@ -21,8 +21,18 @@ MEMORY _estack = ORIGIN(RAM) + LENGTH(RAM) - 8; _sstack = _estack - 16K; +/* +The VfsROM file system is placed at the end of the flash. +For device with SPI flash the number for _sflash_fs might be 0. +That does not matter since these devices do not use the MCU flash file +system. +*/ + _oflash_fs = ORIGIN(FLASH) + _codesize; -_sflash_fs = _flashsize - _codesize - _bootloader; +_sflash_fs = _flashsize - _codesize - _bootloader - _vfsromsize; + +_oflash_vfsrom = ORIGIN(FLASH) + _flashsize - _vfsromsize - _bootloader; +_sflash_vfsrom = _vfsromsize; _sheap = _ebss; _eheap = _sstack; diff --git a/ports/samd/mcu/samd51/manifest.py b/ports/samd/mcu/samd51/manifest.py index 2a19a843f8a9b..8ad1e38ba099a 100644 --- a/ports/samd/mcu/samd51/manifest.py +++ b/ports/samd/mcu/samd51/manifest.py @@ -1,5 +1,2 @@ include("$(PORT_DIR)/boards/manifest.py") include("$(MPY_DIR)/extmod/asyncio") -require("onewire") -require("ds18x20") -require("dht") diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index 9a7b8528f3573..19b29612dfa24 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -18,10 +18,10 @@ unsigned long trng_random_u32(void); #define MICROPY_PY_MACHINE_UART_IRQ (1) // fatfs configuration used in ffconf.h -#define MICROPY_FATFS_ENABLE_LFN (1) -#define MICROPY_FATFS_RPATH (2) -#define MICROPY_FATFS_MAX_SS (4096) -#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ +#define MICROPY_FATFS_ENABLE_LFN (1) +#define MICROPY_FATFS_RPATH (2) +#define MICROPY_FATFS_MAX_SS (4096) +#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define VFS_BLOCK_SIZE_BYTES (1536) // diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk index 9bef5eca166ab..9bb1292434f16 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.mk +++ b/ports/samd/mcu/samd51/mpconfigmcu.mk @@ -5,6 +5,7 @@ CFLAGS_MCU += -DCFG_TUSB_MCU=OPT_MCU_SAMD51 MPY_CROSS_MCU_ARCH = armv7m MICROPY_HW_CODESIZE ?= 368K +MICROPY_HW_VFSROMSIZE ?= 64K MICROPY_VFS_LFS2 ?= 1 MICROPY_VFS_FAT ?= 1 From a237029720741f5b7e4e71faca58a96b461b0205 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Mon, 25 Nov 2024 21:49:04 +0100 Subject: [PATCH 21/33] nrf/modules/flashbdev: Add support for VfsRom. Using the object based capabilities, which avoids complication about different flash block sizes. VfsROM fs sizes: NRF51x22: 12K NRF52632: 128K NRF52840: 128K NRF9160: 128K Tested with Microbit and Arduino Nano Connect. Problem with the test: the MicroBit RAM is too small to run mpremote even if that is the board where VfsROM would be most helpful. So a special small loader would be needed. Signed-off-by: robert-hh --- ports/nrf/boards/memory.ld | 6 +++-- ports/nrf/boards/nrf51x22_256k_16k.ld | 1 + ports/nrf/boards/nrf51x22_256k_32k.ld | 1 + ports/nrf/boards/nrf52832_512k_64k.ld | 1 + ports/nrf/boards/nrf52840_1M_256k.ld | 1 + ports/nrf/boards/nrf9160_1M_256k.ld | 1 + ports/nrf/modules/nrf/flashbdev.c | 32 +++++++++++++++++++++++++++ ports/nrf/mpconfigport.h | 5 +++++ 8 files changed, 46 insertions(+), 2 deletions(-) diff --git a/ports/nrf/boards/memory.ld b/ports/nrf/boards/memory.ld index 9c4c9c8bd1267..fac072516158f 100644 --- a/ports/nrf/boards/memory.ld +++ b/ports/nrf/boards/memory.ld @@ -8,10 +8,12 @@ _head_size = DEFINED(_sd_size) ? _sd_size : _bootloader_head_size; _head_ram = DEFINED(_sd_ram) ? _sd_ram : _bootloader_head_ram_size; _sd_size = DEFINED(_sd_size) ? _sd_size : 0; _sd_ram = DEFINED(_sd_ram) ? _sd_ram : 0; +_vfsrom_size = DEFINED(_vfsrom_size) ? _vfsrom_size : 0; _fs_size = DEFINED(_fs_size) ? _fs_size : 64K; /* TODO: set to 0 if not using the filesystem */ -_app_size = _flash_size - _head_size - _fs_size - _bootloader_tail_size; +_app_size = _flash_size - _head_size - _vfsrom_size - _fs_size - _bootloader_tail_size; _app_start = _head_size; -_fs_start = _head_size + _app_size; +_vfsrom_start = _head_size + _app_size; +_fs_start = _vfsrom_start + _vfsrom_size; _fs_end = _fs_start + _fs_size; _app_ram_start = 0x20000000 + _head_ram; _app_ram_size = _ram_size - _head_ram; diff --git a/ports/nrf/boards/nrf51x22_256k_16k.ld b/ports/nrf/boards/nrf51x22_256k_16k.ld index 8a40ae0f17307..7fd978a358f4c 100644 --- a/ports/nrf/boards/nrf51x22_256k_16k.ld +++ b/ports/nrf/boards/nrf51x22_256k_16k.ld @@ -6,6 +6,7 @@ GROUP(-lgcc -lc -lnosys) _flash_size = 256K; _ram_size = 16K; +_vfsrom_size = 12K; /* Default stack size when there is no SoftDevice */ _stack_size = 4K; diff --git a/ports/nrf/boards/nrf51x22_256k_32k.ld b/ports/nrf/boards/nrf51x22_256k_32k.ld index 06c0914035b4a..e7940e2097c9e 100644 --- a/ports/nrf/boards/nrf51x22_256k_32k.ld +++ b/ports/nrf/boards/nrf51x22_256k_32k.ld @@ -6,6 +6,7 @@ GROUP(-lgcc -lc -lnosys) _flash_size = 256K; _ram_size = 32K; +_vfsrom_size = 12K; /* Default stack size when there is no SoftDevice */ _stack_size = 4K; diff --git a/ports/nrf/boards/nrf52832_512k_64k.ld b/ports/nrf/boards/nrf52832_512k_64k.ld index 22804df5cdb5e..dead8f345c6d0 100644 --- a/ports/nrf/boards/nrf52832_512k_64k.ld +++ b/ports/nrf/boards/nrf52832_512k_64k.ld @@ -4,6 +4,7 @@ _flash_size = 512K; _ram_size = 64K; +_vfsrom_size = 128K; /* produce a link error if there is not this amount of RAM for these sections */ _stack_size = 8K; diff --git a/ports/nrf/boards/nrf52840_1M_256k.ld b/ports/nrf/boards/nrf52840_1M_256k.ld index 16d61af6a30b9..2670b88f50d4d 100644 --- a/ports/nrf/boards/nrf52840_1M_256k.ld +++ b/ports/nrf/boards/nrf52840_1M_256k.ld @@ -4,6 +4,7 @@ _flash_size = 1M; _ram_size = 256K; +_vfsrom_size = 128K; /* produce a link error if there is not this amount of RAM for these sections */ _stack_size = 8K; diff --git a/ports/nrf/boards/nrf9160_1M_256k.ld b/ports/nrf/boards/nrf9160_1M_256k.ld index 6347095a899ce..467a0325e25d5 100644 --- a/ports/nrf/boards/nrf9160_1M_256k.ld +++ b/ports/nrf/boards/nrf9160_1M_256k.ld @@ -7,6 +7,7 @@ _ram_size = 256K; _sd_size = 0x00008000; _sd_ram = 0x00020000; _fs_size = 80K; +_vfsrom_size = 128K; /* produce a link error if there is not this amount of RAM for these sections */ _stack_size = 32K; diff --git a/ports/nrf/modules/nrf/flashbdev.c b/ports/nrf/modules/nrf/flashbdev.c index e490dc53dd677..2a27f8631a484 100644 --- a/ports/nrf/modules/nrf/flashbdev.c +++ b/ports/nrf/modules/nrf/flashbdev.c @@ -202,4 +202,36 @@ void flashbdev_init(void) { nrf_flash_obj.len = num_pages * FLASH_PAGESIZE; } +#if MICROPY_VFS_ROM + +extern byte _vfsrom_start[]; +extern byte _vfsrom_size[]; + +#define MICROPY_HW_ROMFS_BASE ((uint32_t)_vfsrom_start) +#define MICROPY_HW_ROMFS_BYTES ((uint32_t)_vfsrom_size) + +static nrf_flash_obj_t nrf_flash_romfs_obj = { + .base = { &nrf_flashbdev_type }, + .start = MICROPY_HW_ROMFS_BASE, // Get from MCU-Specific loader script. + .len = MICROPY_HW_ROMFS_BYTES, // Get from MCU-Specific loader script. +}; + +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { + if (MICROPY_HW_ROMFS_BYTES <= 0) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + switch (mp_obj_get_int(args[0])) { + case -1: // request object-based capabilities + return MP_OBJ_FROM_PTR(&nrf_flash_romfs_obj); + case 0: // number of segments + return MP_OBJ_NEW_SMALL_INT(1); + case 1: // address + return mp_obj_new_int(MICROPY_HW_ROMFS_BASE); + default: + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } +} + +#endif // MICROPY_VFS_ROM + #endif // MICROPY_PY_NRF && MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 7cc8a66d9840c..7d06fe1bd79a6 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -69,6 +69,11 @@ #define MICROPY_VFS (CORE_FEAT) #endif +// VfsROM filesystem +#ifndef MICROPY_VFS_ROM +#define MICROPY_VFS_ROM (CORE_FEAT) +#endif + // micro:bit filesystem #ifndef MICROPY_MBFS #define MICROPY_MBFS (!MICROPY_VFS) From e75c8a6c6e4a43358511aba1617c0b41a2c1fcdc Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 26 Nov 2024 13:25:29 +0100 Subject: [PATCH 22/33] nrf/main: Use frozen _boot.py to set up and mount the file system. Replacing a mix of C-Code and Python code. The mkfs part has been simplified to save code. Signed-off-by: robert-hh --- ports/nrf/main.c | 18 ++------------- ports/nrf/modules/manifest.py | 2 +- ports/nrf/modules/scripts/_boot.py | 37 ++++++++++++++++++++++++++++++ ports/nrf/modules/scripts/_mkfs.py | 23 ------------------- 4 files changed, 40 insertions(+), 40 deletions(-) create mode 100644 ports/nrf/modules/scripts/_boot.py delete mode 100644 ports/nrf/modules/scripts/_mkfs.py diff --git a/ports/nrf/main.c b/ports/nrf/main.c index 29550bd77a748..17dbe19dfda5d 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -179,22 +179,8 @@ void NORETURN _start(void) { #if MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE flashbdev_init(); - - // Try to mount the flash on "/flash" and chdir to it for the boot-up directory. - mp_obj_t mount_point = MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash); - int ret = mp_vfs_mount_and_chdir_protected((mp_obj_t)&nrf_flash_obj, mount_point); - - if ((ret == -MP_ENODEV) || (ret == -MP_EIO)) { - pyexec_frozen_module("_mkfs.py", false); // Frozen script for formatting flash filesystem. - ret = mp_vfs_mount_and_chdir_protected((mp_obj_t)&nrf_flash_obj, mount_point); - } - - if (ret != 0) { - printf("MPY: can't mount flash\n"); - } else { - mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash)); - mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash_slash_lib)); - } + // Execute _boot.py to set up the filesystem. + pyexec_frozen_module("_boot.py", false); #endif #if MICROPY_MBFS diff --git a/ports/nrf/modules/manifest.py b/ports/nrf/modules/manifest.py index 7ba0f80d884d0..631ad19a8db8a 100644 --- a/ports/nrf/modules/manifest.py +++ b/ports/nrf/modules/manifest.py @@ -1,2 +1,2 @@ -module("_mkfs.py", base_path="$(PORT_DIR)/modules/scripts", opt=3) +module("_boot.py", base_path="$(PORT_DIR)/modules/scripts", opt=3) include("$(MPY_DIR)/extmod/asyncio") diff --git a/ports/nrf/modules/scripts/_boot.py b/ports/nrf/modules/scripts/_boot.py new file mode 100644 index 0000000000000..986f83b0c1abd --- /dev/null +++ b/ports/nrf/modules/scripts/_boot.py @@ -0,0 +1,37 @@ +import gc +import vfs +import sys +import nrf +import os + +try: + vfs.mount(vfs.VfsRom(vfs.rom_ioctl(1)), "/rom") + sys.path.insert(0, "/rom") +except: + pass + +try: + bdev = nrf.Flash() + fs_type = ( + vfs.VfsLfs2 + if hasattr(vfs, "VfsLfs2") + else (vfs.VfsLfs1 if hasattr(vfs, "VfsLfs1") else vfs.VfsFat) + ) + vfs.mount(fs_type(bdev), "/flash") +except AttributeError: + fs_type = None +except: + try: + fs_type.mkfs(bdev) + vfs.mount(fs_type(bdev), "/flash") + except: + pass + +if fs_type is not None: + os.chdir("/flash") + sys.path.append("/flash") + sys.path.append("/flash/lib") + +del os, nrf, vfs, sys, bdev, fs_type +gc.collect() +del gc diff --git a/ports/nrf/modules/scripts/_mkfs.py b/ports/nrf/modules/scripts/_mkfs.py deleted file mode 100644 index 601f9558eb7b5..0000000000000 --- a/ports/nrf/modules/scripts/_mkfs.py +++ /dev/null @@ -1,23 +0,0 @@ -import vfs, nrf - -try: - from vfs import VfsLfs1 - - vfs.VfsLfs1.mkfs(nrf.Flash()) -except ImportError: - try: - from vfs import VfsLfs2 - - vfs.VfsLfs2.mkfs(nrf.Flash()) - except ImportError: - try: - from vfs import VfsFat - - vfs.VfsFat.mkfs(nrf.Flash()) - except ImportError: - pass - except OSError as e: - if e.args[0] == 5: # I/O Error - flashbdev_size = (nrf.Flash.ioctl(4, 0) * nrf.Flash.ioctl(5, 0)) // 1024 - print() - print("Is `FS_SIZE=%iK` enough for FAT filesystem?" % flashbdev_size) From 877953d62eb7c643f69a53e46a67a806f7e0fe9f Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 11 Dec 2024 14:21:18 +0100 Subject: [PATCH 23/33] renesas-ra/storage: Add support for a VfsRom file system. VfsRom file system sizes: EK_RA4M1: 12K RA4M1_CLICKER: 12k EK_RA4W1: 64k EK_RA6M1: 64k EK_RA6M2: 128k EK_RA6M5: 256k ARDUINO_PORTENTA_C33: 192k Tested with Weact RA4M1 core board with EK_RA4M1 firmware and EK_RA6M2. More boards have to be tested. Signed-off-by: robert-hh --- .../boards/ARDUINO_PORTENTA_C33/ra6m5.ld | 6 +- ports/renesas-ra/boards/EK_RA4M1/ra4m1_ek.ld | 9 ++- .../boards/EK_RA4W1/mpconfigboard.h | 2 + ports/renesas-ra/boards/EK_RA4W1/ra4w1_ek.ld | 9 ++- ports/renesas-ra/boards/EK_RA6M1/ra6m1_ek.ld | 5 +- ports/renesas-ra/boards/EK_RA6M2/ra6m2_ek.ld | 11 +++- .../boards/RA4M1_CLICKER/ra4m1_clicker.ld | 5 +- ports/renesas-ra/boards/VK_RA6M5/vk_ra6m5.ld | 6 +- ports/renesas-ra/build_all_boards.sh | 26 -------- ports/renesas-ra/mpconfigboard_common.h | 4 ++ ports/renesas-ra/storage.c | 66 +++++++++++++++++-- 11 files changed, 110 insertions(+), 39 deletions(-) delete mode 100644 ports/renesas-ra/build_all_boards.sh diff --git a/ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/ra6m5.ld b/ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/ra6m5.ld index c1fac5106c37e..3b5be1642ec6c 100644 --- a/ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/ra6m5.ld +++ b/ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/ra6m5.ld @@ -6,7 +6,8 @@ MEMORY { FLASH_BOOT (r) : ORIGIN = 0x00000000, LENGTH = 0x00010000 /* 64K */ - FLASH (rx) : ORIGIN = 0x00010000, LENGTH = 0x000f0000 /* 960KB */ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x000C0000 /* 768KB/2MB */ + VFSROM_FS (r) : ORIGIN = 0x000D0000, LENGTH = 0x00030000 /* 192KB/2MB */ FLASH_FS (r) : ORIGIN = 0x00100000, LENGTH = 0x00100000 /* 1MB */ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00080000 /* 512KB */ OSPI_RAM (rwx) : ORIGIN = 0x68000000, LENGTH = 0x00800000 /* 8MB/8MB */ @@ -304,3 +305,6 @@ _heap_end = __HeapLimit; /* tunable */ _micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); + +_micropy_hw_vfsrom_storage_start = ORIGIN(VFSROM_FS); +_micropy_hw_vfsrom_storage_len = LENGTH(VFSROM_FS); diff --git a/ports/renesas-ra/boards/EK_RA4M1/ra4m1_ek.ld b/ports/renesas-ra/boards/EK_RA4M1/ra4m1_ek.ld index 52f8acf93eb33..e1c1c5b796a61 100644 --- a/ports/renesas-ra/boards/EK_RA4M1/ra4m1_ek.ld +++ b/ports/renesas-ra/boards/EK_RA4M1/ra4m1_ek.ld @@ -3,9 +3,14 @@ */ /* Linker script to configure memory regions. */ +/* + * VFSROM_FS and FLASH_FS must start and length must be a multiple + * of the physical sector size of that region (2k). + */ MEMORY { - FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00037000 /* 220KB/256KB */ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00034000 /* 208KB/256KB */ + VFSROM_FS (r) : ORIGIN = 0x00034000, LENGTH = 0x00003000 /* 12KB/256KB */ FLASH_FS (r) : ORIGIN = 0x00037000, LENGTH = 0x00009000 /* 36KB/256KB */ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 /* 32KB */ DATA_FLASH (rx) : ORIGIN = 0x40100000, LENGTH = 0x00002000 /* 8KB */ @@ -300,3 +305,5 @@ _heap_end = __HeapLimit; /* tunable */ _micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); +_micropy_hw_vfsrom_storage_start = ORIGIN(VFSROM_FS); +_micropy_hw_vfsrom_storage_len = LENGTH(VFSROM_FS); diff --git a/ports/renesas-ra/boards/EK_RA4W1/mpconfigboard.h b/ports/renesas-ra/boards/EK_RA4W1/mpconfigboard.h index 9eda05f0fdd1b..19477f9df9c3e 100644 --- a/ports/renesas-ra/boards/EK_RA4W1/mpconfigboard.h +++ b/ports/renesas-ra/boards/EK_RA4W1/mpconfigboard.h @@ -67,3 +67,5 @@ #define MICROPY_HW_LED_ON(pin) mp_hal_pin_low(pin) #define MICROPY_HW_LED_OFF(pin) mp_hal_pin_high(pin) #define MICROPY_HW_LED_TOGGLE(pin) mp_hal_pin_toggle(pin) + +#define MICROPY_VFS_ROM (1) diff --git a/ports/renesas-ra/boards/EK_RA4W1/ra4w1_ek.ld b/ports/renesas-ra/boards/EK_RA4W1/ra4w1_ek.ld index 1241b5bc2302b..bdc90d545876d 100644 --- a/ports/renesas-ra/boards/EK_RA4W1/ra4w1_ek.ld +++ b/ports/renesas-ra/boards/EK_RA4W1/ra4w1_ek.ld @@ -3,9 +3,14 @@ */ /* Linker script to configure memory regions. */ +/* + * VFSROM_FS and FLASH_FS must start and length must be a multiple + * of the physical sector size of that region (2k). + */ MEMORY { - FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00070000 /* 448KB/512KB */ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00060000 /* 384KB/512KB */ + VFSROM_FS (r) : ORIGIN = 0x00060000, LENGTH = 0x00010000 /* 64KB/512KB */ FLASH_FS (r) : ORIGIN = 0x00070000, LENGTH = 0x00010000 /* 64KB/512KB */ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00018000 /* 96KB */ DATA_FLASH (rx) : ORIGIN = 0x40100000, LENGTH = 0x00002000 /* 8KB */ @@ -300,3 +305,5 @@ _heap_end = __HeapLimit; /* tunable */ _micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); +_micropy_hw_vfsrom_storage_start = ORIGIN(VFSROM_FS); +_micropy_hw_vfsrom_storage_len = LENGTH(VFSROM_FS); diff --git a/ports/renesas-ra/boards/EK_RA6M1/ra6m1_ek.ld b/ports/renesas-ra/boards/EK_RA6M1/ra6m1_ek.ld index c7d85ed3db0a1..c10cdfcbb22f9 100644 --- a/ports/renesas-ra/boards/EK_RA6M1/ra6m1_ek.ld +++ b/ports/renesas-ra/boards/EK_RA6M1/ra6m1_ek.ld @@ -5,7 +5,8 @@ /* Linker script to configure memory regions. */ MEMORY { - FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00070000 /* 448KB/512KB */ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00060000 /* 384KB/512KB */ + VFSROM_FS (r) : ORIGIN = 0x00060000, LENGTH = 0x00010000 /* 64KB/512KB */ FLASH_FS (r) : ORIGIN = 0x00070000, LENGTH = 0x00010000 /* 64KB/512KB */ RAM (rwx) : ORIGIN = 0x1FFE0000, LENGTH = 0x00040000 /* 256KB */ DATA_FLASH (rx) : ORIGIN = 0x40100000, LENGTH = 0x00002000 /* 8KB */ @@ -300,3 +301,5 @@ _heap_end = __HeapLimit; /* tunable */ _micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); +_micropy_hw_vfsrom_storage_start = ORIGIN(VFSROM_FS); +_micropy_hw_vfsrom_storage_len = LENGTH(VFSROM_FS); diff --git a/ports/renesas-ra/boards/EK_RA6M2/ra6m2_ek.ld b/ports/renesas-ra/boards/EK_RA6M2/ra6m2_ek.ld index 086f6630c110a..346ef827fc71d 100644 --- a/ports/renesas-ra/boards/EK_RA6M2/ra6m2_ek.ld +++ b/ports/renesas-ra/boards/EK_RA6M2/ra6m2_ek.ld @@ -3,9 +3,15 @@ */ /* Linker script to configure memory regions. */ + +/* + * VFSROM_FS and FLASH_FS must start and length must be a multiple + * of the physical sector size of that region (32k). + */ MEMORY { - FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x000e0000 /* 896KB/1MB */ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x000e0000 /* 768KB/1MB */ + VFSROM_FS (r) : ORIGIN = 0x000c0000, LENGTH = 0x00020000 /* 128KB/1MB */ FLASH_FS (r) : ORIGIN = 0x000e0000, LENGTH = 0x00020000 /* 128KB/1MB */ RAM (rwx) : ORIGIN = 0x1FFE0000, LENGTH = 0x00060000 /* 384KB */ DATA_FLASH (rx) : ORIGIN = 0x40100000, LENGTH = 0x00008000 /* 32KB */ @@ -300,3 +306,6 @@ _heap_end = __HeapLimit; /* tunable */ _micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); + +_micropy_hw_vfsrom_storage_start = ORIGIN(VFSROM_FS); +_micropy_hw_vfsrom_storage_len = LENGTH(VFSROM_FS); diff --git a/ports/renesas-ra/boards/RA4M1_CLICKER/ra4m1_clicker.ld b/ports/renesas-ra/boards/RA4M1_CLICKER/ra4m1_clicker.ld index 52f8acf93eb33..6667a7153387a 100644 --- a/ports/renesas-ra/boards/RA4M1_CLICKER/ra4m1_clicker.ld +++ b/ports/renesas-ra/boards/RA4M1_CLICKER/ra4m1_clicker.ld @@ -5,7 +5,8 @@ /* Linker script to configure memory regions. */ MEMORY { - FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00037000 /* 220KB/256KB */ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00034000 /* 208KB/256KB */ + VFSROM_FS (r) : ORIGIN = 0x00034000, LENGTH = 0x00003000 /* 12KB/256KB */ FLASH_FS (r) : ORIGIN = 0x00037000, LENGTH = 0x00009000 /* 36KB/256KB */ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 /* 32KB */ DATA_FLASH (rx) : ORIGIN = 0x40100000, LENGTH = 0x00002000 /* 8KB */ @@ -300,3 +301,5 @@ _heap_end = __HeapLimit; /* tunable */ _micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); +_micropy_hw_vfsrom_storage_start = ORIGIN(VFSROM_FS); +_micropy_hw_vfsrom_storage_len = LENGTH(VFSROM_FS); diff --git a/ports/renesas-ra/boards/VK_RA6M5/vk_ra6m5.ld b/ports/renesas-ra/boards/VK_RA6M5/vk_ra6m5.ld index 8363d2e743f24..42fa6682a884e 100644 --- a/ports/renesas-ra/boards/VK_RA6M5/vk_ra6m5.ld +++ b/ports/renesas-ra/boards/VK_RA6M5/vk_ra6m5.ld @@ -5,7 +5,8 @@ /* Linker script to configure memory regions. */ MEMORY { - FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00100000 /* 1MB/2MB */ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x000C0000 /* 768KB/2MB */ + VFSROM_FS (r) : ORIGIN = 0x000C0000, LENGTH = 0x00040000 /* 256KB/2MB */ FLASH_FS (r) : ORIGIN = 0x00100000, LENGTH = 0x00100000 /* 1MB/2MB */ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00080000 /* 512KB */ OSPI_RAM (rwx) : ORIGIN = 0x68000000, LENGTH = 0x00800000 /* 8MB/8MB */ @@ -306,3 +307,6 @@ _micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); _micropy_hw_external_flash_storage_start = ORIGIN(QSPI_FLASH); _micropy_hw_external_flash_storage_end = ORIGIN(QSPI_FLASH) + LENGTH(QSPI_FLASH); + +_micropy_hw_vfsrom_storage_start = ORIGIN(VFSROM_FS); +_micropy_hw_vfsrom_storage_len = LENGTH(VFSROM_FS); diff --git a/ports/renesas-ra/build_all_boards.sh b/ports/renesas-ra/build_all_boards.sh deleted file mode 100644 index 0c192dba93103..0000000000000 --- a/ports/renesas-ra/build_all_boards.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -set -eu -o pipefail -export BOARD="RA4M1_CLICKER" -DT=`date +%Y%m%d%H%M` -make DEBUG=0 BOARD=${BOARD} clean 2>&1 | tee ${BOARD}_build_${DT}.log -make DEBUG=0 BOARD=${BOARD} 2>&1 | tee -a ${BOARD}_build_${DT}.log -# -export BOARD="EK_RA6M2" -DT=`date +%Y%m%d%H%M` -make DEBUG=1 BOARD=${BOARD} clean 2>&1 | tee ${BOARD}_build_${DT}.log -make DEBUG=1 BOARD=${BOARD} 2>&1 | tee -a ${BOARD}_build_${DT}.log -# -export BOARD="EK_RA4M1" -DT=`date +%Y%m%d%H%M` -make DEBUG=0 BOARD=${BOARD} clean 2>&1 | tee ${BOARD}_build_${DT}.log -make DEBUG=0 BOARD=${BOARD} 2>&1 | tee -a ${BOARD}_build_${DT}.log -# -export BOARD="EK_RA4W1" -DT=`date +%Y%m%d%H%M` -make DEBUG=0 BOARD=${BOARD} clean 2>&1 | tee ${BOARD}_build_${DT}.log -make DEBUG=0 BOARD=${BOARD} 2>&1 | tee -a ${BOARD}_build_${DT}.log -# -export BOARD="EK_RA6M1" -DT=`date +%Y%m%d%H%M` -make DEBUG=1 BOARD=${BOARD} clean 2>&1 | tee ${BOARD}_build_${DT}.log -make DEBUG=1 BOARD=${BOARD} 2>&1 | tee -a ${BOARD}_build_${DT}.log diff --git a/ports/renesas-ra/mpconfigboard_common.h b/ports/renesas-ra/mpconfigboard_common.h index 479c9f61d1a68..2bd0eab5611e3 100644 --- a/ports/renesas-ra/mpconfigboard_common.h +++ b/ports/renesas-ra/mpconfigboard_common.h @@ -154,6 +154,10 @@ #define MICROPY_HW_UART_IS_RESERVED(uart_id) (false) #endif +// Whether to support the VFSROM file system +#ifndef MICROPY_VFS_ROM +#define MICROPY_VFS_ROM (1) +#endif /*****************************************************************************/ // General configuration diff --git a/ports/renesas-ra/storage.c b/ports/renesas-ra/storage.c index 12416e4dc7a9f..973b46c1a823d 100644 --- a/ports/renesas-ra/storage.c +++ b/ports/renesas-ra/storage.c @@ -36,6 +36,13 @@ #include "led.h" #include "storage.h" #include "irq.h" +#include "flash.h" + +typedef struct _pyb_flash_obj_t { + mp_obj_base_t base; + uint32_t start; // in bytes + uint32_t len; // in bytes +} pyb_flash_obj_t; #if MICROPY_HW_ENABLE_STORAGE @@ -236,12 +243,6 @@ int storage_readblocks_ext(uint8_t *dest, uint32_t block, uint32_t offset, uint3 } #endif -typedef struct _pyb_flash_obj_t { - mp_obj_base_t base; - uint32_t start; // in bytes - uint32_t len; // in bytes -} pyb_flash_obj_t; - // This Flash object represents the entire available flash, with emulated partition table at start const pyb_flash_obj_t pyb_flash_obj = { { &pyb_flash_type }, @@ -427,3 +428,56 @@ void pyb_flash_init_vfs(fs_user_mount_t *vfs) { } #endif + +#if MICROPY_VFS_ROM + +extern uint32_t _micropy_hw_vfsrom_storage_start, _micropy_hw_vfsrom_storage_len; + +#define MICROPY_HW_ROMFS_BASE ((uint32_t)&_micropy_hw_vfsrom_storage_start) +#define MICROPY_HW_ROMFS_BYTES ((uint32_t)&_micropy_hw_vfsrom_storage_len) +#define VFSROM_BLOCK_SIZE (2048) + +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { + if (MICROPY_HW_ROMFS_BYTES <= 0) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + switch (mp_obj_get_int(args[0])) { + case 0: // number of segments + return MP_OBJ_NEW_SMALL_INT(1); + case 1: // address + return mp_obj_new_int(MICROPY_HW_ROMFS_BASE); + case 2: // num blocks + return MP_OBJ_NEW_SMALL_INT(MICROPY_HW_ROMFS_BYTES / VFSROM_BLOCK_SIZE); + case 3: // block_size + return MP_OBJ_NEW_SMALL_INT(VFSROM_BLOCK_SIZE); + case 4: { // erase one block at the offset address to VFSROM + if (n_args < 2) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + uint32_t dest = MICROPY_HW_ROMFS_BASE + mp_obj_get_int(args[1]); + uint32_t sec_size = sector_size(MICROPY_HW_ROMFS_BASE); + // Erase only at a physical sector boundary. + if ((dest % sec_size) == 0) { + // Erase sector. + flash_erase(dest, sec_size); + } + return MP_OBJ_NEW_SMALL_INT(0); + } + case 5: { // write starting at the byte offset address to VFSROM + if (n_args < 3) { + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } + uint32_t dest = MICROPY_HW_ROMFS_BASE + mp_obj_get_int(args[1]); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); + // Write data to flash. + flash_write(dest, bufinfo.buf, bufinfo.len); + return MP_OBJ_NEW_SMALL_INT(0); + } + + default: + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } +} + +#endif // MICROPY_VFS_ROM From c5c3d04fb7bddaebab842017560fbdc7eb8c268f Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 28 Dec 2024 13:36:11 +0100 Subject: [PATCH 24/33] mimxrt/Makefile: Set VfsRom size in Makefile and define vfsrom symbols. Define and use vfsrom_start and vfsrom_end for the VfsRom file system. The way they are set in the MCU loader files, VfsRom will be placed between the text segment and the existing vfs files system area. The size of the VfsRom file system is set in Makefile or one of the board .mk files by setting the symbol MICROPY_HW_ROMFS_BYTES. Signed-off-by: robert-hh --- ports/mimxrt/Makefile | 10 ++++++++-- ports/mimxrt/boards/MIMXRT1011.ld | 4 +++- ports/mimxrt/boards/MIMXRT1015.ld | 4 +++- ports/mimxrt/boards/MIMXRT1021.ld | 4 +++- ports/mimxrt/boards/MIMXRT1052.ld | 4 +++- ports/mimxrt/boards/MIMXRT1062.ld | 4 +++- ports/mimxrt/boards/MIMXRT1064.ld | 4 +++- ports/mimxrt/boards/MIMXRT1176.ld | 4 +++- ports/mimxrt/mimxrt_flash.c | 15 +++++++++------ 9 files changed, 38 insertions(+), 15 deletions(-) diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 8106ab4f3ff03..e3a942e22124f 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -267,6 +267,11 @@ ifeq ($(USE_UF2_BOOTLOADER),1) CFLAGS += -DMICROPY_MACHINE_UF2_BOOTLOADER=1 endif +# Set the default size of the VfsRom file system. Can be changed at board level +ifeq ($(MICROPY_HW_ROMFS_BYTES),) + MICROPY_HW_ROMFS_BYTES ?= 0x40000 +endif + # Add sources for respective board flash type # Add hal/flexspi_nor_flash.c or hal/flashspi_hyper_flash.c respectively SRC_HAL_C += hal/flexspi_$(subst qspi_,,$(FLEXSPI_FLASH_TYPE)).c @@ -450,9 +455,10 @@ LDFLAGS += \ # LDDEFINES are used for link time adaptation of linker scripts, utilizing # the C preprocessor. Therefore keep LDDEFINES separated from LDFLAGS! -LDDEFINES = \ +LDDEFINES += \ -DMICROPY_HW_FLASH_BASE=$(MICROPY_HW_FLASH_BASE) \ - -DMICROPY_HW_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) + -DMICROPY_HW_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) \ + -DMICROPY_HW_ROMFS_BYTES=$(MICROPY_HW_ROMFS_BYTES) ifdef MICROPY_HW_FLASH_RESERVED LDDEFINES += -DMICROPY_HW_FLASH_RESERVED=$(MICROPY_HW_FLASH_RESERVED) diff --git a/ports/mimxrt/boards/MIMXRT1011.ld b/ports/mimxrt/boards/MIMXRT1011.ld index 0e961a49433f2..b5c5464dd7a65 100644 --- a/ports/mimxrt/boards/MIMXRT1011.ld +++ b/ports/mimxrt/boards/MIMXRT1011.ld @@ -18,8 +18,10 @@ interrupts_start = flash_start + 0x0000C000; interrupts_size = 0x00000400; text_start = flash_start + 0x0000C400; vfs_start = flash_start + 0x00100000; -text_size = ((vfs_start) - (text_start)); vfs_size = ((flash_end) - (vfs_start)); +vfsrom_start = ((vfs_start) - MICROPY_HW_ROMFS_BYTES); +vfsrom_end = ((vfsrom_start) + MICROPY_HW_ROMFS_BYTES); +text_size = ((vfsrom_start) - (text_start)); itcm_start = 0x00000000; itcm_size = 0x00008000; dtcm_start = 0x20000000; diff --git a/ports/mimxrt/boards/MIMXRT1015.ld b/ports/mimxrt/boards/MIMXRT1015.ld index 58b88e0fe3084..64ca7bfd3f2fc 100644 --- a/ports/mimxrt/boards/MIMXRT1015.ld +++ b/ports/mimxrt/boards/MIMXRT1015.ld @@ -18,8 +18,10 @@ interrupts_start = flash_start + 0x0000C000; interrupts_size = 0x00000400; text_start = flash_start + 0x0000C400; vfs_start = flash_start + 0x00100000; -text_size = ((vfs_start) - (text_start)); vfs_size = ((flash_end) - (vfs_start)); +vfsrom_start = ((vfs_start) - MICROPY_HW_ROMFS_BYTES); +vfsrom_end = ((vfsrom_start) + MICROPY_HW_ROMFS_BYTES); +text_size = ((vfsrom_start) - (text_start)); itcm_start = 0x00000000; itcm_size = 0x00008000; dtcm_start = 0x20000000; diff --git a/ports/mimxrt/boards/MIMXRT1021.ld b/ports/mimxrt/boards/MIMXRT1021.ld index 78add04c0c26c..7b032788aa8ee 100644 --- a/ports/mimxrt/boards/MIMXRT1021.ld +++ b/ports/mimxrt/boards/MIMXRT1021.ld @@ -18,8 +18,10 @@ interrupts_start = flash_start + 0x0000C000; interrupts_size = 0x00000400; text_start = flash_start + 0x0000C400; vfs_start = flash_start + 0x00100000; -text_size = ((vfs_start) - (text_start)); vfs_size = ((flash_end) - (vfs_start)); +vfsrom_start = ((vfs_start) - MICROPY_HW_ROMFS_BYTES); +vfsrom_end = ((vfsrom_start) + MICROPY_HW_ROMFS_BYTES); +text_size = ((vfsrom_start) - (text_start)); itcm_start = 0x00000000; itcm_size = 0x00010000; dtcm_start = 0x20000000; diff --git a/ports/mimxrt/boards/MIMXRT1052.ld b/ports/mimxrt/boards/MIMXRT1052.ld index ea034d713e2f6..d1b4d556eba61 100644 --- a/ports/mimxrt/boards/MIMXRT1052.ld +++ b/ports/mimxrt/boards/MIMXRT1052.ld @@ -20,8 +20,10 @@ interrupts_start = flash_start + 0x0000C000; interrupts_size = 0x00000400; text_start = flash_start + 0x0000C400; vfs_start = flash_start + 0x00200000; -text_size = ((vfs_start) - (text_start)); vfs_size = ((flash_end) - (vfs_start)); +vfsrom_start = ((vfs_start) - MICROPY_HW_ROMFS_BYTES); +vfsrom_end = ((vfsrom_start) + MICROPY_HW_ROMFS_BYTES); +text_size = ((vfsrom_start) - (text_start)); itcm_start = 0x00000000; itcm_size = 0x00020000; dtcm_start = 0x20000000; diff --git a/ports/mimxrt/boards/MIMXRT1062.ld b/ports/mimxrt/boards/MIMXRT1062.ld index 3d7e6d0634196..d5da419f7e309 100644 --- a/ports/mimxrt/boards/MIMXRT1062.ld +++ b/ports/mimxrt/boards/MIMXRT1062.ld @@ -20,8 +20,10 @@ interrupts_start = flash_start + 0x0000C000; interrupts_size = 0x00000400; text_start = flash_start + 0x0000C400; vfs_start = flash_start + 0x00100000; -text_size = ((vfs_start) - (text_start)); vfs_size = ((flash_end) - (vfs_start)); +vfsrom_start = ((vfs_start) - MICROPY_HW_ROMFS_BYTES); +vfsrom_end = ((vfsrom_start) + MICROPY_HW_ROMFS_BYTES); +text_size = ((vfsrom_start) - (text_start)); itcm_start = 0x00000000; itcm_size = 0x00020000; dtcm_start = 0x20000000; diff --git a/ports/mimxrt/boards/MIMXRT1064.ld b/ports/mimxrt/boards/MIMXRT1064.ld index 7c35cb60c750b..a8215bc3bf5c0 100644 --- a/ports/mimxrt/boards/MIMXRT1064.ld +++ b/ports/mimxrt/boards/MIMXRT1064.ld @@ -14,8 +14,10 @@ interrupts_start = flash_start + 0x0000C000; interrupts_size = 0x00000400; text_start = flash_start + 0x0000C400; vfs_start = flash_start + 0x00100000; -text_size = ((vfs_start) - (text_start)); vfs_size = ((flash_end) - (vfs_start)); +vfsrom_start = ((vfs_start) - MICROPY_HW_ROMFS_BYTES); +vfsrom_end = ((vfsrom_start) + MICROPY_HW_ROMFS_BYTES); +text_size = ((vfsrom_start) - (text_start)); itcm_start = 0x00000000; itcm_size = 0x00020000; dtcm_start = 0x20000000; diff --git a/ports/mimxrt/boards/MIMXRT1176.ld b/ports/mimxrt/boards/MIMXRT1176.ld index 4d114ef96fa4a..11664a752f041 100644 --- a/ports/mimxrt/boards/MIMXRT1176.ld +++ b/ports/mimxrt/boards/MIMXRT1176.ld @@ -30,8 +30,10 @@ m_core1_image_start = vfs_start - 0x00040000; m_core1_image_size = 0x00040000; #endif -text_size = ((vfs_start) - (text_start)); vfs_size = ((flash_end) - (vfs_start)); +vfsrom_start = ((vfs_start) - MICROPY_HW_ROMFS_BYTES); +vfsrom_end = ((vfsrom_start) + MICROPY_HW_ROMFS_BYTES); +text_size = ((vfsrom_start) - (text_start)); itcm_start = 0x00000000; itcm_size = 0x00020000; dtcm_start = 0x20000000; diff --git a/ports/mimxrt/mimxrt_flash.c b/ports/mimxrt/mimxrt_flash.c index ac5995c33532f..8e52420fb9191 100644 --- a/ports/mimxrt/mimxrt_flash.c +++ b/ports/mimxrt/mimxrt_flash.c @@ -158,14 +158,17 @@ MP_DEFINE_CONST_OBJ_TYPE( #if MICROPY_VFS_ROM -#ifndef MICROPY_HW_ROMFS_BYTES -#define MICROPY_HW_ROMFS_BYTES (256 * 1024) -#endif -// Put ROMFS at the upper end of the respective code space. +extern uint8_t vfsrom_start; +extern uint8_t vfsrom_end; + +// Put VfsRom file system between the code space and the VFS file system. +// The size is defined in Makefile(s) as linker symbol MICROPY_HW_ROMFS_BYTES. // For machine.mem32 the absolute address is required, for the flash functions // erase and write the offset to the flash start address. -#define MICROPY_HW_ROMFS_ADDRESS (((uint32_t)&__vfs_start) - MICROPY_HW_ROMFS_BYTES) -#define MICROPY_HW_ROMFS_BASE (MICROPY_HW_FLASH_STORAGE_BASE - MICROPY_HW_ROMFS_BYTES) +#define MICROPY_HW_ROMFS_ADDRESS ((uint32_t)&vfsrom_start) +#define MICROPY_HW_ROMFS_BASE ((uintptr_t)&vfsrom_start - (uintptr_t)&__flash_start) +#define MICROPY_HW_ROMFS_BYTES ((uintptr_t)&vfsrom_end - (uintptr_t)&vfsrom_start) + static mimxrt_flash_obj_t mimxrt_flash_romfs_obj = { .base = { &mimxrt_flash_type }, From 77f12f3a926a984add728ecb71648c812edd6ee1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 3 Jan 2025 12:28:47 +1100 Subject: [PATCH 25/33] mimxrt: Update rom_ioctl protocol. Signed-off-by: Damien George --- ports/mimxrt/mimxrt_flash.c | 24 +++++++++++++++++------- ports/mimxrt/modules/_boot.py | 2 +- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/ports/mimxrt/mimxrt_flash.c b/ports/mimxrt/mimxrt_flash.c index 8e52420fb9191..09ce2a4fbd898 100644 --- a/ports/mimxrt/mimxrt_flash.c +++ b/ports/mimxrt/mimxrt_flash.c @@ -62,6 +62,19 @@ static mp_obj_t mimxrt_flash_make_new(const mp_obj_type_t *type, size_t n_args, return MP_OBJ_FROM_PTR(&mimxrt_flash_obj); } +static mp_int_t mimxrt_flash_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { + mimxrt_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (flags == MP_BUFFER_READ) { + bufinfo->buf = (void *)((uintptr_t)&__flash_start + self->flash_base); + bufinfo->len = self->flash_size; + bufinfo->typecode = 'B'; + return 0; + } else { + // Write unsupported. + return 1; + } +} + // readblocks(block_num, buf, [offset]) // read size of buffer number of bytes from block (with offset) into buffer static mp_obj_t mimxrt_flash_readblocks(size_t n_args, const mp_obj_t *args) { @@ -153,6 +166,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_Flash, MP_TYPE_FLAG_NONE, make_new, mimxrt_flash_make_new, + buffer, mimxrt_flash_get_buffer, locals_dict, &mimxrt_flash_locals_dict ); @@ -165,11 +179,9 @@ extern uint8_t vfsrom_end; // The size is defined in Makefile(s) as linker symbol MICROPY_HW_ROMFS_BYTES. // For machine.mem32 the absolute address is required, for the flash functions // erase and write the offset to the flash start address. -#define MICROPY_HW_ROMFS_ADDRESS ((uint32_t)&vfsrom_start) #define MICROPY_HW_ROMFS_BASE ((uintptr_t)&vfsrom_start - (uintptr_t)&__flash_start) #define MICROPY_HW_ROMFS_BYTES ((uintptr_t)&vfsrom_end - (uintptr_t)&vfsrom_start) - static mimxrt_flash_obj_t mimxrt_flash_romfs_obj = { .base = { &mimxrt_flash_type }, }; @@ -179,14 +191,12 @@ mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); } switch (mp_obj_get_int(args[0])) { - case -1: // request object-based capabilities + case MP_VFS_ROM_IOCTL_GET_NUMBER_OF_SEGMENTS: + return MP_OBJ_NEW_SMALL_INT(1); + case MP_VFS_ROM_IOCTL_GET_SEGMENT: mimxrt_flash_romfs_obj.flash_base = MICROPY_HW_ROMFS_BASE; mimxrt_flash_romfs_obj.flash_size = MICROPY_HW_ROMFS_BYTES; return MP_OBJ_FROM_PTR(&mimxrt_flash_romfs_obj); - case 0: // number of segments - return MP_OBJ_NEW_SMALL_INT(1); - case 1: // address - return mp_obj_new_int(MICROPY_HW_ROMFS_ADDRESS); default: return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); } diff --git a/ports/mimxrt/modules/_boot.py b/ports/mimxrt/modules/_boot.py index 74b7f1918e04d..b658bf3b9e80f 100644 --- a/ports/mimxrt/modules/_boot.py +++ b/ports/mimxrt/modules/_boot.py @@ -9,7 +9,7 @@ from machine import Pin try: - vfs.mount(vfs.VfsRom(vfs.rom_ioctl(1)), "/rom") + vfs.mount(vfs.VfsRom(vfs.rom_ioctl(2)), "/rom") sys.path.insert(0, "/rom") except: pass From d9111eb9c6dc1c7555ea93550f0ba942e4d8b356 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 3 Jan 2025 12:34:55 +1100 Subject: [PATCH 26/33] samd: Update to use new rom_ioctl protocol. Signed-off-by: Damien George --- ports/samd/modules/_boot.py | 2 +- ports/samd/samd_flash.c | 51 +++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/ports/samd/modules/_boot.py b/ports/samd/modules/_boot.py index 6444dc1d40378..88a9c0c4a9504 100644 --- a/ports/samd/modules/_boot.py +++ b/ports/samd/modules/_boot.py @@ -4,7 +4,7 @@ import sys try: - vfs.mount(vfs.VfsRom(vfs.rom_ioctl(1)), "/rom") + vfs.mount(vfs.VfsRom(vfs.rom_ioctl(2)), "/rom") sys.path.insert(0, "/rom") except: pass diff --git a/ports/samd/samd_flash.c b/ports/samd/samd_flash.c index dfcffbfa10349..fcef6495653ca 100644 --- a/ports/samd/samd_flash.c +++ b/ports/samd/samd_flash.c @@ -26,6 +26,7 @@ #include +#include "py/objarray.h" #include "py/runtime.h" #include "extmod/vfs.h" #include "py/mperrno.h" @@ -192,7 +193,6 @@ extern uint8_t _oflash_vfsrom, _sflash_vfsrom; #define MICROPY_HW_ROMFS_BASE ((uint32_t)&_oflash_vfsrom) #define MICROPY_HW_ROMFS_BYTES ((uint32_t)&_sflash_vfsrom) -#define VFSROM_BLOCK_SIZE (2048) #if MICROPY_HW_MCUFLASH static samd_flash_obj_t samd_flash_romfs_obj = { @@ -200,6 +200,8 @@ static samd_flash_obj_t samd_flash_romfs_obj = { .flash_base = MICROPY_HW_ROMFS_BASE, // Get from MCU-Specific loader script. .flash_size = MICROPY_HW_ROMFS_BYTES, // Get from MCU-Specific loader script. }; +#else +static const MP_DEFINE_MEMORYVIEW_OBJ(samd_flash_romfs_obj, 'B', 0, MICROPY_HW_ROMFS_BYTES, (void *)MICROPY_HW_ROMFS_BASE); #endif mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { @@ -207,43 +209,42 @@ mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); } switch (mp_obj_get_int(args[0])) { - #if MICROPY_HW_MCUFLASH - case -1: // request object-based capabilities + case MP_VFS_ROM_IOCTL_GET_NUMBER_OF_SEGMENTS: + return MP_OBJ_NEW_SMALL_INT(1); + + case MP_VFS_ROM_IOCTL_GET_SEGMENT: return MP_OBJ_FROM_PTR(&samd_flash_romfs_obj); - #endif - case 0: // number of segments - return MP_OBJ_NEW_SMALL_INT(1); - case 1: // address - return mp_obj_new_int(MICROPY_HW_ROMFS_BASE); - - #if !MICROPY_HW_MCUFLASH - case 2: // num blocks - return MP_OBJ_NEW_SMALL_INT(MICROPY_HW_ROMFS_BYTES / VFSROM_BLOCK_SIZE); - case 3: // block_size - return MP_OBJ_NEW_SMALL_INT(VFSROM_BLOCK_SIZE); - case 4: { // erase one block at offset address of flash - if (n_args < 2) { + #if !MICROPY_HW_MCUFLASH + + case MP_VFS_ROM_IOCTL_WRITE_PREPARE: { + // Erase sectors in given range. + if (n_args < 3) { return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); } - // Erase sector. - uint32_t dest_addr = MICROPY_HW_ROMFS_BASE + mp_obj_get_int(args[1]); + uint32_t dest_addr = MICROPY_HW_ROMFS_BASE; + uint32_t dest_addr_max = dest_addr + mp_obj_get_int(args[2]); mp_int_t page_size = flash_get_page_size(&flash_desc); // adf4 API call - flash_erase(&flash_desc, dest_addr, (VFSROM_BLOCK_SIZE / page_size)); + for (; dest_addr < dest_addr_max; dest_addr += page_size) { + flash_erase(&flash_desc, dest_addr, 1); + } return MP_OBJ_NEW_SMALL_INT(0); } - case 5: { // write to byte offset address in flash - if (n_args < 3) { + + case MP_VFS_ROM_IOCTL_WRITE: { + // Write data to flash. + if (n_args < 4) { return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); } - uint32_t dest_addr = MICROPY_HW_ROMFS_BASE + mp_obj_get_int(args[1]); + uint32_t dest_addr = MICROPY_HW_ROMFS_BASE + mp_obj_get_int(args[2]); mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); - // Write data to flash. + mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); flash_write(&flash_desc, dest_addr, bufinfo.buf, bufinfo.len); return MP_OBJ_NEW_SMALL_INT(0); } - #endif + + #endif + default: return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); } From 9d40ed2564626bae97e51f88d074fa8d77a25690 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 3 Jan 2025 12:38:42 +1100 Subject: [PATCH 27/33] nrf: Update to use new rom_ioctl protocol. Signed-off-by: Damien George --- ports/nrf/modules/nrf/flashbdev.c | 22 +++++++++++++++++----- ports/nrf/modules/scripts/_boot.py | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/ports/nrf/modules/nrf/flashbdev.c b/ports/nrf/modules/nrf/flashbdev.c index 2a27f8631a484..feacca8746486 100644 --- a/ports/nrf/modules/nrf/flashbdev.c +++ b/ports/nrf/modules/nrf/flashbdev.c @@ -183,12 +183,26 @@ static mp_obj_t nrf_flashbdev_make_new(const mp_obj_type_t *type, size_t n_args, return MP_OBJ_FROM_PTR(self); } +static mp_int_t nrf_flashbdev_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { + nrf_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (flags == MP_BUFFER_READ) { + bufinfo->buf = (void *)self->start; + bufinfo->len = self->len; + bufinfo->typecode = 'B'; + return 0; + } else { + // Unsupported. + return 1; + } +} + MP_DEFINE_CONST_OBJ_TYPE( nrf_flashbdev_type, MP_QSTR_Flash, MP_TYPE_FLAG_NONE, make_new, nrf_flashbdev_make_new, print, nrf_flashbdev_print, + buffer, nrf_flashbdev_get_buffer, locals_dict, &nrf_flashbdev_locals_dict ); @@ -221,12 +235,10 @@ mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); } switch (mp_obj_get_int(args[0])) { - case -1: // request object-based capabilities - return MP_OBJ_FROM_PTR(&nrf_flash_romfs_obj); - case 0: // number of segments + case MP_VFS_ROM_IOCTL_GET_NUMBER_OF_SEGMENTS: return MP_OBJ_NEW_SMALL_INT(1); - case 1: // address - return mp_obj_new_int(MICROPY_HW_ROMFS_BASE); + case MP_VFS_ROM_IOCTL_GET_SEGMENT: + return MP_OBJ_FROM_PTR(&nrf_flash_romfs_obj); default: return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); } diff --git a/ports/nrf/modules/scripts/_boot.py b/ports/nrf/modules/scripts/_boot.py index 986f83b0c1abd..00cde657dbc9f 100644 --- a/ports/nrf/modules/scripts/_boot.py +++ b/ports/nrf/modules/scripts/_boot.py @@ -5,7 +5,7 @@ import os try: - vfs.mount(vfs.VfsRom(vfs.rom_ioctl(1)), "/rom") + vfs.mount(vfs.VfsRom(vfs.rom_ioctl(2)), "/rom") sys.path.insert(0, "/rom") except: pass From 0013dae0f2db000607beb71d7930e43ed02cd090 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 3 Jan 2025 12:43:24 +1100 Subject: [PATCH 28/33] renesas-ra: Update to use new rom_ioctl protocol. Signed-off-by: Damien George --- ports/renesas-ra/storage.c | 42 ++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/ports/renesas-ra/storage.c b/ports/renesas-ra/storage.c index 973b46c1a823d..57ffd957f8d16 100644 --- a/ports/renesas-ra/storage.c +++ b/ports/renesas-ra/storage.c @@ -28,6 +28,7 @@ #include #include +#include "py/objarray.h" #include "py/runtime.h" #include "py/mperrno.h" #include "extmod/vfs_fat.h" @@ -437,40 +438,41 @@ extern uint32_t _micropy_hw_vfsrom_storage_start, _micropy_hw_vfsrom_storage_len #define MICROPY_HW_ROMFS_BYTES ((uint32_t)&_micropy_hw_vfsrom_storage_len) #define VFSROM_BLOCK_SIZE (2048) +static const MP_DEFINE_MEMORYVIEW_OBJ(romfs_obj, 'B', 0, MICROPY_HW_ROMFS_BYTES, (void *)MICROPY_HW_ROMFS_BASE); + mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { if (MICROPY_HW_ROMFS_BYTES <= 0) { return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); } switch (mp_obj_get_int(args[0])) { - case 0: // number of segments + case MP_VFS_ROM_IOCTL_GET_NUMBER_OF_SEGMENTS: return MP_OBJ_NEW_SMALL_INT(1); - case 1: // address - return mp_obj_new_int(MICROPY_HW_ROMFS_BASE); - case 2: // num blocks - return MP_OBJ_NEW_SMALL_INT(MICROPY_HW_ROMFS_BYTES / VFSROM_BLOCK_SIZE); - case 3: // block_size - return MP_OBJ_NEW_SMALL_INT(VFSROM_BLOCK_SIZE); - case 4: { // erase one block at the offset address to VFSROM - if (n_args < 2) { + + case MP_VFS_ROM_IOCTL_GET_SEGMENT: + return MP_OBJ_FROM_PTR(&romfs_obj); + + case MP_VFS_ROM_IOCTL_WRITE_PREPARE: { + // Erase sectors in given range. + if (n_args < 3) { return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); } - uint32_t dest = MICROPY_HW_ROMFS_BASE + mp_obj_get_int(args[1]); - uint32_t sec_size = sector_size(MICROPY_HW_ROMFS_BASE); - // Erase only at a physical sector boundary. - if ((dest % sec_size) == 0) { - // Erase sector. + uint32_t dest = MICROPY_HW_ROMFS_BASE; + uint32_t dest_max = dest + mp_obj_get_int(args[2]); + uint32_t sec_size = sector_size(dest); + for (; dest < dest_max; dest += sec_size) { flash_erase(dest, sec_size); } - return MP_OBJ_NEW_SMALL_INT(0); + return MP_OBJ_NEW_SMALL_INT(4); // minimum write size } - case 5: { // write starting at the byte offset address to VFSROM - if (n_args < 3) { + + case MP_VFS_ROM_IOCTL_WRITE: { + // Write data to flash. + if (n_args < 4) { return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); } - uint32_t dest = MICROPY_HW_ROMFS_BASE + mp_obj_get_int(args[1]); + uint32_t dest = MICROPY_HW_ROMFS_BASE + mp_obj_get_int(args[2]); mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); - // Write data to flash. + mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); flash_write(dest, bufinfo.buf, bufinfo.len); return MP_OBJ_NEW_SMALL_INT(0); } From ca7810731e2233565cab16dd8d33a1c563b0a58e Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 3 Jan 2025 15:30:10 +1100 Subject: [PATCH 29/33] github/workflows: Use ubuntu-latest for stm32 CI. To get newer arm-none-eabi-gcc that can do better size optimisations. Signed-off-by: Damien George --- .github/workflows/ports_stm32.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ports_stm32.yml b/.github/workflows/ports_stm32.yml index f5e01dc1f620e..a6ceb9ec0708c 100644 --- a/.github/workflows/ports_stm32.yml +++ b/.github/workflows/ports_stm32.yml @@ -26,7 +26,7 @@ jobs: - stm32_pyb_build - stm32_nucleo_build - stm32_misc_build - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install packages From 31e56a26adc680f7b92cfe654640a4e70d75c79a Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 5 Jan 2025 10:03:26 +0100 Subject: [PATCH 30/33] samd/samd_flash: Add the buffer protocol to samd_flash_type. It is needed for VfsRom at devices without external flash. Simplify the code for "case MP_VFS_ROM_IOCTL_WRITE_PREPARE:". Signed-off-by: robert-hh --- ports/samd/samd_flash.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/ports/samd/samd_flash.c b/ports/samd/samd_flash.c index fcef6495653ca..e5bfcab875350 100644 --- a/ports/samd/samd_flash.c +++ b/ports/samd/samd_flash.c @@ -72,6 +72,19 @@ static mp_obj_t samd_flash_make_new(const mp_obj_type_t *type, size_t n_args, si // Return singleton object. return MP_OBJ_FROM_PTR(&samd_flash_obj); } + +static mp_int_t samd_flash_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { + samd_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (flags == MP_BUFFER_READ) { + bufinfo->buf = (void *)((uintptr_t)self->flash_base); + bufinfo->len = self->flash_size; + bufinfo->typecode = 'B'; + return 0; + } else { + // Write unsupported. + return 1; + } +} #endif // MICROPY_HW_MCUFLASH // Flash init (from cctpy) @@ -179,6 +192,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_Flash, MP_TYPE_FLAG_NONE, make_new, samd_flash_make_new, + buffer, samd_flash_get_buffer, locals_dict, &samd_flash_locals_dict ); #endif @@ -223,11 +237,8 @@ mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); } uint32_t dest_addr = MICROPY_HW_ROMFS_BASE; - uint32_t dest_addr_max = dest_addr + mp_obj_get_int(args[2]); mp_int_t page_size = flash_get_page_size(&flash_desc); // adf4 API call - for (; dest_addr < dest_addr_max; dest_addr += page_size) { - flash_erase(&flash_desc, dest_addr, 1); - } + flash_erase(&flash_desc, dest_addr, mp_obj_get_int(args[2]) / page_size); return MP_OBJ_NEW_SMALL_INT(0); } From 0f55bfe5aeb63f52d8cd04d900e8649a786ee417 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 6 Jan 2025 23:50:17 +1100 Subject: [PATCH 31/33] samd/samd_flash: Round up number of pages. Signed-off-by: Damien George --- ports/samd/samd_flash.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ports/samd/samd_flash.c b/ports/samd/samd_flash.c index e5bfcab875350..6e2e07e8d68ef 100644 --- a/ports/samd/samd_flash.c +++ b/ports/samd/samd_flash.c @@ -237,9 +237,10 @@ mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); } uint32_t dest_addr = MICROPY_HW_ROMFS_BASE; + uint32_t bytes_used = mp_obj_get_int(args[2]); mp_int_t page_size = flash_get_page_size(&flash_desc); // adf4 API call - flash_erase(&flash_desc, dest_addr, mp_obj_get_int(args[2]) / page_size); - return MP_OBJ_NEW_SMALL_INT(0); + flash_erase(&flash_desc, dest_addr, (bytes_used + page_size - 1) / page_size); + return MP_OBJ_NEW_SMALL_INT(4); } case MP_VFS_ROM_IOCTL_WRITE: { From dfeec448275750a1d68c58ce5f20cc7dd9e4beb3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 22 Jan 2025 16:26:22 +1100 Subject: [PATCH 32/33] Revert "github/workflows: Use ubuntu-latest for stm32 CI." This reverts commit 3cd0c45c432c4d28bfa2d0499da3499a7e398c1f. --- .github/workflows/ports_stm32.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ports_stm32.yml b/.github/workflows/ports_stm32.yml index a6ceb9ec0708c..f5e01dc1f620e 100644 --- a/.github/workflows/ports_stm32.yml +++ b/.github/workflows/ports_stm32.yml @@ -26,7 +26,7 @@ jobs: - stm32_pyb_build - stm32_nucleo_build - stm32_misc_build - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v4 - name: Install packages From 2431419b9cbf63e6c90a88f27e285ded567ff41a Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 19 Feb 2025 17:16:24 +1100 Subject: [PATCH 33/33] WIP: add manifest support won't work when mpremote is pip installed, because micropython-lib is not available! so would need to fetch via URL Signed-off-by: Damien George --- tools/mpremote/mpremote/romfs.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tools/mpremote/mpremote/romfs.py b/tools/mpremote/mpremote/romfs.py index ae781a36dfe62..2e848c0f96858 100644 --- a/tools/mpremote/mpremote/romfs.py +++ b/tools/mpremote/mpremote/romfs.py @@ -127,6 +127,28 @@ def copy_recursively(vfs, src_dir, print_prefix, mpy_cross): def make_romfs(src_dir, *, mpy_cross): + if src_dir.endswith(".py"): + sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../..")) + import manifestfile + + VARS = {} + VARS["MPY_LIB_DIR"] = os.path.abspath("../../lib/micropython-lib") + manifest = manifestfile.ManifestFile(manifestfile.MODE_FREEZE, VARS) + try: + manifest.execute(src_dir) + except manifestfile.ManifestFileError as er: + print('freeze error executing "{}": {}'.format(src_dir, er.args[0])) + sys.exit(1) + + manifest_dir_structure = {} + for result in manifest.files(): + components = result.target_path.split("/") + s = manifest_dir_structure + for x in components[:-1]: + s = s.setdefault(x, {}) + s[components[-1]] = result + return + if not src_dir.endswith("/"): src_dir += "/" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy