如何使用RAM地址对联合缓冲区进行字节对齐

时间:2016-01-20 11:05:10

标签: c memory-management unions memory-alignment nrf51

我目前正在使用NORDIC(32位ARM Cortex M0)的nRF51 MCU进行C语言编码。

我想通过无线电发送工会的缓冲区。为此,我必须将union的缓冲区地址提供给PACKETPTR。 否则,地址为" PACKETPTR"必须是,根据manuel参考:字节对齐的RAM地址。 如果它没有对齐,它设法采取下一个最接近的一个,但这样接收器将接收不完整的缓冲区和"虚拟"数据...

你可以猜到,我的缓冲区没有字节对齐。这是有关联盟和全局变量。

我的联盟的元素必须打包,以便它们可以适合7个字节;

typedef union
{   
    uint8_t buf[7];  //The buffer I give to PACKETPTR
    __packed struct 
    {
        uint8_t             a[2];
        uint8_t             b;
        uint16_t            c : 10;
        uint16_t            d : 6;  
        uint16_t            e : 14;
        uint16_t            f : 2;
    }parts;
}adv_t;

adv_t m_adv; //The global variable

...

//Later in the code to set PACKETPTR

config_tx(ADV_PIPE, m_adv.buf);

...

void __INLINE config_tx(uint8_t tx_pipe, uint8_t* payload)
{
   NRF_RADIO->TXADDRESS = tx_pipe;
   NRF_RADIO->PACKETPTR = (uint32_t)payload;
}

一开始我在__packed之前添加了typedef union限定词。但就好像m_adv被包装了#34;对于一些以前的数据,因此buf地址与ram地址没有字节对齐。

__packed typedef union /* Previous definition */
{   
    uint8_t buf[7];
    __packed struct 
    {
        ...
    }parts;
}adv_t; 

所以我删除了它,然后buf地址是正确的(即字节与RAM地址对齐)。我认为这是解决方案,但几分钟后它再次变得错位... 我的问题是:__packed限定符是否因为联合而影响buf?有没有办法强制我的全局变量buf地址对齐?或任何建议?

由于

3 个答案:

答案 0 :(得分:1)

您的问题似乎是关于打包,而不是RAM地址的对齐(打包时会对齐,但对齐本身并不重要情况)。

这里的问题是你没有真正打包结构,因为属性放错了位置。它应该是:

typedef union
{   
    uint8_t buf[7];
    struct // not here
    {
        uint8_t             a[2];
        uint8_t             b;
        uint16_t            c : 10;
        uint16_t            d : 6;  
        uint16_t            e : 14;
        uint16_t            f : 2;
    } __packed parts; // here, __packed or __attribute__((packed))

}adv_t;

b之后插入了一个额外的字节,以便在16位边界上对齐以下uint16_t

请注意,如果您不需要访问单个字节,则无需建立联盟。您可以只使用结构并传递结构的地址。

答案 1 :(得分:0)

我不确定您使用的编译器。但是,您可以将结构实例的对齐方式与数据类型的打包分开定义。

例如,GCC定义了一个属性:_attribute__((aligned(4)))
Visual Studio有另一种方法__declspec(align(4))

请查看编译器手册,了解如何明确定义数据成员的对齐方式。

答案 2 :(得分:0)

感谢您的回答。

我的结构成员完全适合buf我想要的(没有填充,MSB / LSB按我的预期放置等),我并不是说我想访问特定的bitfield成员。

我没详细说明,但问题来自接收器。

我收到了前任。 0xEF 0x00 0xFC 0xB2 0x38 0x00 0xB6 代替0xCD 0xAB 0xEF 0x00 0xFC 0xB2 0x38buf内容)。

所以我认为问题是关于buf地址和手册句子谈论PACKETPTR的“RAM地址”我误解了它。问题实际上是来自我的接收器的帧处理。对不起!!