我正在尝试执行理论上应该可行但我开始怀疑是否在 arm-elf-gcc 的能力范围内的内存优化。请告诉我我错了。
我有一个嵌入式系统,它的主内存非常少,电池支持的 nvram 更少。我将校验和配置数据存储在 nvram 中,以便在启动时我可以验证校验和并继续之前的运行或在校验和无效时开始新的运行。在运行期间,我更新了此配置数据中各种大小的字段(这可以使校验和失效,直到稍后重新计算)。
所有这些都在物理地址空间中运行——普通 sram 映射到一个位置,而 nvram 映射到另一个位置。这就是问题所在——所有对 nvram 的访问都必须以 32 位字进行;不允许字节或半字访问(尽管在主存储器中显然没问题)。
所以我可以 a) 将所有配置数据的工作副本存储在主内存中,并在我重新计算校验和时将其 memcpy 到 nvram 或 b) 直接在 nvram 中使用它,但以某种方式说服编译器所有结构都是打包和所有访问不仅必须是 32 位对齐的,而且必须是 32位宽的。
选项 a) 浪费了宝贵的主内存,我更愿意通过选项 b) 进行运行时权衡来保存它(尽管如果代码大小最终浪费的比我节省的数据大小更多)。
我希望它__attribute__ ((packed, aligned(4)))
或其中的一些变体可以在这里有所帮助,但是到目前为止我所做的所有阅读和实验都让我失望了。
这是我正在处理的那种配置数据的玩具示例:
#define __packed __attribute__ ((packed))
struct __packed Foo
{
uint64_t foo;
struct FooFoo foofoo;
}
struct __packed Bar
{
uint32_t something;
uint16_t somethingSmaller;
uint8_t evenSmaller;
}
struct __packed PersistentData
{
struct Foo;
struct Bar;
/* ... */
struct Baz;
uint_32 checksum;
}
您可以想象不同的线程(每个线程执行函数 Foo、Bar 和 Baz)在适当的时候更新它们自己的结构,并在某个时间同步以声明是时候重新计算校验和并进入睡眠状态。