Как я могу использовать SD-карту для записи 16-битных данных по 48 ksamples/s?
Фон
Моя плата включает STM32 микроконтроллер с SD/MMC на SPI и отображает аналоговые данные в 48 ksamples/s. Я использую ядро RTL для библиотеки Keil Realtime, а ELM FatFs.
У меня есть задача с высоким приоритетом, которая фиксирует аналоговые данные через DMA в блоках из 40 выборок (40 x 16 бит/бит); данные передаются через очередь длиной 128 (которая составляет около 107 мкс буферизации выборки) во вторую задачу с низким приоритетом, которая сопоставляет образцы блоков в буфере 2560 байтов (это кратное размеру размером 512 байт SD-сектора и 40 размер блока выборки). когда этот буфер заполнен (32 блока или около 27 мкс), данные записываются в файловую систему.
Наблюдение
Используя код, я вижу, что каждый 32 блока, данные записываются и что запись занимает около 6 мкс. Это поддерживается до тех пор, пока (на FAT16) размер файла не достигнет 1 Мб, когда операция записи занимает 440 мс, и к этому времени очередь заполняется и записывается в журнал. Если я отформатирую карту как FAT32, размер файла перед событием 'long-write' равен 4 MB.
Тот факт, что размер файла, при котором это происходит, изменяется между FAT16 и FAT32, говорит мне о том, что это не ограничение карты, а скорее то, что делает файловая система на 1 МБ или 4 фунтах МБ, которые принимают дополнительное время.
Также представляется, что мои задачи планируются своевременно и что время потребляется в коде ELM FatFs только при граница 1 МБ (или 4 для FAT32).
Вопрос
Есть ли объяснение или решение? Это проблема FAT, или, скорее, специфическая для кода ELM FatFs?
Я рассмотрел использование нескольких файлов, но, по моему опыту, FAT не обрабатывает большое количество файлов в одном каталоге очень хорошо, и это тоже просто провалится. Не использовать файловую систему вообще и писать на карточку raw было бы возможно, но в идеале я хотел бы прочитать данные на ПК со стандартными драйверами и без специального программного обеспечения.
Мне пришло в голову попробовать оптимизировать компиляторы, чтобы сократить время записи; это, кажется, имеет эффект, но время записи показалось гораздо более переменным. На -O2 я получил 8-мегабайтный файл, но результаты были непоследовательными. Теперь я не уверен, существует ли прямая корреляция между размером файла и точкой, в которой он терпит неудачу; Я видел, что он терпит неудачу таким образом при разных длинах файлов без какой-либо конкретной границы. Возможно, это проблема с производительностью карт.
Я еще больше измерил код и применил подход к поколению. Это наблюдение, вероятно, делает вопрос устаревшим, и все предыдущие наблюдения ошибочны или красные сельди.
Я, наконец, сузил его до экземпляра многосекторной записи (CMD25), где время от времени "ожидание" опроса карты занимает 174 мск для первых трех секторов из блока 5. Тайм-аут для ожидания ready установлен в 500 мс, поэтому он будет очень занят - так долго ждать. Использование CMD24 (односекторная запись) итеративно происходит намного медленнее в общем случае - 140 мкс за сектор - а не только изредка.
Так что, похоже, поведение карты в конце концов. Я постараюсь попробовать ряд карт SD и MMC.
Ответы
Ответ 1
Первое, что нужно попробовать, может быть довольно простым: увеличить глубину очереди до 640. Это даст вам 535 буферов и будет выживать по крайней мере в этом конкретном событии файловой системы.
Второе, на что нужно обратить внимание, это конфигурация ELM FatFs. Многие встроенные файловые системы очень скудны с использованием буфера по умолчанию. Я видел тот, который использовал один 512-байтовый блочный буфер для всех операций, и он сканировал для определенных транзакций файловой системы. Мы дали ему пару килобайт, и эта вещь стала на порядок быстрее.
Оба вышеизложенного зависят от того, имеется ли у вас больше RAM.
Третий вариант заключается в том, чтобы предварительно распределить огромный файл, а затем просто перезаписать данные во время сбора данных. Это позволит устранить ряд дорогостоящих кластеров и операций манипуляции FAT.
Так как оптимизация компилятора повлияла на это, вы также должны учитывать возможность многопоточной проблемы. Существуют ли другие потоки, которые могут помешать нити с более низким приоритетом чтения? Вы также должны попробовать изменить буферизацию там на что-то другое, чем кратное размеру выборки и размера флэш-блока, если вы нажмете какой-то системный резонанс.
Ответ 2
Вы (или кто-либо еще читающий этот вопрос) могли бы попробовать эту библиотеку FAT: https://github.com/fernando-rodriguez/fat32lib.
На 40 микропрограмме MIPS dsPIC33 с шиной SPI 10 Мбит/с он может отображать при 230 Кбит/с (16 бит) на любая карта, которую я пробовал.