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

问题描述 投票:0回答:1

我需要在闪存中存储一​​些大块数据,在那里它会经常被读取,偶尔也会用SPM重写。我已经想出如何使用指向__flashpgm_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文件中为该位置发出任何初始化数据?

c avr avr-gcc sections flash-memory
1个回答
1
投票

您似乎没有意识到您实际上需要两个版本的hex文件 - 一个适合在新的(或更糟的:重新使用,因此具有随机Flash内容)芯片初始化闪存的“新”安装确保其中没有可能被解释的任意数据的部分,另一部分用于更新错过本节的预编程芯片,以保持用户已修改的数据。因此,无论如何,您将需要初始化此部分的版本。

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

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

我宁愿尝试使用EEPROM,如果可用的话,还要经历重新编程的麻烦。

© www.soinside.com 2019 - 2024. All rights reserved.