X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/ceb68a06408ca31d41cfb57eb3cd20268c1aed15..2a0c28e6e47c8a173f32fc99cd8666a2633c5c12:/Bootloaders/DFU/BootloaderDFU.c diff --git a/Bootloaders/DFU/BootloaderDFU.c b/Bootloaders/DFU/BootloaderDFU.c index 6bea9b25f..f9c8195f3 100644 --- a/Bootloaders/DFU/BootloaderDFU.c +++ b/Bootloaders/DFU/BootloaderDFU.c @@ -96,7 +96,24 @@ uint16_t EndAddr = 0x0000; * 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,35 +128,23 @@ 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. */ -EVENT_HANDLER(USB_Disconnect) +void EVENT_USB_Disconnect(void) { /* Upon disconnection, run user application */ RunBootloader = false; @@ -149,21 +154,15 @@ EVENT_HANDLER(USB_Disconnect) * 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(USB_UnhandledControlPacket) +void EVENT_USB_UnhandledControlPacket(void) { - /* Discard unused wIndex value */ - Endpoint_Discard_Word(); - - /* Discard unused wValue value */ - Endpoint_Discard_Word(); - /* Get the size of the command and data from the wLength value */ - SentCommand.DataSize = Endpoint_Read_Word_LE(); + SentCommand.DataSize = USB_ControlRequest.wLength; - switch (bRequest) + switch (USB_ControlRequest.bRequest) { case DFU_DNLOAD: - Endpoint_ClearSetupReceived(); + Endpoint_ClearSETUP(); /* Check if bootloader is waiting to terminate */ if (WaitForExit) @@ -178,7 +177,11 @@ EVENT_HANDLER(USB_UnhandledControlPacket) /* If the request has a data stage, load it into the command struct */ if (SentCommand.DataSize) { - while (!(Endpoint_IsSetupOUTReceived())); + 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(); @@ -225,7 +228,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket) { uint16_t Words[2]; uint32_t Long; - } CurrFlashAddress = {Words: {StartAddr, Flash64KBPage}}; + } CurrFlashAddress = {.Words = {StartAddr, Flash64KBPage}}; uint32_t CurrFlashPageStartAddress = CurrFlashAddress.Long; uint8_t WordsInFlashPage = 0; @@ -235,8 +238,13 @@ EVENT_HANDLER(USB_UnhandledControlPacket) /* Check if endpoint is empty - if so clear it and wait until ready for next packet */ if (!(Endpoint_BytesInEndpoint())) { - Endpoint_ClearSetupOUT(); - while (!(Endpoint_IsSetupOUTReceived())); + Endpoint_ClearOUT(); + + while (!(Endpoint_IsOUTReceived())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } } /* Write the next word into the current flash page */ @@ -279,8 +287,13 @@ EVENT_HANDLER(USB_UnhandledControlPacket) /* Check if endpoint is empty - if so clear it and wait until ready for next packet */ if (!(Endpoint_BytesInEndpoint())) { - Endpoint_ClearSetupOUT(); - while (!(Endpoint_IsSetupOUTReceived())); + Endpoint_ClearOUT(); + + while (!(Endpoint_IsOUTReceived())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } } /* Read the byte from the USB interface and write to to the EEPROM */ @@ -296,18 +309,20 @@ EVENT_HANDLER(USB_UnhandledControlPacket) } } - Endpoint_ClearSetupOUT(); + Endpoint_ClearOUT(); + + Endpoint_ClearStatusStage(); - /* Acknowledge status stage */ - while (!(Endpoint_IsSetupINReady())); - Endpoint_ClearSetupIN(); - break; case DFU_UPLOAD: - Endpoint_ClearSetupReceived(); - - while (!(Endpoint_IsSetupINReady())); + Endpoint_ClearSETUP(); + 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 @@ -336,19 +351,24 @@ EVENT_HANDLER(USB_UnhandledControlPacket) { uint16_t Words[2]; uint32_t Long; - } CurrFlashAddress = {Words: {StartAddr, Flash64KBPage}}; + } CurrFlashAddress = {.Words = {StartAddr, Flash64KBPage}}; while (WordsRemaining--) { /* Check if endpoint is full - if so clear it and wait until ready for next packet */ if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE) { - Endpoint_ClearSetupIN(); - while (!(Endpoint_IsSetupINReady())); + Endpoint_ClearIN(); + + 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)); @@ -368,8 +388,13 @@ EVENT_HANDLER(USB_UnhandledControlPacket) /* Check if endpoint is full - if so clear it and wait until ready for next packet */ if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE) { - Endpoint_ClearSetupIN(); - while (!(Endpoint_IsSetupINReady())); + Endpoint_ClearIN(); + + while (!(Endpoint_IsINReady())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } } /* Read the EEPROM byte and send it via USB to the host */ @@ -384,15 +409,12 @@ EVENT_HANDLER(USB_UnhandledControlPacket) DFU_State = dfuIDLE; } - Endpoint_ClearSetupIN(); - - /* Acknowledge status stage */ - while (!(Endpoint_IsSetupOUTReceived())); - Endpoint_ClearSetupOUT(); + Endpoint_ClearIN(); + Endpoint_ClearStatusStage(); break; case DFU_GETSTATUS: - Endpoint_ClearSetupReceived(); + Endpoint_ClearSETUP(); /* Write 8-bit status value */ Endpoint_Write_Byte(DFU_Status); @@ -407,47 +429,35 @@ EVENT_HANDLER(USB_UnhandledControlPacket) /* Write 8-bit state string ID number */ Endpoint_Write_Byte(0); - Endpoint_ClearSetupIN(); + Endpoint_ClearIN(); - /* Acknowledge status stage */ - while (!(Endpoint_IsSetupOUTReceived())); - Endpoint_ClearSetupOUT(); - + Endpoint_ClearStatusStage(); break; case DFU_CLRSTATUS: - Endpoint_ClearSetupReceived(); + Endpoint_ClearSETUP(); /* Reset the status value variable to the default OK status */ DFU_Status = OK; - /* Acknowledge status stage */ - while (!(Endpoint_IsSetupINReady())); - Endpoint_ClearSetupIN(); - + Endpoint_ClearStatusStage(); break; case DFU_GETSTATE: - Endpoint_ClearSetupReceived(); + Endpoint_ClearSETUP(); /* Write the current device state to the endpoint */ Endpoint_Write_Byte(DFU_State); - Endpoint_ClearSetupIN(); + Endpoint_ClearIN(); - /* Acknowledge status stage */ - while (!(Endpoint_IsSetupOUTReceived())); - Endpoint_ClearSetupOUT(); - + Endpoint_ClearStatusStage(); break; case DFU_ABORT: - Endpoint_ClearSetupReceived(); + Endpoint_ClearSETUP(); /* Reset the current state variable to the default idle state */ DFU_State = dfuIDLE; - - /* Acknowledge status stage */ - while (!(Endpoint_IsSetupINReady())); - Endpoint_ClearSetupIN(); + Endpoint_ClearStatusStage(); break; } } @@ -455,7 +465,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket) /** 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) { @@ -463,13 +473,19 @@ static void DiscardFillerBytes(uint8_t NumberOfBytes) { if (!(Endpoint_BytesInEndpoint())) { - Endpoint_ClearSetupOUT(); + Endpoint_ClearOUT(); /* Wait until next data packet received */ - while (!(Endpoint_IsSetupOUTReceived())); + while (!(Endpoint_IsOUTReceived())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } + } + else + { + Endpoint_Discard_Byte(); } - - Endpoint_Discard_Byte(); } } @@ -531,15 +547,15 @@ static void LoadStartEndAddresses(void) { uint8_t Bytes[2]; uint16_t Word; - } Address[2] = {{Bytes: {SentCommand.Data[2], SentCommand.Data[1]}}, - {Bytes: {SentCommand.Data[4], SentCommand.Data[3]}}}; + } 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; } -/** Handler for a Memory Program command issued by the host. This routine handles the preperations needed +/** Handler for a Memory Program command issued by the host. This routine handles the preparations needed * to write subsequent data from the host into the specified memory. */ static void ProcessMemProgCommand(void) @@ -557,7 +573,7 @@ static void ProcessMemProgCommand(void) { uint16_t Words[2]; uint32_t Long; - } CurrFlashAddress = {Words: {StartAddr, Flash64KBPage}}; + } CurrFlashAddress = {.Words = {StartAddr, Flash64KBPage}}; /* Erase the current page's temp buffer */ boot_page_erase(CurrFlashAddress.Long); @@ -569,7 +585,7 @@ static void ProcessMemProgCommand(void) } } -/** Handler for a Memory Read command issued by the host. This routine handles the preperations needed +/** Handler for a Memory Read command issued by the host. This routine handles the preparations needed * to read subsequent data from the specified memory out to the host, as well as implementing the memory * blank check command. */ @@ -591,7 +607,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) @@ -639,7 +655,7 @@ static void ProcessWriteCommand(void) { uint8_t Bytes[2]; AppPtr_t FuncPtr; - } Address = {Bytes: {SentCommand.Data[4], SentCommand.Data[3]}}; + } Address = {.Bytes = {SentCommand.Data[4], SentCommand.Data[3]}}; AppStartPtr = Address.FuncPtr; @@ -677,7 +693,7 @@ 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];