10000 stm32: littlefs support by dpgeorge · Pull Request #5330 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content

stm32: littlefs support #5330

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion extmod/vfs_lfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
enum { LFS_MAKE_ARG_bdev, LFS_MAKE_ARG_readsize, LFS_MAKE_ARG_progsize, LFS_MAKE_ARG_lookahead };

static const mp_arg_t lfs_make_allowed_args[] = {
{ MP_QSTR_, MP_ARG_OBJ },
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_readsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} },
{ MP_QSTR_progsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} },
{ MP_QSTR_lookahead, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} },
Expand Down
2 changes: 1 addition & 1 deletion extmod/vfs_lfsx.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ STATIC void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx *self, mp_obj_t bdev, size_
config->erase = MP_VFS_LFSx(dev_erase);
config->sync = MP_VFS_LFSx(dev_sync);

MP_VFS_LFSx(dev_ioctl)(config, MP_BLOCKDEV_IOCTL_INIT, 0, false); // initialise block device
MP_VFS_LFSx(dev_ioctl)(config, MP_BLOCKDEV_IOCTL_INIT, 1, false); // initialise block device
int bs = MP_VFS_LFSx(dev_ioctl)(config, MP_BLOCKDEV_IOCTL_BLOCK_SIZE, 0, true); // get block size
int bc = MP_VFS_LFSx(dev_ioctl)(config, MP_BLOCKDEV_IOCTL_BLOCK_COUNT, 0, true); // get block count
self->blockdev.block_size = bs;
Expand Down
1 change: 1 addition & 0 deletions ports/stm32/boards/PYBD_SF2/mpconfigboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ extern struct _spi_bdev_t spi_bdev;
)
#define MICROPY_HW_BDEV_READBLOCKS(dest, bl, n) spi_bdev_readblocks(&spi_bdev, (dest), (bl), (n))
#define MICROPY_HW_BDEV_WRITEBLOCKS(src, bl, n) spi_bdev_writeblocks(&spi_bdev, (src), (bl), (n))
#define MICROPY_HW_BDEV_SPIFLASH_EXTENDED (&spi_bdev) // for extended block protocol

// SPI flash #2, to be memory mapped
#define MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 (24)
Expand Down
1 change: 1 addition & 0 deletions ports/stm32/boards/PYBD_SF2/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ MICROPY_PY_LWIP = 1
MICROPY_PY_NETWORK_CYW43 = 1
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
MICROPY_VFS_LFS2 = 1
3 changes: 3 additions & 0 deletions ports/stm32/boards/PYBV10/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ LD_FILES = boards/stm32f405.ld boards/common_ifs.ld
TEXT0_ADDR = 0x08000000
TEXT1_ADDR = 0x08020000
endif

# MicroPython settings
MICROPY_VFS_LFS2 = 1
3 changes: 3 additions & 0 deletions ports/stm32/boards/PYBV11/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ LD_FILES = boards/stm32f405.ld boards/common_ifs.ld
TEXT0_ADDR = 0x08000000
TEXT1_ADDR = 0x08020000
endif

# MicroPython settings
MICROPY_VFS_LFS2 = 1
40 changes: 40 additions & 0 deletions ports/stm32/flashbdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,4 +292,44 @@ bool flash_bdev_writeblock(const uint8_t *src, uint32_t block) {
return true;
}

int flash_bdev_readblocks_ext(uint8_t *dest, uint32_t block, uint32_t offset, uint32_t len) {
// Get data from flash memory, possibly via cache
while (len) {
uint32_t l = MIN(len, FLASH_BLOCK_SIZE - offset);
uint32_t flash_addr = convert_block_to_flash_addr(block);
if (flash_addr == -1) {
// bad block number
return -1;
}
uint8_t *src = flash_cache_get_addr_for_read(flash_addr + offset);
memcpy(dest, src, l);
dest += l;
block += 1;
offset = 0;
len -= l;
}
return 0;
}

int flash_bdev_writeblocks_ext(const uint8_t *src, uint32_t block, uint32_t offset, uint32_t len) {
// Copy to cache
while (len) {
uint32_t l = MIN(len, FLASH_BLOCK_SIZE - offset);
uint32_t flash_addr = convert_block_to_flash_addr(block);
if (flash_addr == -1) {
// bad block number
return -1;
}
uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access
uint8_t *dest = flash_cache_get_addr_for_write(flash_addr + offset);
memcpy(dest, src, l);
restore_irq_pri(basepri);
src += l;
block += 1;
offset = 0;
len -= l;
}
return 0;
}

#endif // MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE
51 changes: 48 additions & 3 deletions ports/stm32/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,13 @@
#include "lib/mp-readline/readline.h"
#include "lib/utils/pyexec.h"
#include "lib/oofatfs/ff.h"
#include "lib/littlefs/lfs1.h"
#include "lib/littlefs/lfs1_util.h"
#include "lib/littlefs/lfs2.h"
#include "lib/littlefs/lfs2_util.h"
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
#include "extmod/vfs_lfs.h"

#if MICROPY_PY_LWIP
#include "lwip/init.h"
Expand Down Expand Up @@ -183,13 +188,53 @@ MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) {
factory_reset_create_filesystem();
}

// Try to mount the flash on "/flash" and chdir to it for the boot-up directory.
// Default block device to entire flash storage
mp_obj_t bdev = MP_OBJ_FROM_PTR(&pyb_flash_obj);

#if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2

// Try to detect the block device used for the main filesystem, based on the first block

uint8_t buf[FLASH_BLOCK_SIZE];
storage_read_blocks(buf, FLASH_PART1_START_BLOCK, 1);

mp_int_t len = -1;

#if MICROPY_VFS_LFS1
if (memcmp(&buf[40], "littlefs", 8) == 0) {
// LFS1
lfs1_superblock_t *superblock = (void*)&buf[12];
uint32_t block_size = lfs1_fromle32(superblock->d.block_size);
uint32_t block_count = lfs1_fromle32(superblock->d.block_count);
len = block_count * block_size;
}
#endif

#if MICROPY_VFS_LFS2
if (memcmp(&buf[8], "littlefs", 8) == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these strings at magic locations part of the official lfs1/2 header formats?

If so, this chunk of code the check the format of the block device would be a good candidate to move to common place for all the ports to use!

Copy link
Member Author

Choose a reason for hiding this comment

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

I found them out by inspecting the littlefs code, the superblocks.

Can certainly move it to a common location for general use.

// LFS2
lfs2_superblock_t *superblock = (void*)&buf[20];
uint32_t block_size = lfs2_fromle32(superblock->block_size);
uint32_t block_count = lfs2_fromle32(superblock->block_count);
len = block_count * block_size;
}
#endif

if (len != -1) {
// Detected a littlefs filesystem so create correct block device for it
mp_obj_t args[] = { MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_NEW_SMALL_INT(len) };
bdev = pyb_flash_type.make_new(&pyb_flash_type, 2, 0, args);
}

#endif

// 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 = vfs_mount_and_chdir(bdev, mount_point);

if (ret == -MP_ENODEV && reset_mode != 3) {
// No filesystem (and didn't already create one), try to create a fresh one
if (ret == -MP_ENODEV && bdev == MP_OBJ_FROM_PTR(&pyb_flash_obj) && reset_mode != 3) {
// No filesystem, bdev is still the default (so didn't detect a possibly corrupt littlefs),
// and didn't already create a filesystem, so try to create a fresh one now.
ret = factory_reset_create_filesystem();
Copy link
Member
@jimmo jimmo Nov 19, 2019

Choose a reason for hiding this comment

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

I think there's a case here where the above code can detect LFS, but mount fails. In which case bdev will now be re-initialised by the len != -1 check above, but should now be reset back to the pyb_flash_obj singleton.

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed: this code will now only run if bdev==pyb_flash_obj, which reduces the chance that it will accidentally wipe a littlefs filesystem

if (ret == 0) {
ret = vfs_mount_and_chdir(bdev, mount_point);
Expand Down
7 changes: 7 additions & 0 deletions ports/stm32/moduos.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "extmod/misc.h"
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
#include "extmod/vfs_lfs.h"
#include "genhdr/mpversion.h"
#include "rng.h"
#include "usb.h"
Expand Down Expand Up @@ -174,6 +175,12 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
#if MICROPY_VFS_FAT
{ MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
#endif
#if MICROPY_VFS_LFS1
{ MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) },
#endif
#if MICROPY_VFS_LFS2
{ MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) },
#endif
};

STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
Expand Down
23 changes: 23 additions & 0 deletions ports/stm32/spibdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ int32_t spi_bdev_ioctl(spi_bdev_t *bdev, uint32_t op, uint32_t arg) {
restore_irq_pri(basepri);
}
return 0;

case BDEV_IOCTL_BLOCK_ERASE: {
uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access
mp_spiflash_erase_block(&bdev->spiflash, arg * MP_SPIFLASH_ERASE_BLOCK_SIZE);
restore_irq_pri(basepri);
return 0;
}
}
return -MP_EINVAL;
}
Expand All @@ -79,4 +86,20 @@ int spi_bdev_writeblocks(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_nu
return ret;
}

int spi_bdev_readblocks_raw(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uint32_t block_offset, uint32_t num_bytes) {
uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access
mp_spiflash_read(&bdev->spiflash, block_num * MP_SPIFLASH_ERASE_BLOCK_SIZE + block_offset, num_bytes, dest);
restore_irq_pri(basepri);

return 0;
}

int spi_bdev_writeblocks_raw(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t block_offset, uint32_t num_bytes) {
uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access
int ret = mp_spiflash_write(&bdev->spiflash, block_num * MP_SPIFLASH_ERASE_BLOCK_SIZE + block_offset, num_bytes, src);
restore_irq_pri(basepri);

return ret;
}

#endif
Loading
0