0

I am working my way through an SD card application code example provided by TI for their MSP530 LaunchPad microcontroller development kit. It appears that the example restricts the number of directories and number of files to 10 each (a total of 100 files) which seems overly restrictive for a 32GB SD card. The current code compiles to use less than half of the program space and less than half of available RAM. I am wondering if I misunderstand the code, or if the code is limited by some other reason, such as the available stack size in memory. Below is the code and my comments.

There are several layers: SDCardLogMode, sdcard (SDCardLib), and ff (HAL layer). I've reduced the code below to illustrate the constructions but not runnable - I am more interested if I understand it correctly and if my solution to increase the number of allowed files and directories is flawed.

SDCardLogMode.c there are two places of interest here. The first is the declaration of char dirs[10][MAX_DIR_LEN] and files[10][MAX_FILE_LEN]. the MAX LENs are 8 and 12 respectively and are the maximum allowed length of a name.

/*******************************************************************************
     *
     * SDCardLogMode.c
     * ******************************************************************************/

    #include "stdlib.h"
    #include "string.h"
    #include "SDCardLogMode.h"
    #include "driverlib.h"
    #include "sdcard.h"
    #include "HAL_SDCard.h"

    #pragma PERSISTENT(numLogFiles)
    uint8_t numLogFiles = 0;


    SDCardLib sdCardLib;
    char dirs[10][MAX_DIR_LEN];
    char files[10][MAX_FILE_LEN]; //10 file names. MAX_FILE_LEN =10
    uint8_t dirNum = 0;
    uint8_t fileNum = 0;

    #define MAX_BUF_SIZE 32
    char buffer[MAX_BUF_SIZE];

    // FatFs Static Variables
    static FIL fil;        /* File object */
    static char filename[31];
    static FRESULT rc;

    //....

Later in the same SDCardLogMode.c file is the following function (also reduced for readability). Here the interesting thing is that the code calls SDCardLib_getDirectory(&sdCardLib, "data_log", dirs, &dirNum, files, &fileNum) which consume the "data_log" path and produces dir, and updates &dirNum, files, and &fileNum. I do not believe &sdCardLib (which holds a handle to the FATFS and an interface pointer) is used in this function. At least not that I can tell.

What is puzzling is what's the point of calling SDCardLib_getDirectory() and then not using anything it produces? I did not find any downstream use of the dirs and files char arrays. Nor did I find any use of dirNum and fileNum either.

In the code snippets I show the code for SDCardLib_getDirectory(). I could not find where SDCardLib parameter is used. And as mentioned earlier, I found no use of files and dirs arrays. I can see where the file and directory count could be used to generate new names, but there are already static variables to hold the file count. Can anyone see a reason why the SDCard_getDirectory() was called?

    /*
     * Store TimeStamp from PC when logging starts to SDCard
     */
    void storeTimeStampSDCard()
    {
        int i = 0;
        uint16_t bw = 0;
        unsigned long long epoch;

    //  FRESULT rc;

        // Increment log file number
        numLogFiles++;
,
        //Detect SD card
        SDCardLib_Status st = SDCardLib_detectCard(&sdCardLib);
        if (st == SDCARDLIB_STATUS_NOT_PRESENT) {
            SDCardLib_unInit(&sdCardLib);
            mode = '0';
            noSDCard = 1; //jn added
            return;
        }

    // Read directory and file
        rc = SDCardLib_getDirectory(&sdCardLib, "data_log", dirs, &dirNum, files, &fileNum);

        //Create the directory under the root directory
        rc = SDCardLib_createDirectory(&sdCardLib, "data_log");
        if (rc != FR_OK && rc != FR_EXIST) {
            SDCardLib_unInit(&sdCardLib);
            mode = '0';
            return;
        }

    //........

    }

Now jumping to sdcard.c (SDCardLib layer) to look at SDCardLib_getDirectory() is interesting. It takes the array pointer assigns it to a one dimensional array (e.g. char (*fileList)[MAX_FILE_LEN] and indexes it each time it writes a filename). This code seem fragile since the SDCardLib_createDirectory() simply returns f_mkdir(directoryName), it does not check how many files already exist. Perhaps TI assumes this checking should be done at the application layer above SDCardLogMode....

void SDCardLib_unInit(SDCardLib * lib)
{
    /* Unregister work area prior to discard it */
    f_mount(0, NULL);
}

FRESULT SDCardLib_getDirectory(SDCardLib * lib,
                            char * directoryName, 
                            char (*dirList)[MAX_DIR_LEN], uint8_t *dirNum,
                            char (*fileList)[MAX_FILE_LEN], uint8_t *fileNum)
{
    FRESULT rc;                                            /* Result code */
    DIRS dir;                                               /* Directory object */
    FILINFO fno;                                           /* File information object */
    uint8_t dirCnt = 0;                /* track current directory count */
    uint8_t fileCnt = 0;                /* track current directory count */

    rc = f_opendir(&dir, directoryName);

    for (;;)
    {
        rc = f_readdir(&dir, &fno);                        // Read a directory item
        if (rc || !fno.fname[0]) break;                    // Error or end of dir
        if (fno.fattrib & AM_DIR)                          //this is a directory
        {
            strcat(*dirList, fno.fname);                      //add this to our list of names
            dirCnt++;
            dirList++;
        }
        else                                               //this is a file
        {
            strcat(*fileList, fno.fname);                      //add this to our list of names
            fileCnt++;
            fileList++;
        }
    }

    *dirNum = dirCnt;
    *fileNum = fileCnt;

    return rc;
}

Below is SDCardLib_createDirectory(SDCardLib *lib, char *directoryName). It just creates a directory, it does not check on the existing number of files.

FRESULT SDCardLib_createDirectory(SDCardLib * lib, char * directoryName)
{
    return f_mkdir(directoryName);
}

So coming back to my questions:

  1. Did I understand this code correctly, does it really does limit the number of directories and files to 10 each?

  2. If so, why would the number of files and directories be so limited? The particular MSP430 that this example code came with has 256KB of program space and 8KB of RAM. The compiled code consumes less than half of the available resources (68KB of program space and about 2.5KB of RAM). Is it because any larger would overflow the stack segment?

  3. I want to increase the number of files that can be stored. If I look at the underlying FATFS code, it does not to impose a limit on the number of files or directories (at least not until the sd card is full). If I never intend to display or search the contents of a directory on the MSP430 my thought is to remove SDCard_getDirectory() and the two char arrays (files and dirs). Would there a reason why this would be a bad idea?

fuz
  • 88,405
  • 25
  • 200
  • 352
jaz_n
  • 41
  • 6

1 Answers1

0

There are other microcontrollers with less memory.

The SDCardLib_getDirectory() function treats its dirList and fileList parameters as simple strings, i.e., it calls strcat() on the same pointers. This means that it can read as many names as fit into 10*8 or 10*12 bytes.

And calling strcat() without adding a delimiter means that it is impossible to get the individual names out of the string.

This codes demonstrates that it is possible to use the FatFs library, and in which order its functions need to be called, but it is not necessarily a good example of how to do that. I recommend that you write your own code.

CL.
  • 173,858
  • 17
  • 217
  • 259
  • The two parameters passed as pointers to dirList and fileList are declared as 2 dimensional char arrays - char dirs[10][MAX_DIR_LEN] and char files[10]{MAX_FILE_LEN].. The array for dirs is [10][8] and for files is [10][12] with the second dimension restricting the allowed length of the name. the first dimension says i can have 10 such names. f_readdir() loops through this array by incrementing the pointer by the length of name field. Thus it can only hold 10 names before overflowing the array and failing. I don't see where the 80 and 100 values came from in your explanation. please say more. – jaz_n Mar 04 '19 at 16:18
  • `f_readdir()` does not ever see these arrays; they are accessed only by the `strcat()` calls. – CL. Mar 04 '19 at 16:59
  • f_readdir doesn't see them but strcat does. strcat uses information extracted from . the fno struct (returned by f_readdir) to write into those arrays.So indirectly all the files and directories found by f_readdir are written to those arrays. – jaz_n Mar 05 '19 at 03:35