Problem with fs and drv and File pointer ESP32 bootloop

cause when I try i obtain a no data with :

Warn: Image draw cannot open the image resource 	(C:\Users\ulric\Documents\Arduino\libraries\LittlevGL\src\src\lv_draw\lv_img_cache.c #118)
Warn: Image draw error 	(C:\Users\ulric\Documents\Arduino\libraries\LittlevGL\src\src\lv_draw\lv_draw_img.c #61)

or a boot loop.

i can give you my drive

 lv_fs_drv_t sd_drv;
  lv_fs_drv_init(&sd_drv);
  sd_drv.file_size = sizeof(File*) + 1;
  sd_drv.letter = 'S';
  sd_drv.open_cb = sd_open_cb;
  sd_drv.close_cb = sd_close_cb;
  sd_drv.read_cb = sd_read_cb;
  sd_drv.seek_cb = sd_seek_cb; /* Fonction de rappel pour se déplacer dans un fichier (déplacer le curseur) */
  sd_drv.tell_cb = sd_tell_cb; /* Fonction de rappel pour donner la position du curseur */
  lv_fs_drv_register(&sd_drv);

And the function linked :


lv_fs_res_t sd_open_cb(struct _lv_fs_drv_t * drv, void * file_p, const char * path, lv_fs_mode_t mode) {
  lv_fs_res_t res = LV_FS_RES_NOT_IMP;

  File f ;
  char buf[256];

  sprintf(buf, "/%s", path);
  Serial.print("path : ");
  Serial.println(buf);


  if (mode == LV_FS_MODE_WR)
  {
    f = SD.open(buf, FILE_WRITE);
    res = LV_FS_RES_OK;
  }
  else if (mode == LV_FS_MODE_RD)
  {
    f = SD.open(buf);
    res = LV_FS_RES_OK;
  }
  else if (mode == (LV_FS_MODE_WR | LV_FS_MODE_RD))
  {
    f = SD.open(buf, FILE_WRITE);
    res = LV_FS_RES_OK;
  }
  if(!f) return LV_FS_RES_UNKNOWN;
  File * fp = (File *) file_p;
  *fp = f; // where the probleme come

  return res;
}


lv_fs_res_t sd_read_cb(struct _lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) {
  lv_fs_res_t res = LV_FS_RES_NOT_IMP;
  File * fp = (File *) file_p;
  uint8_t * buffer = (uint8_t *) buf;

  Serial.print("name sd_read_cb : ");
  Serial.println(fp->name());
  *br = fp->read(buffer, btr);


  res = LV_FS_RES_OK;
  return res;
}

lv_fs_res_t sd_seek_cb(struct _lv_fs_drv_t * drv, void * file_p, uint32_t pos) {
  lv_fs_res_t res = LV_FS_RES_NOT_IMP;
  File * fp = (File *) file_p;
  

  fp->seek(pos);
    Serial.print("name sd_seek_cb : ");
  Serial.println(fp->name());
  res = LV_FS_RES_OK;
  return res;
}

lv_fs_res_t sd_tell_cb(struct _lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) {
  lv_fs_res_t res = LV_FS_RES_NOT_IMP;
  File * fp = (File *) file_p;
  

  * pos_p = fp->position();
  Serial.print("name in sd_tell_cb : ");
  Serial.println(fp->name());
  res = LV_FS_RES_OK;
  return res;

}



lv_fs_res_t sd_close_cb(struct _lv_fs_drv_t * drv, void * file_p) {
  lv_fs_res_t res = LV_FS_RES_NOT_IMP;
  File * fp = (File *) file_p;
  
  Serial.println("close");
  fp->close();
  res = LV_FS_RES_OK;
  return res;
}

i try it with a simple test with a foo.txt who contain :

hello world!!

my test :

  lv_fs_file_t f;
  lv_fs_res_t res;
  res = lv_fs_open(&f, "S:foo.txt", LV_FS_MODE_RD);
  if (res != LV_FS_RES_OK) Serial.print("don't work nothing open");

  File * ftest = (File *) f.file_d;
  Serial.print("name outside sd_open_cb : ");
  Serial.println(ftest->name());


  uint32_t read_num, readpos;
  uint8_t buf[8];

  lv_fs_seek(&f, 2);
  if (res != LV_FS_RES_OK) Serial.print("don't work nothing read");
  res = lv_fs_read(&f, buf, 3, &read_num);
  if (res != LV_FS_RES_OK || read_num != 3) Serial.print("don't work nothing read");
  lv_fs_tell(&f, &readpos);
  lv_fs_close(&f);

  Serial.println((char *) buf);
  Serial.println(readpos);

and it work.

path : /foo.txt
name outside sd_open_cb : /foo.txt
name sd_seek_cb : /foo.txt
name sd_read_cb : /foo.txt
name in sd_tell_cb : /foo.txt
close
llo
5

  lv_obj_t * icon = lv_img_create(lv_scr_act(), NULL);
  lv_img_set_src(icon, "S:/image1.bin");

It looks like you are using the image converter to make a binary image. Why can’t you use the C array option?

Because i don’t want to use too much memory in my chip.

Usually the method you are using now consumes more memory, because it has to load the image into RAM and decode it. The other method only uses Flash (which there is usually more of)

i agree but i need more than 10 photo so it’s better with bin file.

i rather use 200kB then all my memory

In that case, you have the line numbers in your log. I suggest you do some debugging and figure out why it “cannot open the image resource”. I can’t really think of anything else that could be the problem.

that what i’m doing. but i don’t found anything

it’s look like this is the probleme but i don’t understand

#if LV_USE_FILESYSTEM
    else if(src_type == LV_IMG_SRC_FILE) {
        lv_fs_file_t file;
        lv_fs_res_t res;
        uint32_t rn;
        res = lv_fs_open(&file, src, LV_FS_MODE_RD);
        if(res == LV_FS_RES_OK) {
            res = lv_fs_read(&file, header, sizeof(lv_img_header_t), &rn);
            lv_fs_close(&file);
        }

        lv_img_cf_t cf = ((lv_img_dsc_t *)src)->header.cf;
        if(cf < CF_BUILT_IN_FIRST || cf > CF_BUILT_IN_LAST) return LV_RES_INV; // <---here

    }

If you step through with a debugger you should find where the error is coming from.

in which type i need to read the file in my sd for a image ?

I don’t understand the question
 probably a translation issue.

i don’t understant, why cf < CF_BUILT_IN_FIRST ?

lv_img_cf_t cf = ((lv_img_dsc_t *)src)->header.cf;
 if(cf < CF_BUILT_IN_FIRST || cf > CF_BUILT_IN_LAST) return LV_RES_INV;

the format LV_IMG_CF_TRUE_COLOR can’t be use in .bin file ?

and when i open a convert file the 4 first byte is

typedef struct
{

    /* The first 8 bit is very important to distinguish the different source types.
     * For more info see `lv_img_get_src_type()` in lv_img.c */
    uint32_t cf : 5;          /* Color format: See `lv_img_color_format_t`*/
    uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a
                                 non-printable character*/

    uint32_t reserved : 2; /*Reserved to be used later*/

    uint32_t w : 11; /*Width of the image map*/
    uint32_t h : 11; /*Height of the image map*/
} lv_img_header_t;

04 00 05 1e // in HEXA and mean : 

0000 0 // cf 
100 // always_zero
00 // reserved
00000000000 // w
10100011110 // h

That why i ask in which way i must read the header ?

The color formats are represented as numbers. That if statement just checks whether it’s a valid color format or not.

It looks like you must be reading the image header wrong. The always_zero bits are not all zero and the image is zero pixels wide. :confused:

ok the library lv_fs_fatfs.c work great
not for the dir drv but it work !!! finally :smile:

the SD.H and FS.h use by ESP32 on arduino DON’T WORK ! i think is because the read function need a Uint8_t buffer.

size_t read(uint8_t* buf, size_t size);

so don’t weast your time like a do and use the fatfs if you want use image one just : remove the dir function and pretype void* file_p and all work.

don’t forget to initialise your SD card with :

  /* Initialisation de la carte SD */
  Serial.print(F("Init SD card... "));
  if (!SD.begin(SD_CS)) {
    Serial.println(F("FAIL"));
    for (;;); //  appui sur bouton RESET
  }

before init the drive

thanx for you’re time.

**
 * Open a file
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to a file_t variable
 * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt)
 * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR
 * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_open (lv_fs_drv_t * drv, void * file_p, const char * path, lv_fs_mode_t mode)
{
    uint8_t flags = 0;

    if(mode == LV_FS_MODE_WR) flags = FA_WRITE | FA_OPEN_ALWAYS;
    else if(mode == LV_FS_MODE_RD) flags = FA_READ;
    else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = FA_READ | FA_WRITE | FA_OPEN_ALWAYS;

    FRESULT res = f_open((FIL*) file_p, path, flags);

    if(res == FR_OK) {
      f_lseek((FIL*) file_p, 0);
      return LV_FS_RES_OK;
    } else {
      return LV_FS_RES_UNKNOWN;
    }
}


/**
 * Close an opened file
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to a file_t variable. (opened with lv_ufs_open)
 * @return LV_FS_RES_OK: no error, the file is read
 *         any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_close (lv_fs_drv_t * drv, void * file_p)
{
    f_close((FIL*) file_p);
    return LV_FS_RES_OK;
}

/**
 * Read data from an opened file
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to a file_t variable.
 * @param buf pointer to a memory block where to store the read data
 * @param btr number of Bytes To Read
 * @param br the real number of read bytes (Byte Read)
 * @return LV_FS_RES_OK: no error, the file is read
 *         any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_read (lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br)
{
    FRESULT res = f_read((FIL*) file_p, buf, btr, (UINT*)br);
    if(res == FR_OK) return LV_FS_RES_OK;
    else return LV_FS_RES_UNKNOWN;
}

/**
 * Write into a file
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to a file_t variable
 * @param buf pointer to a buffer with the bytes to write
 * @param btr Bytes To Write
 * @param br the number of real written bytes (Bytes Written). NULL if unused.
 * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw)
{
  FRESULT res = f_write((FIL*) file_p, buf, btw, (UINT*)bw);
    if(res == FR_OK) return LV_FS_RES_OK;
    else return LV_FS_RES_UNKNOWN;
}

/**
 * Set the read write pointer. Also expand the file size if necessary.
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to a file_t variable. (opened with lv_ufs_open )
 * @param pos the new position of read write pointer
 * @return LV_FS_RES_OK: no error, the file is read
 *         any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_seek (lv_fs_drv_t * drv, void * file_p, uint32_t pos)
{
    f_lseek((FIL*) file_p, pos);
    return LV_FS_RES_OK;
}

/**
 * Give the size of a file bytes
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to a file_t variable
 * @param size pointer to a variable to store the size
 * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_size (lv_fs_drv_t * drv, void * file_p, uint32_t * size_p)
{
  (*size_p) = f_size(((file_t *)file_p));
    return LV_FS_RES_OK;
}

/**
 * Give the position of the read write pointer
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to a file_t variable.
 * @param pos_p pointer to to store the result
 * @return LV_FS_RES_OK: no error, the file is read
 *         any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_tell (lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
{
  *pos_p = f_tell(((file_t *)file_p));
    return LV_FS_RES_OK;
}

/**
 * Delete a file
 * @param drv pointer to a driver where this function belongs
 * @param path path of the file to delete
 * @return  LV_FS_RES_OK or any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_remove (lv_fs_drv_t * drv, const char *path)
{
    lv_fs_res_t res = LV_FS_RES_NOT_IMP;

    /* Add your code here*/

    return res;
}

/**
 * Truncate the file size to the current position of the read write pointer
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to an 'ufs_file_t' variable. (opened with lv_fs_open )
 * @return LV_FS_RES_OK: no error, the file is read
 *         any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_trunc (lv_fs_drv_t * drv, void * file_p)
{
    f_sync((FIL*) file_p);           /*If not syncronized fclose can write the truncated part*/
    f_truncate((FIL*) file_p);
    return LV_FS_RES_OK;
}

/**
 * Rename a file
 * @param drv pointer to a driver where this function belongs
 * @param oldname path to the file
 * @param newname path with the new name
 * @return LV_FS_RES_OK or any error from 'fs_res_t'
 */
static lv_fs_res_t fs_rename (lv_fs_drv_t * drv, const char * oldname, const char * newname)
{
 
    FRESULT res = f_rename(oldname, newname);

    if(res == FR_OK) return LV_FS_RES_OK;
    else return LV_FS_RES_UNKNOWN;
}

/**
 * Get the free and total size of a driver in kB
 * @param drv pointer to a driver where this function belongs
 * @param letter the driver letter
 * @param total_p pointer to store the total size [kB]
 * @param free_p pointer to store the free size [kB]
 * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_free (lv_fs_drv_t * drv, uint32_t * total_p, uint32_t * free_p)
{
    lv_fs_res_t res = LV_FS_RES_NOT_IMP;

    /* Add your code here*/

    return res;
}

and now we dir include

This version work for esp32 if you want!

/**
 * @file lv_fs_fatfs.c
 * For ESP32
 */

/*********************
 *      INCLUDES
 *********************/

#include <lvgl.h>

#include "ff.h"
#include <SD.h>


/*********************
 *      DEFINES
 *********************/
#define SD_CS          4 // you're CS pin for SPI slave
#define DRIVE_LETTER 'S'
/**********************
 *      TYPEDEFS
 **********************/

/* Create a type to store the required data about your file.*/
typedef  FIL file_t;

/*Similarly to `file_t` create a type for directory reading too */
typedef  FF_DIR dir_t;

/**********************
 *  STATIC PROTOTYPES
 **********************/
static void fs_init(void);

static lv_fs_res_t fs_open (lv_fs_drv_t * drv, void * file_p, const char * path, lv_fs_mode_t mode);
static lv_fs_res_t fs_close (lv_fs_drv_t * drv, void * file_p);
static lv_fs_res_t fs_read (lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw);
static lv_fs_res_t fs_seek (lv_fs_drv_t * drv, void * file_p, uint32_t pos);
static lv_fs_res_t fs_size (lv_fs_drv_t * drv, void * file_p, uint32_t * size_p);
static lv_fs_res_t fs_tell (lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p);
static lv_fs_res_t fs_remove (lv_fs_drv_t * drv, const char *path);
static lv_fs_res_t fs_trunc (lv_fs_drv_t * drv, void * file_p);
static lv_fs_res_t fs_rename (lv_fs_drv_t * drv, const char * oldname, const char * newname);
static lv_fs_res_t fs_free (lv_fs_drv_t * drv, uint32_t * total_p, uint32_t * free_p);
static lv_fs_res_t fs_dir_open (lv_fs_drv_t * drv, void * dir_p, const char *path);
static lv_fs_res_t fs_dir_read (lv_fs_drv_t * drv, void * dir_p, char *fn);
static lv_fs_res_t fs_dir_close (lv_fs_drv_t * drv, void * dir_p);

/**********************
 *  STATIC VARIABLES
 **********************/

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/

void lv_fs_if_init(void)
{
    /*----------------------------------------------------
     * Initialize your storage device and File System
     * -------------------------------------------------*/
    fs_init();

    /*---------------------------------------------------
     * Register the file system interface  in LittlevGL
     *--------------------------------------------------*/

    /* Add a simple drive to open images */
    lv_fs_drv_t fs_drv;                         /*A driver descriptor*/
  lv_fs_drv_init(&fs_drv);

    /*Set up fields...*/
    fs_drv.file_size = sizeof(file_t);
    fs_drv.letter = DRIVE_LETTER;
    fs_drv.open_cb = fs_open;
    fs_drv.close_cb = fs_close;
    fs_drv.read_cb = fs_read;
    fs_drv.write_cb = fs_write;
    fs_drv.seek_cb = fs_seek;
    fs_drv.tell_cb = fs_tell;
    fs_drv.free_space_cb = fs_free;
    fs_drv.size_cb = fs_size;
    fs_drv.remove_cb = fs_remove;
    fs_drv.rename_cb = fs_rename;
    fs_drv.trunc_cb = fs_trunc;
    
    fs_drv.rddir_size = sizeof(dir_t);
    fs_drv.dir_close_cb = fs_dir_close;
    fs_drv.dir_open_cb = fs_dir_open;
    fs_drv.dir_read_cb = fs_dir_read;

    lv_fs_drv_register(&fs_drv);
}

/**********************
 *   STATIC FUNCTIONS
 **********************/

/* Initialize your Storage device and File system. */
static void fs_init(void)
{
  /* Initialisation de la carte SD */
  Serial.print(F("Init SD card... "));
  if (!SD.begin(SD_CS)) {
    Serial.println(F("FAIL"));
    for (;;); //  appui sur bouton RESET
  }
}

/**
 * Open a file
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to a file_t variable
 * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt)
 * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR
 * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_open (lv_fs_drv_t * drv, void * file_p, const char * path, lv_fs_mode_t mode)
{
    uint8_t flags = 0;

    if(mode == LV_FS_MODE_WR) flags = FA_WRITE | FA_OPEN_ALWAYS;
    else if(mode == LV_FS_MODE_RD) flags = FA_READ;
    else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = FA_READ | FA_WRITE | FA_OPEN_ALWAYS;

    FRESULT res = f_open((file_t*) file_p, path, flags);

    if(res == FR_OK) {
      f_lseek((file_t*) file_p, 0);
      return LV_FS_RES_OK;
    } else {
      return LV_FS_RES_UNKNOWN;
    }
}


/**
 * Close an opened file
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to a file_t variable. (opened with lv_ufs_open)
 * @return LV_FS_RES_OK: no error, the file is read
 *         any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_close (lv_fs_drv_t * drv, void * file_p)
{
    f_close((file_t*) file_p);
    return LV_FS_RES_OK;
}

/**
 * Read data from an opened file
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to a file_t variable.
 * @param buf pointer to a memory block where to store the read data
 * @param btr number of Bytes To Read
 * @param br the real number of read bytes (Byte Read)
 * @return LV_FS_RES_OK: no error, the file is read
 *         any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_read (lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br)
{
    FRESULT res = f_read((file_t*) file_p, buf, btr, (UINT*)br);
    if(res == FR_OK) return LV_FS_RES_OK;
    else return LV_FS_RES_UNKNOWN;
}

/**
 * Write into a file
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to a file_t variable
 * @param buf pointer to a buffer with the bytes to write
 * @param btr Bytes To Write
 * @param br the number of real written bytes (Bytes Written). NULL if unused.
 * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw)
{
  FRESULT res = f_write((file_t*) file_p, buf, btw, (UINT*)bw);
    if(res == FR_OK) return LV_FS_RES_OK;
    else return LV_FS_RES_UNKNOWN;
}

/**
 * Set the read write pointer. Also expand the file size if necessary.
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to a file_t variable. (opened with lv_ufs_open )
 * @param pos the new position of read write pointer
 * @return LV_FS_RES_OK: no error, the file is read
 *         any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_seek (lv_fs_drv_t * drv, void * file_p, uint32_t pos)
{
    f_lseek((file_t*) file_p, pos);
    return LV_FS_RES_OK;
}

/**
 * Give the size of a file bytes
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to a file_t variable
 * @param size pointer to a variable to store the size
 * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_size (lv_fs_drv_t * drv, void * file_p, uint32_t * size_p)
{
  (*size_p) = f_size(((file_t *)file_p));
    return LV_FS_RES_OK;
}

/**
 * Give the position of the read write pointer
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to a file_t variable.
 * @param pos_p pointer to to store the result
 * @return LV_FS_RES_OK: no error, the file is read
 *         any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_tell (lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
{
  *pos_p = f_tell(((file_t *)file_p));
    return LV_FS_RES_OK;
}

/**
 * Delete a file
 * @param drv pointer to a driver where this function belongs
 * @param path path of the file to delete
 * @return  LV_FS_RES_OK or any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_remove (lv_fs_drv_t * drv, const char *path)
{
    lv_fs_res_t res = LV_FS_RES_NOT_IMP;

    /* Add your code here*/

    return res;
}

/**
 * Truncate the file size to the current position of the read write pointer
 * @param drv pointer to a driver where this function belongs
 * @param file_p pointer to an 'ufs_file_t' variable. (opened with lv_fs_open )
 * @return LV_FS_RES_OK: no error, the file is read
 *         any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_trunc (lv_fs_drv_t * drv, void * file_p)
{
    f_sync((file_t*) file_p);           /*If not syncronized fclose can write the truncated part*/
    f_truncate((file_t*) file_p);
    return LV_FS_RES_OK;
}

/**
 * Rename a file
 * @param drv pointer to a driver where this function belongs
 * @param oldname path to the file
 * @param newname path with the new name
 * @return LV_FS_RES_OK or any error from 'fs_res_t'
 */
static lv_fs_res_t fs_rename (lv_fs_drv_t * drv, const char * oldname, const char * newname)
{
 
    FRESULT res = f_rename(oldname, newname);

    if(res == FR_OK) return LV_FS_RES_OK;
    else return LV_FS_RES_UNKNOWN;
}

/**
 * Get the free and total size of a driver in kB
 * @param drv pointer to a driver where this function belongs
 * @param letter the driver letter
 * @param total_p pointer to store the total size [kB]
 * @param free_p pointer to store the free size [kB]
 * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_free (lv_fs_drv_t * drv, uint32_t * total_p, uint32_t * free_p)
{
    lv_fs_res_t res = LV_FS_RES_NOT_IMP;

    /* Add your code here*/

    return res;
}

/**
 * Initialize a 'fs_read_dir_t' variable for directory reading
 * @param drv pointer to a driver where this function belongs
 * @param dir_p pointer to a 'fs_read_dir_t' variable
 * @param path path to a directory
 * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_dir_open (lv_fs_drv_t * drv, void * dir_p, const char *path)
{
    FRESULT res = f_opendir((dir_t*)dir_p, path);
    if(res == FR_OK) return LV_FS_RES_OK;
    else return LV_FS_RES_UNKNOWN;
}

/**
 * Read the next filename form a directory.
 * The name of the directories will begin with '/'
 * @param drv pointer to a driver where this function belongs
 * @param dir_p pointer to an initialized 'fs_read_dir_t' variable
 * @param fn pointer to a buffer to store the filename
 * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_dir_read (lv_fs_drv_t * drv, void * dir_p, char *fn)
{
  FRESULT res;
  FILINFO fno;
  fn[0] = '\0';

    do {
      res = f_readdir((dir_t*)dir_p, &fno);
      if(res != FR_OK) return LV_FS_RES_UNKNOWN;

    if(fno.fattrib & AM_DIR) {
      fn[0] = '/';
      strcpy(&fn[1], fno.fname);
    }
    else strcpy(fn, fno.fname);

    } while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0);

    return LV_FS_RES_OK;
}

/**
 * Close the directory reading
 * @param drv pointer to a driver where this function belongs
 * @param dir_p pointer to an initialized 'fs_read_dir_t' variable
 * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
 */
static lv_fs_res_t fs_dir_close (lv_fs_drv_t * drv, void * dir_p)
{
  f_closedir((dir_t*)dir_p);
    return LV_FS_RES_OK;
}

1 Like

Glad to see that it works!

To use JPG images directly you should use RAW color format. TRUE_COLOR will decode the image and create a simple array of pixels.

thx!

this is a video of what i done

i make a fie explorer.

so now, I’can open an image !! I need to add a empty screen between a image and the explorer file to avoid a core panic. (the creation of my dir is a bit slow. is a bit slow but it 's not a probleme).


  lv_group_remove_all_objs(Cross);
  lv_obj_clean(scr1);
  /*Create a list*/
  lv_obj_t * list1 = lv_list_create(scr1, NULL);
  lv_obj_set_size(list1, 320, 240);
  lv_obj_align(list1, NULL, LV_ALIGN_CENTER, 0, 0);
  lv_list_set_scroll_propagation(list1, true);
  /*Add buttons to the list*/
  lv_obj_t * list_btn;
  if (fd.actualpath == "S:/") {
    list_btn = lv_list_add_btn(list1, LV_SYMBOL_HOME, "Menu");
    lv_obj_set_event_cb(list_btn, Back_Menu_Start_event_cb);
  }
  else
  {
    list_btn = lv_list_add_btn(list1, LV_SYMBOL_DIRECTORY, "../");
    lv_obj_set_event_cb(list_btn, dir_event_cb);
  }

  for (int m = 0; m < fd.fnum; m++) {
    if (fd.lfile[m][0] == '/') {
      list_btn = lv_list_add_btn(list1, LV_SYMBOL_DIRECTORY, (char *) fd.lfile[m].c_str());
      lv_obj_set_event_cb(list_btn, dir_event_cb);
    }
    else if (type_file((char *) fd.lfile[m].c_str()) == 'I') {
      list_btn = lv_list_add_btn(list1, LV_SYMBOL_IMAGE, (char *) fd.lfile[m].c_str());
      lv_obj_set_event_cb(list_btn, dir_event_cb);
    }
    else if (type_file((char *) fd.lfile[m].c_str()) == 'T') {
      list_btn = lv_list_add_btn(list1, LV_SYMBOL_DRIVE, (char *)fd.lfile[m].c_str());
      lv_obj_set_event_cb(list_btn, dir_event_cb);
    }
    else if (type_file((char *) fd.lfile[m].c_str()) == 'U') {
      list_btn = lv_list_add_btn(list1, LV_SYMBOL_FILE, (char *) fd.lfile[m].c_str());
      lv_obj_set_event_cb(list_btn, dir_event_cb);
    }
  }
  lv_group_add_obj(Cross, list1);

I a have the same issue when i try to read a txt file but i think i can find why. (end of the video).

the link

Have a good day.

I don’t know what the text means when you open a text file :slight_smile: Form the video it seems you opened a text file and a text appeared.

Are the images opened as JPG?

do you have a complete project file that i can use to test this example i am not able to read files from SD card successfully?

How to show my jpg file from sdcard to my display

is lv_fs_fatfs spi can use tft spi?
when i use same spi to control tft and sdcard.
it always show the “addApbChangeCallback(): duplicate func=400FB0A8 arg=3FFBDD94”.
how to fix it?