Jump to content

    
Sign in to follow this  
__inline__

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

Recommended Posts

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

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

Смотреть размеры буфера драйвера и ФС, ну и честно говоря, не помню, в SPI режиме может ли карта работать с блоками 4К, уже сто лет в однобитке не работал...

Share this post


Link to post
Share on other sites

Эксперимент выявил следующее:

 

Чтение 2048 секторов (8 МБ) мультиблочной командой чтения  занимает 3,6 секунды.  Причем класс скорости не важен - 4 или 10. Всё читается одинаково, ибо этот класс скорости описывает операции записи, которые лично мне в данной задаче неинтересны.   Выходит 2,2 МБайт/с

 

Кеширование секторов в функции move_window() у Чана (FatFS) ни к чему не привело.  Кеширование делал по принципу индексации секторов и проставлению лайков к ним если при чтении кеша они находятся.  Заполнение кеша происходит от начала к концу и в первую очередь по принципу "слабого звена" - чем меньше лайков у индекса (редко используется) тем выше вероятность замены.  Считал сектор - закешируй и поставь ему лайк.....

 

Дальнейшее ускорение я вижу за счёт небольшого сжатия - добавить RLE или Хаффмана для исходных  данных - картинки в формате 16 бит   и звук  -ADPCM.

 

На счёт размера блоков карты памяти  - там от 1 до 512, карт с бОльшим размером блока я не видел.   HxD  под виндами видит сектор 512 байт.  На счёт установить буфер в FatFs больше 512 - это приведет к тому что надо будет чтение 1 сектора  имитировать чтением сразу 4-х.  Под виндой не закинешь на карту ничего, если самому FatFS под виндой не использовать и писать работу с диском через IOCTL (такую штуку я написал давно, но распостранения она не получила)

Edited by __inline__

Share this post


Link to post
Share on other sites
51 минуту назад, __inline__ сказал:

Чтение 2048 секторов (8 МБ) мультиблочной командой чтения  занимает 3,6 секунды.  Причем класс скорости не важен - 4 или 10. Всё читается одинаково, ибо этот класс скорости описывает операции записи, которые лично мне в данной задаче неинтересны.   Выходит 2,2 МБайт/с

Как говорит спецификация на SD:

As opposed to SD mode, the card cannot guarantee its Speed Class. In SPI mode, host shall treat the 
card as Class 0 no matter what Class is indicated in SD Status.

Так что про классы скорости можно забыть. Да и как я понял оттуда же: для высокоскоростных режимов нужно использовать питание 1.8V и соответствующие уровни сигналов. А в SPI это тоже недоступно.

Share this post


Link to post
Share on other sites
13 minutes ago, jcxz said:

Да и как я понял оттуда же: для высокоскоростных режимов нужно использовать питание 1.8V и соответствующие уровни сигналов.

Уровни сигналов 1.8V появились с введением UHS-I, "обычный" 50MHz Hi-Speed работает с уровнями 3.3V. Питание всегда остается 3V (UHS-II не рассматриваем).

 

1 hour ago, __inline__ said:

Под виндой не закинешь на карту ничего, если самому FatFS под виндой не использовать и писать работу с диском через IOCTL (такую штуку я написал давно, но распостранения она не получила)

Звбавно, что под Линуксом такое вполне проходит (сектор диска 512, сектор FAT 4096).

Share this post


Link to post
Share on other sites
18 minutes ago, aaarrr said:

Звбавно, что под Линуксом такое вполне проходит (сектор диска 512, сектор FAT 4096).

У меня стоит убунта второй осью, надо будет попробовать )))  А вообще, я давным давно написал файловый эксплорер на FatFs под винду для SD-карточек ))) Можно делать размер виртуального сектора любым, я делал 8 кБ - скорость на порядок возрастала, да!  Но проблема в том, что отформатировать карту проблема - приходится под виндой тереть нулевой сектор, перевтыкать карту и только потом форматировать своими побрякушками.   Иначе винда определяет логический диск и не даёт отформатировать его.

 

41 minutes ago, jcxz said:

Как говорит спецификация на SD:


As opposed to SD mode, the card cannot guarantee its Speed Class. In SPI mode, host shall treat the 
card as Class 0 no matter what Class is indicated in SD Status.

Так что про классы скорости можно забыть. Да и как я понял оттуда же: для высокоскоростных режимов нужно использовать питание 1.8V и соответствующие уровни сигналов. А в SPI это тоже недоступно.

 

Это очень пичально.. (( Что же они SPI режимы невзлюбили?   Не всегда удаётся SDIO задействовать, по причине банальной занятости ножек контроллера на другие интерфейсы ))) А мультиплексировать и делить во времени тоже не вариант.

 

1 hour ago, __inline__ said:

Дальнейшее ускорение я вижу за счёт небольшого сжатия - добавить RLE или Хаффмана для исходных  данных - картинки в формате 16 бит   и звук  -ADPCM

 

Хаффман плохо жмёт ADPCM, на 18 % выигрыш.  RAR ещё хуже жмёт.  Для звука скорее всего лучше будет только сжатие с потерями качества.   А вот картинку в 16 бит Хаффман ужал в 5 раз почти ( RAR лучше, но он более ресурсоёмкий).

Edited by __inline__

Share this post


Link to post
Share on other sites
56 minutes ago, jcxz said:

Да и как я понял оттуда же: для высокоскоростных режимов нужно использовать питание 1.8V и соответствующие уровни сигналов. А в SPI это тоже недоступно.

Нет.  HighSpeed доступен и при 3,3 V.   Есть ещё более быстрый режим, и он требует 1,8V.    У меня карты без проблем переводятся в HighSpeed при питании 3,3V и через SPI.   Во всяком случае, я вижу прирост скорости.   И ответ после переключения карты получаю положительный.  И на запрос переключится в HighSpeed получаю добро от карты.

 

s8 SDCARD_HighSpeed(void) /* ??? */
{
 u8 CCCR[64];
 u8 crc[2];

 //Проверяем, умеет ли карта HS режим
 {
  SDCARD_Select();

  SDCARD_WaitNotBusy();

  //CMD6 command
  static const u8 cmd[]={0x40|0x06 /* CMD6 */,0x00,0xFF,0xFF,0xF1 /* ARG */,(0x7F<<1)|1 /* CRC7 + end bit*/ };
  SPI_TX((u8*)cmd,sizeof(cmd));

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

  if(SDCARD_WaitDataToken(DATA_TOKEN_CMD6)<0)
  {
   SDCARD_Unselect();
   return -2;
  }

  SDCARD_ReadBytes(CCCR,sizeof(CCCR));

  SDCARD_ReadBytes(crc,sizeof(crc));

  SDCARD_Unselect();

  //Проверка бита SHS регистра карты CCCR
  if((CCCR[63-(400/8)]&0x01)!=0x01) return -3;
 }

 //Просим карту переключиться в HS режим
 {
  SDCARD_Select();

  SDCARD_WaitNotBusy();

  //CMD6 command
  static const u8 cmd[]={0x40|0x06 /* CMD6 */,0x80,0xFF,0xFF,0xF1 /* ARG */,(0x7F<<1)|1 /* CRC7 + end bit*/ };
  SPI_TX((u8*)cmd,sizeof(cmd));

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

  if(SDCARD_WaitDataToken(DATA_TOKEN_CMD6)<0)
  {
   SDCARD_Unselect();
   return -5;
  }

  SDCARD_ReadBytes(CCCR,sizeof(CCCR));

  SDCARD_ReadBytes(crc,sizeof(crc));

  SDCARD_Unselect();
 }

 return 0;
}

 

Edited by __inline__

Share this post


Link to post
Share on other sites

Opus отлично жмёт музыку )))

А RLE оказался лучше Хаффмана на 16-битных картинках (используется модифицированный RLE, который  понимает что сжимать, а что оставлять)

Share this post


Link to post
Share on other sites
5 часов назад, aaarrr сказал:

Звбавно, что под Линуксом такое вполне проходит (сектор диска 512, сектор FAT 4096).

У меня и не под линухом это идет "на ура", только не по SPI, конечно...

Share this post


Link to post
Share on other sites
5 часов назад, __inline__ сказал:

Это очень пичально.. (( Что же они SPI режимы невзлюбили? 

Дык наверно потому, что эи режимы уже при появлении сд карт первой редакции считались устаревшими (перешли в наследство от ММС карточек) вот и прикрывают их совсем уже так сказать...

6 часов назад, __inline__ сказал:

На счёт размера блоков карты памяти  - там от 1 до 512, карт с бОльшим размером блока я не видел.   HxD  под виндами видит сектор 512 байт. 

Сектор-то сектором, но в ФАТе все меряется на кластеры, а вот его размер, как правило, всегда больше сектора, и интерфейс SDIO позволяет читать за один запрос целым блоком по 4, 8, 16 и 32 КБайта. При этом резко повышается скорость чтения, т.к. "накладных расходов" гораздо меньше.

Edited by mantech

Share this post


Link to post
Share on other sites
10 hours ago, mantech said:

Сектор-то сектором, но в ФАТе все меряется на кластеры, а вот его размер, как правило, всегда больше сектора,

 

Так карты давно уже отформатированы на размер кластера 32 кБ программой SDFormatter!  Но FatFs от этого быстрее не заработала. Потому что внутри неё идёт чтение секторов архаичными порциями по 512 байт даже в мультисекторной командой:  ждём токена, выкачиваем 512 байт, 2 байта CRC, и так по кругу. Да и вообще, FatFS не учитывает размер кластера.  Только сектор - минимальный и максимальный (обычно они равны)

 

и интерфейс SDIO позволяет читать за один запрос целым блоком по 4, 8, 16 и 32 КБайта. При этом резко повышается скорость чтения, т.к. "накладных расходов" гораздо меньше.

 

Не видал такого!  В STM-ном коде от кало-куба идёт общение карты через 4-битный SDIO,  но чтение порциями в мультисекторных командах там по-прежнему - по 512 байт :biggrin:

 

Нет такого там чтобы сделать чтение 4 кбайт через SPI, везде идут SPI-чтения по 512 байт.   Тем не менее, мультисекторное чтение даёт и в этом случае выигрыш в разы по сравнению с чтением по 1 сектору.   Но речь шла о том как заставить карту выдать  к примеру 4 кБайт данных, с минимум опросом одного токена + 2 байта ЦРЦ

Edited by __inline__

Share this post


Link to post
Share on other sites
15 часов назад, __inline__ сказал:

е видал такого!  В STM-ном коде от кало-куба идёт общение карты через 4-битный SDIO,  но чтение порциями в мультисекторных командах там по-прежнему - по 512 байт :biggrin:

 

Нет такого там чтобы сделать чтение 4 кбайт через SPI, везде идут SPI-чтения по 512 байт. 

С калокубом к счастью дел не имел, поэтому не знаю, что и чем он там читает... Про spi тоже спорить не буду - очень давно имел с ним дело, но про 4-32К на чтение и запись по SDIO скажу точно - работает! Смотрите, что у вас в фатфс не настроено или версия очень древняя

Edited by mantech

Share this post


Link to post
Share on other sites
16 hours ago, __inline__ said:

Потому что внутри неё идёт чтение секторов архаичными порциями по 512 байт даже в мультисекторной командой:  ждём токена, выкачиваем 512 байт, 2 байта CRC, и так по кругу.

Это чтение одного блока сектора. Я уже не помню, но кажется размер блока тоже можно считать. Есть флешки, у которых стоит 2-4 чипа памяти - дык вот для них размер блока почти всегда выше в 2-4 раза.

Share this post


Link to post
Share on other sites
9 hours ago, AVI-crak said:

Я уже не помню, но кажется

самая употребляемая фраза топика!

максимальный размер транзакции как и сказал @__inline__ для SPI режима не может быть больше 512байт. Для SDHC карт это жестко 512, для SDSC(<=2GB) от 1 до 512 вычитывается из READ_BL_LEN(CSD).

Чтобы не быть голословным, кусочек спеки Physical Layer Simplified Specification

image.thumb.png.738bd8f4f3634d73ac5207e9589ba51d.png

Share this post


Link to post
Share on other sites
On 12/27/2019 at 5:06 PM, Integro said:

Чтобы не быть голословным, кусочек спеки Physical Layer Simplified Specification

 

Спасибо! :yes: Теперь я могу быть спокойным и искать другие пути решения.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this