Unaligned access causes error on ARM Cortex-M4

Following is true for ARM architecture at least (verified on cortex M0):

When using load and store instructions, the memory that we access must be divisible by the number of bytes we are trying to access from/to the memory, or we will get an hard fault exception.

eg:

LDR r0, = 0x1001
LDR r1, [r0]

The second line in the above code will give hard fault since are trying to read 4 bytes but the memory address is not divisible by 4

If we change the second line in above code to the following

LDRB r1, [r0];//Load 1 byte from address

The above line will not produce a hard fault, since we are trying to access 1 byte(1 byte can be accessed from any memory location)

Also notice the following example;

LDR r0,= 0x1002
LDRH r1,[r0];   //Load half word from 0x1002

The above line will not produce a hard fault, since the memory access is 2 bytes and the address is divisible by 2.


On ARM-based systems you frequently cannot address a 32-bit word that is not aligned to a 4-byte boundary (as your error is telling you). On x86 you can access non-aligned data, however there is a huge hit on performance. Where an ARM part does support unaligned accesses (e.g. single word normal load), there is a performance penalty and there should be a configurable exception trap.

Example of boundary error on ARM (here), TLDR: storing a pointer to an unsigned char and then attempting to convert it to a double * (double pointer).

To solve your problem, you would need to request a block of memory that is 4-byte aligned and copy the non-aligned bytes + fill it with garbage bytes to ensure it is 4 byte-aligned (hence perform data structure alignment manually). Then, you can interpret that object as 4-byte aligned from its new address.

From TurboJ in comments, the explicit error:

Cortex-M3 and M4 allow unaligned access by default. But they do not allow unalinged access with the STRD instruction, hence the fault.

You may also find it helpful to look into this for forcing data structure alignment on ARM.