X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/54e69dbee146182a60c258076b8d26e8f5ac752a..5517f96e86b9447780a3e27bb455697f9fc65eea:/Bootloaders/CDC/BootloaderCDC.c?ds=inline diff --git a/Bootloaders/CDC/BootloaderCDC.c b/Bootloaders/CDC/BootloaderCDC.c index 0b2eb810b..38f78daf3 100644 --- a/Bootloaders/CDC/BootloaderCDC.c +++ b/Bootloaders/CDC/BootloaderCDC.c @@ -1,7 +1,7 @@ /* LUFA Library Copyright (C) Dean Camera, 2010. - + dean [at] fourwalledcubicle [dot] com www.fourwalledcubicle.com */ @@ -9,13 +9,13 @@ /* 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 - 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 - 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 @@ -32,20 +32,17 @@ * * Main source file for the CDC class bootloader. This file contains the complete bootloader logic. */ - + #define INCLUDE_FROM_BOOTLOADERCDC_C #include "BootloaderCDC.h" -/** 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 - * current encoding options, including baud rate, character format, parity mode and total number of - * bits in each data chunk. +/** Contains the current baud rate and other settings of the first virtual serial port. This must be retained as some + * operating systems will not open the port unless the settings can be set successfully. */ -CDC_Line_Coding_t LineCoding = { .BaudRateBPS = 9600, - .CharFormat = OneStopBit, - .ParityType = Parity_None, - .DataBits = 8 }; +CDC_Line_Coding_t LineEncoding = { .BaudRateBPS = 0, + .CharFormat = OneStopBit, + .ParityType = Parity_None, + .DataBits = 8 }; /** Current address counter. This stores the current address of the FLASH or EEPROM as set by the host, * and is used when reading or writing to the AVRs memory (either FLASH or EEPROM depending on the issued @@ -60,7 +57,7 @@ uint32_t CurrAddress; bool RunBootloader = true; -/** 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. */ @@ -77,7 +74,7 @@ int main(void) CDC_Task(); USB_USBTask(); } - + /* Disconnect from the host - USB interface will be reset later along with the AVR */ USB_Detach(); @@ -96,11 +93,11 @@ void SetupHardware(void) /* Disable clock division */ clock_prescale_set(clock_div_1); - + /* Relocate the interrupt vector table to the bootloader section */ MCUCR = (1 << IVCE); MCUCR = (1 << IVSEL); - + /* Initialize USB Subsystem */ USB_Init(); } @@ -112,26 +109,24 @@ void EVENT_USB_Device_ConfigurationChanged(void) { /* Setup CDC Notification, Rx and Tx Endpoints */ Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT, - ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE, + ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE, ENDPOINT_BANK_SINGLE); Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK, - ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE, + ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE, ENDPOINT_BANK_SINGLE); Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK, - ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE, + ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE, ENDPOINT_BANK_SINGLE); } /** 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. + * control requests that are not handled internally by the USB library (including the CDC control commands, + * which are all issued via the control endpoint), so that they can be handled appropriately for the application. */ void EVENT_USB_Device_UnhandledControlRequest(void) { - uint8_t* LineCodingData = (uint8_t*)&LineCoding; - /* Process CDC specific control requests */ switch (USB_ControlRequest.bRequest) { @@ -140,43 +135,22 @@ void EVENT_USB_Device_UnhandledControlRequest(void) { Endpoint_ClearSETUP(); - for (uint8_t i = 0; i < sizeof(LineCoding); i++) - Endpoint_Write_Byte(*(LineCodingData++)); - - Endpoint_ClearIN(); - - Endpoint_ClearStatusStage(); + /* Write the line coding data to the control endpoint */ + Endpoint_Write_Control_Stream_LE(&LineEncoding, sizeof(CDC_Line_Coding_t)); + Endpoint_ClearOUT(); } - + break; case REQ_SetLineEncoding: if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { Endpoint_ClearSETUP(); - 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(); - - Endpoint_ClearStatusStage(); - } - - break; - case REQ_SetControlLineState: - if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) - { - Endpoint_ClearSETUP(); - - Endpoint_ClearStatusStage(); + /* Read the line coding data in from the host into the global struct */ + Endpoint_Read_Control_Stream_LE(&LineEncoding, sizeof(CDC_Line_Coding_t)); + Endpoint_ClearIN(); } - + break; } } @@ -190,20 +164,20 @@ static void ReadWriteMemoryBlock(const uint8_t Command) { uint16_t BlockSize; char MemoryType; - + bool HighByte = false; uint8_t LowByte = 0; - + BlockSize = (FetchNextCommandByte() << 8); BlockSize |= FetchNextCommandByte(); - + MemoryType = FetchNextCommandByte(); if ((MemoryType != 'E') && (MemoryType != 'F')) { /* Send error byte back to the host */ WriteNextResponseByte('?'); - + return; } @@ -221,13 +195,13 @@ static void ReadWriteMemoryBlock(const uint8_t Command) #if (FLASHEND > 0xFFFF) WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte)); #else - WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte)); + WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte)); #endif - + /* If both bytes in current word have been read, increment the address counter */ if (HighByte) CurrAddress += 2; - + HighByte = !HighByte; } else @@ -237,7 +211,7 @@ static void ReadWriteMemoryBlock(const uint8_t Command) /* Increment the address counter after use */ CurrAddress += 2; - } + } } } else @@ -249,11 +223,11 @@ static void ReadWriteMemoryBlock(const uint8_t Command) boot_page_erase(PageStartAddress); boot_spm_busy_wait(); } - + while (BlockSize--) { if (MemoryType == 'F') - { + { /* If both bytes in current word have been written, increment the address counter */ if (HighByte) { @@ -268,14 +242,14 @@ static void ReadWriteMemoryBlock(const uint8_t Command) else { LowByte = FetchNextCommandByte(); - + HighByte = true; } } else { /* Write the next EEPROM byte from the endpoint */ - eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte()); + eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte()); /* Increment the address counter after use */ CurrAddress += 2; @@ -287,13 +261,13 @@ static void ReadWriteMemoryBlock(const uint8_t Command) { /* Commit the flash page to memory */ boot_page_write(PageStartAddress); - + /* Wait until write operation has completed */ boot_spm_busy_wait(); } - + /* Send response byte back to the host */ - WriteNextResponseByte('\r'); + WriteNextResponseByte('\r'); } } @@ -306,7 +280,7 @@ static uint8_t FetchNextCommandByte(void) { /* Select the OUT endpoint so that the next data byte can be read */ Endpoint_SelectEndpoint(CDC_RX_EPNUM); - + /* If OUT endpoint empty, clear it and wait for the next packet from the host */ while (!(Endpoint_IsReadWriteAllowed())) { @@ -318,7 +292,7 @@ static uint8_t FetchNextCommandByte(void) return 0; } } - + /* Fetch the next byte from the OUT endpoint */ return Endpoint_Read_Byte(); } @@ -332,19 +306,19 @@ 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 IN endpoint full, clear it and wait until ready for the next packet to the host */ if (!(Endpoint_IsReadWriteAllowed())) { Endpoint_ClearIN(); - + while (!(Endpoint_IsINReady())) - { + { if (USB_DeviceState == DEVICE_STATE_Unattached) return; } } - + /* Write the next byte to the OUT endpoint */ Endpoint_Write_Byte(Response); } @@ -356,7 +330,7 @@ void CDC_Task(void) { /* Select the OUT endpoint */ Endpoint_SelectEndpoint(CDC_RX_EPNUM); - + /* Check if endpoint has a command in it sent from the host */ if (Endpoint_IsOUTReceived()) { @@ -367,17 +341,16 @@ void CDC_Task(void) { if (Command == 'E') RunBootloader = false; - if (Command == 'T') + else if (Command == 'T') FetchNextCommandByte(); /* Send confirmation byte back to the host */ - WriteNextResponseByte('\r'); + WriteNextResponseByte('\r'); } else if (Command == 't') { /* Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader */ WriteNextResponseByte(0x44); - WriteNextResponseByte(0x00); } else if (Command == 'a') @@ -397,13 +370,13 @@ void CDC_Task(void) else if (Command == 'p') { /* Indicate serial programmer back to the host */ - WriteNextResponseByte('S'); + WriteNextResponseByte('S'); } else if (Command == 'S') { /* Write the 7-byte software identifier to the endpoint */ for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++) - WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]); + WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]); } else if (Command == 'V') { @@ -412,17 +385,17 @@ void CDC_Task(void) } else if (Command == 's') { - WriteNextResponseByte(AVR_SIGNATURE_3); + WriteNextResponseByte(AVR_SIGNATURE_3); WriteNextResponseByte(AVR_SIGNATURE_2); WriteNextResponseByte(AVR_SIGNATURE_1); } else if (Command == 'b') { WriteNextResponseByte('Y'); - + /* Send block size to the host */ WriteNextResponseByte(SPM_PAGESIZE >> 8); - WriteNextResponseByte(SPM_PAGESIZE & 0xFF); + WriteNextResponseByte(SPM_PAGESIZE & 0xFF); } else if (Command == 'e') { @@ -436,9 +409,9 @@ void CDC_Task(void) CurrFlashAddress += SPM_PAGESIZE; } - + /* Send confirmation byte back to the host */ - WriteNextResponseByte('\r'); + WriteNextResponseByte('\r'); } else if (Command == 'l') { @@ -450,7 +423,7 @@ void CDC_Task(void) } else if (Command == 'r') { - WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS)); + WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS)); } else if (Command == 'F') { @@ -458,41 +431,41 @@ void CDC_Task(void) } else if (Command == 'N') { - WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS)); + WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS)); } else if (Command == 'Q') { - WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS)); + WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS)); } else if (Command == 'C') - { + { /* Write the high byte to the current flash page */ boot_page_fill(CurrAddress, FetchNextCommandByte()); /* Send confirmation byte back to the host */ - WriteNextResponseByte('\r'); + WriteNextResponseByte('\r'); } else if (Command == 'c') - { + { /* Write the low byte to the current flash page */ boot_page_fill(CurrAddress | 1, FetchNextCommandByte()); - + /* Increment the address */ CurrAddress += 2; /* Send confirmation byte back to the host */ - WriteNextResponseByte('\r'); + WriteNextResponseByte('\r'); } else if (Command == 'm') { /* Commit the flash page to memory */ boot_page_write(CurrAddress); - + /* Wait until write operation has completed */ boot_spm_busy_wait(); /* Send confirmation byte back to the host */ - WriteNextResponseByte('\r'); + WriteNextResponseByte('\r'); } else if ((Command == 'B') || (Command == 'g')) { @@ -504,9 +477,9 @@ void CDC_Task(void) #if (FLASHEND > 0xFFFF) uint16_t ProgramWord = pgm_read_word_far(CurrAddress); #else - uint16_t ProgramWord = pgm_read_word(CurrAddress); + uint16_t ProgramWord = pgm_read_word(CurrAddress); #endif - + WriteNextResponseByte(ProgramWord >> 8); WriteNextResponseByte(ProgramWord & 0xFF); } @@ -514,12 +487,12 @@ void CDC_Task(void) { /* Read the byte from the endpoint and write it to the EEPROM */ eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte()); - - /* Increment the address after use */ + + /* Increment the address after use */ CurrAddress += 2; - + /* Send confirmation byte back to the host */ - WriteNextResponseByte('\r'); + WriteNextResponseByte('\r'); } else if (Command == 'd') { @@ -547,12 +520,12 @@ void CDC_Task(void) /* Send the endpoint data to the host */ Endpoint_ClearIN(); - + /* 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())) - { + { if (USB_DeviceState == DEVICE_STATE_Unattached) return; } @@ -562,11 +535,11 @@ void CDC_Task(void) /* 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); @@ -574,3 +547,4 @@ void CDC_Task(void) Endpoint_ClearOUT(); } } +