Project

General

Profile

Revision 173

Added by Kevin Woo over 13 years ago

  • Added timeouts to the packet handler
  • Bootloader sends nacks due to timeouts or mismatched packets
  • Bootloader clears user code jump before starting to program

View differences:

trunk/toolbox/bootloader/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