SDFileSystem MSCFileSystem conflict

08 Dec 2010

I have problems getting the directories a flash stick and a microSD when both declarations are on the same file.

on the following program if I change the order of

SDFileSystem sd(p5, p6, p7, p8, "sd");  &  MSCFileSystem msc("msc");

then I don't get the directory listing for the microSD.

If I put these 2 functions on separate programs then they work fine, but not here. Any ideas?

 

// sections of this code  taken from mbed website

#include "mbed.h"
#include "SDFileSystem.h"
#include "MSCFileSystem.h"

LocalFileSystem local("local");     
SDFileSystem sd(p5, p6, p7, p8, "sd"); // <<<<<  If change this line by the next one then flash directory is OK but not SD
MSCFileSystem msc("msc");               // <<<<<< it seems that whichever is first wins.

void DIR_FLASH(void)
{
DIR *d;
struct dirent *p;

printf("\n\rFLASH directory\n\r");
d = opendir("/msc");
if (d != NULL) {
while ((p = readdir(d)) != NULL) {
printf(" - %s\n\r", p->d_name);
}
} else {
printf("Could not open directory!\n\r");
}
closedir(d);
}

void DIR_SD(void)
{
DIR *d;
struct dirent *p;

printf("\n\rSD directory\n\r");    
d = opendir("/sd");
if (d != NULL) {
while ((p = readdir(d)) != NULL) {
printf(" - %s\n\r", p->d_name);
}
} else {
printf("Could not open directory!\n\r");
}
closedir(d);
}



int main() {

DIR_SD();
DIR_FLASH();     
}

 

 

08 Dec 2010

Hi,

I see identical behavior on my mbed. I have all 3 filesystems active, SD, MSC and the local flash. I can even have 2 different files open on SD and MSC an dthat works, but not the directory. The local flash is independent here, that works all the time. The problem is then likely in the FAT File System, since MSC and SD both use that.

Even when explicitly opening an existing subdirectory on a USB stick, it will not list this if the SDFilesystem was first in the declarations.

  d = opendir("/usb/sub");
  
  if(d != NULL) {
    while ((p = readdir(d)) != NULL) {
      printf(" - %s\n", p->d_name);
    }
  }

It would also be very nice to get more info from the directory handle, such as file size and attributes. This is buried pretty deep inside the libraries, so maybe someone who ported the file FAT File System can shed a light on this.

Meindert

11 Dec 2010

After some experimentation I have found the solution. For details, please refer to http://elm-chan.org/fsw/ff/00index_e.html, which is teh startpage of the original author of the FAT Filesystem support. This is a powerful bit of software, and the Mbed port with the 'official' functions imposes some restrictions, which in my opinion are a bit unnecessary. Fortunately access to the underlying software is still possible.

It is important to understand that the this FATFiuleSystem has a concept of drives, almost like to good old dos. In this case, the first declared filesystem becomes drive '0:', the second is drive '1:', and this is also how the roots of these filesystems should be referred to.

To read the SD card (when declared first):  d = sd.opendir("0:");

To read the USB directory (2nd): d = sd.opendir("1:");  note that you cannot just use d = opendir, you must refer to the usb or sd class!

More powerful is the direct use of the libraries, which allows you to read subdirectories, file size and other attributes, see the bit of code below:

 

void do_fdir() {
  // list directory entry
  
  FATFS_DIR dj;
  FILINFO finfo;
  FRESULT res ;
  char *fn;
  
  DBG_msg("do_ffdir", inbuf);
      
  if (inbuf[2] != NULL) {
    switch (inbuf[2]) {
      case f_sdcard : res = f_opendir(&dj, "0:/");
                      break;                      // SD is first in the declarations                  
      case f_usb    : res = f_opendir(&dj, "1:/");
                      break;                                            
      default       : do_fdefault();                     // command not recognized
                      break;    
    }     
  } else {
    do_fdefault();      
    return;
  }
  
  if(res == FR_OK) {
    for (;;) {
      res = f_readdir(&dj, &finfo); 
      if ((res != FR_OK) || finfo.fname[0] == 0) break;
                
      printf(" - %s - %d\n", finfo.fname, finfo.fsize);
    }
    
  } else {
    DBG_msg("Could not open directory!", "");
  }
    
  
  DIR *d;
  struct dirent *p;

  d = opendir("1:/");
  
  if(d != NULL) {
    while ((p = readdir(d)) != NULL) {
      printf("MBED - %s \n", p->d_name);
    }  
  } else {
    DBG_msg("Could not open directory!", "MBED method");
  }

  
}

Be aware that the local filesystem does NOT use FATFileSystem, and only the 'regular' functions work, the above does not work on the local flash (unfortunately).

Meindert

 

 

 

16 Jul 2012

I am trying to make a fileselector system and also got stuck at the opendir function not giving file size and attributes. I put in the above code but now I only get the short file names 8+3.

Any ideas how to get longfilename support working with these routines ? I already searched in the FatDirHandle functions and found this:

  #if _USE_LFN
    finfo.lfname = cur_entry.d_name;
    finfo.lfsize = sizeof(cur_entry.d_name);
#endif // _USE_LFN

But I can not find out where this 'cur_entry' struct gets filled with data.

16 Jul 2012

Hello Gert,

I am already interested in using long filenames in my program. Have You any further investigation, now?

16 Jul 2012

I also found some info on page mentoied above http://elm-chan.org/fsw/ff/en/readdir.html with example code.

Is it possible that something like



#define _USE_LFN 1

FRESULT scan_files (
    char* path        /* Start node to be scanned (also used as work area) */
)
{
    FRESULT res;
    FILINFO fno;
    DIR dir;
    int i;
    char *fn;


/* some code */

#if _USE_LFN
    static char lfn[_MAX_LFN + 1];
    fno.lfname = lfn;
    fno.lfsize = sizeof lfn;
#endif


    res = f_opendir(&dir, path);                       /* Open the directory */
    if (res == FR_OK) {
        i = strlen(path);
        for (;;) {
            res = f_readdir(&dir, &fno);                   /* Read a directory item */
            if (res != FR_OK || fno.fname[0] == 0) break;  /* Break on error or end of dir */
            if (fno.fname[0] == '.') continue;             /* Ignore dot entry */
#if _USE_LFN
            fn = *fno.lfname ? fno.lfname : fno.fname;
#else
            fn = fno.fname;
#endif
            if (fno.fattrib & AM_DIR) {                    /* It is a directory */
                sprintf(&path[i], "/%s", fn);
                res = scan_files(path);
                if (res != FR_OK) break;
                path[i] = 0;
            } else {                                       /* It is a file. */
                printf("%s/%s\n", path, fn);
            }
        }
    }

    return res;
}

can turn long filename support on?

16 Jul 2012

Yep, that did the trick. I still do not know where the long file name is filled into 'lfn' but it works:

/media/uploads/gertk/_scaled_2012-07-16_19.25.37.jpg

The date and time are not evaluated by my program yet but those are accessible too. Great!

21 Feb 2013

Hello,

I'm experiencing the same problem. In my application I want to detect if there is a USB Storage connected. If yes, data will be written to that USB, if it is not present, data will be written to SD Card (which is always present).

I'm detecting USB Storage by trying to open a file in append mode.It the file pointer is null after fopen(), then there is no USB device.

Which libraries should I use in order to write to USB Host Mass Storage and SD Card File System without conflicts at runtime?

Thanks!