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.