feat(fs): implement littlefs lfs.h driver support (#5562)

This commit is contained in:
GoT
2024-02-24 16:10:02 +01:00
committed by GitHub
parent 260333583f
commit 45a8af251a
15 changed files with 300 additions and 17 deletions

View File

@@ -1057,6 +1057,13 @@ menu "LVGL configuration"
default 0 default 0
depends on LV_USE_FS_MEMFS depends on LV_USE_FS_MEMFS
config LV_USE_FS_LITTLEFS
bool "File system on top of littlefs API"
config LV_FS_LITTLEFS_LETTER
int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65)"
default 0
depends on LV_USE_FS_LITTLEFS
config LV_USE_LODEPNG config LV_USE_LODEPNG
bool "PNG decoder library" bool "PNG decoder library"

View File

@@ -14,6 +14,7 @@ LVG has built in support for:
- POSIX (Linux and Windows using POSIX function .e.g ``open``, ``read``) - POSIX (Linux and Windows using POSIX function .e.g ``open``, ``read``)
- WIN32 (Windows using Win32 API function .e.g ``CreateFileA``, ``ReadFile``) - WIN32 (Windows using Win32 API function .e.g ``CreateFileA``, ``ReadFile``)
- MEMFS (read a file from a memory buffer) - MEMFS (read a file from a memory buffer)
- LITTLEFS (a little fail-safe filesystem designed for microcontrollers)
You still need to provide the drivers and libraries, this extension You still need to provide the drivers and libraries, this extension
provides only the bridge between FATFS, STDIO, POSIX, WIN32 and LVGL. provides only the bridge between FATFS, STDIO, POSIX, WIN32 and LVGL.

View File

@@ -22,3 +22,4 @@
rlottie rlottie
ffmpeg ffmpeg
rle rle
lfs

59
docs/libs/lfs.rst Normal file
View File

@@ -0,0 +1,59 @@
.. _lfs:
==============
littlefs
==============
littlefs is a little fail-safe filesystem designed for microcontrollers.
Detailed introduction: https://github.com/littlefs-project/littlefs
Usage
-----
Enable :c:macro:`LV_USE_FS_LITTLEFS` and define a :c:macro`LV_FS_LITTLEFS_LETTER` in ``lv_conf.h``.
When enabled :c:macro:`lv_littlefs_set_handler` can be used to set up a mount point.
Example
-------
.. code:: c
#include "lfs.h"
// configuration of the filesystem is provided by this struct
const struct lfs_config cfg = {
// block device operations
.read = user_provided_block_device_read,
.prog = user_provided_block_device_prog,
.erase = user_provided_block_device_erase,
.sync = user_provided_block_device_sync,
// block device configuration
.read_size = 16,
.prog_size = 16,
.block_size = 4096,
.block_count = 128,
.cache_size = 16,
.lookahead_size = 16,
.block_cycles = 500,
};
// mount the filesystem
int err = lfs_mount(&lfs, &cfg);
// reformat if we can't mount the filesystem
// this should only happen on the first boot
if (err) {
lfs_format(&lfs, &cfg);
lfs_mount(&lfs, &cfg);
}
lv_littlefs_set_handler(&lfs);
API
---

View File

@@ -64,7 +64,6 @@ void lv_port_fs_init(void)
* Register the file system interface in LVGL * Register the file system interface in LVGL
*--------------------------------------------------*/ *--------------------------------------------------*/
/*Add a simple drive to open images*/
static lv_fs_drv_t fs_drv; static lv_fs_drv_t fs_drv;
lv_fs_drv_init(&fs_drv); lv_fs_drv_init(&fs_drv);
@@ -195,8 +194,8 @@ static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs
/** /**
* Give the position of the read write pointer * Give the position of the read write pointer
* @param drv pointer to a driver where this function belongs * @param drv pointer to a driver where this function belongs
* @param file_p pointer to a file_t variable. * @param file_p pointer to a file_t variable
* @param pos_p pointer to to store the result * @param pos_p pointer to store the result
* @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum * @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
*/ */
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)

View File

@@ -641,6 +641,12 @@
#define LV_FS_MEMFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #define LV_FS_MEMFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#endif #endif
/*API for LittleFs. */
#define LV_USE_FS_LITTLEFS 0
#if LV_USE_FS_LITTLEFS
#define LV_FS_LITTLEFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#endif
/*LODEPNG decoder library*/ /*LODEPNG decoder library*/
#define LV_USE_LODEPNG 0 #define LV_USE_LODEPNG 0

View File

@@ -160,6 +160,10 @@ typedef struct _lv_global_t {
lv_fs_drv_t win32_fs_drv; lv_fs_drv_t win32_fs_drv;
#endif #endif
#if LV_USE_FS_LITTLEFS
lv_fs_drv_t littlefs_fs_drv;
#endif
#if LV_USE_FREETYPE #if LV_USE_FREETYPE
struct _lv_freetype_context_t * ft_context; struct _lv_freetype_context_t * ft_context;
#endif #endif

View File

@@ -62,7 +62,6 @@ void lv_fs_fatfs_init(void)
* Register the file system interface in LVGL * Register the file system interface in LVGL
*--------------------------------------------------*/ *--------------------------------------------------*/
/*Add a simple drive to open images*/
lv_fs_drv_t * fs_drv_p = &(LV_GLOBAL_DEFAULT()->fatfs_fs_drv); lv_fs_drv_t * fs_drv_p = &(LV_GLOBAL_DEFAULT()->fatfs_fs_drv);
lv_fs_drv_init(fs_drv_p); lv_fs_drv_init(fs_drv_p);
@@ -205,8 +204,8 @@ static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs
/** /**
* Give the position of the read write pointer * Give the position of the read write pointer
* @param drv pointer to a driver where this function belongs * @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FIL variable. * @param file_p pointer to a FIL variable
* @param pos_p pointer to to store the result * @param pos_p pointer to store the result
* @return LV_FS_RES_OK: no error, the file is read * @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum * any error from lv_fs_res_t enum
*/ */

View File

@@ -0,0 +1,188 @@
#include "../../../lvgl.h"
#if LV_USE_FS_LITTLEFS
#include "lfs.h"
#include "../../core/lv_global.h"
typedef struct LittleFile {
lfs_file_t file;
} LittleFile;
/**********************
* STATIC PROTOTYPES
**********************/
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode);
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p);
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw);
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence);
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p);
void lv_littlefs_set_handler(lfs_t * lfs)
{
lv_fs_drv_t * drv = lv_fs_get_drv(LV_FS_LITTLEFS_LETTER);
drv->user_data = lfs;
}
/**
* Register a driver for the LittleFS File System interface
*/
void lv_fs_littlefs_init(void)
{
lv_fs_drv_t * fs_drv = &(LV_GLOBAL_DEFAULT()->littlefs_fs_drv);
lv_fs_drv_init(fs_drv);
fs_drv->letter = LV_FS_LITTLEFS_LETTER;
fs_drv->open_cb = fs_open;
fs_drv->close_cb = fs_close;
fs_drv->read_cb = fs_read;
fs_drv->write_cb = fs_write;
fs_drv->seek_cb = fs_seek;
fs_drv->tell_cb = fs_tell;
fs_drv->dir_close_cb = NULL;
fs_drv->dir_open_cb = NULL;
fs_drv->dir_read_cb = NULL;
lv_fs_drv_register(fs_drv);
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Open a file
* @param drv pointer to a driver where this function belongs
* @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt)
* @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR
* @return a file descriptor or NULL on error
*/
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
{
LV_UNUSED(drv);
int flags;
if(mode == LV_FS_MODE_WR)
flags = LFS_O_WRONLY;
else if(mode == LV_FS_MODE_RD)
flags = LFS_O_RDONLY;
else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD))
flags = LFS_O_RDWR;
LittleFile * lf = (LittleFile *)lv_malloc(sizeof(LittleFile));
LV_ASSERT_NULL(lf);
lfs_t * lfs = (lfs_t *)drv->user_data;
int err = lfs_file_open(lfs, &lf->file, path, flags);
if(err) {
return NULL;
}
return (void *)lf;
}
/**
* Close an opened file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a file_t variable. (opened with fs_open)
* @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
*/
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p)
{
LV_UNUSED(drv);
LittleFile * lf = (LittleFile *)file_p;
lfs_t * lfs = (lfs_t *)drv->user_data;
lfs_file_close(lfs, &lf->file);
lv_free(lf);
return LV_FS_RES_OK;
}
/**
* Read data from an opened file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a file_t variable.
* @param buf pointer to a memory block where to store the read data
* @param btr number of Bytes To Read
* @param br the real number of read bytes (Byte Read)
* @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
*/
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br)
{
LV_UNUSED(drv);
LittleFile * lf = (LittleFile *)file_p;
lfs_t * lfs = (lfs_t *)drv->user_data;
*br = lfs_file_read(lfs, &lf->file, (uint8_t *)buf, btr);
return (int32_t)(*br) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
}
/**
* Write into a file
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a file_t variable
* @param buf pointer to a buffer with the bytes to write
* @param btw Bytes To Write
* @param bw the number of real written bytes (Bytes Written)
* @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
*/
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw)
{
LV_UNUSED(drv);
LittleFile * lf = (LittleFile *)file_p;
lfs_t * lfs = (lfs_t *)drv->user_data;
*bw = lfs_file_write(lfs, &lf->file, (uint8_t *)buf, btw);
return (int32_t)(*bw) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
}
/**
* Set the read write pointer. Also expand the file size if necessary.
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a file_t variable. (opened with fs_open )
* @param pos the new position of read write pointer
* @param whence tells from where to interpret the `pos`. See @lv_fs_whence_t
* @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
*/
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence)
{
LV_UNUSED(drv);
int mode;
if(whence == LV_FS_SEEK_SET)
mode = LFS_SEEK_SET;
else if(whence == LV_FS_SEEK_CUR)
mode = LFS_SEEK_CUR;
else if(whence == LV_FS_SEEK_END)
mode = LFS_SEEK_END;
LittleFile * lf = (LittleFile *)file_p;
lfs_t * lfs = (lfs_t *)drv->user_data;
int rc = lfs_file_seek(lfs, &lf->file, pos, mode);
return rc < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
}
/**
* Give the position of the read write pointer
* @param drv pointer to a driver where this function belongs
* @param file_p pointer to a file_p variable
* @param pos_p pointer to store the result
* @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
*/
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
{
LV_UNUSED(drv);
LittleFile * lf = (LittleFile *)file_p;
lfs_t * lfs = (lfs_t *)drv->user_data;
*pos_p = lfs_file_tell(lfs, &lf->file);
return (int32_t)(*pos_p) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
}
#endif

View File

@@ -84,7 +84,6 @@ void lv_fs_memfs_init(void)
* Register the file system interface in LVGL * Register the file system interface in LVGL
*--------------------------------------------------*/ *--------------------------------------------------*/
/*Add a simple drive to open images*/
lv_fs_drv_init(&fs_drv); lv_fs_drv_init(&fs_drv);
/*Set up fields...*/ /*Set up fields...*/
@@ -194,8 +193,8 @@ static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs
/** /**
* Give the position of the read write pointer * Give the position of the read write pointer
* @param drv pointer to a driver where this function belongs * @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable. * @param file_p pointer to a FILE variable
* @param pos_p pointer to to store the result * @param pos_p pointer to store the result
* @return LV_FS_RES_OK: no error, the file is read * @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum * any error from lv_fs_res_t enum
*/ */

View File

@@ -68,7 +68,6 @@ void lv_fs_posix_init(void)
* Register the file system interface in LVGL * Register the file system interface in LVGL
*--------------------------------------------------*/ *--------------------------------------------------*/
/*Add a simple drive to open images*/
lv_fs_drv_t * fs_drv_p = &(LV_GLOBAL_DEFAULT()->posix_fs_drv); lv_fs_drv_t * fs_drv_p = &(LV_GLOBAL_DEFAULT()->posix_fs_drv);
lv_fs_drv_init(fs_drv_p); lv_fs_drv_init(fs_drv_p);
@@ -200,8 +199,8 @@ static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs
/** /**
* Give the position of the read write pointer * Give the position of the read write pointer
* @param drv pointer to a driver where this function belongs * @param drv pointer to a driver where this function belongs
* @param file_p a file handle variable. * @param file_p a file handle variable
* @param pos_p pointer to to store the result * @param pos_p pointer to store the result
* @return LV_FS_RES_OK: no error, the file is read * @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum * any error from lv_fs_res_t enum
*/ */

View File

@@ -69,7 +69,6 @@ void lv_fs_stdio_init(void)
* Register the file system interface in LVGL * Register the file system interface in LVGL
*--------------------------------------------------*/ *--------------------------------------------------*/
/*Add a simple drive to open images*/
lv_fs_drv_t * fs_drv_p = &(LV_GLOBAL_DEFAULT()->stdio_fs_drv); lv_fs_drv_t * fs_drv_p = &(LV_GLOBAL_DEFAULT()->stdio_fs_drv);
lv_fs_drv_init(fs_drv_p); lv_fs_drv_init(fs_drv_p);
@@ -200,8 +199,8 @@ static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs
/** /**
* Give the position of the read write pointer * Give the position of the read write pointer
* @param drv pointer to a driver where this function belongs * @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable. * @param file_p pointer to a FILE variable
* @param pos_p pointer to to store the result * @param pos_p pointer to store the result
* @return LV_FS_RES_OK: no error, the file is read * @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum * any error from lv_fs_res_t enum
*/ */

View File

@@ -315,8 +315,8 @@ static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs
/** /**
* Give the position of the read write pointer * Give the position of the read write pointer
* @param drv pointer to a driver where this function belongs * @param drv pointer to a driver where this function belongs
* @param file_p pointer to a FILE variable. * @param file_p pointer to a FILE variable
* @param pos_p pointer to to store the result * @param pos_p pointer to store the result
* @return LV_FS_RES_OK: no error, the file is read * @return LV_FS_RES_OK: no error, the file is read
* any error from lv_fs_res_t enum * any error from lv_fs_res_t enum
*/ */

View File

@@ -2139,6 +2139,24 @@
#endif #endif
#endif #endif
/*API for LittleFs. */
#ifndef LV_USE_FS_LITTLEFS
#ifdef CONFIG_LV_USE_FS_LITTLEFS
#define LV_USE_FS_LITTLEFS CONFIG_LV_USE_FS_LITTLEFS
#else
#define LV_USE_FS_LITTLEFS 0
#endif
#endif
#if LV_USE_FS_LITTLEFS
#ifndef LV_FS_LITTLEFS_LETTER
#ifdef CONFIG_LV_FS_LITTLEFS_LETTER
#define LV_FS_LITTLEFS_LETTER CONFIG_LV_FS_LITTLEFS_LETTER
#else
#define LV_FS_LITTLEFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#endif
#endif
#endif
/*LODEPNG decoder library*/ /*LODEPNG decoder library*/
#ifndef LV_USE_LODEPNG #ifndef LV_USE_LODEPNG
#ifdef CONFIG_LV_USE_LODEPNG #ifdef CONFIG_LV_USE_LODEPNG

View File

@@ -265,6 +265,10 @@ void lv_init(void)
lv_fs_memfs_init(); lv_fs_memfs_init();
#endif #endif
#if LV_USE_FS_LITTLEFS
lv_fs_littlefs_init();
#endif
#if LV_USE_LODEPNG #if LV_USE_LODEPNG
lv_lodepng_init(); lv_lodepng_init();
#endif #endif