The -mmcu=atmega328p
compiler flag is needed not only for the compile
phase, but also for the link phase. Otherwise the linker will not know
which CRT (C run time) to link with your program, and it will link none.
The CRT is responsible for things like initializing the stack pointer,
clearing r1
(as required by the AVR calling convention) and calling
your main()
.
Edit: the following simplified Makefile should work if you have a modern version of avrdude that understands ELF files:
CC = avr-gcc
MCU = atmega328p
CFLAGS = -Os -DF_CPU=16000000UL -mmcu=${MCU}
PORT = /dev/ttyACM0
led.elf: led.c
${CC} ${CFLAGS} $< -o $@
install: led.elf
avrdude -c arduino -p ${MCU} -P ${PORT} -b 115200 -U $<
Otherwise you can keep your rules for led.elf → led.hex → install.