1

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
greybeard
  • 2,249
  • 8
  • 30
  • 66
Pankkake
  • 61
  • 1
  • 6
  • If you set up a timer for 0.5Hz (TIMER1 can do that, see http://www.8bit-era.cz/arduino-timer-interrupts-calculator.html) so the interrupt doesn't get called that often and use `if (++intrs >= 2)`, what happens then? BTW is there a proper resistor on your LED? Just checking. – ocrdu Dec 23 '20 at 17:02
  • It still doesn't work; I've used a 1Hz timer since that's what I really want, and got rid of `intrs`. Now both LEDs are dim, and they seem to blink off very briefly every so often. And yes, I did but a 220 Ohms resistor behind each of them. – Pankkake Dec 23 '20 at 17:21
  • Just thought about the `intrs`, the loop keeps setting `intrs` to 0 so the interrupt may never see `++intrs >= 62` (the loop is much faster than the 62Hz interrupt call), but you say it doesn't work even without using `intrs` at all. Hm. It feels like we're missing something very obvious here, but I don't see it. – ocrdu Dec 23 '20 at 17:27
  • The problem doesn't seem to be with the program logic. Even adding a dumb ISR (such as INT0_vect or whatever) seems to break the program - commenting it back out makes it work. – Pankkake Dec 23 '20 at 18:56
  • I don't see what's wrong. Maybe you could check if the example here works: https://microchipdeveloper.com/8avr:interrupts-mega-configuration#toc11 and work back from that, although it looks eerily similar to what you have already tried. – ocrdu Dec 23 '20 at 19:22

1 Answers1

0

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?

elbe
  • 1,363
  • 1
  • 9
  • 13