forked from signal11/pic_linker_script
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pic24f_bootloader_gen.sh
executable file
·180 lines (135 loc) · 5.67 KB
/
pic24f_bootloader_gen.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#!/bin/bash
if [ -z $1 ]; then
echo "usage: $0 [device_name]"
exit 1
fi
DEVICE=$1
OUTPUT=output/${DEVICE}-bootloader.gld
cat >$OUTPUT << ENDHEADER
/************************************************
Linker script for $DEVICE
Generated by the Signal 11 Software
PIC24F Linker Script Generator
http://github.com/signal11/pic_linker_script
This script may be used by anyone for any
purpose and may be redistributed freely.
************************************************/
ENDHEADER
cat ${DEVICE}_mem.txt >> $OUTPUT
echo "" >> $OUTPUT
cat pic24f_mem_bootloader.txt >> $OUTPUT
echo "" >> $OUTPUT
echo "" >> $OUTPUT
echo "#ifdef BOOTLOADER" >> $OUTPUT
echo "/* Alternate interrupt handlers are not mapped into the application */" >> $OUTPUT
echo "#define ALTHANDLER(X) LONG(DEFINED(__Alt##X)? ABSOLUTE(__Alt##X): DEFINED(__##X) ? ABSOLUTE(__##X) : ABSOLUTE(__DefaultInterrupt));" >> $OUTPUT
echo "#endif" >> $OUTPUT
echo "" >> $OUTPUT
echo "#define INTERRUPT_LIST() \\" >> $OUTPUT
cat pic24f_interrupts.txt | while read INTERRUPT IMPLEMENTED
do
if [ $INTERRUPT ]; then
if [ $IMPLEMENTED == "Y" ]; then
echo -e "\t\tINTERRUPT($INTERRUPT) \\" >> $OUTPUT
else
echo -e "\t\tUNUSED_INTERRUPT($INTERRUPT) \\" >> $OUTPUT
fi
fi
done
echo -e "\t\t/* End macro (the comment gives it a last line without a \\) */" >> $OUTPUT
echo "" >> $OUTPUT
echo "" >> $OUTPUT
echo "SECTIONS {" >> $OUTPUT
echo "#ifdef BOOTLOADER" >> $OUTPUT
cat pic24f_reset.txt >> $OUTPUT
echo "#endif" >> $OUTPUT
echo "" >> $OUTPUT
cat pic24f_icd.txt >> $OUTPUT
echo "" >> $OUTPUT
cat pic24f_debug.txt >> $OUTPUT
echo "" >> $OUTPUT
cat pic24f_configs.txt >> $OUTPUT
echo "" >> $OUTPUT
echo "#ifdef BOOTLOADER" >> $OUTPUT
echo "/* This macro reserves space for each entry in the interrupt map. Its" >> $OUTPUT
echo " job is to create a _ADDR variable for the address where the GOTO" >> $OUTPUT
echo " instruction for each interrupt function will go. Only" >> $OUTPUT
echo " implemented interrupts are mapped. The application will put the" >> $OUTPUT
echo " actual mappings in this space, but the bootloader needs to know" >> $OUTPUT
echo " where each one is so it can put the correct addresses in the IVT. */" >> $OUTPUT
echo "#define INTERRUPT(X) X##_ADDR = .; . += 4;" >> $OUTPUT
echo "#define UNUSED_INTERRUPT(X)" >> $OUTPUT
echo "" >> $OUTPUT
echo -e "\t.ivt_map IVT_MAP_BASE : {" >> $OUTPUT
echo -e "\t\t. += 4; /* This is where the reset/start instruction will go. */" >> $OUTPUT
echo -e "\t\tINTERRUPT_LIST()" >> $OUTPUT
echo -e "\t} >ivt_map" >> $OUTPUT
echo "#endif" >> $OUTPUT
echo "" >> $OUTPUT
echo "#undef INTERRUPT" >> $OUTPUT
echo "#undef UNUSED_INTERRUPT" >> $OUTPUT
echo "" >> $OUTPUT
echo "#ifdef BOOTLOADER" >> $OUTPUT
echo "/* This macro is the interrupt handler addresses that go into the IVT." >> $OUTPUT
echo " Point the interrupt handler addresses to the addresses in the" >> $OUTPUT
echo " interrupt map, created above. Only acutal implemented interrupts" >> $OUTPUT
echo " (implemented at the platform level) are mapped. */" >> $OUTPUT
echo "#define INTERRUPT(X) LONG(DEFINED(X##_ADDR)? ABSOLUTE(X##_ADDR): ABSOLUTE(__DefaultInterrupt));" >> $OUTPUT
echo "#define UNUSED_INTERRUPT(X) LONG(ABSOLUTE(__DefaultInterrupt));" >> $OUTPUT
echo "" >> $OUTPUT
echo -e "\t.intvec IVT_BASE : {" >> $OUTPUT
echo -e "\t\tINTERRUPT_LIST()" >> $OUTPUT
echo -e "\t} >ivt" >> $OUTPUT
echo "" >> $OUTPUT
echo "#undef INTERRUPT" >> $OUTPUT
echo "#undef UNUSED_INTERRUPT" >> $OUTPUT
echo "" >> $OUTPUT
echo "" >> $OUTPUT
echo "/* Altertate Interrupt Table (ALT IVT) */" >> $OUTPUT
echo -e "#define INTERRUPT(X) ALTHANDLER(X)" >> $OUTPUT
echo -e "#define UNUSED_INTERRUPT(X) ALTHANDLER(X)" >> $OUTPUT
echo "" >> $OUTPUT
echo -e "\t.altintvec ALT_IVT_BASE : {" >> $OUTPUT
echo -e "\t\tINTERRUPT_LIST()" >> $OUTPUT
echo -e "\t} >aivt" >> $OUTPUT
echo "#endif /* BOOTLOADER */" >> $OUTPUT
echo "" >> $OUTPUT
echo "#undef INTERRUPT" >> $OUTPUT
echo "#undef UNUSED_INTERRUPT" >> $OUTPUT
echo "" >> $OUTPUT
echo "" >> $OUTPUT
echo "" >> $OUTPUT
echo "#ifdef BOOTLOADER_APP" >> $OUTPUT
echo "/* This macro is the Interrupt MAP. The application puts a GOTO" >> $OUTPUT
echo " instruction in each space in the map which jumps to the interrupt" >> $OUTPUT
echo " handler in the application. Note that it takes four words (8 bytes) for each" >> $OUTPUT
echo " goto instruction which is longer than what is stored in the IVT" >> $OUTPUT
echo " which is just the address (and not a GOTO instruction). The first" >> $OUTPUT
echo " slot is special and has a GOTO to the __reset function in libc. This" >> $OUTPUT
echo " way the bootloader just jumps to the beginning of the interrupt map" >> $OUTPUT
echo " to start the application */" >> $OUTPUT
echo "#define INTERRUPT(X) LONG(DEFINED(__##X)? (0x040000 | ABSOLUTE(__##X)) : 0x040000 | ABSOLUTE(__DefaultInterrupt)); \\" >> $OUTPUT
echo " LONG(DEFINED(__##X)? (ABSOLUTE(__##X) >> 16) & 0x7f : (ABSOLUTE(__DefaultInterrupt) >> 16) & 0x7f);" >> $OUTPUT
echo "#define UNUSED_INTERRUPT(X)" >> $OUTPUT
echo "" >> $OUTPUT
echo -e "\t.ivt_map IVT_MAP_BASE : {" >> $OUTPUT
echo -e "\t\tLONG(0x040000 | ABSOLUTE(__reset) & 0xffff);" >> $OUTPUT
echo -e "\t\tLONG((ABSOLUTE(__reset) >> 16) & 0x7f);" >> $OUTPUT
echo -e "\t\tINTERRUPT_LIST()" >> $OUTPUT
echo -e "\t} >ivt_map" >> $OUTPUT
echo "" >> $OUTPUT
echo "#undef INTERRUPT" >> $OUTPUT
echo "#undef UNUSED_INTERRUPT" >> $OUTPUT
echo "" >> $OUTPUT
echo "#endif" >> $OUTPUT
echo "}" >> $OUTPUT # SECTIONS
echo "" >> $OUTPUT
cat ${DEVICE}_regs.txt | while read REG ADDR
do
if [ $REG ]; then
echo -e "$REG = 0x$ADDR;" >> $OUTPUT
echo -e "_$REG = 0x$ADDR;" >> $OUTPUT
echo -e "_${REG}bits = 0x$ADDR;" >> $OUTPUT
fi
done
echo "" >> $OUTPUT