2

In the code below, I can see that the timer is working normally as the LED is always blinking. But the value of the count variable never changes inside the second while.

I don't know what could possibly go wrong?

// count variable used only in main and TIM2_IRQHandler.
uint8_t count=0;

int main(void)
{
    count=0;
    SystemInit();
    GPIOInit();
    NVIC_Configuration();
    TIM_Configuration();
    init_USART3(115200);
    // All initialization is ok.
    USART_puts(USART3, "\r\nConnection ok.\r\n");// Working normally
    while (1)
    {
        if(asterixok==1)// No problem. This code if ok ->>process continue next step.
        {
            GPIO_SetBits(GPIOD , GPIO_Pin_12); // Led on (ok)
            count=0;// count going to zero, timer working, must be change in there
            while(1)
            {
                //Led blinking continue
                //Timer query working normal led (13) blink.
                //There is a problem
                if(count>5) // Timer working, count never change in timer interrupt query (WHY)
                {
                    GPIO_SetBits(GPIOD , GPIO_Pin_14); // LED OFFFFFFFFFFFFFFFF
                    USART_puts(USART3, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r\n");
                    goto nextstate;
                }
            }
            nextstate:
            GPIO_SetBits(GPIOD , GPIO_Pin_15); // Led never going on because code step in while loop.
        }
    }
}

void USART3_IRQHandler(void)
{
    if( USART_GetITStatus(USART3, USART_IT_RXNE) )
    {
        unsigned char t = USART3->DR;
        if(t=='*')
        {
            asterixok=1;
        }
    }
}

void TIM2_IRQHandler(void)
{
    if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET ) 
    {
        TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);
        count++;
        if(count>100)
            count=0;
        if( display ) 
        { 
            GPIO_ResetBits(GPIOD , GPIO_Pin_13);
        }  
        else 
        { 
            GPIO_SetBits(GPIOD , GPIO_Pin_13);
        }
        display = ~display;
    }   
}

I have tried with another Discovery board but the problem continues. Please help. I'm going crazy!

Samuel Peter
  • 4,136
  • 2
  • 34
  • 42
Fico
  • 21
  • 2

1 Answers1

1

You should declare count as volatile, as such :

volatile uint8_t count;

While compiling main the compiler was able to prove that count was not modified in the loop body, and so it probably cached its value in a register and maybe even optimized out the if statement. You could verify that by looking at a disassembly. The compiler does not know about interrupts as per the standard and so is permitted to perform such optimizations. Qualifying count as volatile will forbid the compiler from making these optimizations, forcing it to reload the variable from memory each time it is used.

In this simple case volatile will be enough but please be aware that it doesn't guarantee atomicity of operations, and it doesn't prevent the compiler and CPU from reordering instructions around accesses to the variable. It only forces the compiler to generate memory access instructions each time the variable is used. For atomicity you need locks, and to prevent reordering you need memory barriers.

Samuel Peter
  • 4,136
  • 2
  • 34
  • 42
  • Tahnk you for your solutions. I have tried the volatile variable keyword. Sometimes the problem was repeated again. As I understand it, probably this experiencing if both the interrupt query handler and dependent code access the same "named count" GLOBAL variable. Maybe disable/enable interrupt action fix it this. I'll try it at the appropriate time. – Fico Apr 08 '16 at 17:06