I am using avr-gcc and avrdude to write programs onto an ATMega8515 micro-controller. I have got the blinking LED program working without a hitch. However, when I started to use interrupts and introduce functions other than main() to the code, I came across bugs. Though I could compile the program and write it onto the chip, it did not run as expected - the LEDs that should have been blinking were completely unresponsive. With tweaking I found out that the introduction of any function, not just an interrupt service routine, caused this issue.
I came across near identical issues here:
https://stackoverflow.com/questions/65427371/why-does-my-isr-declaration-break-my-program
"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"
And here:
AVR ATmega32 - C - Gets stuck in function call
"it's just the same statements as before, moved to the pulse_init() function. When I upload this code the timer is set up correctly and the output pulse is OK, but the program never starts blinking the LEDs on PC0..1."
To be clear, these are the commands I am using to compile and write the code to the ATMega:
avr-gcc main.c -O2 -o main.elf avr-objcopy main.elf -O ihex main.hex avrdude -c usbasp -p m8515 -U flash:w:"main.hex":a And this is a sample code snippet that does not work:
#ifndef F_CPU #define F_CPU 1000000UL // 16 MHz clock speed #endif #define __AVR_ATmega8515__ #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> volatile uint8_t toggle_blinking = 1; int main() { sei(); /* set global interrupt enable */ MCUCR = 0b00000100; /* Set the INT1 to trigger on any logic change*/ GICR = 0b10000000; DDRC = 0xFF; // Makes PORTC as output DDRD=0xe0; while(1) { if(toggle_blinking) { PORTC = 0xFF; //Turns ON All LEDs // _delay_ms(500); //1 second delay // _delay_ms(500); //1 second delay } else { PORTC= 0x00; //Turns OFF All LEDs } } } ISR(INT1_vect) { toggle_blinking ^= 1; } The common denominator between all of these programs (mine, and the two linked above) is the use of the avr-gcc optimization flag (-O) which is there to ensure that the util/delay.h functions run correctly. I compiled a program which did not work with the optimization flag again, this time without the optimization flag. And sure enough, the program worked.
To clarify, I am not sure whether other function definitions are "breaking" the program, or if they are just being run instead of main(). Here is the object dump when running running avr-objdump -d main.elf on the .elf file that was generated by compiling the above program with optimization enabled:
00000000 <__ctors_end>: 0: 10 e0 ldi r17, 0x00 ; 0 2: a0 e6 ldi r26, 0x60 ; 96 4: b0 e0 ldi r27, 0x00 ; 0 6: ea e6 ldi r30, 0x6A ; 106 8: f0 e0 ldi r31, 0x00 ; 0 a: 03 c0 rjmp .+6 ; 0x12 <__zero_reg__+0x11> c: c8 95 lpm e: 31 96 adiw r30, 0x01 ; 1 10: 0d 92 st X+, r0 12: a2 36 cpi r26, 0x62 ; 98 14: b1 07 cpc r27, r17 16: d1 f7 brne .-12 ; 0xc <__zero_reg__+0xb> 00000018 <__vector_2>: 18: 1f 92 push r1 1a: 0f 92 push r0 1c: 0f b6 in r0, 0x3f ; 63 1e: 0f 92 push r0 20: 11 24 eor r1, r1 22: 8f 93 push r24 24: 9f 93 push r25 26: 80 91 60 00 lds r24, 0x0060 ; 0x800060 <__data_start> 2a: 91 e0 ldi r25, 0x01 ; 1 2c: 89 27 eor r24, r25 2e: 80 93 60 00 sts 0x0060, r24 ; 0x800060 <__data_start> 32: 9f 91 pop r25 34: 8f 91 pop r24 36: 0f 90 pop r0 38: 0f be out 0x3f, r0 ; 63 3a: 0f 90 pop r0 3c: 1f 90 pop r1 3e: 18 95 reti 00000040 <main>: 40: 78 94 sei 42: 84 e0 ldi r24, 0x04 ; 4 44: 85 bf out 0x35, r24 ; 53 46: 80 e8 ldi r24, 0x80 ; 128 48: 8b bf out 0x3b, r24 ; 59 4a: 8f ef ldi r24, 0xFF ; 255 4c: 84 bb out 0x14, r24 ; 20 4e: 80 ee ldi r24, 0xE0 ; 224 50: 81 bb out 0x11, r24 ; 17 52: 9f ef ldi r25, 0xFF ; 255 54: 80 91 60 00 lds r24, 0x0060 ; 0x800060 <__data_start> 58: 88 23 and r24, r24 5a: 29 f0 breq .+10 ; 0x66 <main+0x26> 5c: 95 bb out 0x15, r25 ; 21 5e: 80 91 60 00 lds r24, 0x0060 ; 0x800060 <__data_start> 62: 81 11 cpse r24, r1 64: fb cf rjmp .-10 ; 0x5c <main+0x1c> 66: 15 ba out 0x15, r1 ; 21 68: f5 cf rjmp .-22 ; 0x54 <main+0x14> And here is the dump from the compiled program without optimization enabled:
00000000 <__ctors_end>: 0: 10 e0 ldi r17, 0x00 ; 0 2: a0 e6 ldi r26, 0x60 ; 96 4: b0 e0 ldi r27, 0x00 ; 0 6: ea ea ldi r30, 0xAA ; 170 8: f0 e0 ldi r31, 0x00 ; 0 a: 03 c0 rjmp .+6 ; 0x12 <__zero_reg__+0x11> c: c8 95 lpm e: 31 96 adiw r30, 0x01 ; 1 10: 0d 92 st X+, r0 12: a2 36 cpi r26, 0x62 ; 98 14: b1 07 cpc r27, r17 16: d1 f7 brne .-12 ; 0xc <__zero_reg__+0xb> 00000018 <main>: 18: cf 93 push r28 1a: df 93 push r29 1c: cd b7 in r28, 0x3d ; 61 1e: de b7 in r29, 0x3e ; 62 20: 78 94 sei 22: 85 e5 ldi r24, 0x55 ; 85 24: 90 e0 ldi r25, 0x00 ; 0 26: 24 e0 ldi r18, 0x04 ; 4 28: e8 2f mov r30, r24 2a: f9 2f mov r31, r25 2c: 20 83 st Z, r18 2e: 8b e5 ldi r24, 0x5B ; 91 30: 90 e0 ldi r25, 0x00 ; 0 32: 20 e8 ldi r18, 0x80 ; 128 34: e8 2f mov r30, r24 36: f9 2f mov r31, r25 38: 20 83 st Z, r18 3a: 84 e3 ldi r24, 0x34 ; 52 3c: 90 e0 ldi r25, 0x00 ; 0 3e: 2f ef ldi r18, 0xFF ; 255 40: e8 2f mov r30, r24 42: f9 2f mov r31, r25 44: 20 83 st Z, r18 46: 81 e3 ldi r24, 0x31 ; 49 48: 90 e0 ldi r25, 0x00 ; 0 4a: 20 ee ldi r18, 0xE0 ; 224 4c: e8 2f mov r30, r24 4e: f9 2f mov r31, r25 50: 20 83 st Z, r18 52: 80 91 60 00 lds r24, 0x0060 ; 0x800060 <__data_start> 56: 88 23 and r24, r24 58: 39 f0 breq .+14 ; 0x68 <__SREG__+0x29> 5a: 85 e3 ldi r24, 0x35 ; 53 5c: 90 e0 ldi r25, 0x00 ; 0 5e: 2f ef ldi r18, 0xFF ; 255 60: e8 2f mov r30, r24 62: f9 2f mov r31, r25 64: 20 83 st Z, r18 66: f5 cf rjmp .-22 ; 0x52 <__SREG__+0x13> 68: 85 e3 ldi r24, 0x35 ; 53 6a: 90 e0 ldi r25, 0x00 ; 0 6c: e8 2f mov r30, r24 6e: f9 2f mov r31, r25 70: 10 82 st Z, r1 72: ef cf rjmp .-34 ; 0x52 <__SREG__+0x13> 00000074 <__vector_2>: 74: 1f 92 push r1 76: 0f 92 push r0 78: 0f b6 in r0, 0x3f ; 63 7a: 0f 92 push r0 7c: 11 24 eor r1, r1 7e: 8f 93 push r24 80: 9f 93 push r25 82: cf 93 push r28 84: df 93 push r29 86: cd b7 in r28, 0x3d ; 61 88: de b7 in r29, 0x3e ; 62 8a: 90 91 60 00 lds r25, 0x0060 ; 0x800060 <__data_start> 8e: 81 e0 ldi r24, 0x01 ; 1 90: 89 27 eor r24, r25 92: 80 93 60 00 sts 0x0060, r24 ; 0x800060 <__data_start> 96: 00 00 nop 98: df 91 pop r29 9a: cf 91 pop r28 9c: 9f 91 pop r25 9e: 8f 91 pop r24 a0: 0f 90 pop r0 a2: 0f be out 0x3f, r0 ; 63 a4: 0f 90 pop r0 a6: 1f 90 pop r1 a8: 18 95 reti It seems as though the memory address location of main() is being affected by compiler optimizations which is causing the issues. Does anyone have a proper explanation for this and/or a fix that would allow me to use compiler optimizations with interrupt routines?
