Search code examples
timerinterruptavravr-gccatmelstudio

Setting a flag does not work in my timer Interrupt (while the Interrupt is working)


I used to write my codes in ICCAVR and I had no problem there, but not for some reason I should migrate to AtmelStudio. in the following code, the LED is flashing in the interrupt, but when I only set a flag in the interrupt and want to flash the LED in polling (using the flag) it wouldn't work:

#include<avr/io.h>
#include<avr/interrupt.h>

#define LED PA1


ISR (TIMER1_OVF_vect)    // Timer1 ISR
{
    //PORTA ^= (1 << LED);
    TCNT1 = 63974;   // for 1 sec at 16 MHz
    PORTA ^= (1 << LED);
}

int main()
{
    DDRA = (0x01 << LED);     //Configure the PORTD4 as output

    TCNT1 = 63974;   // for 1 sec at 16 MHz

    TCCR1A = 0x00;
    TCCR1B = (1<<CS10) | (1<<CS12);;  // Timer mode with 1024 prescler
    TIMSK = (1 << TOIE1) ;   // Enable timer1 overflow interrupt(TOIE1)
    sei();        // Enable global interrupts by setting global interrupt enable bit in SREG

    while(1)
    {

    }
}

while this change would make it not to flash:

#include<avr/io.h>
#include<avr/interrupt.h>

#define LED PA1

unsigned int counter=0;
unsigned char flag=0;

ISR (TIMER1_OVF_vect)    // Timer1 ISR
{
    //PORTA ^= (1 << LED);
    TCNT1 = 63974;   // for 1 sec at 16 MHz
    counter++;
    if(counter>=10)
    {
        flag=1;
        counter=0;
    }
}

int main()
{
    DDRA = (0x01 << LED);     //Configure the PORTD4 as output

    TCNT1 = 63974;   // for 1 sec at 16 MHz

    TCCR1A = 0x00;
    TCCR1B = (1<<CS10) | (1<<CS12);;  // Timer mode with 1024 prescler
    TIMSK = (1 << TOIE1) ;   // Enable timer1 overflow interrupt(TOIE1)
    sei();        // Enable global interrupts by setting global interrupt enable bit in SREG

    while(1)
    {
        if(flag)
        {
            flag=0;
            PORTA ^= (1 << LED);
        }
    }
}

could anyone please help me?


Solution

  • Compiler saw that flag set to 0 at start of program and can't know that the variable can be changed by interrupt handler (the code never called directly in program). So it optimized out flag check in while loop.

    Use volatile qualifier for variables that accessed from different code streams (main code and interrupt handler, different threads in multi-threaded environment).

    volatile unsigned char flag = 0;