From 3a8f8db38d10a12ba84fc4a95ee0eef5306cd2c8 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Sun, 25 Feb 2024 15:44:49 +0100 Subject: [PATCH] ports/embed: Enable use of littlefs. To make use of it, as demonstrated in the embedding-full example: - Include the word(s) "littlefs1" and/or "littlefs2" in EMBED_EXTRA in micropython_embed.mk. - Enable the desired MICROPY_*VFS* features in mpconfigport.h. - Add include path "$(EMBED_DIR)/lib/littlefs" to your application build system. For demonstration, a block device implementation containing a small read-only littlefs2 image is added to the embedding-full example. The block device could have been written in C and interface to some external, possibly writable storage medium, but was written in Python and frozen for simplicity. What makes this a bit awkward is the fact that the littlefs sources are located in lib/ and do need to be compiled into the application, unlike all previous .c files from lib/ that are #included by other C files and must not be compiled separately. Therefore, introduce a new directory 'libsrc' in the embed build output that contains these files and can be added to the application build system as usual, while 'lib' can remain excluded. The headers need to stay in 'lib' because vfs_lfs.c refers to them under that path. I am also not entirely happy about having to add an additional include path to the application build, but see no way around that as long as vfs_lfs.c refers to "lib/littlefs/lfs2.h" while lfs2.c refers to "lfs2.h". Signed-off-by: Christian Walther --- examples/embedding-full/Makefile | 1 + examples/embedding-full/main.c | 11 +++++++- examples/embedding-full/manifest.py | 1 + examples/embedding-full/micropython_embed.mk | 3 +++ examples/embedding-full/modules/fsimage.py | 27 ++++++++++++++++++++ examples/embedding-full/mpconfigport.h | 6 +++++ extmod/modvfs.c | 6 +++++ ports/embed/embed.mk | 16 +++++++++++- 8 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 examples/embedding-full/modules/fsimage.py diff --git a/examples/embedding-full/Makefile b/examples/embedding-full/Makefile index abdf8866e0..abae7b71b8 100644 --- a/examples/embedding-full/Makefile +++ b/examples/embedding-full/Makefile @@ -12,6 +12,7 @@ PROG = embed CFLAGS += -I. CFLAGS += -I$(EMBED_DIR) CFLAGS += -I$(EMBED_DIR)/port +CFLAGS += -I$(EMBED_DIR)/lib/littlefs CFLAGS += -Wall -Og -fno-common SRC += main.c mphal.c modules/c_hello/modc_hello.c diff --git a/examples/embedding-full/main.c b/examples/embedding-full/main.c index f3002c9d6d..f8318ee7ed 100644 --- a/examples/embedding-full/main.c +++ b/examples/embedding-full/main.c @@ -52,12 +52,21 @@ static const char *example_2 = "import c_hello\n" "help(c_hello)\n" "print('c_hello.hello():', c_hello.hello())\n" + "import fsimage, vfs\n" + "vfs.mount(fsimage.BlockDev(), '/lfs', readonly=True)\n" + "print('os.listdir(\\'/lfs\\'):', os.listdir('/lfs'))\n" + "with open('/lfs/lfshello.py', 'rb') as f:\n" + " print('lfshello.py:', f.read())\n" + "sys.path.append('/lfs')\n" + "import lfshello\n" + "help(lfshello)\n" + "print('lfshello.hello():', lfshello.hello())\n" "\n" "print('finish')\n" ; // This array is the MicroPython GC heap. -static char heap[10 * 1024]; +static char heap[12 * 1024]; int main() { #if MICROPY_STACK_CHECK diff --git a/examples/embedding-full/manifest.py b/examples/embedding-full/manifest.py index 19c20cc7e7..69ca7adc21 100644 --- a/examples/embedding-full/manifest.py +++ b/examples/embedding-full/manifest.py @@ -1 +1,2 @@ module("frozenhello.py", base_path="modules") +module("fsimage.py", base_path="modules") diff --git a/examples/embedding-full/micropython_embed.mk b/examples/embedding-full/micropython_embed.mk index e21c88d1fe..881e4b11a4 100644 --- a/examples/embedding-full/micropython_embed.mk +++ b/examples/embedding-full/micropython_embed.mk @@ -19,6 +19,9 @@ EMBED_EXTRA += \ EMBED_EXTRA += \ shared/runtime/sys_stdio_mphal.c +# Include library sources for littlefs 2 in the output. +EMBED_EXTRA += littlefs2 + # Freeze Python modules. FROZEN_MANIFEST ?= manifest.py diff --git a/examples/embedding-full/modules/fsimage.py b/examples/embedding-full/modules/fsimage.py new file mode 100644 index 0000000000..46fbbd4c57 --- /dev/null +++ b/examples/embedding-full/modules/fsimage.py @@ -0,0 +1,27 @@ +# a minimal read-only block device containing a tiny littlefs image + + +class BlockDev: + def readblocks(self, block_num, buf, offset=0): + addr = block_num * 128 + offset + for i in range(len(buf)): + buf[i] = ( + b"\x03\x00\x00\x00\xf0\x0f\xff\xf7littlefs/\xe0\x00\x10\x01\x00\x02\x00\x80\x00\x00\x00\x03\x00\x00\x00" + b"\xff\x00\x00\x00\xff\xff\xff\x7f\xfe\x03\x00\x00 \x00\x04\x13lfshello.py 0\x00\x03\x02" + b"\x00\x00\x006\x00\x00\x00\x100\x00\x00\x00\xda#\xed=!\xb7\x17`\x1f\xf8!\x99\xf8T\x19\xff\xff\xff\xff\xff" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x02\x00\x00\x00\xf0\x0f\xff\xf7littlefs/\xe0\x00\x10\x01\x00\x02\x00\x80\x00\x00\x00\x03\x00\x00\x00" + b"\xff\x00\x00\x00\xff\xff\xff\x7f\xfe\x03\x00\x00\x7f\xef\xfc\x10 \x00\x00\x00R\xaa\xf5\xe6\x0f\xe0\x00\x0cq)\x81\xa1" + b"\x90\x0f\xf8\x04@\x00\x00\x0blfshello.py \x00\x00\x0bp\x1f\xf8%\x12\xbc\x179\xff" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b'def hello():\n return "Hello f' + b'rom a littlefs file!"\n\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + )[addr + i] + + def ioctl(self, op, arg): + if op == 4: # block count + return 3 + if op == 5: # block size + return 128 diff --git a/examples/embedding-full/mpconfigport.h b/examples/embedding-full/mpconfigport.h index bc326a35fd..59bbc2dbfa 100644 --- a/examples/embedding-full/mpconfigport.h +++ b/examples/embedding-full/mpconfigport.h @@ -19,6 +19,12 @@ #define MICROPY_HW_BOARD_NAME "embedded" #define MICROPY_HW_MCU_NAME "C" +// Enable the VFS subsystem, littlefs, importing from VFS, and the vfs module. +#define MICROPY_VFS (1) +#define MICROPY_VFS_LFS2 (1) +#define MICROPY_READER_VFS (1) +#define MICROPY_PY_VFS (1) + // Enable floating point numbers and the math module. #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) diff --git a/extmod/modvfs.c b/extmod/modvfs.c index 32dc0e5d08..611c19bab7 100644 --- a/extmod/modvfs.c +++ b/extmod/modvfs.c @@ -29,9 +29,15 @@ #if MICROPY_PY_VFS #include "extmod/vfs.h" +#if MICROPY_VFS_FAT #include "extmod/vfs_fat.h" +#endif +#if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2 #include "extmod/vfs_lfs.h" +#endif +#if MICROPY_VFS_POSIX #include "extmod/vfs_posix.h" +#endif #if !MICROPY_VFS #error "MICROPY_PY_VFS requires MICROPY_VFS" diff --git a/ports/embed/embed.mk b/ports/embed/embed.mk index bb39f3b529..cd63bc6bdb 100644 --- a/ports/embed/embed.mk +++ b/ports/embed/embed.mk @@ -17,7 +17,7 @@ include $(TOP)/extmod/extmod.mk endif # The parts of EMBED_EXTRA that name literal files and don't need special handling. -EMBED_EXTRA_FILES = $(filter-out extmod,$(EMBED_EXTRA)) +EMBED_EXTRA_FILES = $(filter-out extmod littlefs1 littlefs2,$(EMBED_EXTRA)) # Extra files need to be searched for QSTRs. SRC_QSTR += $(addprefix $(TOP)/,$(EMBED_EXTRA_FILES)) @@ -60,6 +60,9 @@ PACKAGE_DIR_LIST = $(addprefix $(PACKAGE_DIR)/,py extmod shared/runtime genhdr p ifeq ($(filter extmod,$(EMBED_EXTRA)),extmod) PACKAGE_DIR_LIST += $(addprefix $(PACKAGE_DIR)/,lib/uzlib lib/crypto-algorithms lib/re1.5) endif +ifneq ($(filter littlefs1 littlefs2,$(EMBED_EXTRA)),) +PACKAGE_DIR_LIST += $(addprefix $(PACKAGE_DIR)/,lib/littlefs libsrc/littlefs) +endif ifneq ($(FROZEN_MANIFEST),) PACKAGE_DIR_LIST += $(addprefix $(PACKAGE_DIR)/,frozen) endif @@ -83,6 +86,17 @@ ifeq ($(filter extmod,$(EMBED_EXTRA)),extmod) $(Q)$(CP) $(TOP)/lib/re1.5/*.[ch] $(PACKAGE_DIR)/lib/re1.5 else $(Q)$(CP) $(TOP)/extmod/modplatform.h $(PACKAGE_DIR)/extmod +endif +ifneq ($(filter littlefs1 littlefs2,$(EMBED_EXTRA)),) + $(ECHO) "- libsrc" +ifeq ($(filter littlefs1,$(EMBED_EXTRA)),littlefs1) + $(Q)$(CP) $(TOP)/lib/littlefs/lfs1*.h $(PACKAGE_DIR)/lib/littlefs + $(Q)$(CP) $(TOP)/lib/littlefs/lfs1*.c $(PACKAGE_DIR)/libsrc/littlefs +endif +ifeq ($(filter littlefs2,$(EMBED_EXTRA)),littlefs2) + $(Q)$(CP) $(TOP)/lib/littlefs/lfs2*.h $(PACKAGE_DIR)/lib/littlefs + $(Q)$(CP) $(TOP)/lib/littlefs/lfs2*.c $(PACKAGE_DIR)/libsrc/littlefs +endif endif $(ECHO) "- shared" $(Q)$(CP) $(TOP)/shared/runtime/gchelper.h $(PACKAGE_DIR)/shared/runtime