feat(fs): default drive letter + ESP FS docs (#6367)

Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
becseya
2024-08-21 11:47:29 +02:00
committed by GitHub
parent 5f7a5605cd
commit a476098fcc
24 changed files with 333 additions and 39 deletions

View File

@@ -597,6 +597,9 @@
/*File system interfaces for common APIs */ /*File system interfaces for common APIs */
/*Setting a default driver letter allows skipping the driver prefix in filepaths*/
#define LV_FS_DEFAULT_DRIVE_LETTER '\0'
/*API for fopen, fread, etc*/ /*API for fopen, fread, etc*/
#define LV_USE_FS_STDIO 1 #define LV_USE_FS_STDIO 1
#if LV_USE_FS_STDIO #if LV_USE_FS_STDIO

22
Kconfig
View File

@@ -1124,10 +1124,16 @@ menu "LVGL configuration"
endmenu endmenu
menu "3rd Party Libraries" menu "3rd Party Libraries"
config LV_FS_DEFAULT_DRIVE_LETTER
int "Default drive letter (e.g. 65 for 'A')"
default 0
help
Setting a default drive letter allows skipping the driver prefix in filepaths
config LV_USE_FS_STDIO config LV_USE_FS_STDIO
bool "File system on top of stdio API" bool "File system on top of stdio API"
config LV_FS_STDIO_LETTER config LV_FS_STDIO_LETTER
int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65 )" int "Set an upper cased letter on which the drive will accessible (e.g. 65 for 'A')"
default 0 default 0
depends on LV_USE_FS_STDIO depends on LV_USE_FS_STDIO
config LV_FS_STDIO_PATH config LV_FS_STDIO_PATH
@@ -1141,7 +1147,7 @@ menu "LVGL configuration"
config LV_USE_FS_POSIX config LV_USE_FS_POSIX
bool "File system on top of posix API" bool "File system on top of posix API"
config LV_FS_POSIX_LETTER config LV_FS_POSIX_LETTER
int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65)" int "Set an upper cased letter on which the drive will accessible (e.g. 65 for 'A')"
default 0 default 0
depends on LV_USE_FS_POSIX depends on LV_USE_FS_POSIX
config LV_FS_POSIX_PATH config LV_FS_POSIX_PATH
@@ -1155,7 +1161,7 @@ menu "LVGL configuration"
config LV_USE_FS_WIN32 config LV_USE_FS_WIN32
bool "File system on top of Win32 API" bool "File system on top of Win32 API"
config LV_FS_WIN32_LETTER config LV_FS_WIN32_LETTER
int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65)" int "Set an upper cased letter on which the drive will accessible (e.g. 65 for 'A')"
default 0 default 0
depends on LV_USE_FS_WIN32 depends on LV_USE_FS_WIN32
config LV_FS_WIN32_PATH config LV_FS_WIN32_PATH
@@ -1169,7 +1175,7 @@ menu "LVGL configuration"
config LV_USE_FS_FATFS config LV_USE_FS_FATFS
bool "File system on top of FatFS" bool "File system on top of FatFS"
config LV_FS_FATFS_LETTER config LV_FS_FATFS_LETTER
int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65)" int "Set an upper cased letter on which the drive will accessible (e.g. 65 for 'A')"
default 0 default 0
depends on LV_USE_FS_FATFS depends on LV_USE_FS_FATFS
config LV_FS_FATFS_CACHE_SIZE config LV_FS_FATFS_CACHE_SIZE
@@ -1180,28 +1186,28 @@ menu "LVGL configuration"
config LV_USE_FS_MEMFS config LV_USE_FS_MEMFS
bool "File system on top of memory-mapped API" bool "File system on top of memory-mapped API"
config LV_FS_MEMFS_LETTER config LV_FS_MEMFS_LETTER
int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65)" int "Set an upper cased letter on which the drive will accessible (e.g. 65 for 'A')"
default 0 default 0
depends on LV_USE_FS_MEMFS depends on LV_USE_FS_MEMFS
config LV_USE_FS_LITTLEFS config LV_USE_FS_LITTLEFS
bool "File system on top of littlefs API" bool "File system on top of littlefs API"
config LV_FS_LITTLEFS_LETTER config LV_FS_LITTLEFS_LETTER
int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65)" int "Set an upper cased letter on which the drive will accessible (e.g. 65 for 'A')"
default 0 default 0
depends on LV_USE_FS_LITTLEFS depends on LV_USE_FS_LITTLEFS
config LV_USE_FS_ARDUINO_ESP_LITTLEFS config LV_USE_FS_ARDUINO_ESP_LITTLEFS
bool "File system on top of Arduino ESP littlefs API" bool "File system on top of Arduino ESP littlefs API"
config LV_FS_ARDUINO_ESP_LITTLEFS_LETTER config LV_FS_ARDUINO_ESP_LITTLEFS_LETTER
int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65)" int "Set an upper cased letter on which the drive will accessible (e.g. 65 for 'A')"
default 0 default 0
depends on LV_USE_FS_ARDUINO_ESP_LITTLEFS depends on LV_USE_FS_ARDUINO_ESP_LITTLEFS
config LV_USE_FS_ARDUINO_SD config LV_USE_FS_ARDUINO_SD
bool "File system on top of Arduino SD API" bool "File system on top of Arduino SD API"
config LV_FS_ARDUINO_SD_LETTER config LV_FS_ARDUINO_SD_LETTER
int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65)" int "Set an upper cased letter on which the drive will accessible (e.g. 65 for 'A')"
default 0 default 0
depends on LV_USE_FS_ARDUINO_SD depends on LV_USE_FS_ARDUINO_SD
config LV_FS_ARDUINO_SD_CS_PIN config LV_FS_ARDUINO_SD_CS_PIN

View File

@@ -78,5 +78,120 @@ These components share a common public API, making it easy to migrate your proje
To add a display or touch driver to your project, use a command like: To add a display or touch driver to your project, use a command like:
.. code:: sh .. code:: sh
idf.py add-dependency "espressif/esp_lcd_gc9a01^2.0.0" idf.py add-dependency "espressif/esp_lcd_gc9a01^2.0.0"
Using the File System under ESP-IDF
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ESP-IDF uses the standard C functions (``fopen``, ``fread``) in all storage related APIs.
This allows seamless interoperability with LVGL when enabling the :c:macro:`LV_USE_FS_STDIO` configuration.
The process is described in details below, using ``SPIFFS`` as demonstration.
- **Decide what storage system you want to use**
ESP-IDF has many, ready-to-use examples like
`SPIFFS <https://github.com/espressif/esp-idf/tree/master/examples/storage/spiffsgen>`__
,
`SD Card <https://github.com/espressif/esp-idf/tree/master/examples/storage/sd_card/sdspi>`__
and
`LittleFS <https://github.com/espressif/esp-idf/tree/master/examples/storage/littlefs>`__
.
- **Re-configure your own project**
The example project should be examined for details, but in general the changes involve:
- Enabling LVGL's STDIO file system in the configuration
You can use ``menuconfig``:
- ``Component config → LVGL configuration → 3rd Party Libraries``: enable ``File system on top of stdio API``
- Then select ``Set an upper cased letter on which the drive will accessible`` and set it to ``65`` (ASCII **A**)
- You can also set ``Default driver letter`` to 65 to skip the prefix in file paths.
- Modifying the partition table
The exact configuration depends on your flash size and existing partitions,
but the new final result should look something like this:
.. code:: csv
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1400k,
storage, data, spiffs, , 400k,
.. note::
If you are not using a custom ``parition.csv`` yet, it can be added
via ``menuconfig`` (``Partition Table → Partition Table → Custom partition table CSV``).
- Apply changes to the build system
Some ESP file systems provide automatic generation from a host folder using CMake. The proper line(s) must be copied to ``main/CMakeLists.txt``
.. note::
``LittleFS`` has extra dependencies that should be added to ``main/idf_component.yml``
- **Prepare the image files**
LVGL's ``LVGLImage.py`` Python tool can be used to convert images to binary pixel map files.
It supports various formats and compression.
Meanwhile 3rd party libraries
(like :ref:`LodePNG<lodepng>` and :ref:`Tiny JPEG<tjpgd>`)
allow using image files without conversion.
After preparing the files, they should be moved to the target device:
- If properly activated a **SPIFFS** file system based on the ``spiffs_image`` folder should be automatically generated and later flashed to the target
- Similar mechanism for **LittleFS** uses the ``flash_data`` folder, but it's only available for Linux hosts
- For the **SD Card**, a traditional file browser can be used
- **Invoke proper API calls in the application code**
The core functionality requires only a few lines. The following example draws the image as well.
.. code:: c
#include "esp_spiffs.h"
void lv_example_image_from_esp_fs(void) {
esp_vfs_spiffs_conf_t conf = {
.base_path = "/spiffs",
.partition_label = NULL,
.max_files = 5,
.format_if_mount_failed = false
};
esp_err_t ret = esp_vfs_spiffs_register(&conf);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to register SPIFF filesystem");
return;
}
lv_obj_t * obj = lv_image_create(lv_screen_active());
lv_image_set_src(obj, "A:/spiffs/logo.bin");
lv_obj_center(obj);
}
- **Build and flash**
After calling ``idf.py build flash`` the picture should be displayed on the screen.
.. note::
Changes made by ``menuconfig`` are not being tracked in the repository if the ``sdkconfig`` file is added to ``.gitignore``, which is the default for many ESP-IDF projects.
To make your configuration permanent, add the following lines to ``sdkconfig.defaults``:
.. code:: c
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_LV_USE_FS_STDIO=y
CONFIG_LV_FS_STDIO_LETTER=65
CONFIG_LV_LV_FS_DEFAULT_DRIVE_LETTER=65

View File

@@ -16,7 +16,7 @@ Using the simulator on a PC has the following advantages:
- Easy Validation: The simulator is also very useful to report bugs because it - Easy Validation: The simulator is also very useful to report bugs because it
provides a common platform for every user. provides a common platform for every user.
- Better developer experience: On PC Debuggers are usually faster and better, you can log to files, - Better developer experience: On PC Debuggers are usually faster and better, you can log to files,
add a lot of ``printf``s, do profiling, and so on. add a lot of ``printf``-s, do profiling, and so on.
Select an IDE Select an IDE

View File

@@ -8,6 +8,7 @@ LittleFS is a little fail-safe filesystem designed for microcontrollers and inte
when used with ESP32 and ESP8266. when used with ESP32 and ESP8266.
Detailed introduction: Detailed introduction:
- https://github.com/esp8266/Arduino - https://github.com/esp8266/Arduino
- https://github.com/espressif/arduino-esp32 - https://github.com/espressif/arduino-esp32
@@ -15,7 +16,7 @@ Detailed introduction:
Usage Usage
----- -----
Enable :c:macro:`LV_USE_FS_ARDUINO_ESP_LITTLEFS` and define a :c:macro`LV_FS_ARDUINO_ESP_LITTLEFS_LETTER` in ``lv_conf.h``. Enable :c:macro:`LV_USE_FS_ARDUINO_ESP_LITTLEFS` and define a :c:macro:`LV_FS_ARDUINO_ESP_LITTLEFS_LETTER` in ``lv_conf.h``.
API API

View File

@@ -9,13 +9,14 @@ Once an SD memory card is connected to the SPI interface of the Arduino or Genui
and read/write on them. You can also move through directories on the SD card.. and read/write on them. You can also move through directories on the SD card..
Detailed introduction: Detailed introduction:
- https://www.arduino.cc/reference/en/libraries/sd/ - https://www.arduino.cc/reference/en/libraries/sd/
Usage Usage
----- -----
Enable :c:macro:`LV_USE_FS_ARDUINO_SD` and define a :c:macro`LV_FS_ARDUINO_SD_LETTER` in ``lv_conf.h``. Enable :c:macro:`LV_USE_FS_ARDUINO_SD` and define a :c:macro:`LV_FS_ARDUINO_SD_LETTER` in ``lv_conf.h``.
You probably need to configure the :c:macro:`LV_FS_ARDUINO_SD_CS_PIN` and :c:macro:`LV_FS_ARDUINO_SD_FREQUENCY` that You probably need to configure the :c:macro:`LV_FS_ARDUINO_SD_CS_PIN` and :c:macro:`LV_FS_ARDUINO_SD_FREQUENCY` that
corresponds to the pin connected and the frequency used by the chip of the SD CARD. corresponds to the pin connected and the frequency used by the chip of the SD CARD.

View File

@@ -30,9 +30,24 @@ In ``lv_conf.h`` enable ``LV_USE_FS_...`` and assign an upper cased
letter to ``LV_FS_..._LETTER`` (e.g. ``'S'``). After that you can access letter to ``LV_FS_..._LETTER`` (e.g. ``'S'``). After that you can access
files using that driver letter. E.g. ``"S:path/to/file.txt"``. files using that driver letter. E.g. ``"S:path/to/file.txt"``.
The work directory can be set with ``LV_FS_..._PATH``. E.g. Working with common prefixes
""""""""""""""""""""""""""""
A **default driver letter** can be set by ``LV_FS_DEFAULT_DRIVE_LETTER``,
which allows skipping the drive prefix in file paths.
For example if ``LV_FS_DEFAULT_DRIVE_LETTER`` is set the ``'S'`` *"path/to/file.txt"* will mean *"S:path/to/file.txt"*.
This feature is useful if you have only a single driver and don't want to bother with LVGL's driver layer in the file paths.
It also helps to use a unified path with LVGL's file system and normal file systems.
The original mechanism is not affected, so a path starting with drive letter will still work.
The **working directory** can be set with ``LV_FS_..._PATH``. E.g.
``"/home/joe/projects/"`` The actual file/directory paths will be ``"/home/joe/projects/"`` The actual file/directory paths will be
appended to it. appended to it, allowing to skip the common part.
Caching
"""""""
:ref:`Cached reading <overview_file_system_cache>` is also supported if ``LV_FS_..._CACHE_SIZE`` is set to :ref:`Cached reading <overview_file_system_cache>` is also supported if ``LV_FS_..._CACHE_SIZE`` is set to
not ``0`` value. :cpp:func:`lv_fs_read` caches this size of data to lower the not ``0`` value. :cpp:func:`lv_fs_read` caches this size of data to lower the

View File

@@ -12,7 +12,7 @@ Detailed introduction: https://github.com/littlefs-project/littlefs
Usage Usage
----- -----
Enable :c:macro:`LV_USE_FS_LITTLEFS` and define a :c:macro`LV_FS_LITTLEFS_LETTER` in ``lv_conf.h``. 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. When enabled :c:macro:`lv_littlefs_set_handler` can be used to set up a mount point.

View File

@@ -9,6 +9,10 @@ any type of file system. A file system is identified by an assigned
drive letter. For example, if an SD card is associated with the letter drive letter. For example, if an SD card is associated with the letter
``'S'``, a file can be reached using ``"S:path/to/file.txt"``. ``'S'``, a file can be reached using ``"S:path/to/file.txt"``.
.. note::
If you want to skip the drive prefix from the path, you can use the :c:macro:`LV_FS_DEFAULT_DRIVE_LETTER` config parameter.
Ready to use drivers Ready to use drivers
******************** ********************

View File

@@ -246,7 +246,7 @@ Force refreshing
---------------- ----------------
Normally the invalidated areas (marked for redraw) are rendered in :cpp:func:`lv_timer_handler` in every Normally the invalidated areas (marked for redraw) are rendered in :cpp:func:`lv_timer_handler` in every
:cpp:macro:`LV_DEF_REFR_PERIOD`milliseconds. However, by using :cpp:func:`lv_refr_now(display)` you can ask LVGL to :c:macro:`LV_DEF_REFR_PERIOD` milliseconds. However, by using :cpp:func:`lv_refr_now(display)` you can ask LVGL to
redraw the invalid areas immediately. The refreshing will happen in :cpp:func:`lv_refr_now` which might take redraw the invalid areas immediately. The refreshing will happen in :cpp:func:`lv_refr_now` which might take
longer time. longer time.

View File

@@ -41,7 +41,7 @@ To set the source of an image, use :cpp:expr:`lv_image_set_src(img, src)`.
To generate a pixel array from a PNG, JPG or BMP image, use the `Online image converter tool <https://lvgl.io/tools/imageconverter>`__ To generate a pixel array from a PNG, JPG or BMP image, use the `Online image converter tool <https://lvgl.io/tools/imageconverter>`__
and set the converted image with its pointer :cpp:expr:`lv_image_set_src(img1, &converted_img_var)` and set the converted image with its pointer :cpp:expr:`lv_image_set_src(img1, &converted_img_var)`
To make the variable visible in the C file, you need to declare it with To make the variable visible in the C file, you need to declare it with
:cpp:macro:`LV_IMAGE_DECLARE(converted_img_var)`. :cpp:expr:`LV_IMAGE_DECLARE(converted_img_var)`.
To use external files, you also need to convert the image files using To use external files, you also need to convert the image files using
the online converter tool but now you should select the binary output the online converter tool but now you should select the binary output

View File

@@ -685,6 +685,9 @@
/*File system interfaces for common APIs */ /*File system interfaces for common APIs */
/*Setting a default driver letter allows skipping the driver prefix in filepaths*/
#define LV_FS_DEFAULT_DRIVE_LETTER '\0'
/*API for fopen, fread, etc*/ /*API for fopen, fread, etc*/
#define LV_USE_FS_STDIO 0 #define LV_USE_FS_STDIO 0
#if LV_USE_FS_STDIO #if LV_USE_FS_STDIO

View File

@@ -4,6 +4,19 @@
#include "../../core/lv_global.h" #include "../../core/lv_global.h"
#include "LittleFS.h" #include "LittleFS.h"
#if LV_FS_ARDUINO_ESP_LITTLEFS_LETTER == '\0'
#error "LV_FS_ARDUINO_ESP_LITTLEFS_LETTER must be set to a valid value"
#else
#if (LV_FS_ARDUINO_ESP_LITTLEFS_LETTER < 'A') || (LV_FS_ARDUINO_ESP_LITTLEFS_LETTER > 'Z')
#if LV_FS_DEFAULT_DRIVE_LETTER != '\0' /*When using default drive letter, strict format (X:) is mandatory*/
#error "LV_FS_ARDUINO_ESP_LITTLEFS_LETTER must be an upper case ASCII letter"
#else /*Lean rules for backward compatibility*/
#warning LV_FS_ARDUINO_ESP_LITTLEFS_LETTER should be an upper case ASCII letter. \
Using a slash symbol as drive letter should be replaced with LV_FS_DEFAULT_DRIVE_LETTER mechanism
#endif
#endif
#endif
typedef struct ArduinoEspLittleFile { typedef struct ArduinoEspLittleFile {
File file; File file;
} ArduinoEspLittleFile; } ArduinoEspLittleFile;
@@ -178,4 +191,11 @@ static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
return (int32_t)(*pos_p) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK; return (int32_t)(*pos_p) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
} }
#else /*LV_USE_FS_ARDUINO_ESP_LITTLEFS == 0*/
#if defined(LV_FS_ARDUINO_ESP_LITTLEFS_LETTER) && LV_FS_ARDUINO_ESP_LITTLEFS_LETTER != '\0'
#warning "LV_USE_FS_ARDUINO_ESP_LITTLEFS is not enabled but LV_FS_ARDUINO_ESP_LITTLEFS_LETTER is set"
#endif #endif
#endif /*LV_USE_FS_ARDUINO_ESP_LITTLEFS*/

View File

@@ -5,6 +5,19 @@
#include <SPI.h> #include <SPI.h>
#include "SD.h" #include "SD.h"
#if LV_FS_ARDUINO_SD_LETTER == '\0'
#error "LV_FS_ARDUINO_SD_LETTER must be set to a valid value"
#else
#if (LV_FS_ARDUINO_SD_LETTER < 'A') || (LV_FS_ARDUINO_SD_LETTER > 'Z')
#if LV_FS_DEFAULT_DRIVE_LETTER != '\0' /*When using default drive letter, strict format (X:) is mandatory*/
#error "LV_FS_ARDUINO_SD_LETTER must be an upper case ASCII letter"
#else /*Lean rules for backward compatibility*/
#warning LV_FS_ARDUINO_SD_LETTER should be an upper case ASCII letter. \
Using a slash symbol as drive letter should be replaced with LV_FS_DEFAULT_DRIVE_LETTER mechanism
#endif
#endif
#endif
typedef struct SdFile { typedef struct SdFile {
File file; File file;
} SdFile; } SdFile;
@@ -184,4 +197,10 @@ static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
return (int32_t)(*pos_p) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK; return (int32_t)(*pos_p) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
} }
#else /*LV_USE_FS_ARDUINO_SD == 0*/
#if defined(LV_FS_ARDUINO_SD_LETTER) && LV_FS_ARDUINO_SD_LETTER != '\0'
#warning "LV_USE_FS_ARDUINO_SD is not enabled but LV_FS_ARDUINO_SD_LETTER is set"
#endif #endif
#endif /*LV_USE_FS_ARDUINO_SD*/

View File

@@ -21,7 +21,16 @@
#endif #endif
#if LV_FS_FATFS_LETTER == '\0' #if LV_FS_FATFS_LETTER == '\0'
#error "LV_FS_FATFS_LETTER must be set to a valid value"
#else
#if (LV_FS_FATFS_LETTER < 'A') || (LV_FS_FATFS_LETTER > 'Z')
#if LV_FS_DEFAULT_DRIVE_LETTER != '\0' /*When using default drive letter, strict format (X:) is mandatory*/
#error "LV_FS_FATFS_LETTER must be an upper case ASCII letter" #error "LV_FS_FATFS_LETTER must be an upper case ASCII letter"
#else /*Lean rules for backward compatibility*/
#warning LV_FS_FATFS_LETTER should be an upper case ASCII letter. \
Using a slash symbol as drive letter should be replaced with LV_FS_DEFAULT_DRIVE_LETTER mechanism
#endif
#endif
#endif #endif
/********************** /**********************

View File

@@ -4,6 +4,19 @@
#include "lfs.h" #include "lfs.h"
#include "../../core/lv_global.h" #include "../../core/lv_global.h"
#if LV_FS_LITTLEFS_LETTER == '\0'
#error "LV_FS_LITTLEFS_LETTER must be set to a valid value"
#else
#if (LV_FS_LITTLEFS_LETTER < 'A') || (LV_FS_LITTLEFS_LETTER > 'Z')
#if LV_FS_DEFAULT_DRIVE_LETTER != '\0' /*When using default drive letter, strict format (X:) is mandatory*/
#error "LV_FS_LITTLEFS_LETTER must be an upper case ASCII letter"
#else /*Lean rules for backward compatibility*/
#warning LV_FS_LITTLEFS_LETTER should be an upper case ASCII letter. \
Using a slash symbol as drive letter should be replaced with LV_FS_DEFAULT_DRIVE_LETTER mechanism
#endif
#endif
#endif
typedef struct LittleFile { typedef struct LittleFile {
lfs_file_t file; lfs_file_t file;
} LittleFile; } LittleFile;

View File

@@ -47,6 +47,18 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#if LV_FS_MEMFS_LETTER == '\0'
#error "LV_FS_MEMFS_LETTER must be set to a valid value"
#else
#if (LV_FS_MEMFS_LETTER < 'A') || (LV_FS_MEMFS_LETTER > 'Z')
#if LV_FS_DEFAULT_DRIVE_LETTER != '\0' /*When using default drive letter, strict format (X:) is mandatory*/
#error "LV_FS_MEMFS_LETTER must be an upper case ASCII letter"
#else /*Lean rules for backward compatibility*/
#warning LV_FS_MEMFS_LETTER should be an upper case ASCII letter. \
Using a slash symbol as drive letter should be replaced with LV_FS_DEFAULT_DRIVE_LETTER mechanism
#endif
#endif
#endif
/********************** /**********************
* TYPEDEFS * TYPEDEFS

View File

@@ -23,7 +23,16 @@
*********************/ *********************/
#if LV_FS_POSIX_LETTER == '\0' #if LV_FS_POSIX_LETTER == '\0'
#error "LV_FS_POSIX_LETTER must be set to a valid value"
#else
#if (LV_FS_POSIX_LETTER < 'A') || (LV_FS_POSIX_LETTER > 'Z')
#if LV_FS_DEFAULT_DRIVE_LETTER != '\0' /*When using default drive letter, strict format (X:) is mandatory*/
#error "LV_FS_POSIX_LETTER must be an upper case ASCII letter" #error "LV_FS_POSIX_LETTER must be an upper case ASCII letter"
#else /*Lean rules for backward compatibility*/
#warning LV_FS_POSIX_LETTER should be an upper case ASCII letter. \
Using a slash symbol as drive letter should be replaced with LV_FS_DEFAULT_DRIVE_LETTER mechanism
#endif
#endif
#endif #endif
/** The reason for 'fd + 1' is because open() may return a legal fd with a value of 0, /** The reason for 'fd + 1' is because open() may return a legal fd with a value of 0,

View File

@@ -21,6 +21,19 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#if LV_FS_STDIO_LETTER == '\0'
#error "LV_FS_STDIO_LETTER must be set to a valid value"
#else
#if (LV_FS_STDIO_LETTER < 'A') || (LV_FS_STDIO_LETTER > 'Z')
#if LV_FS_DEFAULT_DRIVE_LETTER != '\0' /*When using default drive letter, strict format (X:) is mandatory*/
#error "LV_FS_STDIO_LETTER must be an upper case ASCII letter"
#else /*Lean rules for backward compatibility*/
#warning LV_FS_STDIO_LETTER should be an upper case ASCII letter. \
Using a slash symbol as drive letter should be replaced with LV_FS_DEFAULT_DRIVE_LETTER mechanism
#endif
#endif
#endif
#define MAX_PATH_LEN 256 #define MAX_PATH_LEN 256
/********************** /**********************

View File

@@ -17,6 +17,19 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#if LV_FS_WIN32_LETTER == '\0'
#error "LV_FS_WIN32_LETTER must be set to a valid value"
#else
#if (LV_FS_WIN32_LETTER < 'A') || (LV_FS_WIN32_LETTER > 'Z')
#if LV_FS_DEFAULT_DRIVE_LETTER != '\0' /*When using default drive letter, strict format (X:) is mandatory*/
#error "LV_FS_WIN32_LETTER must be an upper case ASCII letter"
#else /*Lean rules for backward compatibility*/
#warning LV_FS_WIN32_LETTER should be an upper case ASCII letter. \
Using a slash symbol as drive letter should be replaced with LV_FS_DEFAULT_DRIVE_LETTER mechanism
#endif
#endif
#endif
#define MAX_PATH_LEN 256 #define MAX_PATH_LEN 256
/********************** /**********************

View File

@@ -2284,6 +2284,15 @@
/*File system interfaces for common APIs */ /*File system interfaces for common APIs */
/*Setting a default driver letter allows skipping the driver prefix in filepaths*/
#ifndef LV_FS_DEFAULT_DRIVE_LETTER
#ifdef CONFIG_LV_FS_DEFAULT_DRIVE_LETTER
#define LV_FS_DEFAULT_DRIVE_LETTER CONFIG_LV_FS_DEFAULT_DRIVE_LETTER
#else
#define LV_FS_DEFAULT_DRIVE_LETTER '\0'
#endif
#endif
/*API for fopen, fread, etc*/ /*API for fopen, fread, etc*/
#ifndef LV_USE_FS_STDIO #ifndef LV_USE_FS_STDIO
#ifdef CONFIG_LV_USE_FS_STDIO #ifdef CONFIG_LV_USE_FS_STDIO

View File

@@ -17,16 +17,25 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#if LV_FS_DEFAULT_DRIVE_LETTER != '\0' && (LV_FS_DEFAULT_DRIVE_LETTER < 'A' || 'Z' < LV_FS_DEFAULT_DRIVE_LETTER)
#error "When enabled, LV_FS_DEFAULT_DRIVE_LETTER needs to be a capital ASCII letter (A-Z)"
#endif
#define fsdrv_ll_p &(LV_GLOBAL_DEFAULT()->fsdrv_ll) #define fsdrv_ll_p &(LV_GLOBAL_DEFAULT()->fsdrv_ll)
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
typedef struct {
char drive_letter;
const char * real_path;
} resolved_path_t;
/********************** /**********************
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
static const char * lv_fs_get_real_path(const char * path); static resolved_path_t lv_fs_resolve_path(const char * path);
static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t * br); static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t * br);
static lv_fs_res_t lv_fs_write_cached(lv_fs_file_t * file_p, const void * buf, uint32_t btw, uint32_t * bw); static lv_fs_res_t lv_fs_write_cached(lv_fs_file_t * file_p, const void * buf, uint32_t btw, uint32_t * bw);
static lv_fs_res_t lv_fs_seek_cached(lv_fs_file_t * file_p, uint32_t pos, lv_fs_whence_t whence); static lv_fs_res_t lv_fs_seek_cached(lv_fs_file_t * file_p, uint32_t pos, lv_fs_whence_t whence);
@@ -71,8 +80,9 @@ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mo
return LV_FS_RES_INV_PARAM; return LV_FS_RES_INV_PARAM;
} }
char letter = path[0]; resolved_path_t resolved_path = lv_fs_resolve_path(path);
lv_fs_drv_t * drv = lv_fs_get_drv(letter);
lv_fs_drv_t * drv = lv_fs_get_drv(resolved_path.drive_letter);
if(drv == NULL) { if(drv == NULL) {
LV_LOG_WARN("Can't open file (%s): unknown driver letter", path); LV_LOG_WARN("Can't open file (%s): unknown driver letter", path);
@@ -100,8 +110,7 @@ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mo
file_p->file_d = file_p; file_p->file_d = file_p;
} }
else { else {
const char * real_path = lv_fs_get_real_path(path); void * file_d = drv->open_cb(drv, resolved_path.real_path, mode);
void * file_d = drv->open_cb(drv, real_path, mode);
if(file_d == NULL || file_d == (void *)(-1)) { if(file_d == NULL || file_d == (void *)(-1)) {
LV_PROFILER_END; LV_PROFILER_END;
return LV_FS_RES_UNKNOWN; return LV_FS_RES_UNKNOWN;
@@ -297,8 +306,9 @@ lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path)
{ {
if(path == NULL) return LV_FS_RES_INV_PARAM; if(path == NULL) return LV_FS_RES_INV_PARAM;
char letter = path[0]; resolved_path_t resolved_path = lv_fs_resolve_path(path);
lv_fs_drv_t * drv = lv_fs_get_drv(letter);
lv_fs_drv_t * drv = lv_fs_get_drv(resolved_path.drive_letter);
if(drv == NULL) { if(drv == NULL) {
return LV_FS_RES_NOT_EX; return LV_FS_RES_NOT_EX;
@@ -316,8 +326,7 @@ lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path)
LV_PROFILER_BEGIN; LV_PROFILER_BEGIN;
const char * real_path = lv_fs_get_real_path(path); void * dir_d = drv->dir_open_cb(drv, resolved_path.real_path);
void * dir_d = drv->dir_open_cb(drv, real_path);
if(dir_d == NULL || dir_d == (void *)(-1)) { if(dir_d == NULL || dir_d == (void *)(-1)) {
LV_PROFILER_END; LV_PROFILER_END;
@@ -494,16 +503,36 @@ const char * lv_fs_get_last(const char * path)
**********************/ **********************/
/** /**
* Skip the driver letter and the possible : after the letter * Extract the drive letter and the real path from LVGL's "abstracted file system" path string
* @param path path string (E.g. S:/folder/file.txt) * @param path path string (E.g. S:/folder/file.txt)
* @return pointer to the beginning of the real path (E.g. /folder/file.txt)
*/ */
static const char * lv_fs_get_real_path(const char * path) static resolved_path_t lv_fs_resolve_path(const char * path)
{ {
resolved_path_t resolved;
#if LV_FS_DEFAULT_DRIVE_LETTER != '\0' /*When using default drive letter, strict format (X:) is mandatory*/
bool has_drive_prefix = ('A' <= path[0]) && (path[0] <= 'Z') && (path[1] == ':');
if(has_drive_prefix) {
resolved.drive_letter = path[0];
resolved.real_path = path + 2;
}
else {
resolved.drive_letter = LV_FS_DEFAULT_DRIVE_LETTER;
resolved.real_path = path;
}
# else /*Lean rules for backward compatibility*/
resolved.drive_letter = path[0];
if(*path != '\0') {
path++; /*Ignore the driver letter*/ path++; /*Ignore the driver letter*/
if(*path == ':') path++; if(*path == ':') path++;
}
return path; resolved.real_path = path;
#endif
return resolved;
} }
static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t * br) static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t * br)