Revision 195
Using a modified linker script to strip out the unused interrupt vector table in the bootloader. Not tested
trunk/bootloader/bootloader.c | ||
---|---|---|
17 | 17 |
#define LED_PORT PORTB |
18 | 18 |
#define LED PORTB1 |
19 | 19 |
|
20 |
//Function prototypes |
|
20 |
/** |
|
21 |
* Where we store the jump to user code. The jump address is in words |
|
22 |
* due to how the rjmp instruction works. It is 1 word below the bootloader |
|
23 |
*/ |
|
21 | 24 |
void (*main_start)(void) = BOOT_START/2 - 1; |
25 |
|
|
26 |
/** |
|
27 |
* We declare main as naked so that there is no overhead for entering |
|
28 |
* and returning from this function since we don't really care about |
|
29 |
* what happens to it after we leave it |
|
30 |
*/ |
|
22 | 31 |
int main(void) __attribute__ ((naked)); |
23 | 32 |
|
24 | 33 |
typedef union { |
... | ... | |
26 | 35 |
int16_t sword; |
27 | 36 |
} rjump_t; |
28 | 37 |
|
38 |
/** |
|
39 |
* Restore the reset vector to point to the end of ctors. This |
|
40 |
* is because we are stripping out the interrupt vector table |
|
41 |
* from the bootloader as we don't use it. |
|
42 |
*/ |
|
43 |
void ResetVector (void) __attribute__((naked)) |
|
44 |
__attribute__((section(".reset"))); |
|
45 |
void ResetVector(void) { |
|
46 |
asm("rjmp __ctors_end"); |
|
47 |
} |
|
29 | 48 |
|
49 |
|
|
30 | 50 |
// SPM_PAGESIZE is set to 32 bytes |
31 | 51 |
void onboard_program_write(uint16_t page, uint8_t *buf) { |
32 | 52 |
uint16_t i; |
trunk/bootloader/Makefile | ||
---|---|---|
186 | 186 |
# -Wl,...: tell GCC to pass this to linker. |
187 | 187 |
# -Map: create map file |
188 | 188 |
# --cref: add cross reference to map file |
189 |
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref,--section-start=.text=$(BOOTSTART),--section-start=.jumps=$(JUMPSTART),--undefined=_jumptable
|
|
189 |
LDFLAGS = -Wl,--script=linker_script.x,-Map=$(TARGET).map,--cref,--section-start=.text=$(BOOTSTART),--section-start=.jumps=$(JUMPSTART),--undefined=_jumptable,--gc-sections
|
|
190 | 190 |
LDFLAGS += $(EXTMEMOPTS) |
191 | 191 |
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) |
192 | 192 |
|
trunk/bootloader/linker_script.x | ||
---|---|---|
1 |
/* Default linker script, for normal executables */ |
|
2 |
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") |
|
3 |
OUTPUT_ARCH(avr:2) |
|
4 |
MEMORY |
|
5 |
{ |
|
6 |
text (rx) : ORIGIN = 0, LENGTH = 8K |
|
7 |
data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0 |
|
8 |
eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K |
|
9 |
fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K |
|
10 |
lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K |
|
11 |
signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K |
|
12 |
} |
|
13 |
SECTIONS |
|
14 |
{ |
|
15 |
/* Read-only sections, merged into text segment: */ |
|
16 |
.hash : { *(.hash) } |
|
17 |
.dynsym : { *(.dynsym) } |
|
18 |
.dynstr : { *(.dynstr) } |
|
19 |
.gnu.version : { *(.gnu.version) } |
|
20 |
.gnu.version_d : { *(.gnu.version_d) } |
|
21 |
.gnu.version_r : { *(.gnu.version_r) } |
|
22 |
.rel.init : { *(.rel.init) } |
|
23 |
.rela.init : { *(.rela.init) } |
|
24 |
.rel.text : |
|
25 |
{ |
|
26 |
*(.rel.text) |
|
27 |
*(.rel.text.*) |
|
28 |
*(.rel.gnu.linkonce.t*) |
|
29 |
} |
|
30 |
.rela.text : |
|
31 |
{ |
|
32 |
*(.rela.text) |
|
33 |
*(.rela.text.*) |
|
34 |
*(.rela.gnu.linkonce.t*) |
|
35 |
} |
|
36 |
.rel.fini : { *(.rel.fini) } |
|
37 |
.rela.fini : { *(.rela.fini) } |
|
38 |
.rel.rodata : |
|
39 |
{ |
|
40 |
*(.rel.rodata) |
|
41 |
*(.rel.rodata.*) |
|
42 |
*(.rel.gnu.linkonce.r*) |
|
43 |
} |
|
44 |
.rela.rodata : |
|
45 |
{ |
|
46 |
*(.rela.rodata) |
|
47 |
*(.rela.rodata.*) |
|
48 |
*(.rela.gnu.linkonce.r*) |
|
49 |
} |
|
50 |
.rel.data : |
|
51 |
{ |
|
52 |
*(.rel.data) |
|
53 |
*(.rel.data.*) |
|
54 |
*(.rel.gnu.linkonce.d*) |
|
55 |
} |
|
56 |
.rela.data : |
|
57 |
{ |
|
58 |
*(.rela.data) |
|
59 |
*(.rela.data.*) |
|
60 |
*(.rela.gnu.linkonce.d*) |
|
61 |
} |
|
62 |
.rel.ctors : { *(.rel.ctors) } |
|
63 |
.rela.ctors : { *(.rela.ctors) } |
|
64 |
.rel.dtors : { *(.rel.dtors) } |
|
65 |
.rela.dtors : { *(.rela.dtors) } |
|
66 |
.rel.got : { *(.rel.got) } |
|
67 |
.rela.got : { *(.rela.got) } |
|
68 |
.rel.bss : { *(.rel.bss) } |
|
69 |
.rela.bss : { *(.rela.bss) } |
|
70 |
.rel.plt : { *(.rel.plt) } |
|
71 |
.rela.plt : { *(.rela.plt) } |
|
72 |
/* Internal text space or external memory. */ |
|
73 |
.text : |
|
74 |
{ |
|
75 |
bootloader.o(.reset) |
|
76 |
KEEP(*(.reset)) |
|
77 |
*(.vectors) |
|
78 |
/*KEEP(*(.vectors))*/ |
|
79 |
/* For data that needs to reside in the lower 64k of progmem. */ |
|
80 |
*(.progmem.gcc*) |
|
81 |
*(.progmem*) |
|
82 |
. = ALIGN(2); |
|
83 |
__trampolines_start = . ; |
|
84 |
/* The jump trampolines for the 16-bit limited relocs will reside here. */ |
|
85 |
*(.trampolines) |
|
86 |
*(.trampolines*) |
|
87 |
__trampolines_end = . ; |
|
88 |
/* For future tablejump instruction arrays for 3 byte pc devices. |
|
89 |
We don't relax jump/call instructions within these sections. */ |
|
90 |
*(.jumptables) |
|
91 |
*(.jumptables*) |
|
92 |
/* For code that needs to reside in the lower 128k progmem. */ |
|
93 |
*(.lowtext) |
|
94 |
*(.lowtext*) |
|
95 |
__ctors_start = . ; |
|
96 |
*(.ctors) |
|
97 |
__ctors_end = . ; |
|
98 |
__dtors_start = . ; |
|
99 |
*(.dtors) |
|
100 |
__dtors_end = . ; |
|
101 |
KEEP(SORT(*)(.ctors)) |
|
102 |
KEEP(SORT(*)(.dtors)) |
|
103 |
/* From this point on, we don't bother about wether the insns are |
|
104 |
below or above the 16 bits boundary. */ |
|
105 |
*(.init0) /* Start here after reset. */ |
|
106 |
KEEP (*(.init0)) |
|
107 |
*(.init1) |
|
108 |
KEEP (*(.init1)) |
|
109 |
*(.init2) /* Clear __zero_reg__, set up stack pointer. */ |
|
110 |
KEEP (*(.init2)) |
|
111 |
*(.init3) |
|
112 |
KEEP (*(.init3)) |
|
113 |
*(.init4) /* Initialize data and BSS. */ |
|
114 |
KEEP (*(.init4)) |
|
115 |
*(.init5) |
|
116 |
KEEP (*(.init5)) |
|
117 |
*(.init6) /* C++ constructors. */ |
|
118 |
KEEP (*(.init6)) |
|
119 |
*(.init7) |
|
120 |
KEEP (*(.init7)) |
|
121 |
*(.init8) |
|
122 |
KEEP (*(.init8)) |
|
123 |
*(.init9) /* Call main(). */ |
|
124 |
KEEP (*(.init9)) |
|
125 |
*(.text) |
|
126 |
. = ALIGN(2); |
|
127 |
*(.text.*) |
|
128 |
. = ALIGN(2); |
|
129 |
*(.fini9) /* _exit() starts here. */ |
|
130 |
KEEP (*(.fini9)) |
|
131 |
*(.fini8) |
|
132 |
KEEP (*(.fini8)) |
|
133 |
*(.fini7) |
|
134 |
KEEP (*(.fini7)) |
|
135 |
*(.fini6) /* C++ destructors. */ |
|
136 |
KEEP (*(.fini6)) |
|
137 |
*(.fini5) |
|
138 |
KEEP (*(.fini5)) |
|
139 |
*(.fini4) |
|
140 |
KEEP (*(.fini4)) |
|
141 |
*(.fini3) |
|
142 |
KEEP (*(.fini3)) |
|
143 |
*(.fini2) |
|
144 |
KEEP (*(.fini2)) |
|
145 |
*(.fini1) |
|
146 |
KEEP (*(.fini1)) |
|
147 |
*(.fini0) /* Infinite loop after program termination. */ |
|
148 |
KEEP (*(.fini0)) |
|
149 |
_etext = . ; |
|
150 |
} > text |
|
151 |
.data : AT (ADDR (.text) + SIZEOF (.text)) |
|
152 |
{ |
|
153 |
PROVIDE (__data_start = .) ; |
|
154 |
*(.data) |
|
155 |
*(.data*) |
|
156 |
*(.rodata) /* We need to include .rodata here if gcc is used */ |
|
157 |
*(.rodata*) /* with -fdata-sections. */ |
|
158 |
*(.gnu.linkonce.d*) |
|
159 |
. = ALIGN(2); |
|
160 |
_edata = . ; |
|
161 |
PROVIDE (__data_end = .) ; |
|
162 |
} > data |
|
163 |
.bss SIZEOF(.data) + ADDR(.data) : |
|
164 |
{ |
|
165 |
PROVIDE (__bss_start = .) ; |
|
166 |
*(.bss) |
|
167 |
*(.bss*) |
|
168 |
*(COMMON) |
|
169 |
PROVIDE (__bss_end = .) ; |
|
170 |
} > data |
|
171 |
__data_load_start = LOADADDR(.data); |
|
172 |
__data_load_end = __data_load_start + SIZEOF(.data); |
|
173 |
/* Global data not cleared after reset. */ |
|
174 |
.noinit SIZEOF(.bss) + ADDR(.bss) : |
|
175 |
{ |
|
176 |
PROVIDE (__noinit_start = .) ; |
|
177 |
*(.noinit*) |
|
178 |
PROVIDE (__noinit_end = .) ; |
|
179 |
_end = . ; |
|
180 |
PROVIDE (__heap_start = .) ; |
|
181 |
} > data |
|
182 |
.eeprom : |
|
183 |
{ |
|
184 |
*(.eeprom*) |
|
185 |
__eeprom_end = . ; |
|
186 |
} > eeprom |
|
187 |
.fuse : |
|
188 |
{ |
|
189 |
KEEP(*(.fuse)) |
|
190 |
KEEP(*(.lfuse)) |
|
191 |
KEEP(*(.hfuse)) |
|
192 |
KEEP(*(.efuse)) |
|
193 |
} > fuse |
|
194 |
.lock : |
|
195 |
{ |
|
196 |
KEEP(*(.lock*)) |
|
197 |
} > lock |
|
198 |
.signature : |
|
199 |
{ |
|
200 |
KEEP(*(.signature*)) |
|
201 |
} > signature |
|
202 |
/* Stabs debugging sections. */ |
|
203 |
.stab 0 : { *(.stab) } |
|
204 |
.stabstr 0 : { *(.stabstr) } |
|
205 |
.stab.excl 0 : { *(.stab.excl) } |
|
206 |
.stab.exclstr 0 : { *(.stab.exclstr) } |
|
207 |
.stab.index 0 : { *(.stab.index) } |
|
208 |
.stab.indexstr 0 : { *(.stab.indexstr) } |
|
209 |
.comment 0 : { *(.comment) } |
|
210 |
/* DWARF debug sections. |
|
211 |
Symbols in the DWARF debugging sections are relative to the beginning |
|
212 |
of the section so we begin them at 0. */ |
|
213 |
/* DWARF 1 */ |
|
214 |
.debug 0 : { *(.debug) } |
|
215 |
.line 0 : { *(.line) } |
|
216 |
/* GNU DWARF 1 extensions */ |
|
217 |
.debug_srcinfo 0 : { *(.debug_srcinfo) } |
|
218 |
.debug_sfnames 0 : { *(.debug_sfnames) } |
|
219 |
/* DWARF 1.1 and DWARF 2 */ |
|
220 |
.debug_aranges 0 : { *(.debug_aranges) } |
|
221 |
.debug_pubnames 0 : { *(.debug_pubnames) } |
|
222 |
/* DWARF 2 */ |
|
223 |
.debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } |
|
224 |
.debug_abbrev 0 : { *(.debug_abbrev) } |
|
225 |
.debug_line 0 : { *(.debug_line) } |
|
226 |
.debug_frame 0 : { *(.debug_frame) } |
|
227 |
.debug_str 0 : { *(.debug_str) } |
|
228 |
.debug_loc 0 : { *(.debug_loc) } |
|
229 |
.debug_macinfo 0 : { *(.debug_macinfo) } |
|
230 |
} |
Also available in: Unified diff