Насколько быстро чтение флэш-памяти по сравнению с SRAM?
Я работаю над проектом, который в конечном итоге будет масштабироваться до 864 светодиодов на светодиодных лентах WS2815 (три ряда по 288 светодиодов). В настоящее время я запускаю его на Arduino Uno с одной тестовой полоской из 144 светодиодов.
FastLED хранит свои данные в 3-байтовых структурах, поэтому я, очевидно, не могу просто хранить все данные в SRAM и работать с ними напрямую (по крайней мере, без перехода на контроллер с большим объемом памяти). Я собираюсь использовать Raspberry Pi для отправки данных Arduino по одному разделу за раз. Для дальнейшей экономии памяти я хочу реализовать таблицу поиска цветов RGB во flash, а затем вместо
CRGB pixels[PIXEL_COUNT];
занимает более 2 КБ памяти 800+ значений или
CRGB pixels[PIXEL_BUFFER_COUNT];
с буфером из 288 значений RGB, занимающим большую часть моей рабочей памяти (864 байта), я бы справился
CRGB *pixels[PIXEL_BUFFER_COUNT];
Где каждый указатель будет ссылаться на местоположение в таблице PROGMEM
с 256 записями значений CRGB
. Это более управляемые 576 байт в SRAM.
Я понимаю, что FastLED так не работает. Если я это сделаю, мне предстоит много работы, но прежде чем я начну, мой вопрос:
Могу ли я столкнуться с проблемами при чтении фактических данных из флэш-памяти при отправке на светодиодные ленты? Как в настоящее время реализовано в FastLED, данные RGB находятся в SRAM, но каждое разыменование указателя потребует чтения из флэш-памяти. Является ли последующая задержка достаточной, чтобы вызвать проблемы с отправкой данных на полосы?
@anonymous, 👍1
2 ответа
Лучший ответ:
На Arduino Uno или другом Arduino на базе AVR чтение байта из ОЗУ занимает 2 такта процессора. Чтение из flash занимает 3 такта. Итак, вспышка против Оперативная память - это не такие уж большие накладные расходы. Однако, если вы сохраните LUT во флэш-памяти, и индексы цвета в оперативной памяти, то для каждого пикселя потребуется:
- 2 цикла чтения индекса цвета из ОЗУ
- 3 × 3 цикла для чтения значений RGB из флэш-памяти.
Всего 11 циклов, а не 6 циклов, которые потребуются для чтения RGB. значения из оперативной памяти, как это делается в стандартной библиотеке FastLED.
Звучит плохо, но может случиться так, что точное время не такое большое проблема. Я не знаю WS2815, но если они похожи на WS2812, тогда вам не нужно быть настолько точным с таймингами, как даташит предлагает. См. сообщение в блоге NeoPixels раскрыты: как (не необходимо) генерировать точно синхронизированные сигналы.
Обновлено: для указателя потребуется еще несколько циклов арифметика. Я оцениваю что-то около 7 циклов. На низком уровне код для получения цвета должно выглядеть примерно так:
uint8_t *pixel = ...;
uint8_t index = *pixel; // чтение из ОЗУ: 2 цикла
uint8_t pgm_p; // указатель на flash
pgm_p = &pgm_lut + 3 * index; // арифметика указателя: ≥ 7 циклов
struct CRGB color;
color.r = pgm_read_byte(pgm_p++); // чтение из флэш-памяти: 3 цикла
color.g = pgm_read_byte(pgm_p++); // чтение из флэш-памяти: 3 цикла
color.b = pgm_read_byte(pgm_p); // чтение из флэш-памяти: 3 цикла
Поскольку флэш-память находится на другой шине данных, чем SRAM, внутри ЦП требуется дополнительная перетасовка, чтобы доставить данные туда, где они должны быть. При этом используется специальная инструкция «LPM» (загрузка памяти программ), для работы которой требуется дополнительный тактовый цикл. Вдобавок ко всему, единственный способ его использования — через «индексный» регистр Z — здесь нет немедленных или смещенных загрузок. Так что работать с ним может быть немного неуклюже. Все это, конечно же, замаскировано предоставленными функциями C.
В итоге да, чтение с флешки несколько медленнее. Однако насколько медленнее, сказать невозможно. В лучшем случае: каждый доступ займет еще 1 такт. В худшем случае: ну, это невозможно узнать. Это в некоторой степени зависит как от того, как вы реализуете свое чтение CLUT, так и от того, как компилятор объединяет вещи вместе.
Я бы посоветовал вам использовать осциллограф и просто попробовать. Внесите изменения, а затем вручную отрегулируйте задержки и синхронизацию, чтобы получить правильную форму выходного сигнала.
Именно то, что мне нужно было знать. Спасибо., @anonymous
Всегда можно использовать плату на базе 1284P с 16K SRAM, большим количеством места для хранения шаблонов и т. д. для быстрого доступа., @CrossRoads
@CrossRoads Я смотрел на большие платы, но мне нравится это. Хранение моих данных в 32-битных блоках также (вероятно, я не проверял) ускоряет процесс., @anonymous
- Файловая система внешней флэш-памяти
- Как функция/метод может определить, является ли передаваемый массив const PROGMEM (flash) или нет (RAM)?
- Как настроить схему секционирования Wemos D1 mini pro?
- Внешняя оперативная память (23LC1024) и внешняя флэш-память (W25Q64JVSSIQ) с Sparkfun SAMD21
- Портирование «дальнего» доступа к флэш-памяти с Arduino Mega на Due
- Получить доступ к EEPROM ATtiny с помощью кода Arduino?
- Библиотека FastLED: Как настроить яркость одного пикселя в абсолютном масштабе?
- Управлять несколькими полосками WS2812B с разным количеством светодиодов.
WS2815 в основном представляет собой 12-вольтовый WS2812B. Спасибо за подробный разбор., @anonymous
Ваше редактирование также очень полезно. Со статьей NeoPixels Revealed и некоторой буферизацией я мог бы справиться с этим. Поскольку мои светодиоды будут в определенной степени отображать градиент палитры, я могу считывать ближайшие значения
CRGB
в SRAM и просто перемещать указатель вперед по мере необходимости, когда нахожу индекс, которого у меня нет локально., @anonymous