The spec mentions that the M0 will generate a Hardfault when unaligned accesses are detected. I would like to find out where is this implemented in RTL and understand it a little better.
Does the GCC compiler detects unaligned code accesses during compilation as well?
As I understand it the instruction fetch hardware does this. That is an assembly instruction word needs to be aligned to 4 bytes. For example first instruction at address 0x1000 and then second one at 0x1004, etc. What happens is if you have situation where you jump to a bad address, branch to 0x1002 as an example. 0x1002 is not word aligned and hence a hard fault occurs.
These hard faults are common when you have stack overflows, or buffer overflows in your code. They can also happen when you dereference a function to pointer which has not been set correctly.
Thus the compile generates code that is word aligned during compile, but the dynamic aspects of the code can cause the error.
Thanks for the reply.
Can I say that for all other non-runtime unaligned accesses (either code accesses or data read/write) the compiler will catch all these during compilation and return an error? For example a explicit code access at an unaligned 32-bit address, or data access at unaligned word or halfword addresses?
The least significant bit of the PC is ignored. So there is no "unaligned" code. Of course, if you jump in the middle of a 4 byte instruction, you'll get a hard fault.
But unaligned data accesses are possible, but Cortex-M0 does not "care" about. You just get a performance penalty.
Is the performance penalty here referring to the compiler splitting unaligned accesses into separate (more) instructions - say 1 unaligned word access into 2 aligned hword accesses?
Which means in hardware sense the M0 always expects aligned accesses so it is the compilers job to ensure the output code always aligned (possibly multiple accesses but maintaining the initial C code intention)
Code accesses as I understand it now is expected to the word aligned and internally the MCU has hardware to detect unaligned code accesses and issue a hard fault.
eugch said:Code accesses as I understand it now is expected to the word aligned and internally the MCU has hardware to detect unaligned code accesses and issue a hard fault.
There are 4 byte and 2 byte instructions. Each can be on a 4 or 2 byte address. There is no way to have a PC with an odd address or more precisely the least significant bit is ignored (it is the Thumb-2 indication, which is not needed on a Cortex-M which is Thumb-2 only!).
eugch said:Is the performance penalty here referring to the compiler splitting unaligned accesses into separate (more) instructions - say 1 unaligned word access into 2 aligned hword accesses?
_Only_ if the compiler knows about the access.
struct unaligned { char a; int b; } __attribute__((packed));
Here, the compiler will likely split the access to "b" into multiple operations. But you should try. Maybe it "knows" that the Cortex-M can do unaligned accesses.
Note: The struct must be packed, else the compiler will insert 3 dummy bytes _after_ "a".
Also if you do something like this:
char a;
char b;
char c;
char d[4];
GCC will often put each at a word boundary, especially for debug builds (-O0). When you optimize for size it might pack them, it might not. I have seen code done where by luck gcc was placing all variables on word boundaries which masked some bugs in the code. For example one customer was taking 4 byte array to a float by *(float *)d. Which worked just fine because GCC allocated char d[4] on a word boundary by luck.
Thanks guys, that's gives me an idea where to start if I need to pursue this further.
I typically work on the RTL end of the MCU, so I'm trying to understand how the firmware and hardware work together with respect to unaligned/aligned memory accesses.