Long story short I have this in C using the IAR EWARM compiler.
uint8_t packet[2048];
uint32_t* src = (uint32_t*)&packet[9];
uint32_t var = *src++;
That last line causes a bus fault.
uint8_t packet[2048];
uint32_t* src = (uint32_t*)&packet[9];
uint32_t var = 0xFE;
*src++;
Now there is no bus fault. I can see in the debugger src points to the data I expect it to point to. Increment it works as expected but trying to read it casues a bus fault.
Any help?
&packet[9] is probably not aligned correctly for uint32_t. Seeing "Bus Error" on an ARM CPU is often a sign of an alignment error. See here for an explanation of alignment.
On the second example it probably avoids the bus fault by optimizing out the * operation, since you never use the result.
Note that even if you fix this, the code still causes undefined behaviour by violating the strict aliasing rule. (uint8_t may not be aliased as uint32_t). Some compilers may appear to "work correctly" for now but the code could break at any time in future.
The safe equivalent of your code would be:
uint8_t *src = &packet[9];
uint32_t var;
memcpy(&var, src, sizeof var);
src += sizeof var;
Note that if the source data is specified as having a particular byte order for integer (e.g. you are getting it from network stream as opposed to data you saved earlier by the same method) then you will want to use a method to read the data that is independent of the representation of uint32_t. (In other words, "endianness").
It could be that your MCU needs reads of 32 bit integers to be aligned to 32 bits.
&packet[9] is most certainly not 32 bit aligned, that's why you get a fault.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With