Reputation: 27421
I am currently working on a Bootloader in Atmel Studio for Atmega328P (Arduino UNO), and from the disassembly I found the following code (My bootloader starts from 0x3800):
--- ../../../../crt1/gcrt1.S ---------------------------------------------------
00003800 JMP 0x00003834 Jump
00003802 JMP 0x00003979 Jump
00003804 JMP 0x00003979 Jump
00003806 JMP 0x00003979 Jump
00003808 JMP 0x00003979 Jump
0000380A JMP 0x00003979 Jump
0000380C JMP 0x00003979 Jump
0000380E JMP 0x00003979 Jump
--- ../../../../crt1/gcrt1.S ---------------------------------------------------
00003810 JMP 0x00003979 Jump
00003812 JMP 0x00003979 Jump
00003814 JMP 0x00003979 Jump
00003816 JMP 0x00003979 Jump
00003818 JMP 0x00003979 Jump
0000381A JMP 0x00003979 Jump
0000381C JMP 0x00003979 Jump
0000381E JMP 0x00003979 Jump
00003820 JMP 0x00003979 Jump
00003822 JMP 0x00003979 Jump
00003824 JMP 0x00003979 Jump
00003826 JMP 0x00003979 Jump
00003828 JMP 0x00003979 Jump
0000382A JMP 0x00003979 Jump
0000382C JMP 0x00003979 Jump
0000382E JMP 0x00003979 Jump
00003830 JMP 0x00003979 Jump
00003832 JMP 0x00003979 Jump
--- C:\Users\andy\Documents\Atmel Studio\7.0\CannyFlashy\CannyFlashy\CannyFlashy\Debug/.././Sketch.cpp
int main(){
00003834 IN R28,0x3D In from I/O location
Why is GCC generating such code and is there anyway to avoid them?
Upvotes: 3
Views: 531
Reputation: 186
WHAT IS IT
As Javier Silva Ortíz mentioned in the comment, it is an interrupt table placed at the most beginning of the program memory.
The first instruction is a RESET vector, and we can see the address it is pointing at. In the other words, just after reset, MCU executes first JMP 0x00003834
instruction and moves exactly to the beginning of the program.
By the way, have a look at the other JMP
instructions: all of them pointing at the same address, so called __bad_interrupt()
, where the only instruction RETI
is placed. If one of these interrupts accidentally hits (and your program have no idea what to do with this interrupt), then the single RETI
instruction finalizes this interrupt instantly and the program returns to it's normal execution.
AVOIDING IT
If you are absolutely sure there are no possible interrupt hits in your Bootloader, you could avoid interrupt table, passing CFLAGS = -nostartfiles
flag to the compiler.
BE CAREFUL!
Some other things will be broken with -nostartfiles
flag!
The problem is that avr-gcc makes some magic at the beginning of the compiled program. There are some common operations that compiler places just after interrupt table. These operations are devided by the sections, such as __ctors_end
, __do_copy_data
, __do_clear_bss
and so on. What are they needed for?
First of all, r1
register is set to zero during __ctors_end
section. Why is it so important? r1
is used by default every time the compiler compares other registers with zero. Yes, avr-gcc knows about this "magical" r1
and does not write to it, but there are some cases, when it changes (for example, the result of multiplication is placed at the r0:r1 register pair), and every time it changes, avr-gcc nullify it. Everything can go wrong if r1
is not set to zero during startup...
The other thing done at the beginning of the program is setting to zero variables that are supposed to be zero. It is done at the __do_clear_bss
section. Just imagine you expect something to be zero and it is not. What are the consequences?
The other important operation is to copy data from the program memory to SRAM. It is done at __do_copy_data
section. Switching off __do_copy_data
brokes all the static arrays.
AND?..
You should be very careful trying to optimize interrupt table with -nostartfiles
. Do this only if you are 200% sure what are going on.
Upvotes: 5