feat(fs): add caching option for lv_fs-read (#2979)

BREAKING CHANGE:
The `LV_FS_...` related configs needs to be updated.

Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
Adrian Schnyder 2022-01-24 20:52:25 +01:00 committed by Gabor Kiss-Vamosi
parent 4122dda399
commit abba1c351a
13 changed files with 414 additions and 96 deletions

36
Kconfig
View File

@ -869,29 +869,49 @@ menu "LVGL configuration"
menu "3rd Party Libraries"
config LV_USE_FS_STDIO
int "File system on top of stdio API"
default 0
bool "File system on top of stdio API"
config LV_FS_STDIO_LETTER
string "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65 )"
depends on LV_USE_FS_STDIO != 0
config LV_FS_STDIO_PATH
string "Set the working directory"
depends on LV_USE_FS_STDIO != 0
config LV_FS_STDIO_CACHE_SIZE
string ">0 to cache this number of bytes in lv_fs_read()"
depends on LV_USE_FS_STDIO != 0
config LV_USE_FS_POSIX
int "File system on top of posix API"
default 0
bool "File system on top of posix API"
config LV_FS_POSIX_LETTER
int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65)"
depends on LV_USE_FS_POSIX != 0
config LV_FS_POSIX_PATH
string "Set the working directory"
depends on LV_USE_FS_POSIX != 0
config LV_FS_POSIX_CACHE_SIZE
int ">0 to cache this number of bytes in lv_fs_read()"
depends on LV_USE_FS_POSIX != 0
config LV_USE_FS_WIN32
int "File system on top of Win32 API"
default 0
bool "File system on top of Win32 API"
config LV_FS_WIN32_LETTER
int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65)"
depends on LV_USE_FS_WIN32 != 0
config LV_FS_WIN32_PATH
string "Set the working directory"
depends on LV_USE_FS_WIN32 != 0
config LV_FS_WIN32_CACHE_SIZE
int ">0 to cache this number of bytes in lv_fs_read()"
depends on LV_USE_FS_WIN32 != 0
config LV_USE_FS_FATFS
int "File system on top of FatFS"
default 0
bool "File system on top of FatFS"
config LV_FS_FATFS_LETTER
int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65)"
depends on LV_USE_FS_FATFS != 0
config LV_FS_FATFS_CACHE_SIZE
int ">0 to cache this number of bytes in lv_fs_read()"
depends on LV_USE_FS_FATFS != 0
config LV_USE_PNG
bool "PNG decoder library"

View File

@ -21,6 +21,8 @@ static lv_fs_drv_t drv; /*Needs to be static or global*/
lv_fs_drv_init(&drv); /*Basic initialization*/
drv.letter = 'S'; /*An uppercase letter to identify the drive */
drv.cache_size = my_cahce_size; /*Cache size for reading in bytes. 0 to not cache.*/
drv.ready_cb = my_ready_cb; /*Callback to tell if the drive is ready to use */
drv.open_cb = my_open_cb; /*Callback to open a file */
drv.close_cb = my_close_cb; /*Callback to close a file */

View File

@ -9,7 +9,11 @@ void lv_example_bmp_1(void)
lv_obj_t * img = lv_img_create(lv_scr_act());
/* Assuming a File system is attached to letter 'A'
* E.g. set LV_USE_FS_STDIO 'A' in lv_conf.h */
#if LV_COLOR_DEPTH == 32
lv_img_set_src(img, "A:lvgl/examples/libs/bmp/example_32bit.bmp");
#elif LV_COLOR_DEPTH == 16
lv_img_set_src(img, "A:lvgl/examples/libs/bmp/example_16bit.bmp");
#endif
lv_obj_center(img);
}

View File

@ -567,18 +567,38 @@
* 3rd party libraries
*--------------------*/
/*File system interfaces for common APIs
*To enable set a driver letter for that API*/
#define LV_USE_FS_STDIO '\0' /*Uses fopen, fread, etc*/
//#define LV_FS_STDIO_PATH "/home/john/" /*Set the working directory. If commented it will be "./" */
/*File system interfaces for common APIs */
#define LV_USE_FS_POSIX '\0' /*Uses open, read, etc*/
//#define LV_FS_POSIX_PATH "/home/john/" /*Set the working directory. If commented it will be "./" */
/*API for fopen, fread, etc*/
#define LV_USE_FS_STDIO 0
#if LV_USE_FS_STDIO
#define LV_FS_STDIO_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths ill be appended to it.*/
#define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
#endif
#define LV_USE_FS_WIN32 '\0' /*Uses CreateFile, ReadFile, etc*/
//#define LV_FS_WIN32_PATH "C:\\Users\\john\\" /*Set the working directory. If commented it will be ".\\" */
/*API for open, read, etc*/
#define LV_USE_FS_POSIX 0
#if LV_USE_FS_POSIX
#define LV_FS_POSIX_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths ill be appended to it.*/
#define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
#endif
#define LV_USE_FS_FATFS '\0' /*Uses f_open, f_read, etc*/
/*API for CreateFile, ReadFile, etc*/
#define LV_USE_FS_WIN32 0
#if LV_USE_FS_WIN32
#define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory path ill be appended to it.*/
#define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
#endif
/*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/
#define LV_USE_FS_FATFS 0
#if LV_USE_FS_FATFS
#define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#define LV_FS_FATSF_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
#endif
/*PNG decoder library*/
#define LV_USE_PNG 0

View File

@ -141,6 +141,7 @@ static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t *
lv_fs_read(&b.f, header, 54, NULL);
if(0x42 != header[0] || 0x4d != header[1]) {
lv_fs_close(&b.f);
return LV_RES_INV;
}
@ -150,6 +151,26 @@ static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t *
memcpy(&b.bpp, header + 28, 2);
b.row_size_bytes = ((b.bpp * b.px_width + 31) / 32) * 4;
bool color_depth_error = false;
if(LV_COLOR_DEPTH == 32 && (b.bpp != 32 || b.bpp != 24)) {
LV_LOG_WARN("LV_COLOR_DEPTH == 32 but bpp is %d (should be 32 or 24)", b.bpp);
color_depth_error = true;
}
else if(LV_COLOR_DEPTH == 16 && b.bpp != 16) {
LV_LOG_WARN("LV_COLOR_DEPTH == 16 but bpp is %d (should be 16)", b.bpp);
color_depth_error = true;
}
else if(LV_COLOR_DEPTH == 8 && b.bpp != 8) {
LV_LOG_WARN("LV_COLOR_DEPTH == 8 but bpp is %d (should be 8)", b.bpp);
color_depth_error = true;
}
if(color_depth_error) {
dsc->error_msg = "Color depth mismatch";
lv_fs_close(&b.f);
return LV_RES_INV;
}
dsc->user_data = lv_mem_alloc(sizeof(bmp_dsc_t));
LV_ASSERT_MALLOC(dsc->user_data);
if(dsc->user_data == NULL) return LV_RES_INV;

View File

@ -8,13 +8,17 @@
*********************/
#include "../../../lvgl.h"
#if LV_USE_FS_FATFS != '\0'
#if LV_USE_FS_FATFS
#include "ff.h"
/*********************
* DEFINES
*********************/
#if LV_FS_FATFS_LETTER == '\0'
#error "LV_FS_FATFS_LETTER must be an upper case ASCII letter"
#endif
/**********************
* TYPEDEFS
**********************/
@ -62,7 +66,9 @@ void lv_fs_fatfs_init(void)
lv_fs_drv_init(&fs_drv);
/*Set up fields...*/
fs_drv.letter = LV_USE_FS_FATFS;
fs_drv.letter = LV_FS_FATFS_LETTER;
fs_drv.cache_size = LV_FS_FSTFS_CACHE_SIZE;
fs_drv.open_cb = fs_open;
fs_drv.close_cb = fs_close;
fs_drv.read_cb = fs_read;
@ -274,4 +280,11 @@ static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p)
return LV_FS_RES_OK;
}
#endif /*LV_USE_FS_FATFS*/
#else /*LV_USE_FS_FATFS == 0*/
#if defined(LV_FS_FATFS_LETTER) && LV_FS_FATFS_LETTER != '\0'
#warning "LV_USE_FS_FATFS is not enabled but LV_FS_FATFS_LETTER is set"
#endif
#endif /*LV_USE_FS_POSIX*/

View File

@ -8,7 +8,8 @@
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_FS_POSIX != '\0'
#if LV_USE_FS_POSIX
#include <fcntl.h>
#include <stdio.h>
@ -23,6 +24,10 @@
* DEFINES
*********************/
#if LV_FS_POSIX_LETTER == '\0'
#error "LV_FS_POSIX_LETTER must be an upper case ASCII letter"
#endif
/**********************
* TYPEDEFS
**********************/
@ -66,7 +71,9 @@ void lv_fs_posix_init(void)
lv_fs_drv_init(&fs_drv);
/*Set up fields...*/
fs_drv.letter = LV_USE_FS_POSIX;
fs_drv.letter = LV_FS_POSIX_LETTER;
fs_drv.cache_size = LV_FS_POSIX_CACHE_SIZE;
fs_drv.open_cb = fs_open;
fs_drv.close_cb = fs_close;
fs_drv.read_cb = fs_read;
@ -101,15 +108,11 @@ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
else if(mode == LV_FS_MODE_RD) flags = O_RDONLY;
else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = O_RDWR;
#ifdef LV_FS_POSIX_PATH
/*Make the path relative to the current directory (the projects root folder)*/
char buf[256];
sprintf(buf, LV_FS_POSIX_PATH "%s", path);
int f = open(buf, flags);
#else
int f = open(path, flags);
#endif
if(f < 0) return NULL;
return (void *)(lv_uintptr_t)f;
@ -207,25 +210,17 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path)
LV_UNUSED(drv);
#ifndef WIN32
# ifdef LV_FS_POSIX_PATH
/*Make the path relative to the current directory (the projects root folder)*/
char buf[256];
sprintf(buf, LV_FS_POSIX_PATH "%s", path);
return opendir(buf);
# else
return opendir(path);
# endif
#else
HANDLE d = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA fdata;
/*Make the path relative to the current directory (the projects root folder)*/
char buf[256];
# ifdef LV_FS_POSIX_PATH
sprintf(buf, LV_FS_POSIX_PATH "%s\\*", path);
# else
sprintf(buf, "%s\\*", path);
# endif
strcpy(next_fn, "");
d = FindFirstFile(buf, &fdata);
@ -314,5 +309,10 @@ static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p)
#endif
return LV_FS_RES_OK;
}
#else /*LV_USE_FS_POSIX == 0*/
#if defined(LV_FS_POSIX_LETTER) && LV_FS_POSIX_LETTER != '\0'
#warning "LV_USE_FS_POSIX is not enabled but LV_FS_POSIX_LETTER is set"
#endif
#endif /*LV_USE_FS_POSIX*/

View File

@ -65,7 +65,9 @@ void lv_fs_stdio_init(void)
lv_fs_drv_init(&fs_drv);
/*Set up fields...*/
fs_drv.letter = LV_USE_FS_STDIO;
fs_drv.letter = LV_FS_STDIO_LETTER;
fs_drv.cache_size = LV_FS_STDIO_CACHE_SIZE;
fs_drv.open_cb = fs_open;
fs_drv.close_cb = fs_close;
fs_drv.read_cb = fs_read;
@ -101,16 +103,12 @@ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
else if(mode == LV_FS_MODE_RD) flags = "rb";
else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = "rb+";
#ifdef LV_FS_STDIO_PATH
/*Make the path relative to the current directory (the projects root folder)*/
char buf[256];
sprintf(buf, LV_FS_STDIO_PATH "%s", path);
return fopen(buf, flags);
#else
return fopen(path, flags);
#endif
}
/**
@ -204,25 +202,17 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path)
{
LV_UNUSED(drv);
#ifndef WIN32
# ifdef LV_FS_STDIO_PATH
/*Make the path relative to the current directory (the projects root folder)*/
char buf[256];
sprintf(buf, LV_FS_STDIO_PATH "%s", path);
return opendir(buf);
# else
return opendir(path);
# endif
#else
HANDLE d = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA fdata;
/*Make the path relative to the current directory (the projects root folder)*/
char buf[256];
# ifdef LV_FS_STDIO_PATH
sprintf(buf, LV_FS_STDIO_PATH "%s\\*", path);
# else
sprintf(buf, "%s\\*", path);
# endif
strcpy(next_fn, "");
d = FindFirstFile(buf, &fdata);
@ -312,4 +302,11 @@ static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p)
return LV_FS_RES_OK;
}
#endif /*LV_USE_FS_STDIO*/
#else /*LV_USE_FS_STDIO == 0*/
#if defined(LV_FS_STDIO_LETTER) && LV_FS_STDIO_LETTER != '\0'
#warning "LV_USE_FS_STDIO is not enabled but LV_FS_STDIO_LETTER is set"
#endif
#endif /*LV_USE_FS_POSIX*/

View File

@ -63,7 +63,9 @@ void lv_fs_win32_init(void)
lv_fs_drv_init(&fs_drv);
/*Set up fields...*/
fs_drv.letter = LV_USE_FS_WIN32;
fs_drv.letter = LV_FS_WIN32_LETTER;
fs_drv.cache_size = LV_FS_WIN32_CACHE_SIZE;
fs_drv.open_cb = fs_open;
fs_drv.close_cb = fs_close;
fs_drv.read_cb = fs_read;
@ -208,19 +210,13 @@ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
desired_access |= GENERIC_WRITE;
}
#ifdef LV_FS_WIN32_PATH
/*Make the path relative to the current directory (the projects root folder)*/
char buf[MAX_PATH];
sprintf(buf, LV_FS_WIN32_PATH "%s", path);
#endif
return (void *)CreateFileA(
#ifdef LV_FS_WIN32_PATH
buf,
#else
path,
#endif
desired_access,
FILE_SHARE_READ,
NULL,
@ -449,4 +445,10 @@ static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p)
: fs_error_from_win32(GetLastError());
}
#endif /*LV_USE_FS_WIN32*/
#else /*LV_USE_FS_WIN32 == 0*/
#if defined(LV_FS_WIN32_LETTER) && LV_FS_WIN32_LETTER != '\0'
#warning "LV_USE_FS_WIN32 is not enabled but LV_FS_WIN32_LETTER is set"
#endif
#endif

View File

@ -1832,40 +1832,126 @@
* 3rd party libraries
*--------------------*/
/*File system interfaces for common APIs
*To enable set a driver letter for that API*/
/*File system interfaces for common APIs */
/*API for fopen, fread, etc*/
#ifndef LV_USE_FS_STDIO
#ifdef CONFIG_LV_USE_FS_STDIO
#define LV_USE_FS_STDIO CONFIG_LV_USE_FS_STDIO
#else
#define LV_USE_FS_STDIO '\0' /*Uses fopen, fread, etc*/
#define LV_USE_FS_STDIO 0
#endif
#endif
#if LV_USE_FS_STDIO
#ifndef LV_FS_STDIO_LETTER
#ifdef CONFIG_LV_FS_STDIO_LETTER
#define LV_FS_STDIO_LETTER CONFIG_LV_FS_STDIO_LETTER
#else
#define LV_FS_STDIO_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#endif
#endif
#ifndef LV_FS_STDIO_PATH
#ifdef CONFIG_LV_FS_STDIO_PATH
#define LV_FS_STDIO_PATH CONFIG_LV_FS_STDIO_PATH
#else
#define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths ill be appended to it.*/
#endif
#endif
#ifndef LV_FS_STDIO_CACHE_SIZE
#ifdef CONFIG_LV_FS_STDIO_CACHE_SIZE
#define LV_FS_STDIO_CACHE_SIZE CONFIG_LV_FS_STDIO_CACHE_SIZE
#else
#define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
#endif
#endif
#endif
//#define LV_FS_STDIO_PATH "/home/john/" /*Set the working directory. If commented it will be "./" */
/*API for open, read, etc*/
#ifndef LV_USE_FS_POSIX
#ifdef CONFIG_LV_USE_FS_POSIX
#define LV_USE_FS_POSIX CONFIG_LV_USE_FS_POSIX
#else
#define LV_USE_FS_POSIX '\0' /*Uses open, read, etc*/
#define LV_USE_FS_POSIX 0
#endif
#endif
#if LV_USE_FS_POSIX
#ifndef LV_FS_POSIX_LETTER
#ifdef CONFIG_LV_FS_POSIX_LETTER
#define LV_FS_POSIX_LETTER CONFIG_LV_FS_POSIX_LETTER
#else
#define LV_FS_POSIX_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#endif
#endif
#ifndef LV_FS_POSIX_PATH
#ifdef CONFIG_LV_FS_POSIX_PATH
#define LV_FS_POSIX_PATH CONFIG_LV_FS_POSIX_PATH
#else
#define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths ill be appended to it.*/
#endif
#endif
#ifndef LV_FS_POSIX_CACHE_SIZE
#ifdef CONFIG_LV_FS_POSIX_CACHE_SIZE
#define LV_FS_POSIX_CACHE_SIZE CONFIG_LV_FS_POSIX_CACHE_SIZE
#else
#define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
#endif
#endif
#endif
//#define LV_FS_POSIX_PATH "/home/john/" /*Set the working directory. If commented it will be "./" */
/*API for CreateFile, ReadFile, etc*/
#ifndef LV_USE_FS_WIN32
#ifdef CONFIG_LV_USE_FS_WIN32
#define LV_USE_FS_WIN32 CONFIG_LV_USE_FS_WIN32
#else
#define LV_USE_FS_WIN32 '\0' /*Uses CreateFile, ReadFile, etc*/
#define LV_USE_FS_WIN32 0
#endif
#endif
#if LV_USE_FS_WIN32
#ifndef LV_FS_WIN32_LETTER
#ifdef CONFIG_LV_FS_WIN32_LETTER
#define LV_FS_WIN32_LETTER CONFIG_LV_FS_WIN32_LETTER
#else
#define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#endif
#endif
#ifndef LV_FS_WIN32_PATH
#ifdef CONFIG_LV_FS_WIN32_PATH
#define LV_FS_WIN32_PATH CONFIG_LV_FS_WIN32_PATH
#else
#define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory path ill be appended to it.*/
#endif
#endif
#ifndef LV_FS_WIN32_CACHE_SIZE
#ifdef CONFIG_LV_FS_WIN32_CACHE_SIZE
#define LV_FS_WIN32_CACHE_SIZE CONFIG_LV_FS_WIN32_CACHE_SIZE
#else
#define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
#endif
#endif
#endif
//#define LV_FS_WIN32_PATH "C:\\Users\\john\\" /*Set the working directory. If commented it will be ".\\" */
/*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/
#ifndef LV_USE_FS_FATFS
#ifdef CONFIG_LV_USE_FS_FATFS
#define LV_USE_FS_FATFS CONFIG_LV_USE_FS_FATFS
#else
#define LV_USE_FS_FATFS '\0' /*Uses f_open, f_read, etc*/
#define LV_USE_FS_FATFS 0
#endif
#endif
#if LV_USE_FS_FATFS
#ifndef LV_FS_FATFS_LETTER
#ifdef CONFIG_LV_FS_FATFS_LETTER
#define LV_FS_FATFS_LETTER CONFIG_LV_FS_FATFS_LETTER
#else
#define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#endif
#endif
#ifndef LV_FS_FATSF_CACHE_SIZE
#ifdef CONFIG_LV_FS_FATSF_CACHE_SIZE
#define LV_FS_FATSF_CACHE_SIZE CONFIG_LV_FS_FATSF_CACHE_SIZE
#else
#define LV_FS_FATSF_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
#endif
#endif
#endif

View File

@ -8,24 +8,15 @@
*********************/
#include "lv_fs.h"
#include <string.h>
#include "lv_assert.h"
#include "../misc/lv_assert.h"
#include "lv_ll.h"
#include <string.h>
#include "lv_gc.h"
/*********************
* DEFINES
*********************/
/**
* "free" is used as a function pointer (in lv_fs_drv_t).
* We must make sure "free" was not defined to a platform specific
* free function, otherwise compilation would fail.
*/
#ifdef free
#undef free
#endif
/**********************
* TYPEDEFS
**********************/
@ -100,6 +91,12 @@ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mo
file_p->drv = drv;
file_p->file_d = file_d;
if(drv->cache_size) {
file_p->cache = lv_mem_alloc(sizeof(lv_fs_file_cache_t));
LV_ASSERT_MALLOC(file_p->cache);
lv_memset_00(file_p->cache, sizeof(lv_fs_file_cache_t));
}
return LV_FS_RES_OK;
}
@ -115,8 +112,91 @@ lv_fs_res_t lv_fs_close(lv_fs_file_t * file_p)
lv_fs_res_t res = file_p->drv->close_cb(file_p->drv, file_p->file_d);
if(file_p->drv->cache_size && file_p->cache) {
if(file_p->cache->buffer) {
lv_mem_free(file_p->cache->buffer);
}
lv_mem_free(file_p->cache);
}
file_p->file_d = NULL;
file_p->drv = NULL;
file_p->cache = NULL;
return res;
}
static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, char * buf, uint32_t btr, uint32_t * br)
{
lv_fs_res_t res = LV_FS_RES_OK;
uint32_t file_position = file_p->cache->file_position;
uint32_t start = file_p->cache->start;
uint32_t end = file_p->cache->end;
char * buffer = file_p->cache->buffer;
uint16_t buffer_size = file_p->drv->cache_size;
if(start <= file_position && file_position < end) {
/* Data can be read from cache buffer */
uint16_t buffer_offset = file_position - start;
uint16_t buffer_remaining_length = buffer_size - buffer_offset;
if(btr <= buffer_remaining_length) {
/*Data is in cache buffer, and buffer end not reached, no need to read from FS*/
lv_memcpy(buf, buffer + buffer_offset, btr);
}
else {
/*First part of data is in cache buffer, but we need to read rest of data from FS*/
lv_memcpy(buf, buffer + buffer_offset, buffer_remaining_length);
if(btr > buffer_size) {
/*If remaining data chuck is bigger than buffer size, then do not use cache, instead read it directly from FS*/
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)(buf + buffer_remaining_length),
btr - buffer_remaining_length, br);
}
else {
/*If remaining data chunk is smaller than buffer size, then read into cache buffer*/
uint32_t bytes_read_to_buffer = 0;
/*Read into cache buffer:*/
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)buffer, buffer_size, &bytes_read_to_buffer);
file_p->cache->start = file_p->cache->end + 1;
file_p->cache->end = file_p->cache->start + bytes_read_to_buffer;
uint16_t data_chunk_remaining = btr - buffer_remaining_length;
memcpy(buf + buffer_remaining_length, buffer, data_chunk_remaining);
}
}
}
else {
/*Data is not in cache buffer*/
if(btr > buffer_size) {
/*If bigger data is requested, then do not use cache, instead read it directly*/
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)buf, btr, br);
}
else {
/*If small data is requested, then read from FS into cache buffer*/
if(buffer == NULL) {
file_p->cache->buffer = lv_mem_alloc(buffer_size);
LV_ASSERT_MALLOC(file_p->cache->buffer);
buffer = file_p->cache->buffer;
}
uint32_t bytes_read_to_buffer = 0;
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)buffer, buffer_size, &bytes_read_to_buffer);
file_p->cache->start = file_position;
file_p->cache->end = file_p->cache->start + bytes_read_to_buffer;
memcpy(buf, buffer, btr);
}
}
if(res == LV_FS_RES_OK) {
*br = btr;
file_p->cache->file_position += btr;
}
return res;
}
@ -128,7 +208,15 @@ lv_fs_res_t lv_fs_read(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t
if(file_p->drv->read_cb == NULL) return LV_FS_RES_NOT_IMP;
uint32_t br_tmp = 0;
lv_fs_res_t res = file_p->drv->read_cb(file_p->drv, file_p->file_d, buf, btr, &br_tmp);
lv_fs_res_t res;
if(file_p->drv->cache_size) {
res = lv_fs_read_cached(file_p, (char *)buf, btr, &br_tmp);
}
else {
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, buf, btr, &br_tmp);
}
if(br != NULL) *br = br_tmp;
return res;
@ -163,22 +251,73 @@ lv_fs_res_t lv_fs_seek(lv_fs_file_t * file_p, uint32_t pos, lv_fs_whence_t whenc
return LV_FS_RES_NOT_IMP;
}
return file_p->drv->seek_cb(file_p->drv, file_p->file_d, pos, whence);
lv_fs_res_t res = LV_FS_RES_OK;
if(file_p->drv->cache_size) {
switch(whence) {
case LV_FS_SEEK_SET: {
file_p->cache->file_position = pos;
/*FS seek if new position is outside cache buffer*/
if(file_p->cache->file_position < file_p->cache->start || file_p->cache->file_position > file_p->cache->end) {
res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, file_p->cache->file_position, LV_FS_SEEK_SET);
}
break;
}
case LV_FS_SEEK_CUR: {
file_p->cache->file_position += pos;
/*FS seek if new position is outside cache buffer*/
if(file_p->cache->file_position < file_p->cache->start || file_p->cache->file_position > file_p->cache->end) {
res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, file_p->cache->file_position, LV_FS_SEEK_SET);
}
break;
}
case LV_FS_SEEK_END: {
/*Because we don't know the file size, we do a little trick: do a FS seek, then get new file position from FS*/
res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, pos, whence);
if(res == LV_FS_RES_OK) {
uint32_t tmp_position;
res = file_p->drv->tell_cb(file_p->drv, file_p->file_d, &tmp_position);
if(res == LV_FS_RES_OK) {
file_p->cache->file_position = tmp_position;
}
}
break;
}
}
}
else {
res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, pos, whence);
}
return res;
}
lv_fs_res_t lv_fs_tell(lv_fs_file_t * file_p, uint32_t * pos)
{
*pos = 0;
if(file_p->drv == NULL) {
*pos = 0;
return LV_FS_RES_INV_PARAM;
}
if(file_p->drv->tell_cb == NULL) {
*pos = 0;
return LV_FS_RES_NOT_IMP;
}
return file_p->drv->tell_cb(file_p->drv, file_p->file_d, pos);
lv_fs_res_t res;
if(file_p->drv->cache_size) {
*pos = file_p->cache->file_position;
res = LV_FS_RES_OK;
}
else {
res = file_p->drv->tell_cb(file_p->drv, file_p->file_d, pos);
}
return res;
}
lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path)
@ -217,17 +356,19 @@ lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path)
lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t * rddir_p, char * fn)
{
fn[0] = '\0';
if(rddir_p->drv == NULL || rddir_p->dir_d == NULL) {
fn[0] = '\0';
return LV_FS_RES_INV_PARAM;
}
if(rddir_p->drv->dir_read_cb == NULL) {
fn[0] = '\0';
return LV_FS_RES_NOT_IMP;
}
return rddir_p->drv->dir_read_cb(rddir_p->drv, rddir_p->dir_d, fn);
lv_fs_res_t res = rddir_p->drv->dir_read_cb(rddir_p->drv, rddir_p->dir_d, fn);
return res;
}
lv_fs_res_t lv_fs_dir_close(lv_fs_dir_t * rddir_p)
@ -296,10 +437,10 @@ const char * lv_fs_get_ext(const char * fn)
{
size_t i;
for(i = strlen(fn); i > 0; i--) {
if(fn[i - 1] == '.') {
return &fn[i];
if(fn[i] == '.') {
return &fn[i + 1];
}
else if(fn[i - 1] == '/' || fn[i - 1] == '\\') {
else if(fn[i] == '/' || fn[i] == '\\') {
return ""; /*No extension if a '\' or '/' found*/
}
}
@ -325,12 +466,11 @@ char * lv_fs_up(char * path)
size_t i;
for(i = len; i > 0; i--) {
if(path[i - 1] == '/' || path[i - 1] == '\\') {
path[i - 1] = '\0';
break;
}
if(path[i] == '/' || path[i] == '\\') break;
}
if(i > 0) path[i] = '\0';
return path;
}
@ -351,12 +491,14 @@ const char * lv_fs_get_last(const char * path)
size_t i;
for(i = len; i > 0; i--) {
if(path[i - 1] == '/' || path[i - 1] == '\\') break;
if(path[i] == '/' || path[i] == '\\') break;
}
return &path[i];
}
/*No '/' or '\' in the path so return with path itself*/
if(i == 0) return path;
return &path[i + 1];
}
/**********************
* STATIC FUNCTIONS
**********************/

View File

@ -69,6 +69,7 @@ typedef enum {
typedef struct _lv_fs_drv_t {
char letter;
uint16_t cache_size;
bool (*ready_cb)(struct _lv_fs_drv_t * drv);
void * (*open_cb)(struct _lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode);
@ -87,9 +88,17 @@ typedef struct _lv_fs_drv_t {
#endif
} lv_fs_drv_t;
typedef struct {
uint32_t start;
uint32_t end;
uint32_t file_position;
void * buffer;
} lv_fs_file_cache_t;
typedef struct {
void * file_d;
lv_fs_drv_t * drv;
lv_fs_file_cache_t * cache;
} lv_fs_file_t;
typedef struct {

View File

@ -180,8 +180,10 @@ set(LVGL_TEST_OPTIONS_FULL_32BIT
-DLV_LABEL_TEXT_SELECTION=1
${LVGL_TEST_COMMON_EXAMPLE_OPTIONS}
-DLV_FONT_DEFAULT=&lv_font_montserrat_24
-DLV_USE_FS_STDIO='A'
-DLV_USE_FS_POSIX='B'
-DLV_USE_FS_STDIO=1
-DLV_FS_STDIO_LETTER='A'
-DLV_USE_FS_POSIX=1
-DLV_FS_POSIX_LETTER='B'
-DLV_USE_PNG=1
-DLV_USE_BMP=1
-DLV_USE_SJPG=1