Topic : HardFault when using certain structure alignment

Forum : ARM

Original Post
Post Information Post
November 11, 2010 - 12:05pm

Dear Sirs,

I'm encountering a problem when using default structure alignment and addressing a 64bit structure member by means of a pointer to structure.
To clarify:

I have this structure, where SysTick_t is typedef'fed as uint64_t:

struct IoAction_t_tag
   IoActionState      State;
   SysTick_t         Tick;
   uint8_t         LockId;

   SysTick_t         ActionTick;
   SysTick_t         ActionInt;

   IoActionCallback_t   Cb;
   void*         Param;

*Note the out-commenting on the packed attribute

Now when i have a function that sets these members to some default values:

void IoActionInit( IoAction_t* Ctx, SysTick_t Interval, IoActionCallback_t Cb )
   Ctx->LockId = 0;
   Ctx->State = ActionIdle;
   Ctx->Cb = Cb;
   Ctx->ActionTick = 0; // MARK!
   Ctx->ActionInt = Interval;
   Ctx->Param = 0;

On the second call to this function, the STM32 slaps me with a HardFault interrupt, when running the marked line.

When i uncomment the packed attribute, all goes well and the STM stays nice to me.

Looking at the generated assembly ( which is obviously totally different from the packed version ) i notice that the offending instructions sort of look like this:

LDRD R1, address of structure
MOV R2, 0
MOV R3, 0
STRD R2, R3, R1 + some offset, //MARK!

(If necessary i could provide the real code)

So my questions are:
- Are there requirements for the STM32/Cortex-M3 regarding structure members/and or structure alignment i should have known about?
- Is there a know problem with the STRD instruction on Cortex-M3? ( I could not find any )
- The toolchain Ride is using ( "arm-none-eabi-gcc.exe -v" says "gcc version 4.3.2 (2008q3-66" ) is quite old and i'm perhaps encountering a bug which is already solved. Could i use/test a newer toolchain without problem?

I downloaded the latest toolchain and tried that one ( gcc version 4.4.1 (2010q1-188)) and sure enough the same problem is occuring.
With that test my third question is answered.

Post Information Post
November 15, 2010 - 2:33pm
Raisonance Support Team


We already reported some similar problems to ST.

The answer to your problem is that you should never use unpacked nor unaligned structures for handling device peripherals (through the ST Library for instance):
- Unpacked structures are unaligned (implied by the ARM-EABI GCC port), which leads to veeery poor generated code.
- Some peripheral registers cause hardfaults when accessed as 8-bit. And this is what GCC will do with unpacked structures.

The bottom line:
- ALWAYS activate the "packed structures" option.
- for the structures that you need to pack, use the pragma "pack" as follows

#pragma pack(push,1)
struct mystruct
   char c;
   long l;
} mys_packed;
#pragma pack(pop)

You can later check that sizeof(mys_packed) is equal to 5 (i.e., the structure is packed on byte boundaries).

I hope this helps,

November 16, 2010 - 11:26am


- I am not using any device peripherals in this particular instance. The assembly i posted does use CPU registers obviously.
- I am not getting how 'Unpacked structures would lead to to veeery poor generated code'? Unpacked structures in general would lead to better performing code as for example copying a struct would require less instructions. ( This is also what the assembly is showing me, instead of bytewise instructions the compiler is trying to use a doubleword store )
- Ofcourse, as i learned from my search for answers *unaligned* access could trigger a hardfault, this would reduce 'performance' a lot. :)
- 'pragma pack' is actually an MS deviced construct which GCC supports for interoperability. The GCC 'native' way of packing is using __attribute__((packed)).