Revision 173
- Added timeouts to the packet handler
- Bootloader sends nacks due to timeouts or mismatched packets
- Bootloader clears user code jump before starting to program
bootloader.c | ||
---|---|---|
11 | 11 |
#define ADDR 18 |
12 | 12 |
|
13 | 13 |
|
14 |
// Error thresholds |
|
14 | 15 |
#define MAX_TIMEOUT 60000 // Seconds to wait before exiting bootloader mode |
15 |
#define MAIN_ADDR 0x000 |
|
16 |
#define BOOT_START 0x400 |
|
16 |
#define MAX_RETRIES 5 // Number of times to retry before giving up |
|
17 | 17 |
|
18 |
// Memory locations |
|
19 |
#define MAIN_ADDR 0x000 // Where the user code starts |
|
20 |
#define BOOT_START 0x400 // Where the bootloader starts |
|
21 |
|
|
18 | 22 |
//Status LED |
19 | 23 |
#define LED_DDR DDRB |
20 | 24 |
#define LED_PORT PORTB |
... | ... | |
214 | 218 |
uint8_t resp; |
215 | 219 |
uint16_t prog_len; |
216 | 220 |
uint8_t i; |
221 |
uint8_t retries; |
|
217 | 222 |
|
218 |
//main_start = (void*)(BOOT_START - 2); |
|
219 | 223 |
iteration = 0; |
224 |
retries = 0; |
|
220 | 225 |
|
221 | 226 |
init_uart(51); //MAGIC NUMBER?? |
222 | 227 |
|
... | ... | |
228 | 233 |
send_packet(TT_BOOT); |
229 | 234 |
|
230 | 235 |
resp = parse_packet(mbuf); |
236 |
|
|
237 |
// Enter programming mode |
|
231 | 238 |
if (resp == TT_PROGM) { |
232 | 239 |
prog_len = mbuf[0]; |
233 | 240 |
prog_len |= mbuf[1] << 8; |
241 |
|
|
242 |
// This will insert a NOP into the user code jump in case |
|
243 |
// the programming fails |
|
244 |
for (i = 0; i < PROGD_PACKET_SIZE; i++) { |
|
245 |
mbuf[i]= 0; |
|
246 |
} |
|
247 |
onboard_program_write(BOOT_START - SPM_PAGESIZE, mbuf); |
|
248 |
|
|
249 |
// Run user code |
|
234 | 250 |
} else { |
235 |
//PORTB = 0; |
|
236 | 251 |
main_start(); |
237 | 252 |
} |
253 |
|
|
238 | 254 |
send_packet(TT_ACK); |
239 | 255 |
|
240 | 256 |
while(1) { |
241 | 257 |
resp = parse_packet(mbuf); |
242 | 258 |
|
243 | 259 |
if (resp == TT_PROGD) { |
260 |
// We need to muck with the reset vector jump in the first page |
|
244 | 261 |
if (iteration == 0) { |
245 | 262 |
// Store the jump to user code |
246 | 263 |
jbuf.bytes[0] = mbuf[0]; |
247 | 264 |
jbuf.bytes[1] = mbuf[1]; |
248 | 265 |
|
266 |
// Rewrite the user code jump to be correct since we are |
|
267 |
// using relative jumps (rjmp) |
|
249 | 268 |
jbuf.sword &= 0x0FFF; |
250 | 269 |
jbuf.sword -= (BOOT_START >> 1) - 1; |
251 | 270 |
jbuf.sword &= 0x0FFF; |
252 | 271 |
jbuf.sword |= 0xC000; |
253 | 272 |
|
273 |
// Rewrite the reset vector to jump to the bootloader |
|
254 | 274 |
mbuf[0] = (BOOT_START/2 - 1) & 0xFF; |
255 | 275 |
mbuf[1] = 0xC0 | (((BOOT_START/2 - 1) >> 8) & 0x0F); |
256 | 276 |
|
257 | 277 |
iteration = 1; |
258 | 278 |
} |
259 | 279 |
|
280 |
// Write the page to the flash |
|
260 | 281 |
onboard_program_write(caddr, mbuf); |
261 | 282 |
caddr += PROGD_PACKET_SIZE; |
283 |
retries = 0; |
|
262 | 284 |
} else { |
263 |
//main_start(); |
|
264 |
PORTB &= ~_BV(PORTB2); |
|
265 |
while(1); |
|
285 |
send_packet(TT_NACK); |
|
286 |
retries++; |
|
287 |
|
|
288 |
// If we failed too many times, reset. The main_start should |
|
289 |
// no-op back to the start of the bootloader |
|
290 |
if (retries > MAX_RETRIES) { |
|
291 |
main_start(); |
|
292 |
} |
|
266 | 293 |
} |
267 | 294 |
|
268 | 295 |
send_packet(TT_ACK); |
269 | 296 |
|
297 |
// Once we write the last packet we must override the jump to |
|
298 |
// user code to point to the correct address |
|
270 | 299 |
if (prog_len <= PROGD_PACKET_SIZE) { |
271 | 300 |
for (i = 0; i < PROGD_PACKET_SIZE; i++) { |
272 | 301 |
mbuf[i]= 0; |
... | ... | |
277 | 306 |
|
278 | 307 |
onboard_program_write(BOOT_START - SPM_PAGESIZE, mbuf); |
279 | 308 |
|
280 |
PORTB = 0; |
|
281 | 309 |
main_start(); |
282 | 310 |
} else { |
283 | 311 |
prog_len -= PROGD_PACKET_SIZE; |
Also available in: Unified diff