CI: Build on Arch (bleeding-ege) and Ubuntu (stable) AVR-GCC toolchains.
[pub/USBasp.git] / Bootloaders / CDC / BootloaderCDC.c
index f66a483..00755a5 100644 (file)
@@ -1,13 +1,13 @@
 /*
              LUFA Library
-     Copyright (C) Dean Camera, 2014.
+     Copyright (C) Dean Camera, 2018.
 
   dean [at] fourwalledcubicle [dot] com
            www.lufa-lib.org
 */
 
 /*
-  Copyright 2014  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+  Copyright 2018  Dean Camera (dean [at] fourwalledcubicle [dot] com)
 
   Permission to use, copy, modify, distribute, and sell this
   software and its documentation for any purpose is hereby granted
@@ -72,7 +72,17 @@ void Application_Jump_Check(void)
 {
        bool JumpToApplication = false;
 
-       #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
+       #if (BOARD == BOARD_LEONARDO)
+               /* Enable pull-up on the IO13 pin so we can use it to select the mode */
+               PORTC |= (1 << 7);
+               Delay_MS(10);
+
+               /* If IO13 is not jumpered to ground, start the user application instead */
+               JumpToApplication = ((PINC & (1 << 7)) != 0);
+
+               /* Disable pull-up after the check has completed */
+               PORTC &= ~(1 << 7);
+       #elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
                /* Disable JTAG debugging */
                JTAG_DISABLE();
 
@@ -81,21 +91,41 @@ void Application_Jump_Check(void)
                Delay_MS(10);
 
                /* If the TCK pin is not jumpered to ground, start the user application instead */
-               JumpToApplication |= ((PINF & (1 << 4)) != 0);
+               JumpToApplication = ((PINF & (1 << 4)) != 0);
 
                /* Re-enable JTAG debugging */
                JTAG_ENABLE();
+       #else
+               /* Check if the device's BOOTRST fuse is set */
+               if (!(BootloaderAPI_ReadFuse(GET_HIGH_FUSE_BITS) & ~FUSE_BOOTRST))
+               {
+                       /* If the reset source was not an external reset or the key is correct, clear it and jump to the application */
+                       if (!(MCUSR & (1 << EXTRF)) || (MagicBootKey == MAGIC_BOOT_KEY))
+                         JumpToApplication = true;
+
+                       /* Clear reset source */
+                       MCUSR &= ~(1 << EXTRF);
+               }
+               else
+               {
+                       /* If the reset source was the bootloader and the key is correct, clear it and jump to the application;
+                        * this can happen in the HWBE fuse is set, and the HBE pin is low during the watchdog reset */
+                       if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
+                               JumpToApplication = true;
+
+                       /* Clear reset source */
+                       MCUSR &= ~(1 << WDRF);
+               }
        #endif
 
-       /* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
-       if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
-         JumpToApplication |= true;
+       /* Don't run the user application if the reset vector is blank (no app loaded) */
+       bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF);
 
        /* If a request has been made to jump to the user application, honor it */
-       if (JumpToApplication)
+       if (JumpToApplication && ApplicationValid)
        {
                /* Turn off the watchdog */
-               MCUSR &= ~(1<<WDRF);
+               MCUSR &= ~(1 << WDRF);
                wdt_disable();
 
                /* Clear the boot key and jump to the user application */
@@ -127,6 +157,9 @@ int main(void)
                USB_USBTask();
        }
 
+       /* Wait a short time to end all USB transactions and then disconnect */
+       _delay_us(1000);
+
        /* Disconnect from the host - USB interface will be reset later along with the AVR */
        USB_Detach();
 
@@ -264,9 +297,6 @@ static void ReadWriteMemoryBlock(const uint8_t Command)
        /* Check if command is to read a memory block */
        if (Command == AVR109_COMMAND_BlockRead)
        {
-               /* Re-enable RWW section */
-               boot_rww_enable();
-
                while (BlockSize--)
                {
                        if (MemoryType == MEMORY_TYPE_FLASH)
@@ -299,10 +329,7 @@ static void ReadWriteMemoryBlock(const uint8_t Command)
                uint32_t PageStartAddress = CurrAddress;
 
                if (MemoryType == MEMORY_TYPE_FLASH)
-               {
-                       boot_page_erase(PageStartAddress);
-                       boot_spm_busy_wait();
-               }
+                 BootloaderAPI_ErasePage(PageStartAddress);
 
                while (BlockSize--)
                {
@@ -312,7 +339,7 @@ static void ReadWriteMemoryBlock(const uint8_t Command)
                                if (HighByte)
                                {
                                        /* Write the next FLASH word to the current FLASH page */
-                                       boot_page_fill(CurrAddress, ((FetchNextCommandByte() << 8) | LowByte));
+                                       BootloaderAPI_FillWord(CurrAddress, ((FetchNextCommandByte() << 8) | LowByte));
 
                                        /* Increment the address counter after use */
                                        CurrAddress += 2;
@@ -327,7 +354,7 @@ static void ReadWriteMemoryBlock(const uint8_t Command)
                        else
                        {
                                /* Write the next EEPROM byte from the endpoint */
-                               eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
+                               eeprom_update_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
 
                                /* Increment the address counter after use */
                                CurrAddress += 2;
@@ -338,10 +365,7 @@ static void ReadWriteMemoryBlock(const uint8_t Command)
                if (MemoryType == MEMORY_TYPE_FLASH)
                {
                        /* Commit the flash page to memory */
-                       boot_page_write(PageStartAddress);
-
-                       /* Wait until write operation has completed */
-                       boot_spm_busy_wait();
+                       BootloaderAPI_WritePage(PageStartAddress);
                }
 
                /* Send response byte back to the host */
@@ -483,12 +507,7 @@ static void CDC_Task(void)
        {
                /* Clear the application section of flash */
                for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < (uint32_t)BOOT_START_ADDR; CurrFlashAddress += SPM_PAGESIZE)
-               {
-                       boot_page_erase(CurrFlashAddress);
-                       boot_spm_busy_wait();
-                       boot_page_write(CurrFlashAddress);
-                       boot_spm_busy_wait();
-               }
+                       BootloaderAPI_ErasePage(CurrFlashAddress);
 
                /* Send confirmation byte back to the host */
                WriteNextResponseByte('\r');
@@ -497,7 +516,7 @@ static void CDC_Task(void)
        else if (Command == AVR109_COMMAND_WriteLockbits)
        {
                /* Set the lock bits to those given by the host */
-               boot_lock_bits_set(FetchNextCommandByte());
+               BootloaderAPI_WriteLock(FetchNextCommandByte());
 
                /* Send confirmation byte back to the host */
                WriteNextResponseByte('\r');
@@ -505,19 +524,19 @@ static void CDC_Task(void)
        #endif
        else if (Command == AVR109_COMMAND_ReadLockbits)
        {
-               WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS));
+               WriteNextResponseByte(BootloaderAPI_ReadLock());
        }
        else if (Command == AVR109_COMMAND_ReadLowFuses)
        {
-               WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
+               WriteNextResponseByte(BootloaderAPI_ReadFuse(GET_LOW_FUSE_BITS));
        }
        else if (Command == AVR109_COMMAND_ReadHighFuses)
        {
-               WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
+               WriteNextResponseByte(BootloaderAPI_ReadFuse(GET_HIGH_FUSE_BITS));
        }
        else if (Command == AVR109_COMMAND_ReadExtendedFuses)
        {
-               WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
+               WriteNextResponseByte(BootloaderAPI_ReadFuse(GET_EXTENDED_FUSE_BITS));
        }
        #if !defined(NO_BLOCK_SUPPORT)
        else if (Command == AVR109_COMMAND_GetBlockWriteSupport)
@@ -538,7 +557,7 @@ static void CDC_Task(void)
        else if (Command == AVR109_COMMAND_FillFlashPageWordHigh)
        {
                /* Write the high byte to the current flash page */
-               boot_page_fill(CurrAddress, FetchNextCommandByte());
+               BootloaderAPI_FillWord(CurrAddress, FetchNextCommandByte());
 
                /* Send confirmation byte back to the host */
                WriteNextResponseByte('\r');
@@ -546,7 +565,7 @@ static void CDC_Task(void)
        else if (Command == AVR109_COMMAND_FillFlashPageWordLow)
        {
                /* Write the low byte to the current flash page */
-               boot_page_fill(CurrAddress | 0x01, FetchNextCommandByte());
+               BootloaderAPI_FillWord(CurrAddress | 0x01, FetchNextCommandByte());
 
                /* Increment the address */
                CurrAddress += 2;
@@ -557,10 +576,7 @@ static void CDC_Task(void)
        else if (Command == AVR109_COMMAND_WriteFlashPage)
        {
                /* Commit the flash page to memory */
-               boot_page_write(CurrAddress);
-
-               /* Wait until write operation has completed */
-               boot_spm_busy_wait();
+               BootloaderAPI_WritePage(CurrAddress);
 
                /* Send confirmation byte back to the host */
                WriteNextResponseByte('\r');
@@ -581,7 +597,7 @@ static void CDC_Task(void)
        else if (Command == AVR109_COMMAND_WriteEEPROM)
        {
                /* Read the byte from the endpoint and write it to the EEPROM */
-               eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
+               eeprom_update_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
 
                /* Increment the address after use */
                CurrAddress += 2;
@@ -638,4 +654,3 @@ static void CDC_Task(void)
        /* Acknowledge the command from the host */
        Endpoint_ClearOUT();
 }
-