I stumbled upon this tidbit while reviewing the ARM online documentation on unaligned access. Upon review the information seems obvious, but I was not aware of the specific alignment rules.
I am quoting here directly from ARM’s website. If you are debugging unaligned access issues, I recommend reading the full article.
This is an excerpt from How does the ARM Compiler support unaligned accesses? Any emphasis made below is mine.
As mentioned above, a pointer should contain an address with correct alignment for the type.
uint32_t*
requires 4-byte alignmentuint16_t*
requires 2-byte alignmentuint8_t*
requires 1-byte alignment
For structures, the alignment is that of the most aligned member. The compiler will generate code on the assumption that a pointer is correctly aligned. It does not add code to perform run-time checks. A pointer may contain an incorrectly aligned address for a number of reasons. A common cause is casting:
uint8_t tmp;
uint32_t_pMyPointer = (uint32_t_)(&tmp);
This code takes the address of an uint8_t
variable, then casts that address as a uint32_t
pointer. The compiler will still assume that pMyPointer
is correctly aligned for a uint32_t
pointer. The compiler might then generate code that results in an unaligned access unknowingly. This can be avoided using the __packed
qualifier:
__packed uint32_t* pMyPointer = (__packed uint32_t*)(&tmp);
The arm link doesn’t work
Yep, looks like they changed the link. I’m digging around for a new one.