Главная arrow Программирование arrow ARM arrow Библиотека EFSL Sunday, October 22 2017  
ГлавнаяКонтактыАдминистрированиеПрограммированиеСсылки
UK-flag-ico.png English Version
GERMAN-flag-ico.png Die deutsche Version
map.gif карта сайта
нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Поделиться:

Библиотека EFSL Версия для печати
Написал microsin   
10.11.2009

Здесь записаны кое-какие сведения по результатам разборок с исходниками EFSL.

Если кто не знает,  EFSL - бесплатная библиотека для работы с файловой системой FAT (поддерживается FAT12, FAT16 и FAT32). Расшифровывается аббревиатура как Embedded Filesystems Library (предназначенная для микроконтроллеров библиотека файловой системы).

[Подключение к карте SD/MMC]

MMC_SD02.JPG MMC_SD01.JPG

Примеры вариантов подключения карты SD/MMC к микроконтроллеру ARM7 (AT91SAM7X128, AT91SAM7X256, AT91SAM7X512) приведены в таблице ниже. Можно подключить карту либо к SPI0, либо к SPI1. Например, в макетной плате Olimex SAM7-EX256 используется вариант 1 подключения карты SD/MMC. В бутлоадере, можно выбрать любой вариант в зависимости от макроопределений (см. файл at91lib\board\board.h, макрос SELECT_TO_MMC_SPI1). Для подключения сигнала выборки ~CS существует еще больше вариантов, так как каждый из SPIn имеет по 4 аппаратных выхода выборки.


конт.

сигнал
описание
Вариант 1 подключения
(SPI0, PIOA, периферия A)
Вариант 2 подключения
(SPI1, PIOA, периферия B)
1
~CS
выборка карты (режим DAT3 не используется)
PA13
PA21
2
MOSI
данные, приходящие на вход карты
PA17
PA23
3
GND
минус питания карты, сигнальная земля
   
4
VCC
плюс питания карты, от 2.7 до 3.6 вольт, самый лучший вариант 3 вольта
   
5
SCK
такты данных, поступающие на вход карты
PA18
PA22
6
GND
минус питания карты, сигнальная земля    
7
MISO
данные, уходящие с выхода карты (DAT0)
PA16
PA24
8
  не используется (DAT1)
   
9
  не используется (DAT2)
   

[Особенности внутренней реализации и использования библиотеки EFSL]

1. Итак, EFSL поддерживает FAT12, FAT16 and FAT32. VFAT (расширение FAT, позволяющее оперировать длинными именами) не поддерживается, т. е. все имена записываются и читаются строго в формате 8.3. К сожалению, Windows штатными методами (через свойства тома) не позволяет посмотреть тип файловой системы Вашей флешки, т. е. и FAT12, и FAT16 будут отображаться одинаково как FAT. Отформатировать нужным образом (выбрать FAT12, FAT16 или FAT32) тоже нельзя, нужно использовать специальные программы. При использовании FAT12 и FAT16 есть ограничение на количество файлов в корневом каталоге - например, мне не удалось записать больше 330 файлов.

2. Библиотека EFSL, что попала мне в руки (0.2.7, 2005 год) изначально была не рассчитана на поддержку символов русского языка в именах файлов (кодировка CP866) - функция file.c\file_validateChar старательно вырезала символы русского языка (с кодами больше 127) и заменяла их на букву X. Также и заменялись символы '%'. Я немного доработал код функции file_validateChar, чтобы можно было использовать символы русского языка:

/* ****************************************************************************
* Описание: эта функция принимает символ c, и если это недопустимый символ    *
* для имени FAT, то возвращает символ 'X'. если это буква в нижнем регистре,  *
* возвращается эквивалент в верхнем регистреed. Остальные символы передаются  *
* как есть, без изменений.                                                    *
* Возвращаемое значение: приведенный "верный" символ                          *
******************************************************************************/
euint8 file_validateChar(euint8 c)
{
    if( (c<0x20) || (c>0x20&&c<0x30&&c!='-'&&c!='%') || (c>0x39&&c<0x41) || (c>0x5A&&c<0x61&&c!='_')
     || (c>0x7A&&c<0x80&&c!='~') || (c>0xAF&&c<0xE0) || (c>0xEF))
        return(0x58);
    if( c>=0x61 && c<=0x7A )
        return(c-32);

    return(c);
}

3. Для получения списка файлов и папок каталога используют последовательные вызовы функций efs_init, ls_openDir (которой в последнем параметре указывается путь до каталога, список которого надо получить) и ls_getNext (эта функция последовательно получает все имена указанного каталога и атрибут типа объекта - файл, папка или метка тома) - см. примеры из документации по EFSL. Например, чтобы получить список корневого каталога карточки MMC, нужно для функции ls_openDir в качестве пути указать "/", а чтобы прочитать содержимое папки fold01 корневого каталога, нужно указать путь "/fold01/" (путь должен обязательно завершаться слешем!).

Функция ls_getNext выбирает имена друг за другом в неотсортированном порядке (сохранен порядок создания файлов, т. е. появления записей в каталоге).

Навигацию можно начать заново (функция ls_getNext при этом спозиционируется снова в начало списка), если еще раз вызвать ls_openDir (функции, "закрывающей" каталог, нет). Навигацию с помошью функции можно продолжить с произвольной позиции каталога, если её предваритеельно запомнить в переменной типа DirList, а потом запомненное значение использовать в вызове ls_getNext.

По окончании работы с файловой системой нужно вызвать функцию fs_umount.

4. Чтобы получить количество файлов в папке, нужно последовательно прочитать весь список файлов в папке (функциями ls_openDir и ls_getNext), другого более быстрого метода нет.

5. Чтобы получить дату и время создания файла, необходимо открыть файл функцией file_fopen, и прочитать 16-битные значения из полей (EmbeddedFile)file.DirEntry.WriteDate, (EmbeddedFile)file.DirEntry.WriteTime. Дата закодирована следущим образом:
[15][14][13][12][11][10][ 9][ 8][ 7][ 6][ 5][ 4][ 3][ 2][ 1][ 0]
      Y   Y   Y   Y   Y   Y   M   M   M   M   D   D   D   D   D

Время закодировано следующим образом:
[15][14][13][12][11][10][ 9][ 8][ 7][ 6][ 5][ 4][ 3][ 2][ 1][ 0]
  H   H   H   H   H   M   M   M   M   M   M   S   S   S   S   S

При этом секунды кодируются с точностью до пар секунд (в разряды 0..4 пишется число секунд, поделенное на 2).

Для ускорения получения даты и времени (без открытия файла) написал функцию getFileRecord:

/* ***************************************************************************\
    Заполняет поля параметра file->DirEntry. В случае успеха возвращает 0.
*/
esint8 getFileRecord (File* file, FileSystem *fs, eint8* filename)
{
    FileLocation loc;

    if(fs_findFile(fs,filename,&loc,0)==1)
    {
        dir_getFileStructure(fs,&file->DirEntry,&loc);
        return 0;
    }
    return -1;
}

Входные параметры этой функции:

File* file - просто указатель на тупо выделенную память под объект EmbeddedFile file. Все результат работы функции (в котором есть информациия и по дате/времени) сохраняются в этом объекте.

FileSystem *fs - указатель на файловую систему, которую получаем при инициализации библиотеки EFSL.
eint8* filename - указатель на строку с полным путем к нужному файлу.

Пример работы с функцией:

EmbeddedFileSystem efsl;
...
//инициализируем файловую систему
if (!efs_initialized)
{
    if ( efs_init (&efsl, 0) !=0 )
    {
        //printf ( "Could not open filesystem.\n" );
        ErrMsg();
        return;
    }
    else
    {
        efs_initialized = true;
    }
}
//открываем нужный путь
if (ls_openDir ( &list, &(efsl.myFs), arcpath ) != 0)
{
    //printf ( "Could not open list at %s.\n", arcpath );
    ErrMsg();
    memset (foldname, 0, sizeof(foldname));
    crm = CAT_READ_DIRS;
    return;
}
...

DirList list;
...

if (0 != ls_getNext (&list))
{
    //обработка ошибки
}

EmbeddedFile file;
char name[9];
char ext [4];
char full_path [TXTBUF_SIZE/*1 +8+1+3 +1 +8+1+3 +1*/];
memset(name, 0, sizeof(name));
memset(ext , 0, sizeof(ext ));
strncpy(name,(char*) list->currentEntry.FileName,  8);
strncpy(ext, (char*)&list->currentEntry.FileName[8],3);
trim(name);
trim(ext);
//теперь получим дату и время файла
strcpy(full_path, arcpath);
strcat(full_path, name);
strcat(full_path, ".");
strcat(full_path, ext);
if (0 != getFileRecord(&file,&efsl.myFs,full_path))
{
    //Обработка ошибки:
    printf ( "Can`t get file record %s.%s\n", name, ext );
    ...
}
else
{
    DecodeDate(file.DirEntry.WriteDate);
    DecodeTime(file.DirEntry.WriteTime);
}

char* DecodeDate (u16 date)
{
    u8 m, d;
    char y[5];
 
    sprintf (y,"%4i", 1980 + ((date >> 9)&0x3F));
    m = (date >> 5)&0x0F;
    d = date & 0x1F;
    sprintf (datestr, "%02i.%02i.%s", d, m, &y[2]);
    datestr[8] = 0;
    return datestr;
}

char* DecodeTime (u16 time)
{
    u8 h, m, s;
    h = (time >> 11)&0x1F;
    m = (time >> 5) &0x3F;
    s = (time      &0x1F) * 2;
    sprintf (timestr, "%02i:%02i:%02i", h, m, s);
    timestr[8] = 0;
    return timestr;
}

6. Конфигурация кеша arm7_efsl_0_2_7\inc\config.h - #define IOMAN_NUMBUFFER 6, размер кеша 512*3 = 3 кБайта. Попробовал выключить (указать #define IOMAN_NUMBUFFER 0) - чтобы проверить, как кеш влияет на скорость чтения каталога - но компилятор начал ругаться. Если указать #define IOMAN_NUMBUFFER 1, видимого замедления чтения каталога не происходит.

7. С помощью светодиода выяснил, что больше всего времени при прокрутке каталога (вычитывании данных по файлу) занимает подпрограмма dir.c\dir_findinCluster. Она вызывается переменное количество раз для одного файла, причем чем дальше по каталогу, тем бОльшее количество. Из-за этого навигация по каталогу при уходе от начала вглубь сильно замедляется.

8. Функция ls_openDir требует, чтобы в имени открываемой папки в конце присутствовал завершающий слеш.

9. В библиотеке EFSL нет функции удаления папки. Есть только функция rmfile, которая удаляет файлы. Эта функция папки удалять не может (как пустые, так и заполненные). Оказалось все довольно просто - можно взять за основу rmfile, и переделать её так, что она будет удалять и папки. В начале этой функции есть поиск файла вызовом fs_findFile. При удалении файла ожидается, что функция fs_findFile вернет 1. При удалении директории нужно ждать, что функция fs_findFile вернет 2. Вот функция rmdir для удаления папки:

/* ****************************************************************************
* esint16 rmdir (FileSystem *fs, euint8* dir)
* Description: функция удаляет папку по имени, путем освобождения её цепочки
* кластеров, и удаления его записи из директории.
* Return value: 0 если О.К., -1 при ошибке типа файл не найден.
*/
esint16 rmdir (FileSystem *fs, euint8* dir)
{
    FileLocation loc;
    ClusterChain cache;
    euint8* buf;
    euint32 firstCluster=0;

    if((fs_findFile(fs, (eint8*)dir, &loc,0))==2)
    {
        buf=part_getSect(fs->part,loc.Sector,IOM_MODE_READWRITE);
        firstCluster = ex_getb16(buf,loc.Offset*32+20);
        firstCluster <<= 16;
        firstCluster += ex_getb16(buf,loc.Offset*32+26);
        /* Bugfix:
         * Очищая всю структуру, Вы отмечаете конец каталога.
         * If this is not the case, files that are further away cannot
         * be opened anymore by implementations that follow the spec. */
        /*memClr(buf+(loc.Offset*32),32);*/
        *(buf+(loc.Offset*32)+0) = 0xE5; /* Mark file deleted */
        part_relSect(fs->part,buf);
        cache.DiscCluster = cache.LastCluster = cache.Linear = cache.LogicCluster = 0;
        cache.FirstCluster = firstCluster;
        fat_unlinkClusterChain(fs,&cache);
        return(0);
    }
    return(-1);
}

Эту функцию нужно использовать с осторожностью, так как она может "удалить" непустую папку - нет проверки на то, что удаляемая папка содержит файлы. При этом на диске образуются пропавшие кластеры (они относятся к тем файлам, которые были в этой папке). Поэтому перед вызовом rmdir нужно проверить, есть ли в удаляемой папке файлы, и если есть, то либо отказаться от удаления папки, либо предварительно удалить все файлы из папки, а потом вызвать rmdir.

10. При всех операциях записи (удаление файлов, добавление каталогов и т. п.) на карточку напрямую ничего не пишется - все идет через кеш, которым управляет подсистема ввода-вывода второго уровня - IOMan, или iomanager. Таким образом, если Вы удалите какой-нибудь файл функцией rmfile, затем вытащите карточку, не размонтировав файловую систему (вызовом fs_umount(&efsl.myFs)), то удаленный файл все равно на карточке останется. Для принудительной синхронизации кеша и носителя (без размонтирования) удобно пользоваться функцией ioman_flushAll(&efsl.myIOman). Подробнее про IOMan читайте в статье EFSL: I/O Manager (менеджер ввода/вывода).

11. Нашел и исправил несколько ошибок ui.c\short listFiles(FileSystem *fs, char *dirname). Эта функция подсчитывает количество файлов в папке dir. Одна из ошибок была в том, что эта функция не могла посчитать файлы, у которых первая буква в имени была русская. Это поправить было довольно легко. Другая ошибка была в том, что не инициализировались поля локальной переменной File dir, из-за чего не отрабатывал вызов функции file_fread(&dir,offset,512,buf) в условии цикла while. Не инициализировалось поле dir.FileStatus - поправил, добавив вызов file_setAttr(&dir, FILE_STATUS_OPEN, 1), а также поле FileSize, и из-за этого file_fread не могла прочитать файл директории. Тупо исправил ошибку, проинициализировав dir.FileSize значением -1 (потому что не смог разобраться, как узнать размер файла директории). Вот подправленная функция listFiles:

short listFiles(FileSystem *fs, char *dirname)
{
    unsigned long startCluster;
    unsigned char fileEntryCount;
    unsigned short counter=0;
    unsigned long offset=0;
    FileRecord fileEntry;
    FileLocation loc;
    unsigned char buf[512];
    File dir;
    unsigned short i;

    /* Find out if we are searching in the root dir or in */
    if(dirname[0]=='/' && dirname[1]=='\0')
    {
        if( (fs->type == FAT12) || (fs->type == FAT16) )
        {
            for(i=0;i<=(fs->volumeId.RootEntryCount/16);i++)
            {
                loc.Sector=fs->FirstSectorRootDir + i;
                part_readBuf(fs->part,loc.Sector,buf);
                /* I STOPPED HERE*/
                /* FIXME */
            }
        }
    }
    else /* Normal directory */
    {
        /* Check if path given is a directory */
        if(fs_findFile(fs,dirname,&loc,0)!=2)
        {
            //FUNC_OUT((TXT("")));
            return(-1);
        }

        /* Find out what the startcluster of the directory is */
        part_readBuf(fs->part,loc.Sector, buf);
        fileEntry = *(((FileRecord*)buf) + loc.Offset);
        startCluster = (((unsigned long)fileEntry.FirstClusterHigh)<<16)
            + fileEntry.FirstClusterLow;

        /* Init of dir */
        dir.fs=fs;
        dir.Cache.LogicCluster=-1;
        dir.Cache.FirstCluster=startCluster;
        dir.DirEntry.Attribute=ATTR_DIRECTORY;
        file_setAttr(&dir, FILE_STATUS_OPEN, 1);
        dir.FileSize = (euint32)(-1);

        while((file_fread(&dir,offset,512,buf)))
        {
            DBG((TXT("Read 512 bytes from dir with offset %li.\n"),offset));
            for(fileEntryCount=0;fileEntryCount<16;fileEntryCount++)
            {
                fileEntry = *(((FileRecord*)buf) + fileEntryCount);
                if( !( (fileEntry.Attribute & 0x0F) == 0x0F ) )
                {
                    if (fileEntry.FileName[0] == 0xE5)
                        continue;
                    if
                    (
                     (fileEntry.FileName[0]>='A' && fileEntry.FileName[0]<='Z')
                     ||
                     (fileEntry.FileName[0]>='0' && fileEntry.FileName[0]<='9')
                     ||
                     (fileEntry.FileName[0]>='a' && fileEntry.FileName[0]<='z')
                     ||
                     (fileEntry.FileName[0]>=0x80)
                    )
                    {
                        DBG((TXT("Filename: %s\n"),fileEntry.FileName));
                        counter++;
                    }
                }
            }
            offset+=512;
        }
    }
    FUNC_OUT((TXT("")));
    file_setAttr(&dir, FILE_STATUS_OPEN, 0);
    return(counter);
}

12. При проверке корректности удаления файлов и папок из библиотеки EFSL выяснилась интересная фича. Когда я в папке удаляю файлы с русскими именами (они короткие 8.3), то место освобождается не полностью. chkdsk g: пишет, что нашел "поврежденный длинный элемент папки" - сколько было удалено файлов, столько и "поврежденных длинных элементов". Когда я удаляю после этого папку, откуда удалил все файлы, то chkdsk пишет, что ошибок нет. Когда я таким образом удаляю с диска все папки, то ошибок тоже нет, и флешка восстанавливает полностью свободное место (оно равно по объему величине сразу после форматирования). Если я тупо удаляю папку, не удаляя предварительно из неё файлы, то свободное место на диске теряется на потерянные кластеры.

Таким образом, из этого можно сделать вывод - библитека EFSL работает вполне корректно в плане освобождения места при удалении только в том случае, если не используются длинные имена файлов. Возможно, что русские имена тоже относятся к длинным именам, поэтому и происходят ошибки с "поврежденными длинными элементами".

13. Исправил следующие ошибки:
ioman.c -> ioman_flushSector
Было:
if(!(ioman_writeSector(ioman,ioman->sector[bufplace],buf)))
{
    ioman_setError(ioman,IOMAN_ERR_WRITEFAIL);
    return(-1);
}
Поправил:
if(-1 == ioman_writeSector(ioman,ioman->sector[bufplace],buf))
{
    ioman_setError(ioman,IOMAN_ERR_WRITEFAIL);
    return(-1);
}
sc.c -> sd_writeSector
Было:
return(0);
Поправил:
return(1);
Так сделал потому, что ioman_writeSector проверяет результат if_writeBuf, и он должен быть >0.

14. Поддержка даты и времени файлов.

Для того, чтобы создании и модификации файлов корректно указывалось время, нужно сделать две вещи:
- в файле arm7_efsl_0_2_7\inc\config.h раскомментировать строку #define DATE_TIME_SUPPORT
- определить код для функций efsl_getYear, efsl_getMonth, efsl_getDay, efsl_getHour, efsl_getMinute, efsl_getSecond, fs_makeDate, fs_makeTime.

Вот пример объявления таких функций (файл time.h):

/*****************************************************************************\
*             efs - General purpose Embedded Filesystem library               *
*         --------------------- -----------------------------------           *
*                                                                             *
* Filename : types.h                                                          *
* Description : Headerfile for types.c                                        *
*                                                                             *
*                                                    (c)2006 Lennart Yseboodt *
*                                                    (c)2006 Michael De Nil   *
\*****************************************************************************/
#ifndef __TIME_H_
#define __TIME_H_

/*****************************************************************************/
#include "types.h"
/*****************************************************************************/

#ifdef DATE_TIME_SUPPORT
  #define time_getYear(void) efsl_getYear()
  #define time_getMonth(void) efsl_getMonth()
  #define time_getDay(void) efsl_getDay()
  #define time_getHour(void) efsl_getHour()
  #define time_getMinute(void) efsl_getMinute()
  #define time_getSecond(void) efsl_getSecond()
  #define time_getDate(void) fs_makeDate()
  #define time_getTime(void) fs_makeTime()
#else
  #define time_getYear(void) 0x0;
  #define time_getMonth(void) 0x0;
  #define time_getDay(void) 0x0;
  #define time_getHour(void) 0x0;
  #define time_getMinute(void) 0x0;
  #define time_getSecond(void) 0x0;
  #define time_getDate(void) 0x0;
  #define time_getTime(void) 0x0;
#endif

#ifdef DATE_TIME_SUPPORT
euint16 efsl_getYear(void);
euint8 efsl_getMonth(void);
euint8 efsl_getDay(void);
euint8 efsl_getHour(void);
euint8 efsl_getMinute(void);
euint8 efsl_getSecond(void);
#endif

euint8 fs_hasTimeSupport(void);

#endif

Вот пример определения таких функций (файл time.c):

/*****************************************************************************\
*             efs - General purpose Embedded Filesystem library               *
*         --------------------- -----------------------------------           *
*                                                                             *
* Filename : time.c                                                           *
* Description : This file contains functions for time support                 *
*                                                                             *
*                                                    (c)2006 Lennart Yseboodt *
*                                                    (c)2006 Michael De Nil   *
\*****************************************************************************/

/*****************************************************************************/
#include "time.h"
#include "arm7_efsl_0_2_7\inc\fs.h"
/*****************************************************************************/

#include "include/settings.h"
#include "include/vars.h"

euint16 efsl_getYear(void)
{
    //return(2005);
    return(2000 + 10*(currTime.Year>>4) + (currTime.Year&0x0F));
}

euint8 efsl_getMonth(void)
{
    //return(5);
    return (10*(currTime.Month>>4) + (currTime.Month&0x0F));
}

euint8 efsl_getDay(void)
{
    //return(11);
    return (10*(currTime.Day>>4) + (currTime.Day&0x0F));
}

euint8 efsl_getHour(void)
{
    //return(13);
    return (10*(currTime.Hour>>4) + (currTime.Hour&0x0F));
}

euint8 efsl_getMinute(void)
{
    //return(14);
    return (10*(currTime.Minute>>4) + (currTime.Minute&0x0F));
}

euint8 efsl_getSecond(void)
{
    //return(40);
    return (10*(currTime.Second>>4) + (currTime.Second&0x0F));
}

euint16 fs_makeDate(void)
{
#ifndef DATE_TIME_SUPPORT
    return(0);
#else
    euint8 m,d;
    euint16 y;
    
    y = time_getYear()-1980;
    m = time_getMonth();
    d = time_getDay();
    
    return(
        (y>127?127<<9:(y&0x3F)<<9)  |
        ((m==0||m>12)?1:(m&0xF)<<5) |
        ((d==0||d>31)?1:(d&0x1F))
    );
#endif
}
/*****************************************************************************/

euint16 fs_makeTime(void)
{
#ifndef DATE_TIME_SUPPORT
    return(0);
#else
    euint8 s,m,h;
    
    s = time_getSecond();
    m = time_getMinute();
    h = time_getHour();
    
    return(
        (h>23?0:(h&0x1F)<<11) |
        (m>59?0:(m&0x3F)<<5) |
        (s>59?0:(s-s%2)/2)
    );
#endif
}
/*****************************************************************************/

euint8 fs_hasTimeSupport(void)
{
#ifdef DATE_TIME_SUPPORT
    return(1);
#else
    return(0);
#endif
}
/*****************************************************************************/

15. Быстро позиционировать позицию чтения по файлу можно при помощи функции file.c -> file_setpos. Второй способ - можно просто поменять значение свойства file.FilePtr (переменная file имеет тип File или EmbeddedFile). То же самое, кстати, делает и функция file_setpos, поэтому лучше применять именно её.

16. Некоторые карты SD, которые мне попадались, требуют двойной инициализации после подачи питания на карту (после того, как она подключена к считывающему устройству с EFSL). На фото показаны две совершенно идентичные карты SD Kingston 1 Gb.

SD-CARDS-IMAG0179.jpg  

Карта, что на фото слева, требует двойной инициализации физического интерфейса карты, иначе запуск инициализации файловой системы завершится с ошибкой. Та карта, что справа, работает как обычно, с одиночной инициализацией. Вот исправления (выделено красным), которые нужно внести в процедуру if_initInterface (файл at91_spi.c):

esint8 if_initInterface(hwInterface* file, eint8* opts)
{
    euint32 sc;
    
    if_spiInit(file);
    if_spiInit(file);    //добавочный вызов инициализации интерфейса
    
    if(sd_Init(file)<0)    
    {
        //printf("Card failed to init, breaking up...\n\r");
        return(-1);
    }
    
    if(sd_State(file)<0)
    {
        //printf("Card didn't return the ready state, breaking up...\n\r");
        return(-2);
    }
    
    /* file->sectorCount=4; */ /* FIXME ASAP!! */
    /* mthomas: - somehow done - see below */
    sd_getDriveSize(file, &sc);
    file->sectorCount = sc/512;
    if( (sc%512) != 0)
        file->sectorCount--;
    //DBG((TXT("Card Capacity is %u Bytes (%i Sectors)\n\r"), sc, file->sectorCount));
    
    if_spiSetSpeed(SPI_SCBR_MIN);
    //if_spiSetSpeed(100); /* debug - slower */
    
    return(0);
}

С такой правкой нормально работают все известные мне карты SD/MMC.

[Ссылки]

1. Сайт EFSL.
2. IAR EW ARM: работа с файловой системой FAT на карточках SD/MMC.
3. IAR EW ARM: как сделать USB Mass Storage Device на основе MMC/SD.
4. EFSL: I/O Manager (менеджер ввода/вывода).
5. Другая популярная реализации файловой системы для микроконтроллеров - Petit FAT File System Module. См. также FatFs Generic FAT File System Module.

Последнее обновление ( 09.06.2011 )
 

Добавить комментарий

:D:lol::-);-)8):-|:-*:oops::sad::cry::o:-?:-x:eek::zzz:P:roll::sigh:

Защитный код
Обновить

< Пред.   След. >

Top of Page
 
microsin © 2017