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