Skip to content

Commit

Permalink
nrf: Add LittleFS support to nrf52840.
Browse files Browse the repository at this point in the history
To be amended / split / squashed.

LittleFS can be enabled by MICROPY_VFS_LFS1 or MICROPY_VFS_LFS2.

Added support for setting MICROPY_VFS_FAT=0.

Added support for configuring file system size rom makefile invocation.
New parameter `FS_SIZE` can be used to adjust the size of requested partition
for internal flash storage. For example `FS_SIZE=0x40000` or `FS_SIZE=256K`.
  • Loading branch information
glennrub committed Jan 18, 2020
1 parent 7778b99 commit e65941b
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 24 deletions.
6 changes: 5 additions & 1 deletion ports/nrf/Makefile
Expand Up @@ -38,12 +38,13 @@ endif
# qstr definitions (must come before including py.mk)
QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h

MICROPY_VFS_FAT ?= 0

# include py core make definitions
include ../../py/py.mk

GIT_SUBMODULES = lib/nrfx lib/tinyusb

MICROPY_VFS_FAT ?= 0
MPY_CROSS = ../../mpy-cross/mpy-cross
MPY_TOOL = ../../tools/mpy-tool.py

Expand Down Expand Up @@ -118,6 +119,9 @@ LDFLAGS = $(CFLAGS)
LDFLAGS += -Xlinker -Map=$(@:.elf=.map)
LDFLAGS += -mthumb -mabi=aapcs $(addprefix -T,$(LD_FILES)) -L boards/

FS_SIZE ?= 256K
LDFLAGS += -Wl,'--defsym=_fs_size=$(FS_SIZE)'

#Debugging/Optimization
ifeq ($(DEBUG), 1)
#ASMFLAGS += -g -gtabs+
Expand Down
28 changes: 28 additions & 0 deletions ports/nrf/README.md
Expand Up @@ -114,6 +114,34 @@ For example:

make BOARD=pca10040 MICROPY_VFS_FAT=1

## Enable MICROPY_VFS_LFS1 or MICROPY_VFS_LFS2

In order to enable `littlefs` as device flash filesystem, `MICROPY_VFS_LFS1`
or `MICROPY_VFS_LFS2` can be set. This will be in addition of setting
`MICROPY_VFS` in mpconfigport.h or mpconfigboard.h.

For example:

make BOARD=pca10056 MICROPY_VFS_LFS=2

## Set file system size

The size of the file system on the internal flash is configured by the linker
script parameter `_fs_size`. This can either be overriden by the linker script
or dynamically through the makefile. By seting a value to the `FS_SIZE`.
The number will be passed directly to the linker scripts in order to calculate
the start and end of the file system. Note that the parameter value must be in
linker script syntax as it is passed directly.

For example, if we want to override the default 64K file system size set by the
linker scripts to use 256K instead:

make BOARD=pca10056 MICROPY_VFS_LFS2=1 FS_SIZE=256K

Also note that changing this size between builds might cause loss of files
present from a previous firmware as it will format the file system due to a new
location.

## Target Boards and Make Flags

Target Board (BOARD) | Bluetooth Stack (SD) | Bluetooth Support | Flash Util
Expand Down
1 change: 0 additions & 1 deletion ports/nrf/boards/nrf52840_1M_256k.ld
Expand Up @@ -4,7 +4,6 @@

_flash_size = 1M;
_ram_size = 256K;
_fs_size = 256K;
/* produce a link error if there is not this amount of RAM for these sections */
_stack_size = 8K;
_minimum_heap_size = 128K;
1 change: 1 addition & 0 deletions ports/nrf/boards/pca10056/mpconfigboard.h
Expand Up @@ -41,6 +41,7 @@
#define MICROPY_VFS (1)
#define MICROPY_HW_ENABLE_STORAGE (1)
#define MICROPY_MBFS (0)
#define MICROPY_HW_BDEV_READBLOCKS_EXT (1)

#define MICROPY_HW_HAS_LED (1)
#define MICROPY_HW_LED_COUNT (4)
Expand Down
18 changes: 16 additions & 2 deletions ports/nrf/main.c
Expand Up @@ -128,8 +128,9 @@ STATIC int vfs_mount_and_chdir(mp_obj_t bdev, mp_obj_t mount_point) {
}

int factory_reset_filesystem(void) {
#if MICROPY_VFS_FAT
fs_user_mount_t vfs;
flash_init_vfs(&vfs);
flash_init_vfs_fat(&vfs);
uint8_t working_buf[FF_MAX_SS];
FRESULT res = f_mkfs(&vfs.fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf));
if (res != FR_OK) {
Expand All @@ -139,6 +140,19 @@ int factory_reset_filesystem(void) {

// Set label
f_setlabel(&vfs.fatfs, MICROPY_HW_FLASH_FS_LABEL);
#endif
#if MICROPY_VFS_LFS1
// Setup builtin flash
do_str("import uos, nrf\n" \
"uos.VfsLfs1.mkfs(nrf.flashbdev)",
MP_PARSE_FILE_INPUT);
#endif
#if MICROPY_VFS_LFS2
// Setup builtin flash
do_str("import uos, nrf\n" \
"uos.VfsLfs2.mkfs(nrf.flashbdev)",
MP_PARSE_FILE_INPUT);
#endif
return 0;
}
#endif
Expand Down Expand Up @@ -217,7 +231,7 @@ int main(int argc, char **argv) {
mp_obj_t mount_point = MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash);
int ret = vfs_mount_and_chdir((mp_obj_t)&nrf_flashbdev_obj, mount_point);

if (ret == -MP_ENODEV) {
if ((ret == -MP_ENODEV) || (ret == -MP_EIO)) {
ret = factory_reset_filesystem();
if (ret == 0) {
ret = vfs_mount_and_chdir((mp_obj_t)&nrf_flashbdev_obj, mount_point);
Expand Down
60 changes: 41 additions & 19 deletions ports/nrf/modules/uos/modnrf.c
Expand Up @@ -28,6 +28,7 @@
#include <stdio.h>
#include <stdint.h>
#include "py/runtime.h"
#include "py/mperrno.h"
#include "mpconfigboard.h"

#if MICROPY_HW_ENABLE_STORAGE
Expand All @@ -41,6 +42,7 @@ extern byte _fs_end[];

#define FLASH_BLOCK_START (((uint32_t)_fs_start + (FLASH_PAGESIZE-1)) / FLASH_PAGESIZE)

#if MICROPY_VFS_FAT
static int nrf_flashbdev_readblocks_native(uint8_t *buf, size_t block_num, size_t num_blocks) {
mp_int_t address = (FLASH_BLOCK_START + block_num) * FLASH_PAGESIZE;
byte *p = (byte*)address;
Expand All @@ -61,41 +63,51 @@ static int nrf_flashbdev_writeblocks_native(const uint8_t *buf, size_t block_num
}
return 0;
}
#endif

mp_obj_t nrf_flashbdev_readblocks(mp_obj_t self_in, mp_obj_t n_in, mp_obj_t buf_in) {

mp_int_t n = mp_obj_get_int(n_in);
mp_obj_t nrf_flashbdev_readblocks(size_t n_args, const mp_obj_t * args) {
uint32_t block_num = mp_obj_get_int(args[1]);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE);

mp_int_t address = (FLASH_BLOCK_START + block_num) * FLASH_PAGESIZE;

#if defined(MICROPY_HW_BDEV_READBLOCKS_EXT)
if (n_args == 4) {
uint32_t offset = mp_obj_get_int(args[3]);
address += offset;
}
#endif

mp_int_t address = (FLASH_BLOCK_START + n) * FLASH_PAGESIZE;
byte *buf = bufinfo.buf;
byte *p = (byte*)address;
for (int i=0; i<bufinfo.len; i++) {
byte *p = (byte *)address;
for (int i = 0; i < bufinfo.len; i++) {
buf[i] = p[i];
}

return MP_OBJ_NEW_SMALL_INT(0);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(nrf_flashbdev_readblocks_obj, nrf_flashbdev_readblocks);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(nrf_flashbdev_readblocks_obj, 3, 4, nrf_flashbdev_readblocks);

mp_obj_t nrf_flashbdev_writeblocks(mp_obj_t self_in, mp_obj_t n_in, mp_obj_t buf_in) {
mp_int_t n = mp_obj_get_int(n_in);
mp_obj_t nrf_flashbdev_writeblocks(size_t n_args, const mp_obj_t * args) {
uint32_t block_num = mp_obj_get_int(args[1]);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE);

mp_int_t address = (FLASH_BLOCK_START + n) * FLASH_PAGESIZE;
if (address & 0x3 || bufinfo.len & 0x3) {
mp_raise_ValueError("invalid address or buffer length");
}
mp_int_t address = (FLASH_BLOCK_START + block_num) * FLASH_PAGESIZE;

flash_page_erase(address);
#if defined(MICROPY_HW_BDEV_READBLOCKS_EXT)
if (n_args == 4) {
uint32_t offset = mp_obj_get_int(args[3]);
address += offset;
}
#endif

flash_write_bytes(address, bufinfo.buf, bufinfo.len);

return MP_OBJ_NEW_SMALL_INT(0);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(nrf_flashbdev_writeblocks_obj, nrf_flashbdev_writeblocks);

STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(nrf_flashbdev_writeblocks_obj, 3, 4, nrf_flashbdev_writeblocks);

mp_obj_t nrf_flashbdev_ioctl(mp_obj_t self_in, mp_obj_t op_in, mp_obj_t arg_in) {
mp_int_t op = mp_obj_get_int(op_in);
Expand Down Expand Up @@ -123,6 +135,14 @@ mp_obj_t nrf_flashbdev_ioctl(mp_obj_t self_in, mp_obj_t op_in, mp_obj_t arg_in)
}

case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: {
mp_int_t block_num = mp_obj_get_int(arg_in);
mp_int_t address = (FLASH_BLOCK_START + block_num) * FLASH_PAGESIZE;

if ((address & 0x3) || (address % FLASH_PAGESIZE != 0)) {
return MP_OBJ_NEW_SMALL_INT(-MP_EIO);
}

flash_page_erase(address);
return MP_OBJ_NEW_SMALL_INT(0);
}

Expand Down Expand Up @@ -164,7 +184,8 @@ const mp_obj_module_t nrf_module = {
.globals = (mp_obj_dict_t*)&nrf_module_globals,
};

void flash_init_vfs(fs_user_mount_t *vfs) {
#if MICROPY_VFS_FAT
void flash_init_vfs_fat(fs_user_mount_t *vfs) {
vfs->base.type = &mp_fat_vfs_type;

vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_HAVE_IOCTL;
Expand All @@ -185,5 +206,6 @@ void flash_init_vfs(fs_user_mount_t *vfs) {
vfs->blockdev.u.ioctl[0] = MP_OBJ_FROM_PTR(&nrf_flashbdev_ioctl_obj);
vfs->blockdev.u.ioctl[1] = MP_OBJ_FROM_PTR(&nrf_flashbdev_obj);
}
#endif

#endif // MICROPY_PY_NRF
2 changes: 1 addition & 1 deletion ports/nrf/modules/uos/modnrf.h
Expand Up @@ -37,6 +37,6 @@ typedef struct {

extern const mp_obj_type_t nrf_flashbdev_obj;

void flash_init_vfs(fs_user_mount_t *vfs);
void flash_init_vfs_fat(fs_user_mount_t *vfs);

#endif // MODNRF_H__
11 changes: 11 additions & 0 deletions ports/nrf/modules/uos/moduos.c
Expand Up @@ -36,6 +36,7 @@
#include "modules/uos/microbitfs.h"
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
#include "extmod/vfs_lfs.h"
#include "genhdr/mpversion.h"
//#include "timeutils.h"
#include "uart.h"
Expand Down Expand Up @@ -87,10 +88,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname);
/// \function sync()
/// Sync all filesystems.
STATIC mp_obj_t os_sync(void) {
#if MICROPY_VFS_FAT
for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) {
// this assumes that vfs->obj is fs_user_mount_t with block device functions
disk_ioctl(MP_OBJ_TO_PTR(vfs->obj), CTRL_SYNC, NULL);
}
#endif
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_0(mod_os_sync_obj, os_sync);
Expand Down Expand Up @@ -176,8 +179,16 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
#if MICROPY_VFS
{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) },
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) },
#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
#endif
};

STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
Expand Down

0 comments on commit e65941b

Please sign in to comment.