rp2: Implement vfs.rom_ioctl with support for external flash.

Not enabled by default on any board.  A board can enable a ROMFS partition
by defining `MICROPY_HW_ROMFS_BYTES` in its `mpconfigboard.h` file.  For
example:

    #define MICROPY_HW_ROMFS_BYTES (128 * 1024)

The ROMFS partition is placed at the end of the flash allocated for the
firmware, giving less space for the firmware.  It then lives between the
firmware and the read/write filesystem.

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Damien George 2022-03-04 10:57:38 +11:00
parent 45c36f87ea
commit 50a7362b3e
2 changed files with 53 additions and 3 deletions

View file

@ -67,6 +67,16 @@
#endif
#endif
// Number of bytes of flash to allocate to the ROMFS partition.
#ifndef MICROPY_HW_ROMFS_BYTES
#define MICROPY_HW_ROMFS_BYTES (0)
#endif
// Number of bytes of flash to allocate to read/write filesystem storage.
#ifndef MICROPY_HW_FLASH_STORAGE_BYTES
#define MICROPY_HW_FLASH_STORAGE_BYTES (1408 * 1024)
#endif
#ifndef MICROPY_CONFIG_ROM_LEVEL
#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES)
#endif
@ -170,6 +180,7 @@
#define MICROPY_VFS (1)
#define MICROPY_VFS_LFS2 (1)
#define MICROPY_VFS_FAT (1)
#define MICROPY_VFS_ROM (MICROPY_HW_ROMFS_BYTES > 0)
#define MICROPY_SSL_MBEDTLS (1)
#define MICROPY_PY_LWIP_PPP (MICROPY_PY_NETWORK_PPP_LWIP)
#define MICROPY_PY_LWIP_SOCK_RAW (MICROPY_PY_LWIP)

View file

@ -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"
@ -35,15 +36,16 @@
#define BLOCK_SIZE_BYTES (FLASH_SECTOR_SIZE)
#ifndef MICROPY_HW_FLASH_STORAGE_BYTES
#define MICROPY_HW_FLASH_STORAGE_BYTES (1408 * 1024)
#endif
static_assert(MICROPY_HW_ROMFS_BYTES % 4096 == 0, "ROMFS size must be a multiple of 4K");
static_assert(MICROPY_HW_FLASH_STORAGE_BYTES % 4096 == 0, "Flash storage size must be a multiple of 4K");
#ifndef MICROPY_HW_FLASH_STORAGE_BASE
#define MICROPY_HW_FLASH_STORAGE_BASE (PICO_FLASH_SIZE_BYTES - MICROPY_HW_FLASH_STORAGE_BYTES)
#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");
@ -53,6 +55,14 @@ typedef struct _rp2_flash_obj_t {
uint32_t flash_size;
} rp2_flash_obj_t;
#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
static rp2_flash_obj_t rp2_flash_obj = {
.base = { &rp2_flash_type },
.flash_base = MICROPY_HW_FLASH_STORAGE_BASE,
@ -138,6 +148,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 +241,21 @@ 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
);
#if MICROPY_VFS_ROM_IOCTL
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);
}
}
#endif