cmakefilearduinoarduino-uno

Makefile failing to flash code to ATmega328p


A couple months ago, I asked why my blink program, written in C and flashed to a ATmega328p on an Arduino R3 Uno, kept failing, if I had an ISR defined. I eventually narrowed the issue down to the way my Makefile was written (I was using it with avr-gcc and avrdude), and got around it by copy-pasting the code into the Arduino IDE and uploading it using the built-in tool.

Now, I want to go back and understand precisely why the Makefile is failing. I've been going through the documentation for avr-gcc and avrdude and believe I have narrowed down the issue to the memory regions I am writing to. The sample C project I'm working with is the following:

int main(void)
{
    // set the data direction for the pin connected to
    // onboard LED
    DDRB |= _BV(DDB5);
    PORTB |= _BV(PORTB5);

    // no-op loop
    while (1) ;;

    // keep compiler happy
    return 0;
}

The program is intentionally simple; it just turns on the onboard LED and keeps it on. At this point, flashing with the following make file works just fine:

AVRFLAGS = -F -v -p m328p -c arduino -P /dev/ttyACM0 -U flash:w:blink.hex


default: blink.elf
    avr-objcopy -O ihex blink.elf blink.hex

blink.o:
    avr-gcc -g -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o blink.o blink.c

blink.elf: blink.o
    avr-gcc -o blink.elf blink.o

flash:
    sudo avrdude ${AVRFLAGS} blink.hex

clean:
    rm -rf *.o *.hex *.elf

HOWEVER, the moment I add an ISR to the top of the file:

ISR (TIMER1_COMPA_vect)
{
  PORTB ^= _BV(PORTB5);
}

and attempt to flash, everything breaks. I have attempted this both with and without the Timer/Counter 1 setup code (redacted here for demonstration purposes), and do not believe that it impacts the success of the flash. I have used this exact ISR -- and the exact same setup code for Timer/Counter 1 -- in other programs that work just fine, provided I flash them using the Arduino IDE built-in tool; otherwise, the Arduino Uno blinks that it's receiving data, then the onboard LED starts flashing and keeps flashing. This exact same pattern of flashes appears whenever any program gets flashed poorly. I've compiled with -j .text -j .data, .eeprom, and other options, but to no avail.

I just want to know why this is failing.


Solution

  • You forgot to pass -mmcu=atmega328p to link stage. Without this option no CRT and interrupt vector table added. While you have only one main() function, it starts from address 0 (reset vector), and everything seems to work. Since you added ISR, now ISR code is at address 0.

    For GNU Make you can use COMPILE.c and LINK.c built-in variables to get correct compilation and linkage commands.