1. Missing -mmcu=atmega8515 when Compiling and Linking
avr-gcc main.c -O2 -o main.elf
Always (like in ALWAYS) specify the MCU for which you are generating code! Both for compiling and linking. (You are performing both steps by means of one command, so -mmcu= is missing in both build steps.
The outcome of missing -mmcu= will be:
The compiler is using the wrong command line options (as per wrong specs file). With
-mmcu=atmega8515the compiler will usespecs-atmega8515which provides options for many sub-processes like compiler proper (cc1for C orcc1plusfor C++), assembler (as) and linker (ld).One outcome of missing
specs-atmega8515is that built-in macro__AVR_ATmega8515__is not defined which is required so AVR-LibC can pick the right sub-header in#include <avr/io.h>. You hacked around that by hand-defining__AVR_ATmega8515__. Don't to that! The macro is defined inspecs-atmega8515which will be used with-mmcu=atmega8515. Without that option, the default is-mmcu=avr2, and the specs filespecs-avr2does not provide any device-specific options and defines.Linking without
-mmcu=atmega8515will have the effect that the compiler driver (avr-gcc) will call the linker without providing AVR-LibC's startup-code and vector table for ATmega8515 incrtatmega8515.o. The startup-code will initialize SP, set R1 aka.__zero_reg__to zero, etc. When your code is missing all these relevant bits, it will malfunction.Linking without
-mmcu=atmega8515will have the effect that the compiler driver (avr-gcc) will not link againstlibatmega8515.a. Functions like EEPROM routineseeprom_read_bytefromavr/eeprom.hare missing.
To get an overview what commands avr-gcc is issuing, add -v to the command line options and compare the output with[out] -mmcu=atmega8515.
2. Only issue SEI after properly setting up all IRQs.
Only globally enable interrupts after the IRQs etc. are properly initialized. This means that sei() will never be the first instruction in main for any sensible program.