Revision 173 trunk/toolbox/bootloader/bootloader.c
| bootloader.c (revision 173) | ||
|---|---|---|
| 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