Лучшая практика буферизации для непрерывной записи на SD-карту

esp32 uart sd

В упрощенном примере у меня есть микроконтроллер, функционирующий как устройство сбора данных - данные датчиков принимаются через UART, а затем сохраняются на SD-карту.

Эти полученные данные представлены в виде 12-байтовой структуры, принятой на частоте 1 кГц. Микроконтроллер, принимающий данные, представляет собой esp32 с SD-картой, подключенной через spi. Это не редкость, но если при каждом получении новых данных запускается обычная запись на SD-карту, то для записи данных потребуется больше времени, чем промежуток между выборками.

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

В моем конкретном примере у меня есть бонусное второе ядро процессора в esp32. Поэтому я думаю использовать 2 чередующихся буфера. Данные будут получены на ядре 1 и помещены в активный буфер. Когда буфер заполнится, входящие данные будут записаны во второй буфер, а первые будут записаны ядром 2 на SD-карту.

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

, 👍3

Обсуждение

данные всегда будут получены быстрее , чем они могут быть записаны ... это означает , что вы потеряете данные ... сжатие данных может помочь .... пожалуйста, приведите несколько примеров из 12 байт данных, @jsotola

SD-карты могут быть записаны по 1-битной или 4-битной шине. Последнее работает быстрее и, насколько я помню, требует лицензии для внедрения. Кроме того, скорость работы SD-карт сильно варьируется. Если ваш драйвер может воспользоваться этим преимуществом, попробуйте использовать более быструю SD-карту. Наконец, все SD-карты содержат контроллер соответствия требованиям. Так что выбор подходящего производителя для ваших нужд может помочь. (Я бы пошел по рекомендации @ jsotola 1st, попробуйте сжатие потерь, если сможете. Лучше всего просто.), @st2000

`если обычная запись на SD-карту запускается каждый раз, когда поступают новые данные", то это не так. Внутренний буфер размером 512 байт поддерживается библиотекой SD для хранения всего блока данных. Когда он будет заполнен, он сбросит его на SD-карту за один раз и получит (или выделит) следующий., @Majenko

Я полагаю, вопрос заключается не столько в том, как можно ускорить сам процесс записи SD, сколько в том, как входящие данные могут быть сохранены во время записи, @nuggetbram


4 ответа


2

Буферы помогут вам, если в какой-то момент входной поток остановится, поэтому "более медленное" устройство (например, SD-карта) может перехватить его. Если данные всегда будут приниматься быстрее, чем они могут быть записаны (обратите внимание, всегда), то никакой буфер вам не поможет.

Но я предполагаю, что вы имели в виду, что в тех случаях, когда вы получаете пакеты входных данных с частотой 1 кГц, это прекратится. Таким образом, пока средняя скорость ввода данных ниже, чем способность SD сохранять данные, все будет в порядке.

В библиотеке SD-карт уже есть буфер (как указал @Majenko), так что, скорее всего, вам ничего не нужно будет делать. Кажется, что-то, что вы можете протестировать относительно просто.

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

,

К сожалению, в этом случае входные данные поступают с постоянной скоростью, от начала до конца без перерывов. Кроме того, данные хранятся максимум до 30 минут, что означает, что это немного выходит за рамки простой записи во встроенную память и сброса на SD-карту в конце, отсюда и идея 2 core. Если полная запись на SD 512 байт занимает всего 3000us, данные могут быть записаны со средней скоростью, превышающей скорость их поступления, но что делать с данными, полученными во время записи на SD?, @nuggetbram


3

Является ли это разумным решением проблемы?

Нет, к сожалению, нет. Размер буфера ограничен доступной оперативной памятью на вашем чипе. Переключение между несколькими буферами или ядрами этого не изменит, поскольку это аппаратное ограничение.

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

Когда вы постоянно получаете сообщения быстрее, чем можете записать, у вас есть только 2 варианта:

  • Повышение скорости записи
  • Уменьшите необходимый размер данных

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

  • Повышение скорости записи:

    • На разных сайтах я читал, что вы можете использовать SD-карту с разными частотами SPI. Более высокая частота будет означать более высокую скорость транзакций. На этом этапе вы можете продолжить расследование.
    • Одновременная запись полной страницы размером 512 байт и повторное закрытие и открытие файла только в случае реальной необходимости повысят общую скорость.
  • Уменьшите необходимый размер данных

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

О буферах:

Я бы сказал, что обычный циклический буфер не принесет вам здесь особых преимуществ, так как с SD-картой вы не хотите выполнять байтовую передачу данных. Подход с 2 буферами, о котором вы упомянули, кажется мне хорошим. Хотя обработка с разными ядрами не имеет для меня особого смысла. Сам прием UART осуществляется аппаратным обеспечением и некоторыми ISR. Вы можете выполнять все передачи с SD-карты в своем основном коде, просто убедившись, что вы регулярно копируете полученные данные из последовательного буфера в свой буфер.

,

0

Простите мою нетехническую аналогию, но мой мозг работает именно так. Надеюсь, вы сможете отказаться от вывода о том, что «это не технический ответ», пока вы хотя бы не посмотрите на это с другой точки зрения.

Буферы, входные потоки, частоты дискретизации и скорости хранения тесно связаны с заполнением ванны. Краны, вода, ванны и пробки? ВТФ?

Попробуйте слегка заблокировать сливное отверстие в ванне и полностью откройте оба крана.

Слитая вода — это скорость, с которой данные сохраняются на SD-карте. Это скорость хранения.

Оставшаяся вода, которая не сливается достаточно быстро, приводит к переполнению ванны. Вода — это частота дискретизации, ванна — это буфер.

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

Поэтому, если засор не устранить, ванна в конечном итоге переполнится.

Либо вы закрываете краны, либо используете ванну большего размера, либо увеличиваете скорость слива.

,

0

Один из подходов — использовать циклическую буферизацию. Он предполагает использование буфера фиксированного размера, который охватывает сам себя, позволяя непрерывно записывать и перезаписывать данные. Этот подход устраняет необходимость в дорогостоящих операциях перераспределения памяти или смещения. По мере записи новых данных старые данные перезаписываются по кругу. Но вам нужно будет выбрать подходящий размер буфера. Больший размер буфера может помочь справиться с большими объемами данных. Однако большие буферы также потребляют больше памяти.

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

Другой метод — использовать DMA, если ваш микроконтроллер или система его поддерживает, что, я думаю, так и есть. Использование DMA для записи на SD-карту может разгрузить ЦП задачу передачи данных. DMA обеспечивает прямой доступ к памяти без вмешательства процессора, обеспечивая более быструю и эффективную передачу данных. DMA может значительно снизить накладные расходы, связанные с непрерывной записью на SD-карту.

Для DMA вы можете проверить следующее: https://github.com/RobTillaart/DAC8552/issues/8 и это: https://github.com/espressif/esp-idf/blob/master/ примеры/периферийные устройства/spi_master/lcd/main/spi_master_example_main.c

,