Pankkake
Pankkake

Reputation: 71

Why does my ISR declaration break my program?

I am trying to make two LEDs blink on my Arduino Uno R3 (for learning purposes). I use avr-gcc and avrdude to compile and load my program.

The first one I make blink within a while loop in main. I am trying to use Timer0 to turn the second one on and off.

First, the code that works :

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

int main() {
    TCCR0B |= (1 << CS02) | (1 << CS00);
    TIMSK0 |= (1 << TOIE0);

    DDRD = 1 << PD3;
    DDRB = 1 << PB5;
    PORTB = 0;

    while(1) {
        PORTD ^= 1 << PD3;
        _delay_ms(500);
    }
    return 0;
}

As expected, this code makes my LED blink on and off, and start again every second. I am also setting up (but not using) the second LED and the timer.

Now, the issues start when I add an interrupt vector:

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

volatile uint8_t intrs;

ISR(TIMER0_OVF_vect) {
    if (++intrs >= 62) { // meant to execute every second
        PORTB ^= (1 << PB5);
        intrs = 0;
    }
}

int main() {
    intrs = 0;
    ... // old setup
    sei();
    while(1) { ... }
}

Now, none of the LEDs blink. Even weirder, none of them blink when I remove the sei(). The only way I've found to make the first LED blink again is to comment out the ISR declaration or to mark it ISR_NAKED.

So, what gives?

PS : I use a makefile to compile & load. When I run it, it looks like this:

$ make
avr-gcc -c -Os -DF_CPU=16000000UL -mmcu=atmega328p -Wall -Wextra main.c
avr-gcc -o prog.elf main.o 
avr-objcopy -O ihex -R .eeprom prog.elf prog.hex
avrdude -C/etc/avrdude.conf -v -V -carduino -patmega328p -P/dev/ttyACM0 -b115200 -D -Uflash:w:prog.hex
.. # avrdude logs

Upvotes: 1

Views: 430

Answers (1)

elbe
elbe

Reputation: 1508

I use the arduino framework with setup() and loop() functions. It might not be an optimal choice, but it's easier. Timer 0 is used by wiring.c, which is responsible for delay functions (not _delay_ms() which doesn't use interrupts). This can be disabled, as explained in this post or timer 2 can be used instead. In the latter case, your second code works fine. Could it be that you face a similar problem?

Upvotes: 0

Related Questions