Когда использовать PROGMEM?

Я считаю, что PROGMEM используется для хранения больших данных (например, строк), которые не меняются. Поэтому он освобождает SRAM.

в справочнике Ardunio упоминается, что.

«Использование PROGMEM также является двухэтапной процедурой. После помещения данных во флэш-память требуются специальные методы (функции), также определенные в библиотеке pgmspace.h, для считывания данных из памяти программ обратно в SRAM, чтобы мы могли сделать с ними что-то полезное».

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

, 👍5


3 ответа


Лучший ответ:

12

Скажем, у вас есть строка из 1000 символов во Flash, и вы хотите напечатать ее в Serial. Да, вам нужно загрузить ее в ОЗУ, чтобы передать эти данные по месту для печати. Но нужно ли вам помещать все их в ОЗУ сразу? Нет. Вам нужен только один символ за раз. Поэтому вместо того, чтобы брать 1000 символов, выделять 1000 байт ОЗУ и копировать все это в ОЗУ, а затем печатать, вам просто нужно выделить 1 байт ОЗУ* и копировать каждый символ по очереди и печатать его.

Поскольку из Flash-файла можно считывать только один символ за раз, нет никакого смысла считывать все сразу.


*На самом деле, из-за оптимизаций компилятора, это, вероятно, даже не касается оперативной памяти и просто остается в регистре ЦП.

,

4

Если в вашем коде есть константная c-строка (массив символов) без макроса F или программной памяти, то строка копируется в оперативную память при запуске и остается там.

Если в функции вы используете макрос F или создаете буфер символов определенного размера и копируете строку progmem в буфер, при возврате функции переменные удаляются из стека и память освобождается.

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

,

1

Как сказал Маженко, вам не нужно помещать все, что у вас есть во флэш-памяти, в ОЗУ сразу. Вы можете перемещать элементы в SRAM по мере необходимости и повторно использовать память, когда закончите.

Однако вы не ограничены перемещением одного байта за раз. Существуют функции, определенные в avr/pgmspace.h, которые могут обрабатывать перемещение данных для вас.

Например, вы можете сделать что-то вроде:

const struct mystruct_s my_value PROGMEM = { value = 1234 };

// ...

struct mystruct_s working_copy;
memcpy_P(&working_copy, &my_value, sizeof(struct mystruct_s));
int foo = working_copy.value / 2;
,