CI: Build on Arch (bleeding-ege) and Ubuntu (stable) AVR-GCC toolchains.
[pub/USBasp.git] / Bootloaders / CDC / BootloaderCDC.c
index 5f1047e..00755a5 100644 (file)
@@ -1,13 +1,13 @@
 /*
              LUFA Library
 /*
              LUFA Library
-     Copyright (C) Dean Camera, 2013.
+     Copyright (C) Dean Camera, 2018.
 
   dean [at] fourwalledcubicle [dot] com
            www.lufa-lib.org
 */
 
 /*
 
   dean [at] fourwalledcubicle [dot] com
            www.lufa-lib.org
 */
 
 /*
-  Copyright 2013  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
 
   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;
 
 {
        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();
 
                /* 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 */
                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();
 
                /* 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
 
        #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 a request has been made to jump to the user application, honor it */
-       if (JumpToApplication)
+       if (JumpToApplication && ApplicationValid)
        {
                /* Turn off the watchdog */
        {
                /* Turn off the watchdog */
-               MCUSR &= ~(1<<WDRF);
+               MCUSR &= ~(1 << WDRF);
                wdt_disable();
 
                /* Clear the boot key and jump to the user application */
                wdt_disable();
 
                /* Clear the boot key and jump to the user application */
@@ -127,6 +157,9 @@ int main(void)
                USB_USBTask();
        }
 
                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();
 
        /* 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)
        {
        /* 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)
                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)
                uint32_t PageStartAddress = CurrAddress;
 
                if (MemoryType == MEMORY_TYPE_FLASH)
-               {
-                       boot_page_erase(PageStartAddress);
-                       boot_spm_busy_wait();
-               }
+                 BootloaderAPI_ErasePage(PageStartAddress);
 
                while (BlockSize--)
                {
 
                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 */
                                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;
 
                                        /* 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 */
                        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;
 
                                /* 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 */
                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 */
                }
 
                /* 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)
        {
                /* 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');
 
                /* 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 */
        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');
 
                /* 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)
        {
        #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)
        {
        }
        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)
        {
        }
        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)
        {
        }
        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)
        }
        #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 */
        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');
 
                /* 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 */
        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;
 
                /* 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 */
        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');
 
                /* 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 */
        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;
 
                /* Increment the address after use */
                CurrAddress += 2;
@@ -638,4 +654,3 @@ static void CDC_Task(void)
        /* Acknowledge the command from the host */
        Endpoint_ClearOUT();
 }
        /* Acknowledge the command from the host */
        Endpoint_ClearOUT();
 }
-