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

时间:2018-12-09 10:17:11

标签: c arduino avr atmega

我的Arduino中有一个静态全局变量(例如ATmega328P),与其他任何静态非PROGMEM存储器一样,该变量在启动后会自动加载到SRAM。我将其设置为默认值,该默认值由setup()中EEPROM中存储的值替换。我想提供将变量重置为其原始默认值的功能,而无需在代码中再次定义该值。
例如,是否可以在Arduino中获取静态全局变量的闪存地址,以通过pgm_read_byte()将其原始数据从闪存加载到SRAM?如果可以,怎么办?

P.S。有问题的静态全局变量是一个相当大的结构。重新定义它是毫无疑问的。

1 个答案:

答案 0 :(得分:2)

可以通过将常量数据声明为PROGMEM使其可寻址。由于AVR程序存储器在单独的地址空间中被组织为16位字,因此必须使用special functions进行读取。

#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;
}

确认以上示例的大小符合预期:默认数据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)

默认数据(以aaabacadaeaf开头,以994个零开始)已经在中断向量之后放置在程序存储器中。可以在运行时通过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  ................
[...]
相关问题