c - 如何在Arduino中获取全局变量的flash地址

标签 c arduino avr atmega

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

附言所讨论的静态全局变量是一个相当大的结构。重新定义它是不可能的。

最佳答案

可以通过将常量数据声明为 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 个零)已被放置在程序存储器中,紧跟在中断 vector 之后。它可以在运行时通过 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  ................
[...]

关于c - 如何在Arduino中获取全局变量的flash地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53691292/

相关文章:

c - 不使用字符串库函数对字符串进行排序和比较

从一组单元测试中组成一个组合测试套件程序

azure - 将 Arduino Uno 数据直接解析到 IoT

c - 阿杜诺 & C : put a function and global variable in external file

c - AVR Xmega USART 读取完整字符串时出现问题

c - avr if 语句优化速度或大小

c - 为什么我不应该在 C 文件中使用 sizeof(double)

c - 如何在arduino板上创建一种线程?

c++ - 如何在 AVR 上制作 2D PROGMEM 阵列的 1D PROGMEM 阵列(存储在闪存中)(例如 : ATMega) or Arduino microcontrollers

c - 为什么线程2要等待线程1结束?