代码之家  ›  专栏  ›  技术社区  ›  Bergi

如何为数据保留固定的闪存部分?

  •  1
  • Bergi  · 技术社区  · 6 年前

    我需要将一些大数据块存储在闪存中,在闪存中可以经常读取,偶尔也可以使用SPM重写。我已经知道如何使用指针 __flash pgm_read_byte 要访问它,如何不忽略 const (尽管我写了这篇文章),如何在循环中实际访问数组,以便它不会得到完全优化(内联后),但我真的不知道如何声明我的数组。

    const uint8_t persistent_data[1024] __attribute__(( aligned(SPM_PAGESIZE), 
                                                        section("mycustomdata") )) = {};
    

    很好,只是我不想初始化它。在对我的设备(Arduino ATmega328P)进行编程时,我希望保留此部分,以便它保留应用程序先前写入的数据。上面的零初始化它,我的十六进制文件包含零,程序员很乐意使用这些零来覆盖我的数据。

    使用 __闪光灯 修改器而不是 __attribute__(( section("…") )) 在这里也是一样的,只是它将数组放在其他地方,我无法控制它放在哪里。当我使用 __闪光灯 省略初始化(尽管我得到了一个“ 未初始化变量“persistent\u data”放入程序内存区[-Wuninitialized] “警告”)。

    现在我试图省略初始化器:

    const uint8_t persistent_data[1024] __attribute__(( aligned(SPM_PAGESIZE),
                                                        section("mycustomdata") ));
    

    并得到意想不到的结果。中的节数据。lss输出显示

    Idx Name          Size      VMA       LMA       File off  Algn
      …
      1 mycustomdata  00000480  00800480  000055e2  00005700  2**7
                      CONTENTS, ALLOC, LOAD, DATA
      2 .text         00005280  00000000  00000000  000000d4  2**1
                      CONTENTS, ALLOC, LOAD, READONLY, CODE
    

    这会将所有初始化零放在十六进制文件中的加载内存地址55E2处(而不是忽略它们),而虚拟内存地址(变量 persistent_data 指向)参考0480-在文本部分的代码中间!

    (我还试图省略 常量 ,并省略 常量 和初始化器,两者的效果与仅省略初始化器相同)。

    我不知所措。我需要使用 extern 大概(任何这样做的尝试最终都会导致“ 对persistent\u数据的未定义引用 “错误)。是否需要使用链接器脚本?

    我该怎么做 persistent\u数据 引用的位置是没有被任何其他数据使用的程序内存,并且编译器没有在十六进制文件中为该位置发出任何初始化数据吗?

    1 回复  |  直到 6 年前
        1
  •  2
  •   tofro    6 年前

    你似乎没有意识到你真的需要 十六进制文件的版本-适用于新芯片上的“新”安装(或更糟:重复使用,因此带有随机闪存内容),该芯片初始化闪存部分以确保其中没有可能被解释的任意数据,另一个用于 使现代化 一种预先编程的芯片,它遗漏了这一部分,以便保存用户已经修改过的数据。因此,无论如何,您都需要初始化此部分的版本。

    实现这一点的最简单方法与第一个示例类似,初始化数据以构建代码的“裸芯片”版本,并通过使用从对象文件中删除此初始化部分来生成“更新”版本 对象复制 (假设您使用GNU工具链)。请参见 -R 此工具的选项。

    此外,请确保此数据节位于固定地址—您不希望每次更改代码中的某些内容时都移动它。

    我宁愿尝试使用EEPROM(如果可用),也不愿经历重新编程的麻烦。