How to use LittleFS as driver in LVGL

gotrunko
Posts: 2
Joined: Sun Feb 20, 2022 7:11 pm

How to use LittleFS as driver in LVGL

Postby gotrunko » Sun Feb 20, 2022 7:54 pm

Hi everyone,
I’m currently trying to use LittleFS for Esp32 but I’m facing an issue with how the fs_open is working.
  1. #include <Arduino.h>
  2. #include "lv_port_fs_littlefs.h"
  3. #include <LittleFS.h>
  4.  
  5. static void fs_init(void);
  6.  
  7. static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode);
  8. static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p);
  9. static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
  10. static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw);
  11. static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence);
  12. static lv_fs_res_t fs_size(lv_fs_drv_t * drv, void * file_p, uint32_t * size_p);
  13. static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p);
  14.  
  15. static void * fs_dir_open(lv_fs_drv_t * drv, const char * path);
  16. static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * rddir_p, char * fn);
  17. static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * rddir_p);
  18.  
  19.  
  20. void lv_port_littlefs_init(void)
  21. {
  22.   fs_init();
  23.  
  24.   /*Add a simple drive to open images*/
  25.   static lv_fs_drv_t fs_drv;
  26.   lv_fs_drv_init(&fs_drv);
  27.  
  28.   fs_drv.letter = 'L';
  29.   fs_drv.open_cb = fs_open;
  30.   fs_drv.close_cb = fs_close;
  31.   fs_drv.read_cb = fs_read;
  32.   fs_drv.write_cb = fs_write;
  33.   fs_drv.seek_cb = fs_seek;
  34.   fs_drv.tell_cb = NULL;
  35.  
  36.   fs_drv.dir_close_cb = NULL;
  37.   fs_drv.dir_open_cb = NULL;
  38.   fs_drv.dir_read_cb = NULL;
  39.  
  40.   lv_fs_drv_register(&fs_drv);
  41. }
  42.  
  43. /**********************
  44.  *   STATIC FUNCTIONS
  45.  **********************/
  46.  
  47. /*Initialize your Storage device and File system.*/
  48. static void fs_init(void)
  49. {
  50.   LittleFS.begin();
  51. }
  52.  
  53. /**
  54.  * Open a file
  55.  * @param drv       pointer to a driver where this function belongs
  56.  * @param path      path to the file beginning with the driver letter (e.g. S:/folder/file.txt)
  57.  * @param mode      read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR
  58.  * @return          a file descriptor or NULL on error
  59.  */
  60. static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
  61. {
  62.   LV_UNUSED(drv);
  63.  
  64.   const char * flags = "";
  65.  
  66.   if (mode == LV_FS_MODE_WR) flags = FILE_WRITE;
  67.   else if (mode == LV_FS_MODE_RD) flags = FILE_READ;
  68.   else if (mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = FILE_WRITE;
  69.  
  70.   char complete_path[strlen(path) + 1];
  71.   complete_path[0] = '/';
  72.   complete_path[1] = '\0';
  73.   strcat(complete_path, path);
  74.   Serial.printf("Try to open file: %s\n", complete_path);
  75.   File f = LittleFS.open(complete_path, flags);
  76.   if (!f) {
  77.     Serial.printf("Error with file: %s\n", complete_path);
  78.   } else {
  79.     Serial.println(f.name());
  80.     time_t t = f.getLastWrite();
  81.     struct tm * tmstruct = localtime(&t);
  82.     Serial.printf("  LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct->tm_year)+1900,( tmstruct->tm_mon)+1, tmstruct->tm_mday,tmstruct->tm_hour , tmstruct->tm_min, tmstruct->tm_sec);
  83.   }
  84.  
  85.   return (void*)f;
  86. }
  87.  
  88. /**
  89.  * Close an opened file
  90.  * @param drv       pointer to a driver where this function belongs
  91.  * @param file_p    pointer to a file_t variable. (opened with fs_open)
  92.  * @return          LV_FS_RES_OK: no error or  any error from @lv_fs_res_t enum
  93.  */
  94. static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p)
  95. {
  96.   LV_UNUSED(drv);
  97.   File* file = (File*)file_p;
  98.   file->close();
  99.   return LV_FS_RES_OK;
  100. }
  101.  
  102. /**
  103.  * Read data from an opened file
  104.  * @param drv       pointer to a driver where this function belongs
  105.  * @param file_p    pointer to a file_t variable.
  106.  * @param buf       pointer to a memory block where to store the read data
  107.  * @param btr       number of Bytes To Read
  108.  * @param br        the real number of read bytes (Byte Read)
  109.  * @return          LV_FS_RES_OK: no error or  any error from @lv_fs_res_t enum
  110.  */
  111. static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br)
  112. {
  113.   LV_UNUSED(drv);
  114.   File* file = (File*)file_p;
  115.   *br = file->read((uint8_t*)buf, btr);
  116.   return (int32_t)(*br) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
  117. }
  118.  
  119. /**
  120.  * Write into a file
  121.  * @param drv       pointer to a driver where this function belongs
  122.  * @param file_p    pointer to a file_t variable
  123.  * @param buf       pointer to a buffer with the bytes to write
  124.  * @param btw       Bytes To Write
  125.  * @param bw        the number of real written bytes (Bytes Written). NULL if unused.
  126.  * @return          LV_FS_RES_OK: no error or  any error from @lv_fs_res_t enum
  127.  */
  128. static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw)
  129. {
  130.   LV_UNUSED(drv);
  131.   File* file = (File*)file_p;
  132.   *bw = file->write((uint8_t*)buf, btw);
  133.   return (int32_t)(*bw) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
  134. }
  135.  
  136. /**
  137.  * Set the read write pointer. Also expand the file size if necessary.
  138.  * @param drv       pointer to a driver where this function belongs
  139.  * @param file_p    pointer to a file_t variable. (opened with fs_open )
  140.  * @param pos       the new position of read write pointer
  141.  * @param whence    tells from where to interpret the `pos`. See @lv_fs_whence_t
  142.  * @return          LV_FS_RES_OK: no error or  any error from @lv_fs_res_t enum
  143.  */
  144. static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence)
  145. {
  146.   LV_UNUSED(drv);
  147.   SeekMode mode;
  148.   if (whence == LV_FS_SEEK_SET) mode = SeekSet;
  149.   else if (whence == LV_FS_SEEK_CUR) mode = SeekCur;
  150.   else if (whence == LV_FS_SEEK_END) mode = SeekEnd;
  151.  
  152.   File* file = (File*)file_p;
  153.   file->seek(pos, mode);
  154.   return LV_FS_RES_OK;
  155. }
The current code raises
  1. lib/lv_conf/lv_port_fs_littlefs.cpp: In function 'void* fs_open(lv_fs_drv_t*, const char*, lv_fs_mode_t)':
  2. lib/lv_conf/lv_port_fs_littlefs.cpp:85:17: error: invalid cast from type 'fs::File' to type 'void*'
  3.    return (void*)f;
  4.                  ^
  5. *** [.pio/build/m5stack-core2/libe34/lv_conf/lv_port_fs_littlefs.cpp.o] Error 1
I tried with another class which was encapsulate the File element, but same, it's not working, does someone already do something like that?
Is it possible to use File object as pointer?

gotrunko
Posts: 2
Joined: Sun Feb 20, 2022 7:11 pm

Re: How to use LittleFS as driver in LVGL

Postby gotrunko » Mon Feb 21, 2022 3:46 pm

I finally found a way to use it, but it's really slow, and it seems to load files a lot of time before rendering it:
https://github.com/PierreRambaud/pokego ... ttlefs.cpp
It's now an issue with how I use LVGL ^^

Who is online

Users browsing this forum: No registered users and 96 guests