X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/2ee9fc707784e115d744dbc229bdc893f4bb6bc1..d26a9ed5fd6fc60a0dfa61d04f5ae2bd7163a85d:/Bootloaders/DFU/BootloaderDFU.c diff --git a/Bootloaders/DFU/BootloaderDFU.c b/Bootloaders/DFU/BootloaderDFU.c index 10a30167b..157b78ffb 100644 --- a/Bootloaders/DFU/BootloaderDFU.c +++ b/Bootloaders/DFU/BootloaderDFU.c @@ -1,21 +1,21 @@ /* LUFA Library - Copyright (C) Dean Camera, 2009. + Copyright (C) Dean Camera, 2010. dean [at] fourwalledcubicle [dot] com www.fourwalledcubicle.com */ /* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in 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 + Copyright 2010 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 + without fee, provided that the above copyright notice appear in + 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 software without specific, written prior permission. The author disclaim all warranties with regard to this @@ -92,11 +92,29 @@ uint16_t StartAddr = 0x0000; */ uint16_t EndAddr = 0x0000; + /** 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. */ -int main (void) +int main(void) +{ + /* Configure hardware required by the bootloader */ + SetupHardware(); + + /* 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(); + + /* Start the user application */ + AppStartPtr(); +} + +/** Configures all hardware required for the bootloader. */ +void SetupHardware(void) { /* Disable watchdog if enabled by bootloader/fuses */ MCUSR &= ~(1 << WDRF); @@ -111,45 +129,24 @@ int main (void) /* Initialize the USB subsystem */ USB_Init(); +} - /* Run the USB management task while the bootloader is supposed to be running */ - while (RunBootloader || WaitForExit) - USB_USBTask(); - +/** Resets all configured hardware required for the bootloader back to their original states. */ +void ResetHardware(void) +{ /* Shut down the USB subsystem */ USB_ShutDown(); /* Relocate the interrupt vector table back to the application section */ MCUCR = (1 << IVCE); MCUCR = 0; - - /* Reset any used hardware ports back to their defaults */ - PORTD = 0; - DDRD = 0; - - #if defined(PORTE) - PORTE = 0; - DDRE = 0; - #endif - - /* Start the user application */ - AppStartPtr(); } -/** Event handler for the USB_Disconnect event. This indicates that the bootloader should exit and the user - * application started. - */ -void EventHandler_USB_Disconnect(void) -{ - /* Upon disconnection, run user application */ - RunBootloader = false; -} - -/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific +/** 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. */ -void EventHandler_USB_UnhandledControlPacket(void) +void EVENT_USB_Device_UnhandledControlRequest(void) { /* Get the size of the command and data from the wLength value */ SentCommand.DataSize = USB_ControlRequest.wLength; @@ -172,7 +169,11 @@ void EventHandler_USB_UnhandledControlPacket(void) /* If the request has a data stage, load it into the command struct */ if (SentCommand.DataSize) { - while (!(Endpoint_IsOUTReceived())); + 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(); @@ -204,8 +205,8 @@ void EventHandler_USB_UnhandledControlPacket(void) /* Throw away the filler bytes before the start of the firmware */ DiscardFillerBytes(DFU_FILLER_BYTES_SIZE); - /* Throw away the page alignment filler bytes before the start of the firmware */ - DiscardFillerBytes(StartAddr % SPM_PAGESIZE); + /* 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); @@ -230,7 +231,12 @@ void EventHandler_USB_UnhandledControlPacket(void) if (!(Endpoint_BytesInEndpoint())) { Endpoint_ClearOUT(); - while (!(Endpoint_IsOUTReceived())); + + while (!(Endpoint_IsOUTReceived())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } } /* Write the next word into the current flash page */ @@ -274,7 +280,12 @@ void EventHandler_USB_UnhandledControlPacket(void) if (!(Endpoint_BytesInEndpoint())) { Endpoint_ClearOUT(); - while (!(Endpoint_IsOUTReceived())); + + while (!(Endpoint_IsOUTReceived())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } } /* Read the byte from the USB interface and write to to the EEPROM */ @@ -292,16 +303,18 @@ void EventHandler_USB_UnhandledControlPacket(void) Endpoint_ClearOUT(); - /* Acknowledge status stage */ - while (!(Endpoint_IsINReady())); - Endpoint_ClearIN(); - + Endpoint_ClearStatusStage(); + break; case DFU_UPLOAD: Endpoint_ClearSETUP(); - while (!(Endpoint_IsINReady())); - + while (!(Endpoint_IsINReady())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } + if (DFU_State != dfuUPLOAD_IDLE) { if ((DFU_State == dfuERROR) && IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Blank Check @@ -338,11 +351,16 @@ void EventHandler_USB_UnhandledControlPacket(void) if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE) { Endpoint_ClearIN(); - while (!(Endpoint_IsINReady())); + + while (!(Endpoint_IsINReady())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } } /* Read the flash word and send it via USB to the host */ - #if defined(RAMPZ) + #if (FLASHEND > 0xFFFF) Endpoint_Write_Word_LE(pgm_read_word_far(CurrFlashAddress.Long)); #else Endpoint_Write_Word_LE(pgm_read_word(CurrFlashAddress.Long)); @@ -363,7 +381,12 @@ void EventHandler_USB_UnhandledControlPacket(void) if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE) { Endpoint_ClearIN(); - while (!(Endpoint_IsINReady())); + + while (!(Endpoint_IsINReady())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } } /* Read the EEPROM byte and send it via USB to the host */ @@ -380,10 +403,7 @@ void EventHandler_USB_UnhandledControlPacket(void) Endpoint_ClearIN(); - /* Acknowledge status stage */ - while (!(Endpoint_IsOUTReceived())); - Endpoint_ClearOUT(); - + Endpoint_ClearStatusStage(); break; case DFU_GETSTATUS: Endpoint_ClearSETUP(); @@ -403,10 +423,7 @@ void EventHandler_USB_UnhandledControlPacket(void) Endpoint_ClearIN(); - /* Acknowledge status stage */ - while (!(Endpoint_IsOUTReceived())); - Endpoint_ClearOUT(); - + Endpoint_ClearStatusStage(); break; case DFU_CLRSTATUS: Endpoint_ClearSETUP(); @@ -414,10 +431,7 @@ void EventHandler_USB_UnhandledControlPacket(void) /* Reset the status value variable to the default OK status */ DFU_Status = OK; - /* Acknowledge status stage */ - while (!(Endpoint_IsINReady())); - Endpoint_ClearIN(); - + Endpoint_ClearStatusStage(); break; case DFU_GETSTATE: Endpoint_ClearSETUP(); @@ -427,21 +441,15 @@ void EventHandler_USB_UnhandledControlPacket(void) Endpoint_ClearIN(); - /* Acknowledge status stage */ - while (!(Endpoint_IsOUTReceived())); - Endpoint_ClearOUT(); - + Endpoint_ClearStatusStage(); break; case DFU_ABORT: Endpoint_ClearSETUP(); /* Reset the current state variable to the default idle state */ DFU_State = dfuIDLE; - - /* Acknowledge status stage */ - while (!(Endpoint_IsINReady())); - Endpoint_ClearIN(); + Endpoint_ClearStatusStage(); break; } } @@ -449,7 +457,7 @@ void EventHandler_USB_UnhandledControlPacket(void) /** Routine to discard the specified number of bytes from the control endpoint stream. This is used to * discard unused bytes in the stream from the host, including the memory program block suffix. * - * \param NumberOfBytes Number of bytes to discard from the host from the control endpoint + * \param[in] NumberOfBytes Number of bytes to discard from the host from the control endpoint */ static void DiscardFillerBytes(uint8_t NumberOfBytes) { @@ -460,10 +468,16 @@ static void DiscardFillerBytes(uint8_t NumberOfBytes) Endpoint_ClearOUT(); /* Wait until next data packet received */ - while (!(Endpoint_IsOUTReceived())); + while (!(Endpoint_IsOUTReceived())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } + } + else + { + Endpoint_Discard_Byte(); } - - Endpoint_Discard_Byte(); } } @@ -585,7 +599,7 @@ static void ProcessMemReadCommand(void) while (CurrFlashAddress < BOOT_START_ADDR) { /* Check if the current byte is not blank */ - #if defined(RAMPZ) + #if (FLASHEND > 0xFFFF) if (pgm_read_byte_far(CurrFlashAddress) != 0xFF) #else if (pgm_read_byte(CurrFlashAddress) != 0xFF) @@ -671,16 +685,12 @@ static void ProcessWriteCommand(void) static void ProcessReadCommand(void) { const uint8_t BootloaderInfo[3] = {BOOTLOADER_VERSION, BOOTLOADER_ID_BYTE1, BOOTLOADER_ID_BYTE2}; - const uint8_t SignatureInfo[3] = {SIGNATURE_0, SIGNATURE_1, SIGNATURE_2}; + const uint8_t SignatureInfo[3] = {AVR_SIGNATURE_1, AVR_SIGNATURE_2, AVR_SIGNATURE_3}; uint8_t DataIndexToRead = SentCommand.Data[1]; if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00)) // Read bootloader info - { - ResponseByte = BootloaderInfo[DataIndexToRead]; - } + ResponseByte = BootloaderInfo[DataIndexToRead]; else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Read signature byte - { - ResponseByte = SignatureInfo[DataIndexToRead - 0x30]; - } + ResponseByte = SignatureInfo[DataIndexToRead - 0x30]; }