This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Passing by address results in compiler miscalculation?

When I use a local struct variable of type RCC_ClocksTypeDef (part of the ST peripheral library) and I call the RCC_GetClocksFreq() function passing the local struct as the parameter, for some reason the compiler increments the address by 4 so the data is all misaligned. However, if I use a global variable of the same type, the compiler handles this ok.

The issue only occurs with compiler optimization level of 0 or 1.

I'm using Keil MDK-Arm 4.13a and targeting the STM32F103. Using the simulator for now. I have the latest version of the ST peripheral library. My code snip in 'C' looks like:

.....

RCC_ClocksTypeDef  grcc_clocks;

int main(void)
{
   RCC_ClocksTypeDef  rcc_clocks;
   RCC_GetClocksFreq(&rcc_clocks);
         RCC_GetClocksFreq(&grcc_clocks);
}

So with the code optimization set to Level 0 or 1, where the code does not result in the expected result, here is the asm:

   106:    RCC_ClocksTypeDef  rcc_clocks;
0x0800357C B086      SUB      sp,sp,#0x18
   107:    RCC_GetClocksFreq(&rcc_clocks);
0x0800357E A801      ADD      r0,sp,#0x04
0x08003580 F7FEFCBC  BL.W     RCC_GetClocksFreq (0x08001EFC)
   108:          RCC_GetClocksFreq(&grcc_clocks);
   109:
0x08003584 4842      LDR      r0,[pc,#264]  ; @0x08003690
0x08003586 F7FEFCB9  BL.W     RCC_GetClocksFreq (0x08001EFC)

So now with the code optimized to 2 or 3, THIS code works properly:

   106:    RCC_ClocksTypeDef  rcc_clocks;
0x0800332C B086      SUB      sp,sp,#0x18
   107:    RCC_GetClocksFreq(&rcc_clocks);
0x0800332E 4668      MOV      r0,sp
0x08003330 F7FEFD88  BL.W     RCC_GetClocksFreq (0x08001E44)
   108:          RCC_GetClocksFreq(&grcc_clocks);
   109:
0x08003334 4842      LDR      r0,[pc,#264]  ; @0x08003440
0x08003336 F7FEFD85  BL.W     RCC_GetClocksFreq (0x08001E44)

So the issue seems to be this line:

0x0800357E A801      ADD      r0,sp,#0x04

Is this a compiler error?

  • "...increments the address by 4 so the data is all misaligned..."

    Typically on ARM, I would expect the alignment of a structure to be 4. So adding 4 to an address would mean that the alignment were the same; i.e., if it had correct alignment before, then it would have correct alignment after.

    For what you're seeing, it would depend upon where the compiler chose to place the local structure within the stack frame. Maybe different optimisation levels would just cause the compiler to make different decisions upon that placement.

    The most important questions are surely 'does the code work?' and 'why do you suspect there is a problem?'.

  • The compiler places the variable at the same address (0x20000128 for global and 0x20000250 for local) irregardless of optimization.

    To answer your question, NO the code does not work when 4 is added to the address because the struct members are modified by the GetClocksFrerq function. When it returns, the data is all shifted by 4 bytes.