La respuesta aceptada es excelente ya que me ha dado una valiosa lección en todo tipo de herramientas de depuración (avr-objdump -D se ha convertido en un amigo cercano). A saber, la línea:
${OBJCOPY} -O ihex -R .eeprom $< $@
le falta la bandera de arquitectura y debería leer
$ {OBJCOPY} -mmcu = atmega328p -O ihex -R .eeprom $ <$ @
Sin el indicador de arquitectura -mmcu, avr-gcc supone que estamos compilando para la arquitectura 8515 (definitivamente no) y produce el archivo .elf sin instrucciones iniciales para la inicialización, es decir, sin instrucciones para llamar a la función "principal", etc.
Esto da como resultado un comportamiento confuso ya que cualquier programa simple (por ejemplo, parpadeo) con solo la función "principal" funciona perfectamente, pero si define otra función antes o después de "principal", ejecuta esa función y nunca llama a "principal" o se reinicia todo el tiempo etc.
Tampoco soy un fanático particular de evitar la verificación del tipo correcto de MCU y el programa cargado, por lo que recomendaría no usar -F y -V y usar -v en su lugar.
Entonces, la respuesta mejorada podría ser:
PKG=led
BIN=${PKG}
OBJS=${PKG}.o
MCU=atmega328p
CC=avr-gcc
OBJCOPY=avr-objcopy
CFLAGS=-Os -DF_CPU=16000000UL -mmcu=${MCU} -Wall
PORT=/dev/ttyACM0
${BIN}.hex: ${BIN}.elf
${OBJCOPY} -O ihex $< $@
${BIN}.elf: ${OBJS}
${CC} -mmcu=${MCU} -o $@ $^
install: ${BIN}.hex
avrdude -v -c arduino -p ${MCU} -P ${PORT} -b 115200 -U flash:w:$<
clean:
rm -f ${BIN}.elf ${BIN}.hex ${OBJS}
-I/usr/share/arduino/hardware/arduino/cores/arduino -I/usr/share/arduino/hardware/arduino/variants/standard
y enlazarlibcore.a
. :-)