Skip to content

Conversation

@robert-hh
Copy link
Contributor

Provide VFS ROM support for the MIXRT, SAMD, NRF and Renesas port.

This is a combined PR with commits for each of the mentioned ports. It's based on the implementation already merged
for ESP8266, ESP32 and RP2. The PR is meant as reminder that the implementation is still due for these ports.

Testing

Tested with a set of boards from each of the ports. Details are shown in the respective commit messages.

@github-actions
Copy link

github-actions bot commented Jun 7, 2025

Code size report:

Reference:  tools/ci.sh: Run natmod tests as part of CI for Unix/RV64. [d871c97]
Comparison: nrf: Add support for VfsRom filesystem. [merge of 6105520]
  mpy-cross:    +0 +0.000% 
   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:    +0 +0.000% standard
      stm32:    +0 +0.000% PYBV10
     mimxrt: +2216 +0.588% TEENSY40[incl +12(data)]
        rp2:    +0 +0.000% RPI_PICO_W
       samd:  +684 +0.251% ADAFRUIT_ITSYBITSY_M4_EXPRESS[incl +32(bss)]
  qemu rv32:    +0 +0.000% VIRT_RV32

@dpgeorge
Copy link
Member

Thanks @robert-hh for working on this, it's great to have ROMFS enabled for all the ports.

I would have reviewed and merged this earlier, but I really wanted to implement a partition table before going down the path of enabling ROMFS on all the ports and boards. IMO a partition table is needed because there should be a way for the user to define how big the ROMFS and writable FS's are.

Prior to ROMFS there was just the firmware and the filesystem. For boards with an external flash filesystem, the decision is easy: the firmware takes all the internal flash, and the filesystem takes all the external flash. For boards with just internal (eg stm32 Nucleo boards) or just external flash (eg esp32, rp2) it's also not that hard of a decision, we just pick a boundary between firmware and filesystem such that the firmware fits and has a bit of room to grow.

But with ROMFS we now need to make two decisions: the boundary between firmware and ROMFS, and then between ROMFS and writable filesystem. And it gets more complicated when some of the flash is memory mappable and some is not, because ROMFS must go in mappable flash. There's really no one-size-fits all choice for how big the ROMFS should be. Eg I have some projects when I use ROMFS and I need it to be very large (up to 1MiB) to store lots of font data.

So, we need a partition table to define the layout of the flash. I have been slowly working on that, but it's a lot harder than I originally expected it would be. When that lands, we will need to reorganise the flash layout of pretty much every board. That's why I thought it best to wait until fully enabling ROMFS on all the boards, so we don't have to change everything again.

Anyway, I don't know when I'll be able to get a working implementation of a partition table. So I'm happy to move forward with this PR now and merge it.

Copy link
Member

@dpgeorge dpgeorge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this on TEENS40 and it works well!

For samd: if possible I'd rather not change the size of the existing writable filesystems, which is the case when the board does not have external SPI flash. Is it possible to only enable ROMFS on samd boards that have external SPI flash? That way, users won't have to reformat their filesystem, and if they have external SPI flash then their boards will just be upgraded to have a new ROMFS (which takes up unused space at the end of the existing firmware section of flash).

@robert-hh
Copy link
Contributor Author

Thank you Damien for reviewing the PR. I will try to implement the changes after Christmas.
I agree that it would be best to have common approach for all ports & boards. That would also have an API to handle a partition table, making modifications independent from building and updating the firmware.

@robert-hh robert-hh changed the title ports: Provide VFS ROM support for the MIXRT, SAMD, NRF and Renesas port. ports: Provide VFS ROM support for the MIMXRT, SAMD, NRF and Renesas port. Dec 22, 2025
@dpgeorge
Copy link
Member

Thanks, there's no hurry.

@robert-hh
Copy link
Contributor Author

robert-hh commented Dec 31, 2025

@dpgeorge Your review comments are implemented. There is the observation with MIMXRT: romfs fails with Hyperflash, probably due to the huge sector size of 256kB.

Note: The text segment for SAMD21 devices is full, sometimes 98-99%. ROMFS is consuming the space left at devices with SPI flash. Time for a diet and maybe drop ROMFS support for SAMD21.
Edit: Another option would be to drop MATH support, which gains 8k of code.

@robert-hh robert-hh force-pushed the ports_vfsrom branch 2 times, most recently from 7cb07fe to 43cd966 Compare January 1, 2026 14:55
The default size for the ROM partition is 256k, and it is placed in flash
between the text and writable vfs sections.  Its size can be changed in
`mpconfigboard.mk` by defining `MICROPY_HW_ROMFS_BYTES` to a different
value, but it must not be smaller than a single sector.

The MIMXRT1170_EVK and SEEED ARCH MIX ROMFS boards use a larger size of
512kB.  ROMFS support is disabled for MIMXRT1050_EVKB due to issues with
Hyperflash.

The extents of the ROM partition are defined by the linker-level symbols
`_micropy_hw_romfs_part0_start` and `_micropy_hw_romfs_part0_size`,
following existing ports.

Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: robert-hh <robert@hammelrath.com>
The flash driver is update to support the new `mp_vfs_rom_ioctl()`
function, and the buffer protocol is added to `samd_flash_type` (it is
needed for VfsRom on devices without external flash).

For SAMD21, only boards with external SPI flash have VfsRom enabled, due
to size constraints.  For such boards, the VfsRom filesystem has a size of
12k and is placed at the upper end of the flash.  The `onewire`, `ds18x20`
and `dht` drivers have been removed from frozen bytecode as they can be
placed into the VfsRom files when needed.

For SAMD51, the VfsRom filesystem has a default size of 64k for SAMD51x19
and 256K for SAMD51x20.  It is placed at the upper end of the flash.
For boards with external SPI flash, the code size is reduced from 496K to
432K.  If that is not sufficient for some boards or configurations, it can
be changed for each board or board variant.

Tested with ADAFRUIT_ITSYBITSY_M0_EXPRESS, ADAFRUIT_ITSYBITSY_M4_EXPRESS,
SPARKFUN_SAMD51_THING_PLUS, SEEED_XIAO_SAMD21, SAMD_GENERIC_D51X19, and
SAMD_GENERIC_D51X20.

Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: robert-hh <robert@hammelrath.com>
The ROM partition is taken from the last part of the flash text section, so
the existing writable filesystem is untouched.  VfsRom file system sizes:
- EK_RA4M1: 12K
- RA4M1_CLICKER: 12k
- EK_RA4W1: 64k
- EK_RA6M1: 64k
- EK_RA6M2: 256k
- VK_RA6M5: 384k
- ARDUINO_PORTENTA_C33: 256k

Tested with Weact RA4M1 core board with EK_RA4M1 firmware and EK_RA6M2.

Signed-off-by: robert-hh <robert@hammelrath.com>
Signed-off-by: Damien George <damien@micropython.org>
The implementation uses the object based capabilities, which avoids
complication about different flash block sizes.  The ROM partition is
placed between the text and writable filesystem sections, and the latter
size is unchanged.  VfsRom sizes are:
- NRF51x22: 12K
- NRF52832: 128K
- NRF52840: 256K
- NRF9160:  256K

Use frozen `_boot.py` to set up and mount the filesystem, replacing a mix
of C-Code and Python code.  The mkfs part has been simplified to save code.

Tested with Microbit and Arduino Nano Connect.

Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: robert-hh <robert@hammelrath.com>
Copy link
Member

@dpgeorge dpgeorge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for updating, this looks good now.

I've squashed the commits to one per port, and made a few minor fixes:

  • increased ROM partition size from 128k to 256k in nrf9160_1M_256k.ld (as we agreed, but I think you forgot to push that change)
  • fixed ARDUINO_PORTENTA_C33 so that the FLASH starts after the bootloader:
--- a/ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/ra6m5.ld
+++ b/ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/ra6m5.ld
@@ -6,7 +6,7 @@
 MEMORY
 {
   FLASH_BOOT (r)     : ORIGIN = 0x00000000, LENGTH = 0x00010000  /* 64K */
-  FLASH (rx)         : ORIGIN = 0x00000000, LENGTH = 0x000B0000  /* 704KB/2MB */
+  FLASH (rx)         : ORIGIN = 0x00010000, LENGTH = 0x000B0000  /* 704KB/2MB */
   FLASH_ROMFS (r)    : ORIGIN = 0x000C0000, LENGTH = 0x00040000  /* 256KB/2MB */
   FLASH_FS (r)       : ORIGIN = 0x00100000, LENGTH = 0x00100000  /* 1MB */
   RAM (rwx)          : ORIGIN = 0x20000000, LENGTH = 0x00080000  /* 512KB */
  • fixed VK_RA6M5 so FLASH_ROMFS doesn't run into FLASH_FS:
--- a/ports/renesas-ra/boards/VK_RA6M5/vk_ra6m5.ld
+++ b/ports/renesas-ra/boards/VK_RA6M5/vk_ra6m5.ld
@@ -6,7 +6,7 @@
 MEMORY
 {
   FLASH (rx)         : ORIGIN = 0x00000000, LENGTH = 0x000A0000  /* 640KB/2MB */
-  FLASH_ROMFS (r)    : ORIGIN = 0x000A0000, LENGTH = 0x000A0000  /* 384KB/2MB */
+  FLASH_ROMFS (r)    : ORIGIN = 0x000A0000, LENGTH = 0x00060000  /* 384KB/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 */

@dpgeorge dpgeorge merged commit 6105520 into micropython:master Jan 2, 2026
11 checks passed
@robert-hh robert-hh deleted the ports_vfsrom branch January 2, 2026 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants