cgccarmembeddedcortex-m

How to do unaligned int store on ARM Cortex M4?


How can C code take advantage of the Cortex M4's unaligned 4-byte store instruction? *(int*)p = x mostly works, but occasionally I end up with something like this:

void Store(uint8_t* p, uint32_t a, uint32_t b)
{
  *(uint32_t*)(p + 0) = a;
  *(uint32_t*)(p + 4) = b;
}

which gcc then compiles to:

00000000 <Store>:
   0:   e9c0 1200       strd    r1, r2, [r0]
   4:   4770            bx      lr
   6:   bf00            nop

which of course gives a HardFault because 8-byte stores must be aligned. Is there a way to write the stores so that gcc knows they can be unaligned? Is there maybe an unaligned int type, perhaps?


Solution

  • Sinc you are using GCC, you can use a packed structure:

    struct p { uint32_t u; } __attribute__((__packed__));
    
    void Store(void *vp, uint32_t a, uint32_t b)
    {
        struct p *pp = vp;
        pp[0].u = a;
        pp[1].u = b;
    }
    

    This generates:

    Store:
            str     r1, [r0]  @ unaligned
            str     r2, [r0, #4]      @ unaligned
            bx      lr
    

    Note that you should consider the aliasing rules when doing this. If the destination is defined with a different type, storing the data with this structure type could require some workaround for that.