Перейти к содержанию
    

FatFS и SD-карта. Ускорить чтение файлов с карты

Добрый день.

 

Проблема такая.  Использую SD-карту по SPI (SDIO нет и не будет), перевожу её в High Speed mode, всё успешно: статус-регистры возвращаются как надо.  Тактовая частота карты:  48 МГц. Прикрутил Fat FS ревизия 87030.   Файлы видятся, работает чтение.

 

 Но скорость чтения данных с файлов не радует.   6 файлов общим объёмом 10 МБ  читаются в течение 5,5 секунд.  SD карты 4-го и 10-го класса скоростей на ёмкость 16 ГБ.   Для чтения применяю мульти-секторную команду чтения (Read Begin, Read Data, Read End).   Пробовал закешировать первый мегабайт (начальные сектора карты) - не помогает, видать файлы находятся дальше.   Читаю с помощью fread()

 

Какие есть пути (программные) повышения скорости чтения данных файлов?  Нужно именно быстрое чтение данных, запись вообще не треуется.

 

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А куда читаются файлы? Может, обработка содержимого файлов тормозит?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, __inline__ said:

Какие есть пути (программные) повышения скорости чтения данных файлов?

Кэширование с упреждающим чтением (строками, как процессор заполняет кэш).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

25 minutes ago, AHTOXA said:

А куда читаются файлы? Может, обработка содержимого файлов тормозит?

Читаются большими блоками в память.

 

17 minutes ago, aaarrr said:

Кэширование с упреждающим чтением (строками, как процессор заполняет кэш).

Применительно к секторам карты ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 minutes ago, jcxz said:

Есть подозрение, что максимальные скорости доступны только по SDIO.

Сравнивал время чтения файлов : в случае дефолтного режима (24 МГц)  и High Speed (48 МГц) - соответственно 7 и 5,5 с.

 

Поиск в интернете по "read ahead" толком ничего не находит.   Ткните носом в существующие решения файлового кеша или дискового, изобретать велосипед как-то не хочется.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, __inline__ сказал:

Поиск в интернете по "read ahead" толком ничего не находит.   Ткните носом в существующие решения файлового кеша или дискового, изобретать велосипед как-то не хочется.

Насколько помню - там есть команды как посекторного чтения так и мультисекторного. Да и вообще разные команды. Какие используете?

PS: А всё - вижу, не прочитал выше...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 минут назад, __inline__ сказал:

Сравнивал время чтения файлов : в случае дефолтного режима (24 МГц)  и High Speed (48 МГц) - соответственно 7 и 5,5 с.

Поиск в интернете по "read ahead" толком ничего не находит.   Ткните носом в существующие решения файлового кеша или дискового, изобретать велосипед как-то не хочется.

при наличие свободной памяти смахните fat таблицу в память и попробуйте объяснить это fatfs, тут хоть немного будет ускорения при доступе к цепочке кластеров..

а вообще по однопроводке сильно быстро не будет, ваши 48МГц перемежаются старт-стопами spi и куча накладных расходов - проверьте сырую скорость считывания по интерфейсу и может проще будет сделать жесткую разбивку, допустим по 10МБ на файл при последовательном хранение с 0 сектора, а файлы обновлять через программную прослойку или через dd в линукс-машине

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 минуты назад, Jury093 сказал:

тут хоть немного будет ускорения при доступе к цепочке кластеров..

а вообще по однопроводке сильно быстро не будет, ваши 48МГц перемежаются старт-стопами spi и куча накладных расходов

Тоже хотел это сказать, мне больше 3мб\сек по 1 проводу не удавалось выбить даже из самой скоростной карты...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 минут назад, mantech сказал:

Тоже хотел это сказать, мне больше 3мб\сек по 1 проводу не удавалось выбить даже из самой скоростной карты...

Это можно быстро глянуть осциллом или лог.анализатором. Вангую - там даже при чтении последовательной цепочки секторов будут большие дырки из 0xFF-ок между данными на MISO.

Тогда - только кешировать. На уровне секторов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 minutes ago, jcxz said:

Это можно быстро глянуть осциллом или лог.анализатором. Вангую - там даже при чтении последовательной цепочки секторов будут большие дырки из 0xFF-ок между данными на MISO.

 

Да, так оно и есть. львиная доля времени уходит на получение ответа готовности карты выдать ОЧЕРЕДНУЮ порцию данных по 512 байт.  Хоть и мультисекторная команда.

Код:

 

DRESULT MMC_disk_read(BYTE* buff,DWORD sector,UINT count)
{
 SDCARD_ReadBegin(sector);
 for(u32 i=0;i<count;i++)SDCARD_ReadData(&buff[i<<9]);
 SDCARD_ReadEnd();

 return RES_OK; //all OK
}

s8 SDCARD_ReadBegin(u32 blockNum) {
    SDCARD_Select();

      SDCARD_WaitNotBusy();

    /* CMD18 (READ_MULTIPLE_BLOCK) command */
    u8 cmd[] = {
        0x40 | 0x12 /* CMD18 */,
        (blockNum >> 24) & 0xFF, /* ARG */
        (blockNum >> 16) & 0xFF,
        (blockNum >> 8) & 0xFF,
        blockNum & 0xFF,
        (0x7F << 1) | 1 /* CRC7 + end bit */
    };
    SPI_TX((u8*)cmd,sizeof(cmd));

    if(SDCARD_ReadR1() != 0x00) {
        SDCARD_Unselect();
        return -2;
    }

    SDCARD_Unselect();
    return 0;
}

s8 SDCARD_ReadEnd(void) {
    SDCARD_Select();

    /* CMD12 (STOP_TRANSMISSION) */
    {
        static const u8 cmd[] = { 0x40 | 0x0C /* CMD12 */, 0x00, 0x00, 0x00, 0x00 /* ARG */, (0x7F << 1) | 1 };
        SPI_TX((u8*)cmd,sizeof(cmd));
    }


   SPI(0xFF);

    if(SDCARD_ReadR1() != 0x00) {
        SDCARD_Unselect();
        return -2;
    }
    
    SDCARD_Unselect();
    return 0;
}

static inline s8 SDCARD_ReadData(u8* buff)
{
 SDCARD_Select();

 if(SDCARD_WaitDataToken(DATA_TOKEN_CMD18)<0)
 {
  SDCARD_Unselect();
  return -1;
 }

 SDCARD_ReadBytes(buff,512);

 SPI(0xFF);
 SPI(0xFF);

 SDCARD_Unselect();

 return 0;
}

static inline void SDCARD_ReadBytes(u8* buff, u32 buff_size)
{
 while(buff_size>0)
 {
  *buff++=SPI(0xFF);
  buff_size--;
 }
}

 

Как видно, между полезными данными куча служебной лабуды...

 

Интересную тему нашёл: https://electronix.ru/forum/index.php?app=forums&module=forums&controller=topic&id=78105&page=1

 

То что описал уважаемый aarrrr - замечательно,  в моём случае такой подход к кешированию поможет?   Оперативной памяти под кеш могу до 8 МБ занять.     Файлы читаю разом - крупным блоком сразу:  открыл - считал - закрыл.   Далее следующий файл...   Файлов много (больше 10, меньше 100), есть папки с уровнем вложенности до 3,  размер файлов 100 кБ - 20 МБ

 

36 minutes ago, mantech said:

Тоже хотел это сказать, мне больше 3мб\сек по 1 проводу не удавалось выбить даже из самой скоростной карты...

 

3 мега-бита в секунду?  Тогда 10 МБ должно открыться за 3,5 с,   а не за 5,5 как в моём случае ))

 

59 minutes ago, Jury093 said:

при наличие свободной памяти смахните fat таблицу в память и попробуйте объяснить это fatfs, тут хоть немного будет ускорения при доступе к цепочке кластеров..

а вообще по однопроводке сильно быстро не будет, ваши 48МГц перемежаются старт-стопами spi и куча накладных расходов - проверьте сырую скорость считывания по интерфейсу и может проще будет сделать жесткую разбивку, допустим по 10МБ на файл при последовательном хранение с 0 сектора, а файлы обновлять через программную прослойку или через dd в линукс-машине

 

Есть ли способ быстро узнать стартовый сектор и размер таблицы FAT? Используется FAT32 с LFN

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, __inline__ сказал:

Есть ли способ быстро узнать стартовый сектор и размер таблицы FAT? Используется FAT32 с LFN

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

без кеширования у вас постоянно идет считывание секторов fat таблицы для поиска адреса очередного кластера. поищите, может есть отключение LFN, может даст минимальный прирост при обработке имен..

ЗЫ я в fat32 заглядывал лет 10 назад, когда к atmega прикручивал fat16 и целился подключить hdd. т.ч. больше знаний нет

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 часа назад, __inline__ сказал:

3 мега-бита в секунду?

2-3.5 мегабайта в сек, по среднему, где-то 2.5, на файлах поменьше, полтора мегабайта - это максимум, карта - трансенд, на всяких смартбаях еле до полутора дотягивало.

4 часа назад, __inline__ сказал:

То что описал уважаемый aarrrr - замечательно,  в моём случае такой подход к кешированию поможет?

Кеширование файлов не поможет, ФС - возможно. Кеш файлов использовал только для распаковки картинок, т.к. в том же GIF требуется постоянное обращение за несколькими десятками байт - вот там кэш на 16-30Кбайт очень помог - скорость стала на порядок выше, с анимацией - еще больше, но если читать большие линейные куски - выигрыша нет совсем. Кэш заметно помогает при записи, но там своих проблем тоже не мало..

4 часа назад, __inline__ сказал:

Да, так оно и есть. львиная доля времени уходит на получение ответа готовности карты выдать ОЧЕРЕДНУЮ порцию данных по 512 байт. 

Ну, эт понятно, где-то и в стандарте про это писалось, там сначала из нанда идет выборка, потом всяческое буферирование и подсчет всяких КС, и только потом выдача в порт.

ЗЫ, да и по 512 байт уже давно никто не читает, 4К - сейчас это минимум..

Изменено пользователем mantech

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 hours ago, mantech said:

ЗЫ, да и по 512 байт уже давно никто не читает, 4К - сейчас это минимум..

Не могли бы вы осветить этот момент подробнее? Пробовал читать больше чем по 512 байт:  по 1024 и по 4096 - файловая система работает некорректно с такими длинами чтений.

Интересует  SDCARD_ReadData(u8* buff)

Там после каждых 512 байт надо делать опрос SDCARD_WaitDataToken(DATA_TOKEN_CMD18)<0)  , иначе неправильно работает.

 

Прорабатываю вариант без LFN, имена директорий и файлов в формате 8.3

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, __inline__ said:

Прорабатываю вариант без LFN, имена директорий и файлов в формате 8.3

Прироста в скорости переход с LFN на 8.3 не дал. Флажок в ffconf LFN выставлен в 0.

 

Тут пишут, что мультиблочное чтение всёравно должно идти порциями по 512 байт и нужно ждать дата-токена и считывать 2 байта CRC.   Разом не считаешь без дата-токена - нужно ждать. А это плохо.

https://www.avrfreaks.net/forum/writeread-multiple-blocks-sd-card-0

 

Read multiple blocks is same as above except:

Send READ_MULTIPLE_BLOCK command to card with address, number of blocks etc
Repeat for number of blocks
{
 Poll card for 0xFE (data token)
 Receive the 512 bytes.
 receive 2 CRC bytes
}

+ READ END CMD

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...