Fixed possible lost data in the XPLAINBridge, USBtoSerial and Benito projects when...
[pub/USBasp.git] / Bootloaders / DFU / BootloaderDFU.c
index c14bd26..f2247eb 100644 (file)
@@ -1,21 +1,21 @@
 /*
              LUFA Library
      Copyright (C) Dean Camera, 2010.
 /*
              LUFA Library
      Copyright (C) Dean Camera, 2010.
-              
+
   dean [at] fourwalledcubicle [dot] com
   dean [at] fourwalledcubicle [dot] com
-      www.fourwalledcubicle.com
+           www.lufa-lib.org
 */
 
 /*
   Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)
 
 */
 
 /*
   Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)
 
-  Permission to use, copy, modify, distribute, and sell this 
+  Permission to use, copy, modify, distribute, and sell this
   software and its documentation for any purpose is hereby granted
   software and its documentation for any purpose is hereby granted
-  without fee, provided that the above copyright notice appear in 
+  without fee, provided that the above copyright notice appear in
   all copies and that both that the copyright notice and this
   all copies and that both that the copyright notice and this
-  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 
+  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
   software without specific, written prior permission.
 
   The author disclaim all warranties with regard to this
   software without specific, written prior permission.
 
   The author disclaim all warranties with regard to this
@@ -93,7 +93,7 @@ uint16_t StartAddr = 0x0000;
 uint16_t EndAddr = 0x0000;
 
 
 uint16_t EndAddr = 0x0000;
 
 
-/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously 
+/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously
  *  runs the bootloader processing routine until instructed to soft-exit, or hard-reset via the watchdog to start
  *  the loaded application code.
  */
  *  runs the bootloader processing routine until instructed to soft-exit, or hard-reset via the watchdog to start
  *  the loaded application code.
  */
@@ -101,17 +101,34 @@ int main(void)
 {
        /* Configure hardware required by the bootloader */
        SetupHardware();
 {
        /* Configure hardware required by the bootloader */
        SetupHardware();
+
+       #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
+       /* Disable JTAG debugging */
+       MCUCR |= (1 << JTD);
+       MCUCR |= (1 << JTD);
+
+       /* 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 */
+       RunBootloader = (!(PINF & (1 << 4)));
        
        
+       /* Re-enable JTAG debugging */
+       MCUCR &= ~(1 << JTD);
+       MCUCR &= ~(1 << JTD);   
+       #endif
+
        /* Enable global interrupts so that the USB stack can function */
        sei();
 
        /* Run the USB management task while the bootloader is supposed to be running */
        while (RunBootloader || WaitForExit)
          USB_USBTask();
        /* Enable global interrupts so that the USB stack can function */
        sei();
 
        /* Run the USB management task while the bootloader is supposed to be running */
        while (RunBootloader || WaitForExit)
          USB_USBTask();
-       
+
        /* Reset configured hardware back to their original states for the user application */
        ResetHardware();
        /* Reset configured hardware back to their original states for the user application */
        ResetHardware();
-       
+
        /* Start the user application */
        AppStartPtr();
 }
        /* Start the user application */
        AppStartPtr();
 }
@@ -125,7 +142,7 @@ void SetupHardware(void)
 
        /* Disable clock division */
        clock_prescale_set(clock_div_1);
 
        /* Disable clock division */
        clock_prescale_set(clock_div_1);
-       
+
        /* Relocate the interrupt vector table to the bootloader section */
        MCUCR = (1 << IVCE);
        MCUCR = (1 << IVSEL);
        /* Relocate the interrupt vector table to the bootloader section */
        MCUCR = (1 << IVCE);
        MCUCR = (1 << IVSEL);
@@ -139,51 +156,58 @@ void ResetHardware(void)
 {
        /* Shut down the USB subsystem */
        USB_ShutDown();
 {
        /* Shut down the USB subsystem */
        USB_ShutDown();
-       
+
        /* Relocate the interrupt vector table back to the application section */
        MCUCR = (1 << IVCE);
        MCUCR = 0;
 }
 
        /* Relocate the interrupt vector table back to the application section */
        MCUCR = (1 << IVCE);
        MCUCR = 0;
 }
 
-/** Event handler for the USB_UnhandledControlRequest event. This is used to catch standard and class specific
- *  control requests that are not handled internally by the USB library (including the DFU commands, which are
- *  all issued via the control endpoint), so that they can be handled appropriately for the application.
+/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
+ *  the device from the USB host before passing along unhandled control requests to the library for processing
+ *  internally.
  */
  */
-void EVENT_USB_Device_UnhandledControlRequest(void)
+void EVENT_USB_Device_ControlRequest(void)
 {
        /* Get the size of the command and data from the wLength value */
        SentCommand.DataSize = USB_ControlRequest.wLength;
 {
        /* Get the size of the command and data from the wLength value */
        SentCommand.DataSize = USB_ControlRequest.wLength;
+       
+       /* Ignore any requests that aren't directed to the DFU interface */
+       if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
+           (REQTYPE_CLASS | REQREC_INTERFACE))
+       {
+               return;
+       }
 
        switch (USB_ControlRequest.bRequest)
        {
 
        switch (USB_ControlRequest.bRequest)
        {
-               case DFU_DNLOAD:
+               case REQ_DFU_DNLOAD:
                        Endpoint_ClearSETUP();
                        Endpoint_ClearSETUP();
-                       
+
                        /* Check if bootloader is waiting to terminate */
                        if (WaitForExit)
                        {
                                /* Bootloader is terminating - process last received command */
                                ProcessBootloaderCommand();
                        /* Check if bootloader is waiting to terminate */
                        if (WaitForExit)
                        {
                                /* Bootloader is terminating - process last received command */
                                ProcessBootloaderCommand();
-                               
+
                                /* Indicate that the last command has now been processed - free to exit bootloader */
                                WaitForExit = false;
                        }
                                /* Indicate that the last command has now been processed - free to exit bootloader */
                                WaitForExit = false;
                        }
-                         
+
                        /* If the request has a data stage, load it into the command struct */
                        if (SentCommand.DataSize)
                        {
                                while (!(Endpoint_IsOUTReceived()))
                        /* If the request has a data stage, load it into the command struct */
                        if (SentCommand.DataSize)
                        {
                                while (!(Endpoint_IsOUTReceived()))
-                               {                               
+                               {
                                        if (USB_DeviceState == DEVICE_STATE_Unattached)
                                          return;
                                }
 
                                /* First byte of the data stage is the DNLOAD request's command */
                                SentCommand.Command = Endpoint_Read_Byte();
                                        if (USB_DeviceState == DEVICE_STATE_Unattached)
                                          return;
                                }
 
                                /* First byte of the data stage is the DNLOAD request's command */
                                SentCommand.Command = Endpoint_Read_Byte();
-                                       
+
                                /* One byte of the data stage is the command, so subtract it from the total data bytes */
                                SentCommand.DataSize--;
                                /* One byte of the data stage is the command, so subtract it from the total data bytes */
                                SentCommand.DataSize--;
-                               
+
                                /* Load in the rest of the data stage as command parameters */
                                for (uint8_t DataByte = 0; (DataByte < sizeof(SentCommand.Data)) &&
                                     Endpoint_BytesInEndpoint(); DataByte++)
                                /* Load in the rest of the data stage as command parameters */
                                for (uint8_t DataByte = 0; (DataByte < sizeof(SentCommand.Data)) &&
                                     Endpoint_BytesInEndpoint(); DataByte++)
@@ -191,14 +215,14 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
                                        SentCommand.Data[DataByte] = Endpoint_Read_Byte();
                                        SentCommand.DataSize--;
                                }
                                        SentCommand.Data[DataByte] = Endpoint_Read_Byte();
                                        SentCommand.DataSize--;
                                }
-                               
+
                                /* Process the command */
                                ProcessBootloaderCommand();
                        }
                                /* Process the command */
                                ProcessBootloaderCommand();
                        }
-                       
+
                        /* Check if currently downloading firmware */
                        if (DFU_State == dfuDNLOAD_IDLE)
                        /* Check if currently downloading firmware */
                        if (DFU_State == dfuDNLOAD_IDLE)
-                       {                                                                       
+                       {
                                if (!(SentCommand.DataSize))
                                {
                                        DFU_State = dfuIDLE;
                                if (!(SentCommand.DataSize))
                                {
                                        DFU_State = dfuIDLE;
@@ -210,21 +234,21 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
 
                                        /* Throw away the packet alignment filler bytes before the start of the firmware */
                                        DiscardFillerBytes(StartAddr % FIXED_CONTROL_ENDPOINT_SIZE);
 
                                        /* Throw away the packet alignment filler bytes before the start of the firmware */
                                        DiscardFillerBytes(StartAddr % FIXED_CONTROL_ENDPOINT_SIZE);
-                                       
+
                                        /* Calculate the number of bytes remaining to be written */
                                        uint16_t BytesRemaining = ((EndAddr - StartAddr) + 1);
                                        /* Calculate the number of bytes remaining to be written */
                                        uint16_t BytesRemaining = ((EndAddr - StartAddr) + 1);
-                                       
+
                                        if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00))        // Write flash
                                        {
                                                /* Calculate the number of words to be written from the number of bytes to be written */
                                                uint16_t WordsRemaining = (BytesRemaining >> 1);
                                        if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00))        // Write flash
                                        {
                                                /* Calculate the number of words to be written from the number of bytes to be written */
                                                uint16_t WordsRemaining = (BytesRemaining >> 1);
-                                       
+
                                                union
                                                {
                                                        uint16_t Words[2];
                                                        uint32_t Long;
                                                } CurrFlashAddress                 = {.Words = {StartAddr, Flash64KBPage}};
                                                union
                                                {
                                                        uint16_t Words[2];
                                                        uint32_t Long;
                                                } CurrFlashAddress                 = {.Words = {StartAddr, Flash64KBPage}};
-                                               
+
                                                uint32_t CurrFlashPageStartAddress = CurrFlashAddress.Long;
                                                uint8_t  WordsInFlashPage          = 0;
 
                                                uint32_t CurrFlashPageStartAddress = CurrFlashAddress.Long;
                                                uint8_t  WordsInFlashPage          = 0;
 
@@ -236,7 +260,7 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
                                                                Endpoint_ClearOUT();
 
                                                                while (!(Endpoint_IsOUTReceived()))
                                                                Endpoint_ClearOUT();
 
                                                                while (!(Endpoint_IsOUTReceived()))
-                                                               {                               
+                                                               {
                                                                        if (USB_DeviceState == DEVICE_STATE_Unattached)
                                                                          return;
                                                                }
                                                                        if (USB_DeviceState == DEVICE_STATE_Unattached)
                                                                          return;
                                                                }
@@ -255,7 +279,7 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
                                                                /* Commit the flash page to memory */
                                                                boot_page_write(CurrFlashPageStartAddress);
                                                                boot_spm_busy_wait();
                                                                /* Commit the flash page to memory */
                                                                boot_page_write(CurrFlashPageStartAddress);
                                                                boot_spm_busy_wait();
-                                                               
+
                                                                /* Check if programming incomplete */
                                                                if (WordsRemaining)
                                                                {
                                                                /* Check if programming incomplete */
                                                                if (WordsRemaining)
                                                                {
@@ -268,10 +292,10 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
                                                                }
                                                        }
                                                }
                                                                }
                                                        }
                                                }
-                                       
+
                                                /* Once programming complete, start address equals the end address */
                                                StartAddr = EndAddr;
                                                /* Once programming complete, start address equals the end address */
                                                StartAddr = EndAddr;
-                                       
+
                                                /* Re-enable the RWW section of flash */
                                                boot_rww_enable();
                                        }
                                                /* Re-enable the RWW section of flash */
                                                boot_rww_enable();
                                        }
@@ -285,7 +309,7 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
                                                                Endpoint_ClearOUT();
 
                                                                while (!(Endpoint_IsOUTReceived()))
                                                                Endpoint_ClearOUT();
 
                                                                while (!(Endpoint_IsOUTReceived()))
-                                                               {                               
+                                                               {
                                                                        if (USB_DeviceState == DEVICE_STATE_Unattached)
                                                                          return;
                                                                }
                                                                        if (USB_DeviceState == DEVICE_STATE_Unattached)
                                                                          return;
                                                                }
@@ -293,12 +317,12 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
 
                                                        /* Read the byte from the USB interface and write to to the EEPROM */
                                                        eeprom_write_byte((uint8_t*)StartAddr, Endpoint_Read_Byte());
 
                                                        /* Read the byte from the USB interface and write to to the EEPROM */
                                                        eeprom_write_byte((uint8_t*)StartAddr, Endpoint_Read_Byte());
-                                                       
+
                                                        /* Adjust counters */
                                                        StartAddr++;
                                                }
                                        }
                                                        /* Adjust counters */
                                                        StartAddr++;
                                                }
                                        }
-                                       
+
                                        /* Throw away the currently unused DFU file suffix */
                                        DiscardFillerBytes(DFU_FILE_SUFFIX_SIZE);
                                }
                                        /* Throw away the currently unused DFU file suffix */
                                        DiscardFillerBytes(DFU_FILE_SUFFIX_SIZE);
                                }
@@ -309,15 +333,15 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
                        Endpoint_ClearStatusStage();
 
                        break;
                        Endpoint_ClearStatusStage();
 
                        break;
-               case DFU_UPLOAD:
+               case REQ_DFU_UPLOAD:
                        Endpoint_ClearSETUP();
 
                        while (!(Endpoint_IsINReady()))
                        Endpoint_ClearSETUP();
 
                        while (!(Endpoint_IsINReady()))
-                       {                               
+                       {
                                if (USB_DeviceState == DEVICE_STATE_Unattached)
                                  return;
                        }
                                if (USB_DeviceState == DEVICE_STATE_Unattached)
                                  return;
                        }
-                                                       
+
                        if (DFU_State != dfuUPLOAD_IDLE)
                        {
                                if ((DFU_State == dfuERROR) && IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01))       // Blank Check
                        if (DFU_State != dfuUPLOAD_IDLE)
                        {
                                if ((DFU_State == dfuERROR) && IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01))       // Blank Check
@@ -356,7 +380,7 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
                                                        Endpoint_ClearIN();
 
                                                        while (!(Endpoint_IsINReady()))
                                                        Endpoint_ClearIN();
 
                                                        while (!(Endpoint_IsINReady()))
-                                                       {                               
+                                                       {
                                                                if (USB_DeviceState == DEVICE_STATE_Unattached)
                                                                  return;
                                                        }
                                                                if (USB_DeviceState == DEVICE_STATE_Unattached)
                                                                  return;
                                                        }
@@ -366,13 +390,13 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
                                                #if (FLASHEND > 0xFFFF)
                                                        Endpoint_Write_Word_LE(pgm_read_word_far(CurrFlashAddress.Long));
                                                #else
                                                #if (FLASHEND > 0xFFFF)
                                                        Endpoint_Write_Word_LE(pgm_read_word_far(CurrFlashAddress.Long));
                                                #else
-                                                       Endpoint_Write_Word_LE(pgm_read_word(CurrFlashAddress.Long));                                                   
+                                                       Endpoint_Write_Word_LE(pgm_read_word(CurrFlashAddress.Long));
                                                #endif
 
                                                /* Adjust counters */
                                                CurrFlashAddress.Long += 2;
                                        }
                                                #endif
 
                                                /* Adjust counters */
                                                CurrFlashAddress.Long += 2;
                                        }
-                                       
+
                                        /* Once reading is complete, start address equals the end address */
                                        StartAddr = EndAddr;
                                }
                                        /* Once reading is complete, start address equals the end address */
                                        StartAddr = EndAddr;
                                }
@@ -384,9 +408,9 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
                                                if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE)
                                                {
                                                        Endpoint_ClearIN();
                                                if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE)
                                                {
                                                        Endpoint_ClearIN();
-                                                       
+
                                                        while (!(Endpoint_IsINReady()))
                                                        while (!(Endpoint_IsINReady()))
-                                                       {                               
+                                                       {
                                                                if (USB_DeviceState == DEVICE_STATE_Unattached)
                                                                  return;
                                                        }
                                                                if (USB_DeviceState == DEVICE_STATE_Unattached)
                                                                  return;
                                                        }
@@ -408,16 +432,16 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
 
                        Endpoint_ClearStatusStage();
                        break;
 
                        Endpoint_ClearStatusStage();
                        break;
-               case DFU_GETSTATUS:
+               case REQ_DFU_GETSTATUS:
                        Endpoint_ClearSETUP();
                        Endpoint_ClearSETUP();
-                       
+
                        /* Write 8-bit status value */
                        Endpoint_Write_Byte(DFU_Status);
                        /* Write 8-bit status value */
                        Endpoint_Write_Byte(DFU_Status);
-                       
+
                        /* Write 24-bit poll timeout value */
                        Endpoint_Write_Byte(0);
                        Endpoint_Write_Word_LE(0);
                        /* Write 24-bit poll timeout value */
                        Endpoint_Write_Byte(0);
                        Endpoint_Write_Word_LE(0);
-                       
+
                        /* Write 8-bit state value */
                        Endpoint_Write_Byte(DFU_State);
 
                        /* Write 8-bit state value */
                        Endpoint_Write_Byte(DFU_State);
 
@@ -425,30 +449,30 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
                        Endpoint_Write_Byte(0);
 
                        Endpoint_ClearIN();
                        Endpoint_Write_Byte(0);
 
                        Endpoint_ClearIN();
-                       
+
                        Endpoint_ClearStatusStage();
                        Endpoint_ClearStatusStage();
-                       break;          
-               case DFU_CLRSTATUS:
+                       break;
+               case REQ_DFU_CLRSTATUS:
                        Endpoint_ClearSETUP();
                        Endpoint_ClearSETUP();
-                       
+
                        /* Reset the status value variable to the default OK status */
                        DFU_Status = OK;
 
                        Endpoint_ClearStatusStage();
                        break;
                        /* Reset the status value variable to the default OK status */
                        DFU_Status = OK;
 
                        Endpoint_ClearStatusStage();
                        break;
-               case DFU_GETSTATE:
+               case REQ_DFU_GETSTATE:
                        Endpoint_ClearSETUP();
                        Endpoint_ClearSETUP();
-                       
+
                        /* Write the current device state to the endpoint */
                        Endpoint_Write_Byte(DFU_State);
                        /* Write the current device state to the endpoint */
                        Endpoint_Write_Byte(DFU_State);
-               
+
                        Endpoint_ClearIN();
                        Endpoint_ClearIN();
-                       
+
                        Endpoint_ClearStatusStage();
                        break;
                        Endpoint_ClearStatusStage();
                        break;
-               case DFU_ABORT:
+               case REQ_DFU_ABORT:
                        Endpoint_ClearSETUP();
                        Endpoint_ClearSETUP();
-                       
+
                        /* Reset the current state variable to the default idle state */
                        DFU_State = dfuIDLE;
 
                        /* Reset the current state variable to the default idle state */
                        DFU_State = dfuIDLE;
 
@@ -472,7 +496,7 @@ static void DiscardFillerBytes(uint8_t NumberOfBytes)
 
                        /* Wait until next data packet received */
                        while (!(Endpoint_IsOUTReceived()))
 
                        /* Wait until next data packet received */
                        while (!(Endpoint_IsOUTReceived()))
-                       {                               
+                       {
                                if (USB_DeviceState == DEVICE_STATE_Unattached)
                                  return;
                        }
                                if (USB_DeviceState == DEVICE_STATE_Unattached)
                                  return;
                        }
@@ -501,10 +525,10 @@ static void ProcessBootloaderCommand(void)
                        /* Set the state and status variables to indicate the error */
                        DFU_State  = dfuERROR;
                        DFU_Status = errWRITE;
                        /* Set the state and status variables to indicate the error */
                        DFU_State  = dfuERROR;
                        DFU_Status = errWRITE;
-                       
+
                        /* Stall command */
                        Endpoint_StallTransaction();
                        /* Stall command */
                        Endpoint_StallTransaction();
-                       
+
                        /* Don't process the command */
                        return;
                }
                        /* Don't process the command */
                        return;
                }
@@ -544,7 +568,7 @@ static void LoadStartEndAddresses(void)
                uint16_t Word;
        } Address[2] = {{.Bytes = {SentCommand.Data[2], SentCommand.Data[1]}},
                        {.Bytes = {SentCommand.Data[4], SentCommand.Data[3]}}};
                uint16_t Word;
        } Address[2] = {{.Bytes = {SentCommand.Data[2], SentCommand.Data[1]}},
                        {.Bytes = {SentCommand.Data[4], SentCommand.Data[3]}}};
-               
+
        /* Load in the start and ending read addresses from the sent data packet */
        StartAddr = Address[0].Word;
        EndAddr   = Address[1].Word;
        /* Load in the start and ending read addresses from the sent data packet */
        StartAddr = Address[0].Word;
        EndAddr   = Address[1].Word;
@@ -560,7 +584,7 @@ static void ProcessMemProgCommand(void)
        {
                /* Load in the start and ending read addresses */
                LoadStartEndAddresses();
        {
                /* Load in the start and ending read addresses */
                LoadStartEndAddresses();
-               
+
                /* If FLASH is being written to, we need to pre-erase the first page to write to */
                if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00))
                {
                /* If FLASH is being written to, we need to pre-erase the first page to write to */
                if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00))
                {
@@ -569,12 +593,12 @@ static void ProcessMemProgCommand(void)
                                uint16_t Words[2];
                                uint32_t Long;
                        } CurrFlashAddress = {.Words = {StartAddr, Flash64KBPage}};
                                uint16_t Words[2];
                                uint32_t Long;
                        } CurrFlashAddress = {.Words = {StartAddr, Flash64KBPage}};
-                       
+
                        /* Erase the current page's temp buffer */
                        boot_page_erase(CurrFlashAddress.Long);
                        boot_spm_busy_wait();
                }
                        /* Erase the current page's temp buffer */
                        boot_page_erase(CurrFlashAddress.Long);
                        boot_spm_busy_wait();
                }
-               
+
                /* Set the state so that the next DNLOAD requests reads in the firmware */
                DFU_State = dfuDNLOAD_IDLE;
        }
                /* Set the state so that the next DNLOAD requests reads in the firmware */
                DFU_State = dfuDNLOAD_IDLE;
        }
@@ -611,7 +635,7 @@ static void ProcessMemReadCommand(void)
                                /* Save the location of the first non-blank byte for response back to the host */
                                Flash64KBPage = (CurrFlashAddress >> 16);
                                StartAddr     = CurrFlashAddress;
                                /* Save the location of the first non-blank byte for response back to the host */
                                Flash64KBPage = (CurrFlashAddress >> 16);
                                StartAddr     = CurrFlashAddress;
-                       
+
                                /* Set state and status variables to the appropriate error values */
                                DFU_State  = dfuERROR;
                                DFU_Status = errCHECK_ERASED;
                                /* Set state and status variables to the appropriate error values */
                                DFU_State  = dfuERROR;
                                DFU_Status = errCHECK_ERASED;
@@ -634,26 +658,30 @@ static void ProcessWriteCommand(void)
                /* Indicate that the bootloader is terminating */
                WaitForExit = true;
 
                /* Indicate that the bootloader is terminating */
                WaitForExit = true;
 
-               /* Check if empty request data array - an empty request after a filled request retains the
-                  previous valid request data, but initialises the reset */
-               if (!(SentCommand.DataSize))
+               /* Check if data supplied for the Start Program command - no data executes the program */
+               if (SentCommand.DataSize)
                {
                {
-                       if (SentCommand.Data[1] == 0x00)                                   // Start via watchdog
+                       if (SentCommand.Data[1] == 0x01)                                   // Start via jump
                        {
                        {
-                               /* Start the watchdog to reset the AVR once the communications are finalized */
-                               wdt_enable(WDTO_250MS);
-                       }
-                       else                                                               // Start via jump
-                       {
-                               /* Load in the jump address into the application start address pointer */
                                union
                                {
                                        uint8_t  Bytes[2];
                                        AppPtr_t FuncPtr;
                                } Address = {.Bytes = {SentCommand.Data[4], SentCommand.Data[3]}};
 
                                union
                                {
                                        uint8_t  Bytes[2];
                                        AppPtr_t FuncPtr;
                                } Address = {.Bytes = {SentCommand.Data[4], SentCommand.Data[3]}};
 
+                               /* Load in the jump address into the application start address pointer */
                                AppStartPtr = Address.FuncPtr;
                                AppStartPtr = Address.FuncPtr;
-                               
+                       }
+               }
+               else
+               {
+                       if (SentCommand.Data[1] == 0x00)                                   // Start via watchdog
+                       {
+                               /* Start the watchdog to reset the AVR once the communications are finalized */
+                               wdt_enable(WDTO_250MS);
+                       }
+                       else                                                               // Start via jump
+                       {
                                /* Set the flag to terminate the bootloader at next opportunity */
                                RunBootloader = false;
                        }
                                /* Set the flag to terminate the bootloader at next opportunity */
                                RunBootloader = false;
                        }
@@ -676,7 +704,7 @@ static void ProcessWriteCommand(void)
 
                /* Re-enable the RWW section of flash as writing to the flash locks it out */
                boot_rww_enable();
 
                /* Re-enable the RWW section of flash as writing to the flash locks it out */
                boot_rww_enable();
-                                       
+
                /* Memory has been erased, reset the security bit so that programming/reading is allowed */
                IsSecure = false;
        }
                /* Memory has been erased, reset the security bit so that programming/reading is allowed */
                IsSecure = false;
        }
@@ -697,3 +725,4 @@ static void ProcessReadCommand(void)
        else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01))                    // Read signature byte
          ResponseByte = SignatureInfo[DataIndexToRead - 0x30];
 }
        else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01))                    // Read signature byte
          ResponseByte = SignatureInfo[DataIndexToRead - 0x30];
 }
+