首页 文章

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

提问于
浏览
0

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

附:有问题的静态全局变量是一个相当大的结构 . 重新定义它是不可能的 .

1 回答

  • 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  ................
    [...]
    

相关问题