From 9aabb6c01ba4166bb389e28b55f21614fca5aa7f Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 7 Sep 2019 14:03:41 +1000 Subject: [PATCH] extmod: Factor out block-device struct to make independent of fatfs. --- extmod/vfs.h | 20 +++++++++++++++++++ extmod/vfs_fat.c | 24 +++++++++++------------ extmod/vfs_fat.h | 19 +----------------- extmod/vfs_fat_diskio.c | 38 ++++++++++++++++++------------------ ports/cc3200/mods/pybflash.c | 18 ++++++++--------- ports/cc3200/mptask.c | 2 +- ports/nrf/main.c | 2 +- ports/stm32/main.c | 4 ++-- ports/stm32/sdcard.c | 18 ++++++++--------- ports/stm32/storage.c | 18 ++++++++--------- 10 files changed, 83 insertions(+), 80 deletions(-) diff --git a/extmod/vfs.h b/extmod/vfs.h index 730dea0431..85b020faa5 100644 --- a/extmod/vfs.h +++ b/extmod/vfs.h @@ -38,6 +38,12 @@ #define MP_S_IFDIR (0x4000) #define MP_S_IFREG (0x8000) +// these are the values for mp_vfs_blockdev_t.flags +#define MP_BLOCKDEV_FLAG_NATIVE (0x0001) // readblocks[2]/writeblocks[2] contain native func +#define MP_BLOCKDEV_FLAG_FREE_OBJ (0x0002) // fs_user_mount_t obj should be freed on umount +#define MP_BLOCKDEV_FLAG_HAVE_IOCTL (0x0004) // new protocol with ioctl +#define MP_BLOCKDEV_FLAG_NO_FILESYSTEM (0x0008) // the block device has no filesystem on it + // constants for block protocol ioctl #define BP_IOCTL_INIT (1) #define BP_IOCTL_DEINIT (2) @@ -50,6 +56,20 @@ typedef struct _mp_vfs_proto_t { mp_import_stat_t (*import_stat)(void *self, const char *path); } mp_vfs_proto_t; +typedef struct _mp_vfs_blockdev_t { + uint16_t flags; + mp_obj_t readblocks[4]; + mp_obj_t writeblocks[4]; + // new protocol uses just ioctl, old uses sync (optional) and count + union { + mp_obj_t ioctl[4]; + struct { + mp_obj_t sync[2]; + mp_obj_t count[2]; + } old; + } u; +} mp_vfs_blockdev_t; + typedef struct _mp_vfs_mount_t { const char *str; // mount point with leading / size_t len; diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index ec7aaed388..dcfb677b1f 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -68,27 +68,27 @@ STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_ // create new object fs_user_mount_t *vfs = m_new_obj(fs_user_mount_t); vfs->base.type = type; - vfs->flags = FSUSER_FREE_OBJ; + vfs->blockdev.flags = MP_BLOCKDEV_FLAG_FREE_OBJ; vfs->fatfs.drv = vfs; // load block protocol methods - mp_load_method(args[0], MP_QSTR_readblocks, vfs->readblocks); - mp_load_method_maybe(args[0], MP_QSTR_writeblocks, vfs->writeblocks); - mp_load_method_maybe(args[0], MP_QSTR_ioctl, vfs->u.ioctl); - if (vfs->u.ioctl[0] != MP_OBJ_NULL) { + mp_load_method(args[0], MP_QSTR_readblocks, vfs->blockdev.readblocks); + mp_load_method_maybe(args[0], MP_QSTR_writeblocks, vfs->blockdev.writeblocks); + mp_load_method_maybe(args[0], MP_QSTR_ioctl, vfs->blockdev.u.ioctl); + if (vfs->blockdev.u.ioctl[0] != MP_OBJ_NULL) { // device supports new block protocol, so indicate it - vfs->flags |= FSUSER_HAVE_IOCTL; + vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_HAVE_IOCTL; } else { // no ioctl method, so assume the device uses the old block protocol - mp_load_method_maybe(args[0], MP_QSTR_sync, vfs->u.old.sync); - mp_load_method(args[0], MP_QSTR_count, vfs->u.old.count); + mp_load_method_maybe(args[0], MP_QSTR_sync, vfs->blockdev.u.old.sync); + mp_load_method(args[0], MP_QSTR_count, vfs->blockdev.u.old.count); } // mount the block device so the VFS methods can be used FRESULT res = f_mount(&vfs->fatfs); if (res == FR_NO_FILESYSTEM) { // don't error out if no filesystem, to let mkfs()/mount() create one if wanted - vfs->flags |= FSUSER_NO_FILESYSTEM; + vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NO_FILESYSTEM; } else if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } @@ -380,11 +380,11 @@ STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs // 1. readonly=True keyword argument // 2. nonexistent writeblocks method (then writeblocks[0] == MP_OBJ_NULL already) if (mp_obj_is_true(readonly)) { - self->writeblocks[0] = MP_OBJ_NULL; + self->blockdev.writeblocks[0] = MP_OBJ_NULL; } // check if we need to make the filesystem - FRESULT res = (self->flags & FSUSER_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK; + FRESULT res = (self->blockdev.flags & MP_BLOCKDEV_FLAG_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK; if (res == FR_NO_FILESYSTEM && mp_obj_is_true(mkfs)) { uint8_t working_buf[FF_MAX_SS]; res = f_mkfs(&self->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf)); @@ -392,7 +392,7 @@ STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } - self->flags &= ~FSUSER_NO_FILESYSTEM; + self->blockdev.flags &= ~MP_BLOCKDEV_FLAG_NO_FILESYSTEM; return mp_const_none; } diff --git a/extmod/vfs_fat.h b/extmod/vfs_fat.h index ba2915386f..83685b5027 100644 --- a/extmod/vfs_fat.h +++ b/extmod/vfs_fat.h @@ -26,30 +26,13 @@ #ifndef MICROPY_INCLUDED_EXTMOD_VFS_FAT_H #define MICROPY_INCLUDED_EXTMOD_VFS_FAT_H -#include "py/lexer.h" #include "py/obj.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs.h" -// these are the values for fs_user_mount_t.flags -#define FSUSER_NATIVE (0x0001) // readblocks[2]/writeblocks[2] contain native func -#define FSUSER_FREE_OBJ (0x0002) // fs_user_mount_t obj should be freed on umount -#define FSUSER_HAVE_IOCTL (0x0004) // new protocol with ioctl -#define FSUSER_NO_FILESYSTEM (0x0008) // the block device has no filesystem on it - typedef struct _fs_user_mount_t { mp_obj_base_t base; - uint16_t flags; - mp_obj_t readblocks[4]; - mp_obj_t writeblocks[4]; - // new protocol uses just ioctl, old uses sync (optional) and count - union { - mp_obj_t ioctl[4]; - struct { - mp_obj_t sync[2]; - mp_obj_t count[2]; - } old; - } u; + mp_vfs_blockdev_t blockdev; FATFS fatfs; } fs_user_mount_t; diff --git a/extmod/vfs_fat_diskio.c b/extmod/vfs_fat_diskio.c index e80d612411..25b1310670 100644 --- a/extmod/vfs_fat_diskio.c +++ b/extmod/vfs_fat_diskio.c @@ -69,16 +69,16 @@ DRESULT disk_read ( return RES_PARERR; } - if (vfs->flags & FSUSER_NATIVE) { - mp_uint_t (*f)(uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->readblocks[2]; + if (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_NATIVE) { + mp_uint_t (*f)(uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->blockdev.readblocks[2]; if (f(buff, sector, count) != 0) { return RES_ERROR; } } else { mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, count * SECSIZE(&vfs->fatfs), buff}; - vfs->readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); - vfs->readblocks[3] = MP_OBJ_FROM_PTR(&ar); - mp_call_method_n_kw(2, 0, vfs->readblocks); + vfs->blockdev.readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); + vfs->blockdev.readblocks[3] = MP_OBJ_FROM_PTR(&ar); + mp_call_method_n_kw(2, 0, vfs->blockdev.readblocks); // TODO handle error return } @@ -101,21 +101,21 @@ DRESULT disk_write ( return RES_PARERR; } - if (vfs->writeblocks[0] == MP_OBJ_NULL) { + if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) { // read-only block device return RES_WRPRT; } - if (vfs->flags & FSUSER_NATIVE) { - mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->writeblocks[2]; + if (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_NATIVE) { + mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->blockdev.writeblocks[2]; if (f(buff, sector, count) != 0) { return RES_ERROR; } } else { mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, count * SECSIZE(&vfs->fatfs), (void*)buff}; - vfs->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); - vfs->writeblocks[3] = MP_OBJ_FROM_PTR(&ar); - mp_call_method_n_kw(2, 0, vfs->writeblocks); + vfs->blockdev.writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); + vfs->blockdev.writeblocks[3] = MP_OBJ_FROM_PTR(&ar); + mp_call_method_n_kw(2, 0, vfs->blockdev.writeblocks); // TODO handle error return } @@ -140,7 +140,7 @@ DRESULT disk_ioctl ( // First part: call the relevant method of the underlying block device mp_obj_t ret = mp_const_none; - if (vfs->flags & FSUSER_HAVE_IOCTL) { + if (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_HAVE_IOCTL) { // new protocol with ioctl static const uint8_t op_map[8] = { [CTRL_SYNC] = BP_IOCTL_SYNC, @@ -150,21 +150,21 @@ DRESULT disk_ioctl ( }; uint8_t bp_op = op_map[cmd & 7]; if (bp_op != 0) { - vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(bp_op); - vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused - ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl); + vfs->blockdev.u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(bp_op); + vfs->blockdev.u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused + ret = mp_call_method_n_kw(2, 0, vfs->blockdev.u.ioctl); } } else { // old protocol with sync and count switch (cmd) { case CTRL_SYNC: - if (vfs->u.old.sync[0] != MP_OBJ_NULL) { - mp_call_method_n_kw(0, 0, vfs->u.old.sync); + if (vfs->blockdev.u.old.sync[0] != MP_OBJ_NULL) { + mp_call_method_n_kw(0, 0, vfs->blockdev.u.old.sync); } break; case GET_SECTOR_COUNT: - ret = mp_call_method_n_kw(0, 0, vfs->u.old.count); + ret = mp_call_method_n_kw(0, 0, vfs->blockdev.u.old.count); break; case GET_SECTOR_SIZE: @@ -211,7 +211,7 @@ DRESULT disk_ioctl ( if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) { // error initialising stat = STA_NOINIT; - } else if (vfs->writeblocks[0] == MP_OBJ_NULL) { + } else if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) { stat = STA_PROTECT; } else { stat = 0; diff --git a/ports/cc3200/mods/pybflash.c b/ports/cc3200/mods/pybflash.c index 51f4cb5172..185913ce31 100644 --- a/ports/cc3200/mods/pybflash.c +++ b/ports/cc3200/mods/pybflash.c @@ -96,14 +96,14 @@ const mp_obj_type_t pyb_flash_type = { void pyb_flash_init_vfs(fs_user_mount_t *vfs) { vfs->base.type = &mp_fat_vfs_type; - vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; + vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL; vfs->fatfs.drv = vfs; - vfs->readblocks[0] = (mp_obj_t)&pyb_flash_readblocks_obj; - vfs->readblocks[1] = (mp_obj_t)&pyb_flash_obj; - vfs->readblocks[2] = (mp_obj_t)sflash_disk_read; // native version - vfs->writeblocks[0] = (mp_obj_t)&pyb_flash_writeblocks_obj; - vfs->writeblocks[1] = (mp_obj_t)&pyb_flash_obj; - vfs->writeblocks[2] = (mp_obj_t)sflash_disk_write; // native version - vfs->u.ioctl[0] = (mp_obj_t)&pyb_flash_ioctl_obj; - vfs->u.ioctl[1] = (mp_obj_t)&pyb_flash_obj; + vfs->blockdev.readblocks[0] = (mp_obj_t)&pyb_flash_readblocks_obj; + vfs->blockdev.readblocks[1] = (mp_obj_t)&pyb_flash_obj; + vfs->blockdev.readblocks[2] = (mp_obj_t)sflash_disk_read; // native version + vfs->blockdev.writeblocks[0] = (mp_obj_t)&pyb_flash_writeblocks_obj; + vfs->blockdev.writeblocks[1] = (mp_obj_t)&pyb_flash_obj; + vfs->blockdev.writeblocks[2] = (mp_obj_t)sflash_disk_write; // native version + vfs->blockdev.u.ioctl[0] = (mp_obj_t)&pyb_flash_ioctl_obj; + vfs->blockdev.u.ioctl[1] = (mp_obj_t)&pyb_flash_obj; } diff --git a/ports/cc3200/mptask.c b/ports/cc3200/mptask.c index d35338be18..c253804267 100644 --- a/ports/cc3200/mptask.c +++ b/ports/cc3200/mptask.c @@ -300,7 +300,7 @@ STATIC void mptask_init_sflash_filesystem (void) { // Initialise the local flash filesystem. // init the vfs object fs_user_mount_t *vfs_fat = sflash_vfs_fat; - vfs_fat->flags = 0; + vfs_fat->blockdev.flags = 0; pyb_flash_init_vfs(vfs_fat); // Create it if needed, and mount in on /flash. diff --git a/ports/nrf/main.c b/ports/nrf/main.c index 26ac0ad6c9..f7d42060e8 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -180,7 +180,7 @@ pin_init0(); } vfs->str = "/sd"; vfs->len = 3; - vfs->flags = FSUSER_FREE_OBJ; + vfs->flags = MP_BLOCKDEV_FLAG_FREE_OBJ; sdcard_init_vfs(vfs); // put the sd device in slot 1 (it will be unused at this point) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 2da3626f12..685dbd10c7 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -161,7 +161,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(pyb_main_obj, 1, pyb_main); MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { // init the vfs object fs_user_mount_t *vfs_fat = &fs_user_mount_flash; - vfs_fat->flags = 0; + vfs_fat->blockdev.flags = 0; pyb_flash_init_vfs(vfs_fat); // try to mount the flash @@ -230,7 +230,7 @@ STATIC bool init_sdcard_fs(void) { if (vfs == NULL || vfs_fat == NULL) { break; } - vfs_fat->flags = FSUSER_FREE_OBJ; + vfs_fat->blockdev.flags = MP_BLOCKDEV_FLAG_FREE_OBJ; sdcard_init_vfs(vfs_fat, part_num); // try to mount the partition diff --git a/ports/stm32/sdcard.c b/ports/stm32/sdcard.c index 44b1c807d8..da9c1c681a 100644 --- a/ports/stm32/sdcard.c +++ b/ports/stm32/sdcard.c @@ -873,17 +873,17 @@ const mp_obj_type_t pyb_mmcard_type = { void sdcard_init_vfs(fs_user_mount_t *vfs, int part) { pyb_sdmmc_flags = (pyb_sdmmc_flags & PYB_SDMMC_FLAG_ACTIVE) | PYB_SDMMC_FLAG_SD; // force SD mode vfs->base.type = &mp_fat_vfs_type; - vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; + vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL; vfs->fatfs.drv = vfs; vfs->fatfs.part = part; - vfs->readblocks[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_readblocks_obj); - vfs->readblocks[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); - vfs->readblocks[2] = MP_OBJ_FROM_PTR(sdcard_read_blocks); // native version - vfs->writeblocks[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_writeblocks_obj); - vfs->writeblocks[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); - vfs->writeblocks[2] = MP_OBJ_FROM_PTR(sdcard_write_blocks); // native version - vfs->u.ioctl[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_ioctl_obj); - vfs->u.ioctl[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); + vfs->blockdev.readblocks[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_readblocks_obj); + vfs->blockdev.readblocks[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); + vfs->blockdev.readblocks[2] = MP_OBJ_FROM_PTR(sdcard_read_blocks); // native version + vfs->blockdev.writeblocks[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_writeblocks_obj); + vfs->blockdev.writeblocks[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); + vfs->blockdev.writeblocks[2] = MP_OBJ_FROM_PTR(sdcard_write_blocks); // native version + vfs->blockdev.u.ioctl[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_ioctl_obj); + vfs->blockdev.u.ioctl[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); } #endif // MICROPY_HW_ENABLE_SDCARD || MICROPY_HW_ENABLE_MMCARD diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index b150d73763..7685f6f175 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -290,17 +290,17 @@ const mp_obj_type_t pyb_flash_type = { void pyb_flash_init_vfs(fs_user_mount_t *vfs) { vfs->base.type = &mp_fat_vfs_type; - vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; + vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL; vfs->fatfs.drv = vfs; vfs->fatfs.part = 1; // flash filesystem lives on first partition - vfs->readblocks[0] = MP_OBJ_FROM_PTR(&pyb_flash_readblocks_obj); - vfs->readblocks[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); - vfs->readblocks[2] = MP_OBJ_FROM_PTR(storage_read_blocks); // native version - vfs->writeblocks[0] = MP_OBJ_FROM_PTR(&pyb_flash_writeblocks_obj); - vfs->writeblocks[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); - vfs->writeblocks[2] = MP_OBJ_FROM_PTR(storage_write_blocks); // native version - vfs->u.ioctl[0] = MP_OBJ_FROM_PTR(&pyb_flash_ioctl_obj); - vfs->u.ioctl[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); + vfs->blockdev.readblocks[0] = MP_OBJ_FROM_PTR(&pyb_flash_readblocks_obj); + vfs->blockdev.readblocks[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); + vfs->blockdev.readblocks[2] = MP_OBJ_FROM_PTR(storage_read_blocks); // native version + vfs->blockdev.writeblocks[0] = MP_OBJ_FROM_PTR(&pyb_flash_writeblocks_obj); + vfs->blockdev.writeblocks[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); + vfs->blockdev.writeblocks[2] = MP_OBJ_FROM_PTR(storage_write_blocks); // native version + vfs->blockdev.u.ioctl[0] = MP_OBJ_FROM_PTR(&pyb_flash_ioctl_obj); + vfs->blockdev.u.ioctl[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); } #endif