Приложение для SD-карты MSP430, запущенное поверх FATFS, кажется слишком ограничительным. Правильно ли я понимаю?

#c #msp430 #fatfs

#c #msp430 #fatfs

Вопрос:

Я работаю над примером кода приложения для SD-карты, предоставленным TI для их комплекта разработки микроконтроллеров MSP530 LaunchPad. Похоже, что в примере количество каталогов и количество файлов ограничено 10 в каждом (всего 100 файлов), что кажется чрезмерно ограничительным для SD-карты объемом 32 ГБ. Текущий код компилируется для использования менее половины программного пространства и менее половины доступной оперативной памяти. Мне интересно, не понимаю ли я неправильно код или код ограничен по какой-либо другой причине, например, доступным размером стека в памяти. Ниже приведен код и мои комментарии.

Существует несколько уровней: SDCardLogMode, sdcard (SDCardLib) и ff (уровень HAL). Я сократил приведенный ниже код, чтобы проиллюстрировать конструкции, но не выполнимо — меня больше интересует, правильно ли я это понимаю и не является ли мое решение по увеличению количества разрешенных файлов и каталогов ошибочным.

SDCardLogMode.c здесь представляют интерес два места. Первое — это объявление каталогов char[10][MAX_DIR_LEN] и files[10][MAX_FILE_LEN]. МАКСИМАЛЬНЫЕ значения объектива равны 8 и 12 соответственно и являются максимально допустимой длиной имени.

 /*******************************************************************************
     *
     * 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;

    //....
  

Позже в том же файле SDCardLogMode.c есть следующая функция (также сокращенная для удобства чтения). Здесь интересно то, что код вызывает SDCardLib_getDirectory(amp;sdCardLib, «data_log», каталоги, amp;dirNum, files, amp;fileNum), который использует путь «data_log» и создает каталог, а также обновляет amp;dirNum, files и amp;fileNum . Я не верю, что amp;sdCardLib (который содержит дескриптор FATFS и указатель интерфейса) используется в этой функции. По крайней мере, я не могу сказать.

Что вызывает недоумение, так это какой смысл вызывать SDCardLib_getDirectory(), а затем не использовать ничего, что оно создает? Я не нашел никакого последующего использования каталогов и массивов символов files. Я также не нашел никакого использования dirNum и fileNum.

Во фрагментах кода я показываю код для SDCardLib_getDirectory(). Я не смог найти, где используется параметр SDCardLib. И, как упоминалось ранее, я не нашел использования файлов и массивов dirs. Я вижу, где количество файлов и каталогов может быть использовано для генерации новых имен, но уже существуют статические переменные для хранения количества файлов. Кто-нибудь может увидеть причину, по которой был вызван SDCard_getDirectory()?

     /*
     * 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(amp;sdCardLib);
        if (st == SDCARDLIB_STATUS_NOT_PRESENT) {
            SDCardLib_unInit(amp;sdCardLib);
            mode = '0';
            noSDCard = 1; //jn added
            return;
        }

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

        //Create the directory under the root directory
        rc = SDCardLib_createDirectory(amp;sdCardLib, "data_log");
        if (rc != FR_OK amp;amp; rc != FR_EXIST) {
            SDCardLib_unInit(amp;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(amp;dir, directoryName);

    for (;;)
    {
        rc = f_readdir(amp;dir, amp;fno);                        // Read a directory item
        if (rc || !fno.fname[0]) break;                    // Error or end of dir
        if (fno.fattrib amp; 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;
}
  

Ниже приведен SDCardLib_createDirectory(SDCardLib * lib, char * directoryName). Оно просто создает каталог, оно не проверяет существующее количество файлов.

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

Итак, возвращаясь к моим вопросам:

  1. Правильно ли я понял этот код, действительно ли он ограничивает количество каталогов и файлов до 10 в каждом?

  2. Если да, то почему количество файлов и каталогов должно быть таким ограниченным? Конкретный MSP430, с которым поставляется этот пример кода, имеет 256 КБ программного пространства и 8 КБ оперативной памяти. Скомпилированный код потребляет менее половины доступных ресурсов (68 КБ программного пространства и около 2,5 КБ оперативной памяти). Это потому, что любой больший размер переполнит сегмент стека?

  3. Я хочу увеличить количество файлов, которые можно хранить. Если я посмотрю на базовый код FATFS, он не налагает ограничения на количество файлов или каталогов (по крайней мере, пока SD-карта не заполнится). Если я никогда не собираюсь отображать содержимое каталога в MSP430 или выполнять поиск в нем, я думаю, что следует удалить SDCard_getDirectory() и два массива символов (files и dirs). Есть ли причина, по которой это было бы плохой идеей?

Ответ №1:

Существуют другие микроконтроллеры с меньшим объемом памяти.

SDCardLib_getDirectory() Функция обрабатывает свои dirList и fileList параметры как простые строки, т. е. она вызывает strcat() по тем же указателям. Это означает, что оно может считывать столько имен, сколько помещается в 10 * 8 или 10 * 12 байт.

А вызов strcat() без добавления разделителя означает, что невозможно извлечь отдельные имена из строки.

Этот код демонстрирует, что можно использовать библиотеку FatFs и в каком порядке нужно вызывать ее функции, но это не обязательно хороший пример того, как это сделать. Я рекомендую вам написать свой собственный код.

Комментарии:

1. Два параметра, передаваемые как указатели на dirList и FileList, объявляются как двумерные массивы символов — char dirs[10][MAX_DIR_LEN] и char files[10]{MAX_FILE_LEN].. Массив для каталогов равен [10] [8], а для файлов равен [10][12], причем второе измерение ограничивает допустимую длину имени. первое измерение говорит, что у меня может быть 10 таких имен. f_readdir() перебирает этот массив, увеличивая указатель на длину поля name. Таким образом, оно может содержать только 10 имен, прежде чем переполнит массив и завершится сбоем. Я не понимаю, откуда в вашем объяснении взялись значения 80 и 100. пожалуйста, расскажите подробнее.

2. f_readdir() никогда не видит эти массивы; к ним обращаются только strcat() вызовы.

3. f_readdir их не видит, но strcat видит. strcat использует информацию, извлеченную из . структура fno (возвращаемая f_readdir) для записи в эти массивы. Таким образом, косвенно все файлы и каталоги, найденные с помощью f_readdir, записываются в эти массивы.