Dean Camera committed May 08, 2010 1 2 /* LUFA Library  Dean Camera committed Feb 04, 2012 3  Copyright (C) Dean Camera, 2012.  4   Dean Camera committed May 08, 2010 5  dean [at] fourwalledcubicle [dot] com  Dean Camera committed Oct 28, 2010 6  www.lufa-lib.org  Dean Camera committed May 08, 2010 7 8 9 */ /*  Dean Camera committed Feb 04, 2012 10  Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)  Dean Camera committed May 08, 2010 11   12  Permission to use, copy, modify, distribute, and sell this  Dean Camera committed May 08, 2010 13  software and its documentation for any purpose is hereby granted  14  without fee, provided that the above copyright notice appear in  Dean Camera committed May 08, 2010 15  all copies and that both that the copyright notice and this  16 17 18  permission notice and warranty disclaimer appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the  Dean Camera committed May 08, 2010 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34  software without specific, written prior permission. The author disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall the author be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. */ /** \file * * Main source file for the CDC class bootloader. This file contains the complete bootloader logic. */  35   Dean Camera committed May 08, 2010 36 37 38 #define INCLUDE_FROM_BOOTLOADERCDC_C #include "BootloaderCDC.h"  Dean Camera committed Sep 28, 2010 39 40 41 /** Contains the current baud rate and other settings of the first virtual serial port. This must be retained as some * operating systems will not open the port unless the settings can be set successfully. */  Dean Camera committed Feb 10, 2011 42 43 44 45 static CDC_LineEncoding_t LineEncoding = { .BaudRateBPS = 0, .CharFormat = CDC_LINEENCODING_OneStopBit, .ParityType = CDC_PARITY_None, .DataBits = 8 };  Dean Camera committed Sep 28, 2010 46   Dean Camera committed May 08, 2010 47 48 49 50 /** Current address counter. This stores the current address of the FLASH or EEPROM as set by the host, * and is used when reading or writing to the AVRs memory (either FLASH or EEPROM depending on the issued * command.) */  Dean Camera committed Feb 10, 2011 51 static uint32_t CurrAddress;  Dean Camera committed May 08, 2010 52 53 54 55 56  /** Flag to indicate if the bootloader should be running, or should exit and allow the application code to run * via a watchdog reset. When cleared the bootloader will exit, starting the watchdog and entering an infinite * loop until the AVR restarts and the application runs. */  Dean Camera committed Feb 10, 2011 57 static bool RunBootloader = true;  Dean Camera committed May 08, 2010 58   Dean Camera committed Apr 29, 2012 59 60 61 62 63 /** Magic lock for forced application start. If the HWBE fuse is programmed and BOOTRST is unprogrammed, the bootloader * will start if the /HWB line of the AVR is held low and the system is reset. However, if the /HWB line is still held * low when the application attempts to start via a watchdog reset, the bootloader will re-start. If set to the value * \ref MAGIC_BOOT_KEY the special init function \ref Application_Jump_Check() will force the application to start. */  Dean Camera committed Jul 07, 2012 64 uint16_t MagicBootKey ATTR_NO_INIT;  Dean Camera committed Apr 29, 2012 65 66 67 68 69 70 71 72  /** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application * start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid, * this will force the user application to start via a software jump. */ void Application_Jump_Check(void) {  Dean Camera committed Jun 09, 2012 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89  bool JumpToApplication = false; #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) /* Disable JTAG debugging */ JTAG_DISABLE(); /* Enable pull-up on the JTAG TCK pin so we can use it to select the mode */ PORTF |= (1 << 4); Delay_MS(10); /* If the TCK pin is not jumpered to ground, start the user application instead */ JumpToApplication |= ((PINF & (1 << 4)) != 0); /* Re-enable JTAG debugging */ JTAG_ENABLE(); #endif  Dean Camera committed May 05, 2012 90  /* If the reset source was the bootloader and the key is correct, clear it and jump to the application */  Dean Camera committed Apr 29, 2012 91  if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))  Dean Camera committed Jun 09, 2012 92 93 94 95  JumpToApplication |= true; /* If a request has been made to jump to the user application, honor it */ if (JumpToApplication)  Dean Camera committed Apr 29, 2012 96  {  Dean Camera committed May 21, 2012 97 98 99 100 101  /* Turn off the watchdog */ MCUSR &= ~(1< 0xFFFF) WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte)); #else  270  WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte));  Dean Camera committed May 08, 2010 271  #endif  272   Dean Camera committed May 08, 2010 273 274 275  /* If both bytes in current word have been read, increment the address counter */ if (HighByte) CurrAddress += 2;  276   Dean Camera committed May 08, 2010 277 278 279 280 281  HighByte = !HighByte; } else { /* Read the next EEPROM byte into the endpoint */  282  WriteNextResponseByte(eeprom_read_byte((uint8_t*)(intptr_t)(CurrAddress >> 1)));  Dean Camera committed May 08, 2010 283 284 285  /* Increment the address counter after use */ CurrAddress += 2;  286  }  Dean Camera committed May 08, 2010 287 288 289 290 291 292 293 294 295 296 297  } } else { uint32_t PageStartAddress = CurrAddress; if (MemoryType == 'F') { boot_page_erase(PageStartAddress); boot_spm_busy_wait(); }  298   Dean Camera committed May 08, 2010 299 300 301  while (BlockSize--) { if (MemoryType == 'F')  302  {  Dean Camera committed May 08, 2010 303 304 305 306 307 308 309 310 311 312 313 314 315  /* If both bytes in current word have been written, increment the address counter */ if (HighByte) { /* Write the next FLASH word to the current FLASH page */ boot_page_fill(CurrAddress, ((FetchNextCommandByte() << 8) | LowByte)); /* Increment the address counter after use */ CurrAddress += 2; } else { LowByte = FetchNextCommandByte(); }  Dean Camera committed Dec 23, 2011 316   Dean Camera committed Oct 29, 2010 317  HighByte = !HighByte;  Dean Camera committed May 08, 2010 318 319 320 321  } else { /* Write the next EEPROM byte from the endpoint */  322  eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());  Dean Camera committed May 08, 2010 323 324 325 326 327 328 329 330 331 332 333  /* Increment the address counter after use */ CurrAddress += 2; } } /* If in FLASH programming mode, commit the page after writing */ if (MemoryType == 'F') { /* Commit the flash page to memory */ boot_page_write(PageStartAddress);  334   Dean Camera committed May 08, 2010 335 336 337  /* Wait until write operation has completed */ boot_spm_busy_wait(); }  338   Dean Camera committed May 08, 2010 339  /* Send response byte back to the host */  340  WriteNextResponseByte('\r');  Dean Camera committed May 08, 2010 341 342  } }  Dean Camera committed Oct 29, 2010 343 #endif  Dean Camera committed May 08, 2010 344 345 346 347 348 349 350 351 352  /** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if needed * to allow reception of the next data packet from the host. * * \return Next received byte from the host in the CDC data OUT endpoint */ static uint8_t FetchNextCommandByte(void) { /* Select the OUT endpoint so that the next data byte can be read */  Dean Camera committed Apr 14, 2012 353  Endpoint_SelectEndpoint(CDC_RX_EPADDR);  354   Dean Camera committed May 08, 2010 355 356 357 358 359 360 361 362 363 364 365  /* If OUT endpoint empty, clear it and wait for the next packet from the host */ while (!(Endpoint_IsReadWriteAllowed())) { Endpoint_ClearOUT(); while (!(Endpoint_IsOUTReceived())) { if (USB_DeviceState == DEVICE_STATE_Unattached) return 0; } }  366   Dean Camera committed May 08, 2010 367  /* Fetch the next byte from the OUT endpoint */  Dean Camera committed Apr 04, 2011 368  return Endpoint_Read_8();  Dean Camera committed May 08, 2010 369 370 371 372 373 374 375 376 377 378 } /** Writes the next response byte to the CDC data IN endpoint, and sends the endpoint back if needed to free up the * bank when full ready for the next byte in the packet to the host. * * \param[in] Response Next response byte to send to the host */ static void WriteNextResponseByte(const uint8_t Response) { /* Select the IN endpoint so that the next data byte can be written */  Dean Camera committed Apr 14, 2012 379  Endpoint_SelectEndpoint(CDC_TX_EPADDR);  380   Dean Camera committed May 08, 2010 381 382 383 384  /* If IN endpoint full, clear it and wait until ready for the next packet to the host */ if (!(Endpoint_IsReadWriteAllowed())) { Endpoint_ClearIN();  385   Dean Camera committed May 08, 2010 386  while (!(Endpoint_IsINReady()))  387  {  Dean Camera committed May 08, 2010 388 389 390 391  if (USB_DeviceState == DEVICE_STATE_Unattached) return; } }  392   Dean Camera committed Nov 24, 2010 393  /* Write the next byte to the IN endpoint */  Dean Camera committed Apr 04, 2011 394  Endpoint_Write_8(Response);  Dean Camera committed May 08, 2010 395 396 397 398 399 } /** Task to read in AVR910 commands from the CDC data OUT endpoint, process them, perform the required actions * and send the appropriate response back to the host. */  Dean Camera committed Jan 15, 2012 400 static void CDC_Task(void)  Dean Camera committed May 08, 2010 401 402 { /* Select the OUT endpoint */  Dean Camera committed Apr 14, 2012 403  Endpoint_SelectEndpoint(CDC_RX_EPADDR);  404   Dean Camera committed May 08, 2010 405  /* Check if endpoint has a command in it sent from the host */  Dean Camera committed Oct 29, 2010 406 407  if (!(Endpoint_IsOUTReceived())) return;  Dean Camera committed May 08, 2010 408   Dean Camera committed Oct 29, 2010 409 410  /* Read in the bootloader command (first byte sent from host) */ uint8_t Command = FetchNextCommandByte();  Dean Camera committed May 08, 2010 411   Dean Camera committed Oct 29, 2010 412 413 414  if (Command == 'E') { RunBootloader = false;  Dean Camera committed Dec 23, 2011 415   Dean Camera committed Oct 29, 2010 416 417 418 419 420 421  /* Send confirmation byte back to the host */ WriteNextResponseByte('\r'); } else if (Command == 'T') { FetchNextCommandByte();  Dean Camera committed May 08, 2010 422   Dean Camera committed Oct 29, 2010 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475  /* Send confirmation byte back to the host */ WriteNextResponseByte('\r'); } else if ((Command == 'L') || (Command == 'P')) { /* Send confirmation byte back to the host */ WriteNextResponseByte('\r'); } else if (Command == 't') { /* Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader */ WriteNextResponseByte(0x44); WriteNextResponseByte(0x00); } else if (Command == 'a') { /* Indicate auto-address increment is supported */ WriteNextResponseByte('Y'); } else if (Command == 'A') { /* Set the current address to that given by the host */ CurrAddress = (FetchNextCommandByte() << 9); CurrAddress |= (FetchNextCommandByte() << 1); /* Send confirmation byte back to the host */ WriteNextResponseByte('\r'); } else if (Command == 'p') { /* Indicate serial programmer back to the host */ WriteNextResponseByte('S'); } else if (Command == 'S') { /* Write the 7-byte software identifier to the endpoint */ for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++) WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]); } else if (Command == 'V') { WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR); WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR); } else if (Command == 's') { WriteNextResponseByte(AVR_SIGNATURE_3); WriteNextResponseByte(AVR_SIGNATURE_2); WriteNextResponseByte(AVR_SIGNATURE_1); } else if (Command == 'e') { /* Clear the application section of flash */  Dean Camera committed Jun 01, 2012 476  for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < (uint32_t)BOOT_START_ADDR; CurrFlashAddress += SPM_PAGESIZE)  Dean Camera committed May 08, 2010 477  {  Dean Camera committed Oct 29, 2010 478 479 480 481  boot_page_erase(CurrFlashAddress); boot_spm_busy_wait(); boot_page_write(CurrFlashAddress); boot_spm_busy_wait();  Dean Camera committed May 08, 2010 482  }  483   Dean Camera committed Oct 29, 2010 484 485 486 487 488 489 490 491  /* Send confirmation byte back to the host */ WriteNextResponseByte('\r'); } #if !defined(NO_LOCK_BYTE_WRITE_SUPPORT) else if (Command == 'l') { /* Set the lock bits to those given by the host */ boot_lock_bits_set(FetchNextCommandByte());  Dean Camera committed May 08, 2010 492   Dean Camera committed Oct 29, 2010 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516  /* Send confirmation byte back to the host */ WriteNextResponseByte('\r'); } #endif else if (Command == 'r') { WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS)); } else if (Command == 'F') { WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS)); } else if (Command == 'N') { WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS)); } else if (Command == 'Q') { WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS)); } #if !defined(NO_BLOCK_SUPPORT) else if (Command == 'b') { WriteNextResponseByte('Y');  Dean Camera committed Oct 29, 2010 517   Dean Camera committed Oct 29, 2010 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532  /* Send block size to the host */ WriteNextResponseByte(SPM_PAGESIZE >> 8); WriteNextResponseByte(SPM_PAGESIZE & 0xFF); } else if ((Command == 'B') || (Command == 'g')) { /* Delegate the block write/read to a separate function for clarity */ ReadWriteMemoryBlock(Command); } #endif #if !defined(NO_FLASH_BYTE_SUPPORT) else if (Command == 'C') { /* Write the high byte to the current flash page */ boot_page_fill(CurrAddress, FetchNextCommandByte());  Dean Camera committed May 08, 2010 533   Dean Camera committed Oct 29, 2010 534 535 536 537 538 539 540  /* Send confirmation byte back to the host */ WriteNextResponseByte('\r'); } else if (Command == 'c') { /* Write the low byte to the current flash page */ boot_page_fill(CurrAddress | 0x01, FetchNextCommandByte());  541   Dean Camera committed Oct 29, 2010 542 543  /* Increment the address */ CurrAddress += 2;  Dean Camera committed May 08, 2010 544   Dean Camera committed Oct 29, 2010 545 546 547 548 549 550 551  /* Send confirmation byte back to the host */ WriteNextResponseByte('\r'); } else if (Command == 'm') { /* Commit the flash page to memory */ boot_page_write(CurrAddress);  552   Dean Camera committed Oct 29, 2010 553 554  /* Wait until write operation has completed */ boot_spm_busy_wait();  Dean Camera committed May 08, 2010 555   Dean Camera committed Oct 29, 2010 556 557 558 559 560 561 562 563 564  /* Send confirmation byte back to the host */ WriteNextResponseByte('\r'); } else if (Command == 'R') { #if (FLASHEND > 0xFFFF) uint16_t ProgramWord = pgm_read_word_far(CurrAddress); #else uint16_t ProgramWord = pgm_read_word(CurrAddress);  Dean Camera committed Oct 29, 2010 565  #endif  566   Dean Camera committed Oct 29, 2010 567 568 569 570 571 572 573 574 575  WriteNextResponseByte(ProgramWord >> 8); WriteNextResponseByte(ProgramWord & 0xFF); } #endif #if !defined(NO_EEPROM_BYTE_SUPPORT) else if (Command == 'D') { /* Read the byte from the endpoint and write it to the EEPROM */ eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());  576   Dean Camera committed Oct 29, 2010 577 578  /* Increment the address after use */ CurrAddress += 2;  Dean Camera committed May 08, 2010 579   Dean Camera committed Oct 29, 2010 580 581 582 583 584 585 586  /* Send confirmation byte back to the host */ WriteNextResponseByte('\r'); } else if (Command == 'd') { /* Read the EEPROM byte and write it to the endpoint */ WriteNextResponseByte(eeprom_read_byte((uint8_t*)((intptr_t)(CurrAddress >> 1))));  Dean Camera committed May 08, 2010 587   Dean Camera committed Oct 29, 2010 588 589 590 591 592 593 594 595 596  /* Increment the address after use */ CurrAddress += 2; } #endif else if (Command != 27) { /* Unknown (non-sync) command, return fail code */ WriteNextResponseByte('?'); }  Dean Camera committed May 08, 2010 597   Dean Camera committed Oct 29, 2010 598  /* Select the IN endpoint */  Dean Camera committed Apr 14, 2012 599  Endpoint_SelectEndpoint(CDC_TX_EPADDR);  600   Dean Camera committed Oct 29, 2010 601 602  /* Remember if the endpoint is completely full before clearing it */ bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());  Dean Camera committed May 08, 2010 603   Dean Camera committed Oct 29, 2010 604 605  /* Send the endpoint data to the host */ Endpoint_ClearIN();  Dean Camera committed May 08, 2010 606   Dean Camera committed Oct 29, 2010 607 608 609  /* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal end of transfer */ if (IsEndpointFull) {  Dean Camera committed May 08, 2010 610  while (!(Endpoint_IsINReady()))  611  {  Dean Camera committed May 08, 2010 612 613 614  if (USB_DeviceState == DEVICE_STATE_Unattached) return; }  615   Dean Camera committed Oct 29, 2010 616 617  Endpoint_ClearIN(); }  Dean Camera committed May 08, 2010 618   Dean Camera committed Oct 29, 2010 619 620 621 622 623  /* Wait until the data has been sent to the host */ while (!(Endpoint_IsINReady())) { if (USB_DeviceState == DEVICE_STATE_Unattached) return;  Dean Camera committed May 08, 2010 624  }  Dean Camera committed Oct 29, 2010 625 626  /* Select the OUT endpoint */  Dean Camera committed Apr 14, 2012 627  Endpoint_SelectEndpoint(CDC_RX_EPADDR);  Dean Camera committed Oct 29, 2010 628 629 630  /* Acknowledge the command from the host */ Endpoint_ClearOUT();  Dean Camera committed May 08, 2010 631 }  632