X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/e5e7eaee7af719cee00a8c2cb6fb4649dde0aa05..d26a9ed5fd6fc60a0dfa61d04f5ae2bd7163a85d:/Bootloaders/CDC/BootloaderCDC.c?ds=sidebyside diff --git a/Bootloaders/CDC/BootloaderCDC.c b/Bootloaders/CDC/BootloaderCDC.c index 6b69421e0..482859bda 100644 --- a/Bootloaders/CDC/BootloaderCDC.c +++ b/Bootloaders/CDC/BootloaderCDC.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 @@ -36,7 +36,6 @@ #define INCLUDE_FROM_BOOTLOADERCDC_C #include "BootloaderCDC.h" -/* Globals: */ /** Line coding options for the virtual serial port. Although the virtual serial port data is never * sent through a physical serial port, the line encoding data must still be read and preserved from * the host, or the host will detect a problem and fail to open the port. This structure contains the @@ -67,6 +66,26 @@ bool RunBootloader = true; */ int main(void) { + /* Setup hardware required for the bootloader */ + SetupHardware(); + + while (RunBootloader) + { + CDC_Task(); + USB_USBTask(); + } + + /* Reset all configured hardware to their default states for the user app */ + ResetHardware(); + + /* Start the user application */ + AppPtr_t AppStartPtr = (AppPtr_t)0x0000; + AppStartPtr(); +} + +/** Configures all hardware required for the bootloader. */ +void SetupHardware(void) +{ /* Disable watchdog if enabled by bootloader/fuses */ MCUSR &= ~(1 << WDRF); wdt_disable(); @@ -80,18 +99,11 @@ int main(void) /* Initialize USB Subsystem */ USB_Init(); +} - while (RunBootloader) - { - USB_USBTask(); - CDC_Task(); - } - - Endpoint_SelectEndpoint(CDC_TX_EPNUM); - - /* Wait until any pending transmissions have completed before shutting down */ - while (!(Endpoint_IsINReady())); - +/** Resets all configured hardware required for the bootloader back to their original states. */ +void ResetHardware(void) +{ /* Shut down the USB subsystem */ USB_ShutDown(); @@ -99,36 +111,14 @@ int main(void) 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 - /* Re-enable RWW section */ boot_rww_enable(); - - /* Start the user application */ - AppPtr_t AppStartPtr = (AppPtr_t)0x0000; - AppStartPtr(); -} - -/** Event handler for the USB_Disconnect event. This indicates that the bootloader should exit and the user - * application started. - */ -EVENT_HANDLER(USB_Disconnect) -{ - /* Upon disconnection, run user application */ - RunBootloader = false; } /** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready * to relay data to and from the attached USB host. */ -EVENT_HANDLER(USB_ConfigurationChanged) +void EVENT_USB_Device_ConfigurationChanged(void) { /* Setup CDC Notification, Rx and Tx Endpoints */ Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT, @@ -144,21 +134,19 @@ EVENT_HANDLER(USB_ConfigurationChanged) ENDPOINT_BANK_SINGLE); } -/** 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, so that they can be handled appropriately * for the application. */ -EVENT_HANDLER(USB_UnhandledControlPacket) +void EVENT_USB_Device_UnhandledControlRequest(void) { uint8_t* LineCodingData = (uint8_t*)&LineCoding; - Endpoint_Discard_Word(); - /* Process CDC specific control requests */ - switch (bRequest) + switch (USB_ControlRequest.bRequest) { case REQ_GetLineEncoding: - if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) + if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) { Endpoint_ClearSETUP(); @@ -167,38 +155,36 @@ EVENT_HANDLER(USB_UnhandledControlPacket) Endpoint_ClearIN(); - /* Acknowledge status stage */ - while (!(Endpoint_IsOUTReceived())); - Endpoint_ClearOUT(); + Endpoint_ClearStatusStage(); } break; case REQ_SetLineEncoding: - if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) + if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { Endpoint_ClearSETUP(); - while (!(Endpoint_IsOUTReceived())); - + while (!(Endpoint_IsOUTReceived())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } + for (uint8_t i = 0; i < sizeof(LineCoding); i++) *(LineCodingData++) = Endpoint_Read_Byte(); Endpoint_ClearOUT(); - /* Acknowledge status stage */ - while (!(Endpoint_IsINReady())); - Endpoint_ClearIN(); + Endpoint_ClearStatusStage(); } break; case REQ_SetControlLineState: - if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) + if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { Endpoint_ClearSETUP(); - /* Acknowledge status stage */ - while (!(Endpoint_IsINReady())); - Endpoint_ClearIN(); + Endpoint_ClearStatusStage(); } break; @@ -208,7 +194,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket) /** Reads or writes a block of EEPROM or FLASH memory to or from the appropriate CDC data endpoint, depending * on the AVR910 protocol command issued. * - * \param Command Single character AVR910 protocol command indicating what memory operation to perform + * \param[in] Command Single character AVR910 protocol command indicating what memory operation to perform */ static void ReadWriteMemoryBlock(const uint8_t Command) { @@ -239,18 +225,10 @@ static void ReadWriteMemoryBlock(const uint8_t Command) while (BlockSize--) { - if (MemoryType == 'E') - { - /* Read the next EEPROM byte into the endpoint */ - WriteNextResponseByte(eeprom_read_byte((uint8_t*)(uint16_t)(CurrAddress >> 1))); - - /* Increment the address counter after use */ - CurrAddress += 2; - } - else + if (MemoryType == 'F') { /* Read the next FLASH byte from the current FLASH page */ - #if defined(RAMPZ) + #if (FLASHEND > 0xFFFF) WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte)); #else WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte)); @@ -262,6 +240,14 @@ static void ReadWriteMemoryBlock(const uint8_t Command) HighByte = !HighByte; } + else + { + /* Read the next EEPROM byte into the endpoint */ + WriteNextResponseByte(eeprom_read_byte((uint8_t*)(uint16_t)(CurrAddress >> 1))); + + /* Increment the address counter after use */ + CurrAddress += 2; + } } } else @@ -335,7 +321,12 @@ static uint8_t FetchNextCommandByte(void) while (!(Endpoint_IsReadWriteAllowed())) { Endpoint_ClearOUT(); - while (!(Endpoint_IsOUTReceived())); + + while (!(Endpoint_IsOUTReceived())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return 0; + } } /* Fetch the next byte from the OUT endpoint */ @@ -345,18 +336,23 @@ static uint8_t FetchNextCommandByte(void) /** Writes the next response byte to the CDC data IN endpoint, and sends the endpoint back if needed to free up the * bank when full ready for the next byte in the packet to the host. * - * \param Response Next response byte to send to the host + * \param[in] Response Next response byte to send to the host */ static void WriteNextResponseByte(const uint8_t Response) { /* Select the IN endpoint so that the next data byte can be written */ Endpoint_SelectEndpoint(CDC_TX_EPNUM); - /* If OUT endpoint empty, clear it and wait for the next packet from the host */ + /* If IN endpoint full, clear it and wait until ready for the next packet to the host */ if (!(Endpoint_IsReadWriteAllowed())) { Endpoint_ClearIN(); - while (!(Endpoint_IsINReady())); + + while (!(Endpoint_IsINReady())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } } /* Write the next byte to the OUT endpoint */ @@ -366,7 +362,7 @@ static void WriteNextResponseByte(const uint8_t Response) /** Task to read in AVR910 commands from the CDC data OUT endpoint, process them, perform the required actions * and send the appropriate response back to the host. */ -TASK(CDC_Task) +void CDC_Task(void) { /* Select the OUT endpoint */ Endpoint_SelectEndpoint(CDC_RX_EPNUM); @@ -426,9 +422,9 @@ TASK(CDC_Task) } else if (Command == 's') { - WriteNextResponseByte(SIGNATURE_0); - WriteNextResponseByte(SIGNATURE_1); - WriteNextResponseByte(SIGNATURE_2); + WriteNextResponseByte(AVR_SIGNATURE_3); + WriteNextResponseByte(AVR_SIGNATURE_2); + WriteNextResponseByte(AVR_SIGNATURE_1); } else if (Command == 'b') { @@ -515,7 +511,7 @@ TASK(CDC_Task) } else if (Command == 'R') { - #if defined(RAMPZ) + #if (FLASHEND > 0xFFFF) uint16_t ProgramWord = pgm_read_word_far(CurrAddress); #else uint16_t ProgramWord = pgm_read_word(CurrAddress); @@ -527,7 +523,7 @@ TASK(CDC_Task) else if (Command == 'D') { /* Read the byte from the endpoint and write it to the EEPROM */ - eeprom_write_byte((uint8_t*)(uint16_t)(CurrAddress >> 1), FetchNextCommandByte()); + eeprom_write_byte((uint8_t*)((uint16_t)(CurrAddress >> 1)), FetchNextCommandByte()); /* Increment the address after use */ CurrAddress += 2; @@ -538,7 +534,7 @@ TASK(CDC_Task) else if (Command == 'd') { /* Read the EEPROM byte and write it to the endpoint */ - WriteNextResponseByte(eeprom_read_byte((uint8_t*)(uint16_t)(CurrAddress >> 1))); + WriteNextResponseByte(eeprom_read_byte((uint8_t*)((uint16_t)(CurrAddress >> 1)))); /* Increment the address after use */ CurrAddress += 2; @@ -565,9 +561,21 @@ TASK(CDC_Task) /* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal end of transfer */ if (IsEndpointFull) { - while (!(Endpoint_IsINReady())); + while (!(Endpoint_IsINReady())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } + Endpoint_ClearIN(); } + + /* Wait until the data has been sent to the host */ + while (!(Endpoint_IsINReady())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } /* Select the OUT endpoint */ Endpoint_SelectEndpoint(CDC_RX_EPNUM);