Можно ли во время выполнения определить, объявлен ли указатель PROGMEM?

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

, 👍1


2 ответа


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

2

Не совсем, если вы спрашиваете, можете ли вы определить (просто по его значению), находится ли 0x100 в RAM или PROGMEM. Оба являются возможными кандидатами на место в памяти.

Макрос F() решает эту проблему, изменяя тип переменной во время компиляции, чтобы компилятор мог выбрать подходящий метод печати. Например:

Serial.println ("Hello, world");
Serial.println (F("Hello, world"));

В этом случае соответствующая функция println выбирается компилятором во время компиляции на основе типа (одна будет const char *, другая — __FlashStringHelper тип).

Лучше всего придумать способ (аналогичный макросу F()), с помощью которого можно будет принимать решение во время компиляции.

,

1

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

Микроконтроллеры AVR принадлежат Harvard Architecture. Пространства памяти данных и программ разделены. Есть также несколько областей памяти данных, например, SRAM, EEPROM, PROGMEM. Каждый из них имеет собственное адресное пространство, и для доступа к ним используются специальные инструкции.

В программном обеспечении все возможно :), поэтому можно унифицировать адресные пространства и использовать механизм времени выполнения для выполнения соответствующих операций чтения и записи. Простой метод заключается в использовании старших битов для определения адресного пространства. Например,

SRAM 0x0000..0x7fff
EEPROM 0x8000..0x8fff
PROGMEM 0x9000..0xffff

У указателей SRAM все как обычно, у указателей EEPROM есть дополнительный 0x8000, а у указателей PROGMEM дополнительный 0x9000.

Следующим шагом является написание простой функции отображения из единого адресного пространства в отдельные адресные пространства памяти. Это можно обернуть в интеллектуальный указатель C++ и/или простую иерархию классов C++.

Пример этого метода можно найти в 1) Виртуальная машина Forth для Arduino, https://github.com/mikaelpatel/ Arduino-FVM (см. https://github.com/mikaelpatel /Arduino-FVM/blob/master/src/FVM.cpp#L85), 2) командная оболочка RPN Postscript/Forth для Arduino, https://github.com/mikaelpatel/Arduino-Shell (см. https://github.com/mikaelpatel/Arduino-Shell/blob/master/Shell.h#L1059).

Ура!

PS: Интересная деталь архитектуры AVR заключается в том, что регистры 0..31 и регистры io сопоставляются с адресным пространством SRAM.

,