Dear All,
I have been using arm complier V5 for a couple of years and it works very good actually. I finished one complete project using V5 -O3 optimization level. However, I started new project and I would like to use V6. I read some notes like how to migrate or what should I consider when I write C code which will be complied V6. I developed a very simple code just blinking a LED. It is "Hello World" code and it should work. However, it doesn't work V6 with any optimization level except -O0. I complied the code again with V5 -O3 and -Otime and it worked well.
Let me write my simple code and then explain what happens:
-----------------------------
Counter = 0;
while (1) { if (Counter < 5) { GPIOD->BSRR = GPIO_PIN_5; // Output is set and LED should give light. } else { GPIOD->BSRR = (uint32_t)GPIO_PIN_5<< 16 ; // Output is set and LED should give light. } if(Counter > 10) { Counter = 0; } }
//************************************************************************ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) // Timer 3 Interrupt subroutine It hits every 100ms. { if(htim == &htim3) { Counter++; } }
-------------------------------------------------------------------------------------
Counter increments every 100ms with Timer-3 interrupt in the related interrupt subroutine. So, every 500ms LED should be gives light and turn off again. However, it is continuously gives light and never turn off. I think that the complier optimizes the code and Counter is zero at the beginning and it never changes in While(1) loop. So the complier decided Counter won't be greater than 5 so no need to compile remaining code and it only builds “GPIOD->BSRR = GPIO_PIN_5;” line. If I change "if condition" that Counter is greater than 5 then the complier takes only "GPIOD->BSRR = (uint32_t)GPIO_PIN_5<< 16 ; " this line and removes others. So, this time LED stays off...
I complied with V6 -O0 and it worked but -O1,-O2,-Oz etc... it doesn't work. It works V5 -O3 with -Otime. So, what should I do? Is there any option that I don't know?
Most of my code run inside interrupt subroutines. Many variables are changed inside these subroutines and they are used in main loop which are not time critical. So, if V6 removes all my code like mentioned above I cannot use V6. I don't except that Arm made this kind of mistake. I am sure there are options that I haven't known yet.
Please help me about the issue.
Best Regards
Hi Ayanik,
My first thought would be that you have not declared the variable as volatile.
Can you provide a complete project example so I can investigate? You can email to me at first.lastname<at>arm.com
Ronan
Dear Ronan
You are right. I didn't declare the variable as volatile. Migration document doesn't carefully mention about volatile. It gives good example about inline or other compatibility issues. But it mentiones volatile issue very short and I thought my variables are not "volatile". As a word "volatile" means someting is not perminant. Generaly engineer uses volatile variable in subroutines. All my variables are global variables and they are not volatile. That is why I didn't focus carefully on "volatile" issue. After your message I download Arm® Compiler Version 6.13 User Guide and it explains on page 57. It says:
-------------------------------------------------
What volatile means:
The declaration of a variable as volatile tells the compiler that the variable can be modified at any timeexternally to the implementation, for example:
• By the operating system.• By another thread of execution such as an interrupt routine or signal handler.• By hardware.
This ensures that the compiler does not optimize any use of the variable on the assumption that this variable is unused or unmodified.
----------------------------------------------
I declared "Counter" variable as volatile and code worked well. I complied V6 -Ofast. I copied some part of Page57 and pasted above for other forum members to read easly.
Thank you very much indeed. I need to read more about usage of volatile, because I may face many problem in my code. Most of variables are changed in interrupt subroutines.
Hi, I'm Product Manager Compilers - sorry to hear you've had problems with your migration to AC6 but thanks Ronan for great advice!
It looks like AC6 has managed to find a few additional ways to optimize code than the older AC5 compiler: we've worked hard for years to get you a compiler with the performance and code density you need to make your products successful. There is a downside of course, in that to give AC6 the visibility it needs to make optimization decisions, sometimes we need to be clearer in the information we give. In this case the compiler has become more sensitive to appropriate use of volatile specifiers - things which we could get away with for AC5 now become more important with AC6.
Many thanks for your feedback on our documentation, this isn't the first time that volatile (rather, missing volatile) has caused problems. We'll review our docs and see if any changes would be helpful.
Paul.