【问题标题】:Alignment of C structure in Internal FLASH memory内部 FLASH 存储器中 C 结构的对齐
【发布时间】:2012-01-20 22:57:46
【问题描述】:

我有一个配置结构,我想保存在 ARM cortex M3 的内部闪存上。 根据规范,保存在内部flash中的数据,必须对齐32bit。 因为我的结构中有很多布尔值和字符,我不想使用 32 位来存储 8 位...我决定使用 __packed 预处理器编译指示来打包结构,然后当我将它作为一个整体保存时结构,我只需要确保结构大小可被 4 整除(4 字节 = 32 位),如果需要,我通过添加填充字节来做到这一点。 目前,在开发过程中,我对结构进行了很多更改,为了使其与 32 位对齐,我需要一直更改填充字节。 目前的结构是这样的

typedef __packed struct
{
uint8_t status;
uint16_t delay;
uint32_t blabla;
uint8_t foo[5];
uint8_t padding[...] // this has to be changed every time I alter the structure.
} CONFIG;

有没有更好的方法来实现我正在做的事情? 我是嵌入式编程的新手,我想确保我没有犯错。

编辑:请注意。数据在内部闪存的末尾持久化,因此省略填充将不起作用...

【问题讨论】:

  • 我相信你的理解是不正确的。闪存中的指令可能必须对齐,这将由编译器保证。但即使未对齐存储在闪存中的数据也可以通过 arm cortex m3 内核进行管理。你用的是哪家公司的MCU?

标签: c memory-alignment cortex-m3 iar


【解决方案1】:

也许这是一个想法:

typedef __packed struct {
    uint8_t status;
    uint16_t delay;
    uint32_t blabla;
    uint8_t foo[5];
} CONFIG;

typedef __packed struct {
    CONFIG cfg;
    uint8_t padding[4 - (sizeof(CONFIG) % 4)]
} CONFIGWRAPPER;

【讨论】:

  • 其实我想到的时候。如果它已经对齐,那么我们就添加 4 个字节
【解决方案2】:

解决方案 1:您可以将其放在包含您的结构和字符数组的联合中:

union
{
  CONFIG config;
  uint8_t total_size[32];
} my_union;

【讨论】:

  • 这很有趣,假设sizeof(CONFIG)小于total_size的大小。我在联合中设置了配置。 sizeof(my_union) 是多少?
  • 如果CONFIG小于total_size,那么sizeof(my_union)将是total_size的大小,具体为32。
【解决方案3】:

首先,通常要避免打包对齐,如果您最终得到的数据未与其自然边界对齐,则某些 CPU 会在您尝试访问它们时发出陷阱。

首先,按顺序存储成员,这样编译器就不会为对齐添加间隙(或者如果有,它会在末尾添加)。如果可以的话,让 1. 成员具有您想要的对齐要求 - 因为这会强制编译器至少为结构提供那么多对齐。

这需要您了解平台和编译器的对齐要求,例如摆脱填充数组,并更改

typedef struct
{
uint8_t status;
uint16_t delay;
uint32_t blabla;
uint8_t foo[5];
uint8_t padding[...];
} CONFIG;

typedef struct
{
uint32_t blabla;
uint16_t delay;
uint8_t status;
uint8_t foo[5];
} CONFIG;

然后告诉编译器这个结构需要 4 字节对齐(在这种情况下,它可能已经需要,因为第一个成员有 4 字节或更多的对齐要求)。例如与 gcc 一起使用 attribute((__aligned__(4))

然后编写一个小测试程序来验证你的对齐要求(这只是一个在你的结构上使用 sizeof() 和 alignof() 的小程序),这甚至会告诉你是否需要添加指令要对齐的结构。将该程序作为构建/打包的一部分运行。

【讨论】:

  • 优秀的答案和明确的陈述。示例测试程序对您的成功或失败至关重要,如果您想对跨编译域的结构执行您尝试执行的操作(将硬件视为编译域),则不能跳过此步骤。
【解决方案4】:

解决方案 2:您可以使用 IAR 特定功能 #pragma location 将配置数据放置在特定位置,例如闪存末尾的 32 处。这样你就不需要以任何方式填充结构:

/* Fictitious end of flash location. */ 
#pragma location=0x1234FFE0
struct [... your struct goes here ...]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 2013-06-12
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多