Arduino static progmem

PROGMEM

Description

Store data in flash (program) memory instead of SRAM. There’s a description of the various types of memory available on an Arduino board.

The PROGMEM keyword is a variable modifier, it should be used only with the datatypes defined in pgmspace.h. It tells the compiler «put this information into flash memory», instead of into SRAM, where it would normally go.

PROGMEM is part of the pgmspace.h library. It is included automatically in modern versions of the IDE. However, if you are using an IDE version below 1.0 (2011), you’ll first need to include the library at the top of your sketch, like this:

Using PROGMEM is also a two-step procedure. After getting the data into Flash memory, it requires special methods (functions), also defined in the pgmspace.h library, to read the data from program memory back into SRAM, so we can do something useful with it.

Syntax

const dataType variableName[] PROGMEM = ;

Note that because PROGMEM is a variable modifier, there is no hard and fast rule about where it should go, so the Arduino compiler accepts all of the definitions below, which are also synonymous. However, experiments have indicated that, in various versions of Arduino (having to do with GCC version), PROGMEM may work in one location and not in another. The «string table» example below has been tested to work with Arduino 13. Earlier versions of the IDE may work better if PROGMEM is included after the variable name.

const dataType variableName[] PROGMEM = <>; // use this form
const PROGMEM dataType variableName[] = <>; // or this one
const dataType PROGMEM variableName[] = <>; // not this one

Parameters

dataType : Allowed data types: any variable type.
variableName : the name for your array of data.

Example Code

The following code fragments illustrate how to read and write unsigned chars (bytes) and ints (2 bytes) to PROGMEM.

Arrays of strings

It is often convenient when working with large amounts of text, such as a project with an LCD, to setup an array of strings. Because strings themselves are arrays, this is actually an example of a two-dimensional array.

These tend to be large structures so putting them into program memory is often desirable. The code below illustrates the idea.

Notes and Warnings

Please note that variables must be either globally defined, OR defined with the static keyword, in order to work with PROGMEM.

The following code will NOT work when inside a function:

The following code WILL work, even if locally defined within a function:

Источник

Arduino static progmem

Variable Scope & Qualifiers

Description

Store data in flash (program) memory instead of SRAM. There’s a description of the various types of memory available on an Arduino board.

The PROGMEM keyword is a variable modifier, it should be used only with the data types defined in pgmspace.h. It tells the compiler «put this information into flash memory», instead of into SRAM, where it would normally go.

PROGMEM is part of the pgmspace.h library. It is included automatically in modern versions of the IDE. However, if you are using an IDE version below 1.0 (2011), you’ll first need to include the library at the top of your sketch, like this:

While PROGMEM could be used on a single variable, it is really only worth the fuss if you have a larger block of data that needs to be stored, which is usually easiest in an array, (or another C++ data structure beyond our present discussion).

Using PROGMEM is also a two-step procedure. After getting the data into Flash memory, it requires special methods (functions), also defined in the pgmspace.h library, to read the data from program memory back into SRAM, so we can do something useful with it.

Syntax

const dataType variableName[] PROGMEM = ;

Note that because PROGMEM is a variable modifier, there is no hard and fast rule about where it should go, so the Arduino compiler accepts all of the definitions below, which are also synonymous. However, experiments have indicated that, in various versions of Arduino (having to do with GCC version), PROGMEM may work in one location and not in another. The «string table» example below has been tested to work with Arduino 13. Earlier versions of the IDE may work better if PROGMEM is included after the variable name.

Источник

PROGMEM

Описание
Храните данные во флэш-памяти вместо SRAM. Есть описание различных типов памяти, доступных на плате Arduino.

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

PROGMEM является частью библиотеки pgmspace.h. Он автоматически включается в современные версии IDE. Однако, если вы используете версию IDE ниже 1.0 (2011 г.), вам сначала нужно включить библиотеку в верхней части скетча, например:

Хотя PROGMEM можно использовать с одной переменной, на самом деле это стоит суеты только в том случае, если у вас есть большой блок данных, который необходимо сохранить, что обычно проще всего в массиве (или другой структуре данных C++, выходящей за рамки нашего настоящего обсуждения).

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

Синтаксис
const dataType variableName[] PROGMEM = ;

Обратите внимание, что, поскольку PROGMEM является модификатором переменной, нет жесткого и быстрого правила о том, куда он должен разместиться, поэтому компилятор Arduino принимает все определения ниже, которые также являются синонимами. Однако эксперименты показали, что в различных версиях Arduino (связанных с версией GCC) PROGMEM может работать в одном месте, а не в другом. Приведенный ниже пример «таблицы строк» ​​был протестирован для работы с Arduino 13. Более ранние версии IDE могут работать лучше, если PROGMEM будет добавлен после имени переменной.

const dataType variableName[] PROGMEM = <>; // используйте эту форму
const PROGMEM dataType variableName[] = <>; // или эту
const dataType PROGMEM variableName[] = <>; // но не эту

Пример
Следующие фрагменты кода показывают, как читать и записывать беззнаковые символы (байты) и целые числа (2 байта) в PROGMEM.

unsigned int displayInt;
char myChar;

void setup() <
Serial.begin(9600);
while (!Serial); // wait for serial port to connect. Needed for native USB

// put your setup code here, to run once:
// read back a 2-byte int
for (byte k = 0; k http://www.nongnu.org/avr-libc/user-manual/pgmspace.html

Настройка таблицы (массива) строк в памяти программы немного сложна, но
вот хороший шаблон для повторения.

Настройка строк — это двухэтапный процесс. Сначала определите строки.
*/

#include
const char string_0[] PROGMEM = «String 0»; // «String 0» и т.д. — строки для текста.
const char string_1[] PROGMEM = «String 1»;
const char string_2[] PROGMEM = «String 2»;
const char string_3[] PROGMEM = «String 3»;
const char string_4[] PROGMEM = «String 4»;
const char string_5[] PROGMEM = «String 5»;

// Затем создайте таблицу, чтобы ссылаться на ваши строки.

char buffer[30]; // убедитесь, что достаточно для самой большой строки

void setup() <
Serial.begin(9600);
while (!Serial); // дождитесь подключения последовательного порта
Serial.println(«OK»);
>

void loop() <
/* Использование таблицы строк в флеш памятим требует использования специальных функций для извлечения данных.
Функция strcpy_P копирует строку из области программы в строку в ОЗУ («буфер»).
Убедитесь, что ваша строка в ОЗУ достаточно велика, чтобы вместить все,
что вы получаете из памяти. */

for (int i = 0; i const char long_str[] PROGMEM = «Hi, I would like to tell you a bit about myself.\n»;

Следующий код БУДЕТ работать, даже если он определен локально в функции:

const static char long_str[] PROGMEM = «Hi, I would like to tell you a bit about myself.\n»

Макрос F()
Инструкция типа:

Serial.print(«Write something on the Serial Monitor»);

Печатаемая строка обычно сохраняется в ОЗУ. Если ваш скетч печатает много чего чарез последовательный порт, вы можете легко заполнить оперативную память. Если у вас есть свободное место во флэш-памяти, вы можете легко указать, что строка должна быть сохранена во флэш-памяти, используя синтаксис:

Источник

PROGMEM / Arduino

Описание

Хранит данные во флэш-памяти (памяти программ) вместо SRAM.

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

PROGMEM является частью библиотеки pgmspace.h . В современные версии IDE она включается автоматически, однако, если вы используете версию IDE ниже 1.0 (2011), сначала вам нужно включить библиотеку вначале вашего скетча, например:

Синтаксис

dataType – тип переменной.

variableName – имя вашего массива данных.

Обратите внимание, что поскольку PROGMEM является модификатором переменной, нет жесткого и быстрого правила о том, где он должен идти, поэтому компилятор Arduino принимает все приведенные ниже определения, которые также являются синонимами. Однако эксперименты показали, что в различных версиях Arduino (имеющих отношение к версии GCC) PROGMEM может в одном месте работать, а в другом – нет. Пример строк ниже был протестирован на работоспособность с Arduino 13. Более ранние версии IDE могут работать лучше, если PROGMEM включен после имени переменной.

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

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

Пример кода

Следующие фрагменты кода иллюстрируют, как читать и записывать символы (байты) и int (2 байта) в PROGMEM .

Массивы строк

Часто при работе с большими объемами текста, например, в проекте с LCD дисплеем, удобно устанавливать массив строк. Поскольку сами строки являются массивами, на самом деле это пример работы с двумерным массивом.

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

Примечания и предупреждения

Обратите внимание, что переменные, чтобы работать с PROGMEM , должны быть определены глобально ИЛИ с ключевым словом static .

Следующий код НЕ будет работать, если находится внутри функции:

Следующий код БУДЕТ работать, даже если определен локально внутри функции:

Макрос F()

Когда используется инструкция, подобная следующей:

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

Источник

sticilface / PROGMEM.md

Guide to PROGMEM on ESP8266 and Arduino IDE

On low memory devices like the arduino and esp8266 you do not want strings to be stored in RAM. This occurs by default on these systems. Declare a string const char * xyz = «this is a string» and it will use up RAM.

The solution on these devices is to allow strings to be stored in read only memory, in Arduino this is the PROGMEM macro. Most of my experience is with the ESP8266 which is a 32bit micros controller. This device stores PROGMEM data in flash. The macro PROGMEM on ESP8266 is simply

Which in turn is defined by:

Which places the variable in the .irom.text section ie flash.

The key to understanding PROGMEM is to understand how the strings are stored and then how they are retrieved from flash.

Declare a global string to be stored in flash.

Declare a flash string within code block.

For this you can use the PSTR macro. Which are all defined in pgmspace.h

The two examples above will store these strings in flash. To retrieve and manipulate flash strings is not straight forward as the esp8266 must read from flash in 4byte words. In the Arduino IDE for esp8266 there are several functions that can help retrieve strings from flash that have been stored using PROGMEM. Both of the examples above will give you a const char * back, however if you try to do anything with these pointers, without correct 32bit alignment you will get a seg fault and the esp will crash. You must read from the flash 32 bit aligned.

Functions to read back from PROGMEM

Which are all defined in pgmspace.h

There are a lot of functions there but in reality they are _P versions of standard c functions that are adapted to read from the esp8266 32bit aligned flash. All of them take a PGM_P which is essentially a const char * . Under the hood these functions all use:

which reads backs the bytes without causing a seg fault.

This works well when you have designed a function as above that is specialised for dealing with PROGMEM pointers but there is no type checking except against const char * . This means that it is totally legitimate, as far as the compiler is concerned, for you to pass it any const char * string, which is obviously not true and will lead to undefined behaviour. This makes it impossible to create any overloaded functions that can use flash strings when they are defined as PGM_P . If you try you will get an ambiguous overload error as PGM_P == const char * .

Enter the __FlashStringHelper.

This is a wrapper class that allows flash strings to be used as a class, this means that type checking and function overloading can be used with flash strings. Most people will be familiar with the F() macro and possibly the FPSTR() macro. These are defined in WString.h:

So FSPTR() takes a PROGMEM pointer to a string and casts it to this __FlashStringHelper class. Thus if you have defined a string as above xyz you can use FPSTR() to convert it to __FlashStringHelper for passing into functions that take it.

The F() combines both of these methods to create an easy and quick way to store an inline string in flash, and return the type __FlashStringHelper . For example:

Although these two functions provide a similar function, they serve different roles. FPSTR() allows you to define a global flash string and then use it in any function that takes __FlashStringHelper . F() allows you to define these flash strings in place, but you can’t use them anywhere else. The consequence of this is sharing common strings is possible using FPSTR() but not F() . __FlashStringHelper is what the String class uses to overload its constructor:

This allows you to write:

How do I write a function to use __FlashStringHelper?

Simples: cast the pointer back to a PGM_P and use the _P functions shown above. This an example implementation for String for the concat function.

How do I declare a global flash string and use it?

How do I use inline flash strings?

How do I declare and use data in PROGMEM?

How do I declare some data in PROGMEM, and retrieve one byte from it.

Declare the data as done previously, then use pgm_read_byte to get the value back.

It is easy to store strings in flash using PROGMEM and PSTR but you have to create functions that specifically use the pointers they generate as they are basically const char * . On the other hand FPSTR and F() give you a class that you can do implicit conversions from, very useful when overloading functions, and doing implicit type conversions. It is worth adding that if you wish to store an int , float or pointer these can be stored and read back directly as they are 4 bytes in size and therefor will be always aligned!

Источник

Adblock
detector