If I have a struct declared like the following:
volatile struct { uint8_t foo; int16_t bar[1]; } __attribute__((packed)) foobar;
The code emitted uses LDRSH to access bar[0] and causes a hardfault at runtime. But If I were to declared it using the __packed qualifier:
__packed volatile struct { uint8_t foo; int16_t bar[1]; } foobar;
Then the compiler correctly recognizes the potential misalignment and emits LDRB instead. Is this the expected behavior? I'm using uVision v5.17 with Armcc v5.06 update 1 (build 61). Thanks.
It seems strange if the compiler supports a construct where it does pack the data but at the same time accesses the data with instructions that does not support packed data.
If you had instead used a pointer, then I would have assumed that the compiler didn't support one of the two ways of specifying packed data.
Or might something happen where the compiler do not support one of the constructs but the attribute survives all the way down to the linker so the linker takes non-packed data and links it to an odd address?
Hello David,
Did you see this entry in the manual:
I assume you are using the --gnu or such in your Project-> Options for target -> "C/ C++ " tab, compiler control string, because based on this article:
infocenter.arm.com/.../index.jsp
It sounds like you are running into the scenario:
In GNU mode, __attribute__((packed)) has the effect of #pragma packed. Taking the address of a field covered by __attribute__((packed)) does not produce a __packed qualified pointer.
For more details, see: infocenter.arm.com/.../index.jsp
There is good stuff there, but of particular interest is the "Comparison of a __packed struct and a #pragma packed struct" section. It looks simular to the issues you are having.
A good work around may be to, rather than packing the whole struct, pack only the parts you care about (maybe just uint8_t foo;). There is a performance penalty for marking the whole struct as packed.
In my experience, packing the struct is something you only do if you are desperate for space - leaving the struct members at their natural data alignment makes it much simpler code. Also, there can be headaches when referencing pointers to pointers of a packed struct, if not done right.