Forum : ARM
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. 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; }/*__attribute__((packed))*/; *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: [edit] |
Hi,
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
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,
Bruno
- 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)).