cmemory-managementunionsmemory-alignmentnrf51

How to byte-align a union's buffer with RAM address


I am currently coding in C and using nRF51 MCU from NORDIC (32-bit ARM Cortex M0).

I would like to send an union's buffer by radio. For this purpose I have to give the address of the union's buffer to PACKETPTR. Otherwise the address given to "PACKETPTR" has to be, according to the manuel reference: a byte aligned RAM address. If it isn't aligned, it manages to take the next closest one but in this way the receiver will receive incomplete buffer and "dummy" data...

As you can guess, my buffer isn't byte aligned. Here is the concerned union and the global variable.

My union's elements have to be packed so that they can fit in 7 bytes;

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;
}

At the beginning I added __packed qualifier before typedef union. But it was as if m_adv was "packed" with some previous data, hence buf address wasn't byte aligned with ram address.

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

So I removed it, and then buf address was correct (ie. byte aligned with RAM address). I thought that was the solution, but few minutes later it became mis-aligned again... My questions are: Does the __packed qualifier affects also buf because of the union? is there a way to force buf address from my global variable to be aligned? Or any suggestion?

Thanks


Solution

  • Thank you for your answers.

    My struct members fit perfectly in buf as I wanted (no padding, MSB/LSB placed as I expected etc.), and I didn't mean I want to access to particular bitfield members.

    I didn't detail enough, but the problem went from the receiver.

    I received for ex. 0xEF 0x00 0xFC 0xB2 0x38 0x00 0xB6 instead of 0xCD 0xAB 0xEF 0x00 0xFC 0xB2 0x38 (bufcontent).

    So I thought the problem was about buf address and the Manual sentence talking about "RAM address" for PACKETPTR I misunderstood it.. The problem was effectively coming from the frame processing of my receiver... sorry!!