1

我目前正在用 C 编写代码并使用 NORDIC(32 位 ARM Cortex M0)的 nRF51 MCU。

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

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

我的 union 元素必须被打包,以便它们可以容纳 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;
}

一开始我__packedtypedef union. 但它好像m_adv是用一些以前的数据“打包”的,因此buf地址不是与 ram 地址字节对齐的。

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

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

谢谢

4

3 回答 3

1

您的问题似乎是关于packing,而不是 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以将以下内容uint16_t与 16 位边界对齐。

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

于 2016-01-20T11:51:06.023 回答
0

谢谢您的回答。

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

我没有足够详细,但问题出在接收器上。

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

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

于 2016-01-20T17:13:12.883 回答
0

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

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

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

于 2016-01-20T11:26:09.297 回答