简体   繁体   English

如何在Arduino中获取全局变量的闪存地址

[英]How to get flash address of global variable in Arduino

I have a static global variable in my Arduino (ATmega328P for example) which is, as any other static non-PROGMEM storage, automatically loaded to SRAM after startup. 我的Arduino中有一个静态全局变量(例如ATmega328P),与其他任何静态非PROGMEM存储器一样,该变量在启动后会自动加载到SRAM。 I set it to a default value which is replaced by the stored value from EEPROM in setup() . 我将其设置为默认值,该默认值将替换为setup() EEPROM中的存储值。 I would like to offer the ability to reset the variable to its original default value without defining the value again in my code. 我想提供将变量重置为其原始默认值的功能,而无需在代码中再次定义该值。
Is it possible to get the flash address of a static global variable in Arduino to load its original data from flash to SRAM via pgm_read_byte() for example? 例如,是否可以获取Arduino中静态全局变量的闪存地址,以通过pgm_read_byte()将其原始数据从闪存加载到SRAM? If so, how? 如果是这样,怎么办?

PS The static global variable in question is a rather large structure. PS所讨论的静态全局变量是一个相当大的结构。 Re-defining it is out of question. 重新定义它是毫无疑问的。

Constant data can be made addressable by declaring it as PROGMEM . 通过将常量数据声明为PROGMEM可以使常量数据可寻址。 Since AVR program memory is organized as 16-bit words in a separate address space, special functions have to be used for reading. 由于AVR程序存储器在单独的地址空间中被组织为16位字,因此必须使用特殊功能进行读取。

#include <assert.h>
#include <string.h>                        // memcpy
#include <avr/pgmspace.h>                  // AVR PROGMEM, memcpy_P

#define SIZE 1000
struct large {                             // arbitrary large data structure
  unsigned char data[SIZE];
};

struct large l;                            // global variable (in SRAM)

const struct large l_default PROGMEM = {   // default value (in PROGMEM)
  { 0xaa, 0xab, 0x0ac, 0xad, 0xae, 0xaf }
};

void setup(void)                           // load values from EEPROM
{
  memset(&l, 1, SIZE);                     // simulate reading from real EEPROM
}

int main(void)
{
  setup();                                 // initialize from EEPROM
  assert(l.data[0] == 1);

  memcpy_P(l.data, &l_default, SIZE);      // reset to defaults (from PROGMEM)
  assert(l.data[0] == 0xaa);

  return 0;
}

Confirming that sizes from the above example are as expected: 1000 additional bytes in Program for the default data, 1000 bytes total in Data for the global variable. 确认以上示例中的大小符合预期:对于默认数据, Program增加了1000个字节,对于全局变量, Data总共增加了1000个字节。

$ avr-size -C -x main.bin
AVR Memory Usage
----------------
Device: Unknown

Program:    1252 bytes
(.text + .data + .bootloader)

Data:       1000 bytes
(.data + .bss + .noinit)

The default data (starting with aaabacadaeaf and continuing with 994 zeros) has been placed in program memory right after the interrupt vectors. 默认数据(以aaabacadaeaf ,以994零开始)已在中断向量之后立即存储在程序存储器中。 It can be accessed at runtime through the pgm_read_ family of functions. 可以在运行时通过pgm_read_系列函数进行访问。

$ avr-objdump -s main.bin

main.bin:     file format elf32-avr

Contents of section .text:
0000 0c942802 0c943a02 0c943a02 0c943a02  ..(...:...:...:.
0010 0c943a02 0c943a02 0c943a02 0c943a02  ..:...:...:...:.
0020 0c943a02 0c943a02 0c943a02 0c943a02  ..:...:...:...:.
0030 0c943a02 0c943a02 0c943a02 0c943a02  ..:...:...:...:.
0040 0c943a02 0c943a02 0c943a02 0c943a02  ..:...:...:...:.
0050 0c943a02 0c943a02 0c943a02 0c943a02  ..:...:...:...:.
0060 0c943a02 0c943a02 aaabacad aeaf0000  ..:...:.........
0070 00000000 00000000 00000000 00000000  ................
0080 00000000 00000000 00000000 00000000  ................
0090 00000000 00000000 00000000 00000000  ................
[...]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM