Search code examples
cmicrocontrolleravratmelstudioisr

Using reti() at the end of an ISR


i have problem that this code doesnt work .. the ISR is working .. i tested the blinking of it in other code ..

but to put the x++ in ISR and reading X in main() function it never blinks. ..

im not familier with asm i thought this is compiler optomization so i put the variable volatile but it didnt work ..

#define F_CPU 16000000UL

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

volatile static uint8_t x = 1;

ISR( TIMER0_OVF_vect )
{
    x++;
    reti();
}

int main(void)
{

    /* Replace with your application code */
    DDRB = DDRB | 0B00100000 ; // pinMode(13,OUTPUT);
    TCCR0A = 0;
    TCCR0B = (1 << CS00 ) | (1 << CS02 ); //1024 prescaler
    TIMSK0 |= 1 << TOIE0 ;
    sei();

    while (1) 
    {

        if (x  >= 61) //never happens ? 
        {
            PORTB ^= 0B00100000;
            x=0;    
        }

    }
}

Solution

  • For a normal ISR, your compiler generates some "boilerplate" code that e.g. includes saving and restoring CPU registers and surrounds the code you write yourself in the ISR body. This doesn't happen when you declare your ISR "naked".

    As in your code, the ISR is not naked, this boilerplate code is present, but you still use reti(), which instantly leaves the ISR. Therefore, your ISR will execute the "prologue" part, but never the "epilogue" part, which might cause all kinds of issues, e.g. messing with register contents.

    BTW, the last instruction in the epilogue boilerplate is a reti anyways. Only use reti() if you ever write a naked ISR.