This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
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

segger embedded studio with gcc volatile problem

Hi,

I use SES import my keil project, and my keel project work well. With SES, i meed a problem, that is , i have a global variable like this:

uint32_t               g_ulMainLoopCounter = 0;

and i decrease it in timmer isr:

if  (g_ulMainLoopCounter > 0)
{
    g_ulMainLoopCounter--;
}

in my main function, i wait until 'g_ulMainLoopCounter' decrease to 0:

int main(void)
{   
    system_init();                                      //init timer etc...
   
    g_ulMainLoopCounter = 500;
    while (g_ulMainLoopCounter)
    {
    }

   ....
}

now the problem is , my code after 'while' will never be executioned, even 'g_ulMainLoopCounter' decrease to 0. This work well in keil.

Then, if i use 'volatile' qualifier for 'g_ulMainLoopCounter', it works, the code then like this:

volatile uint32_t g_ulMainLoopCounter = 0;

My optimization level set to none, means do not optimize my code.

I know use 'volatile' qualifier is a better way, but 'g_ulMainLoopCounter' is just only a example, there are lots of variables which used like "g_ulMainLoopCounter" (means multi-access variable, change the value in a function or isr and comparison in other function)in my program, must i check every variable in my program and determine if the variable is needed use 'volatile' qualifier? If so, i think that's too difficult.Is there any easy solutions?

Parents
  • Did you mean it worked by adding volatile in front ? That is the correct behaviour. There is no bug with GCC but might be a bug in Keil if it is compiled with full optimization. The volatile key word tells the compiler to always load data from memory. This is for this type of multi-access to guarantee that the value is loaded before comparison. Without it, optimization will preload the value in register and use locally in the loop. Hence when the interrupt updates the value it will not reflect in the main loop. So you will loop endlessly.

  • Yes, i agree with you about this, and i understand what the effect of "volatile" is. But, in my program, there are lots of variables which used like "g_ulUartTimeoutCounter" , for example:

    if ((!g_ulMainLoopCounter) && (!g_tMainLoopInterface.iap_state))
    {
        //do something
    }
    

    When i use keil MDK, it works well,and when i use SES, the code in this "if" segment never be executioned, even "g_ulMainLoopCounter" used 'volatile' qualifier, because the member "iap_state" of struct "g_tMainLoopInterface" is not 'volatile', and i change the value of 'iap_state' in other function(not isr).

    So, if i want use SES(or other IDE used gcc),must i check every variable in my program and determine if the variable is needed use 'volatile' qualifier(it's very difficult i think)? Is there any easy solutions?

Reply
  • Yes, i agree with you about this, and i understand what the effect of "volatile" is. But, in my program, there are lots of variables which used like "g_ulUartTimeoutCounter" , for example:

    if ((!g_ulMainLoopCounter) && (!g_tMainLoopInterface.iap_state))
    {
        //do something
    }
    

    When i use keil MDK, it works well,and when i use SES, the code in this "if" segment never be executioned, even "g_ulMainLoopCounter" used 'volatile' qualifier, because the member "iap_state" of struct "g_tMainLoopInterface" is not 'volatile', and i change the value of 'iap_state' in other function(not isr).

    So, if i want use SES(or other IDE used gcc),must i check every variable in my program and determine if the variable is needed use 'volatile' qualifier(it's very difficult i think)? Is there any easy solutions?

Children
No Data
Related