我需要将一些大块数据存储在闪存中,在那里它会经常被读取,偶尔会使用SPM重写。我已经想出如何使用指向__flash
和pgm_read_byte
的指针来访问它,如何不省略const
(尽管我写了它),如何实际访问数组循环,以便它没有完全优化(内联后),但我真的不明白如何声明我的数组。
const uint8_t persistent_data[1024] __attribute__(( aligned(SPM_PAGESIZE),
section("mycustomdata") )) = {};
工作得很好,除了我不想初始化它。在编程我的设备(Arduino ATmega328P)时,我想要保留此部分,以便它保留以前由应用程序编写的数据。上面的内容对它进行了零初始化,我的hex文件包含程序员愉快地用来覆盖我的数据的零。
使用__flash
修饰符代替__attribute__(( section("…") ))
在这里大致相同,只是它将数组放在其他位置并且我无法控制它的放置位置。当我使用__flash
并省略初始化时它仍然会这样做(虽然我得到一个“未初始化的变量'persistent_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的hex文件中(而不是省略它们),而虚拟内存地址(变量persistent_data
指向的)指的是0480 - 在文本部分的代码中间!
(我也尝试省略const
,并省略const
和初始化,这两者都与仅省略初始化具有相同的效果。)
我不知所措。我是否需要使用extern
? (任何这样做的尝试最终都会出现“未定义的对persistent_data 的引用”错误)。我需要使用链接描述文件吗?
如何使persistent_data
引用一个位置是程序存储器,该程序存储器未被任何其他数据使用,并且编译器不会在hex文件中为该位置发出任何初始化数据?
答案 0 :(得分:1)
您似乎没有意识到您实际上需要两个版本的hex文件 - 一个适合新版本的“新”安装(或者更糟:重复使用,因此随机闪存内容)芯片初始化闪存部分以确保其中没有可能被解释的任意数据,另一个用于更新预先编程的芯片,错过了本节的顺序保持用户已修改的数据。因此,无论如何,您将需要初始化此部分的版本。
实现此目的的最简单方法就像您的第一个示例,初始化数据以构建代码的“裸芯片”版本,并通过使用 objcopy (假设您使用GNU工具链)。请参阅此工具的-R
选项。
另外,请确保此数据部分位于固定地址 - 您不希望每次更改代码中的某些内容时都会移动它。
如果可行的话,我宁愿尝试使用EEPROM,也不愿意经历重新编程的麻烦。