mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-14 06:42:58 +08:00
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:
parent
4122dda399
commit
abba1c351a
36
Kconfig
36
Kconfig
@ -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"
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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*/
|
||||
|
||||
|
@ -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*/
|
||||
|
@ -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*/
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
200
src/misc/lv_fs.c
200
src/misc/lv_fs.c
@ -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
|
||||
**********************/
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user