Topic : Bug in Ride7 when using pack structure members

Forum : ARM

Original Post
Post Information Post
October 13, 2010 - 2:22pm
Guest

Hello

I would like to pack some structures so I selected "Yes" on the " pack structure members" option.

But when I compiled my project the code got about 30KByte bigger!!! And when I tried to debug it through Rlink the execution ended up instantly in HardFault_Handler().

So if this is a bug I would like to know another way to pack my structure members.

If I have a typedef for example:

typedef struct
{
u8_t a;
u16_t b;
} ab_t;

How can I pack that struct?

I'm going to save some structs to an external memory and would need to pack them.

Replies
Post Information Post
+1
0
-1
October 13, 2010 - 2:39pm
Raisonance Support Team

Hi Sima,

Structure packing is supposed to work, we do not have any registered issue about this.

In order to understand the issue you are facing, we need the Version of Ride7 and RKit that you are using. You can get these from the Ride7 "Help | About" dialog box.

Please check from the Raisonance downloads page at http://www.mcu-raisonance.com/mcu_downloads.html that you are using the latest version of the tools.

If you still see the problem:
- Provide the steps you followed to raise the error.
- Please send us a copy of your whole project (with all files included)

We will experiment about it in our Labs and try to understand the problem.

Regards,

+1
0
-1
October 24, 2010 - 1:15am
Guest

Hi,

I've experienced the same problem with the compiler, and have reduced a project to the barest minimum required to replicate the issue. This project simply enables LED1 on the STM32 EVAL board, and using the Systick Interrupt running at 5Hz blinks the LED.

When compiled with "Pack Structure Members = YES" the code ends up the the HardFault Handler.
When compiled with "Pack Structure Members = NO" the code operates properly and blinks LED1 at 2.5Hz.

NOTE: Always perform a CLEAN before a BUILD, otherwise the project files aren't recompiled/updated correctly.

Version Information:
Ride7 - 7.30.10.0159
Ride7 Patch - 7.30.10.0169
RKit-ARM for Ride7 - 1.26.10.0130

Hmmm ... how do I attach a file in this forum???

I will send the example project files to instead.

Regards,
Robert.

+1
0
-1
October 25, 2010 - 5:39pm
Raisonance Support Team

Hi Robert,

Thanks for your detailed report. We have been able to reproduce this behavior in our Labs.
It looks like we have 2 problems here:

  1. For some reason, when using packed structures GCC generates a very specific code on the following line:

    FLASH->ACR |= FLASH_ACR_PRFTBE; /* Enable Prefetch Buffer */

    The generated code will perform four 8-bit load/or/store patterns, which is poorly optimized.

    [/*]

  2. When writing a byte (using the "ldrb" opcode) to address 0x40022000 (address of FLASH->ACR), the STM32 goes direct to HardFault_Handler() [/*]

We will check whether point 1) should be corrected.
Concerning point 2), we need some information from ST to qualify the problem further (it may be a standard behavior).

As a workaround, I suggest that you explicitly pack the structures that you NEED to pack, and leave all other structures unpacked.

The "#pragma pack" GCC directives can be used for such, as in the following example:

I hope this helps,

volatile int titi;

#pragma pack(push,1)
struct mys 
{
    char c;
    long l;
} toto;     // This structure is held in 5 bytes
#pragma pack(pop)

struct mys2
{
    char c;
    long l;
} toto2;    // This structure requires 8 bytes (it is NOT packed)

titi = sizeof (toto);    // titi equals 5
titi = sizeof (toto2);   // titi equals 8
+1
0
-1
October 25, 2010 - 10:20pm
Guest

Hi Bruno,

I'm pleased that you were able to replicate it easily, and thank you for the quick reply.

For my needs I had already done the #pragma workaround (first thing I tried actually), and have therefore only applied it to my structures (as per your example) and not globally to the project.

It also appears that there is a large amount of compiler inefficiency when packing structures = YES (locally and globally), as the code size goes up dramatically - so it is quite possibly a bug in the compiler or potentially in the optimiser.

Point 2) is something I would not have expected. It might just be a combination of opcode/address which is unexpected for access to that register. Errata: 'Just don't do it that way!' ;-)

Thanks again - please update this thread again when the issues have been resolved/addressed.

Cheers,
Robert.

+1
0
-1
November 12, 2010 - 2:01pm
Guest

BearTM wrote:

It also appears that there is a large amount of compiler inefficiency when packing structures = YES (locally and globally), as the code size goes up dramatically - so it is quite possibly a bug in the compiler or potentially in the optimiser.

This could very well be the case as load/store operations on a packed struct might generate bytewise access ( lots of shifts and masks ) instructions if it's not aligned to what the ARM core wants.

With regards to point 2 Bruno is mentioning:
In my search for the problem in my own topic ( which has also to do with struct member alignment ) i came across some info regarding the Cortex-M3 core having some errata on LDRD operations, maybe thats causing your problem?
Is also seems that arm-gcc has some workaround for that ( -mfix-cortex-m3-ldrd ).

[edit]
According to this page : http://gcc.gnu.org/gcc-4.4/changes.html the flag i mention is in GCC 4.4.something, ergo the version you are using probably doesnt support it.

[edit2]
Even more info:
The Cortex M3 requires that access to memory be aligned. In your OP, when instructing the compiler to pack the struct the access to the u16 field might or might not be aligned (depends on the base address of the struct ) because there is a one byte field in front of it.
( See also http://lwn.net/Articles/259732/ for more info about aligned/unaligned access )

+1
0
-1
November 14, 2010 - 3:10am
Guest

farlane wrote:
BearTM wrote:

It also appears that there is a large amount of compiler inefficiency when packing structures = YES (locally and globally), as the code size goes up dramatically - so it is quite possibly a bug in the compiler or potentially in the optimiser.

This could very well be the case as load/store operations on a packed struct might generate bytewise access ( lots of shifts and masks ) instructions if it's not aligned to what the ARM core wants.

I realise this, but the scale of the codesize change is far larger than I would think it should be - on the order of 50% larger for the trivial example I had provided to Raisonance.

The structs are (generally) aligned on short or long boundaries, which shouldn't require byte access and shifting. The compiler appears to pad out the compiled map (for some reason), and inserts dead space as well. I don't have the project handy at the moment, but might check into this later.

farlane wrote:

With regards to point 2 Bruno is mentioning:
In my search for the problem in my own topic ( which has also to do with struct member alignment ) i came across some info regarding the Cortex-M3 core having some errata on LDRD operations, maybe thats causing your problem?
Is also seems that arm-gcc has some workaround for that ( -mfix-cortex-m3-ldrd ).

[edit]
According to this page : http://gcc.gnu.org/gcc-4.4/changes.html the flag i mention is in GCC 4.4.something, ergo the version you are using probably doesnt support it.

[edit2]
Even more info:
The Cortex M3 requires that access to memory be aligned. In your OP, when instructing the compiler to pack the struct the access to the u16 field might or might not be aligned (depends on the base address of the struct ) because there is a one byte field in front of it.
( See also http://lwn.net/Articles/259732/ for more info about aligned/unaligned access )

Very interesting! Thanks for the research & links. I wonder if the best answer is to wait for Raisonance to upgrade GCC to 4.4? :-)

Anyways ... still trying to solve another odd MCU lockup bug when using SPI2 and DMA ... (Brief Summary:) After about 6 to 20 hours under full/continuous load, I manage to get the MCU to entirely lock up. No bus fault, no obvious failure, no interrupts happening - basically nothing. Only PWM and (apparently) timers are still running ... but no interrupts are being called. This is very, odd. Nothing in the Errata I can find ... but I'm trying to solve this one now ...

+1
0
-1
November 15, 2010 - 8:41am
Guest

BearTM wrote:

Very interesting! Thanks for the research & links. I wonder if the best answer is to wait for Raisonance to upgrade GCC to 4.4? :-)

Regarding the other bug: Could it be that for some reason you are not clearing some interrupt and it is only processing higher priority interrupts and for the rest handling your 'not cleared interrupt' very fast? That situation could seem like the CPU is locking up, but not for some specific interrupts.

+1
0
-1
November 15, 2010 - 2:44pm
Raisonance Support Team

Hi all,

The next RKit-ARM release will be based on GCC 4.4, with lots of other goodies.
We are waiting for a marketing annoucment from ST before releasing it. Hold your breath until then...

Regards,

+1
0
-1
November 15, 2010 - 11:14pm
Guest

farlane wrote:
Regarding the other bug: Could it be that for some reason you are not clearing some interrupt and it is only processing higher priority interrupts and for the rest handling your 'not cleared interrupt' very fast? That situation could seem like the CPU is locking up, but not for some specific interrupts.

I've checked for that, and can't find a fault. There is some race condition occurring, since this only happens after many hours of continuous operation. I've also verified priorities in the NVIC and to try and track it down, I have now added a LED toggle to the highest level interrupt and will see if this keeps toggling or not. The last test I did I had no other interrupts executing (keyscan, timeout, I2C, serial, etc.) and no watchdog reset either. Full lockup as far as I could tell. Very odd.

Bruno wrote:
BearTM wrote:

I wonder if the best answer is to wait for Raisonance to upgrade GCC to 4.4? :-)

The next RKit-ARM release will be based on GCC 4.4, with lots of other goodies.
We are waiting for a marketing annoucment from ST before releasing it. Hold your breath until then...

I think I have my answer then ... and I definitely like more goodies!
Although, not sure if I can hold my breath for much longer than about 2 minutes maximum!

BTW: The #pragma workaround is still working fine, so I'm not overly concerned for the moment.

Cheers,
Robert.