Rename new CDC class bootloader NO_LOCK_BYTE_SUPPORT compile time option to NO_LOCK_BYTE_WRITE_SUPPORT as reads are still permitted.

Clean up CDC bootloader command processing code.
pull/1469/head
Dean Camera 14 years ago
parent 475323e400
commit 40db485c79

@ -332,223 +332,230 @@ void CDC_Task(void)
Endpoint_SelectEndpoint(CDC_RX_EPNUM); Endpoint_SelectEndpoint(CDC_RX_EPNUM);
/* Check if endpoint has a command in it sent from the host */ /* Check if endpoint has a command in it sent from the host */
if (Endpoint_IsOUTReceived()) if (!(Endpoint_IsOUTReceived()))
{ return;
/* Read in the bootloader command (first byte sent from host) */
uint8_t Command = FetchNextCommandByte();
if ((Command == 'L') || (Command == 'P') || (Command == 'T') || (Command == 'E')) /* Read in the bootloader command (first byte sent from host) */
{ uint8_t Command = FetchNextCommandByte();
if (Command == 'E')
RunBootloader = false;
else if (Command == 'T')
FetchNextCommandByte();
/* Send confirmation byte back to the host */ if (Command == 'E')
WriteNextResponseByte('\r'); {
} RunBootloader = false;
else if (Command == 't')
{ /* Send confirmation byte back to the host */
/* Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader */ WriteNextResponseByte('\r');
WriteNextResponseByte(0x44); }
WriteNextResponseByte(0x00); else if (Command == 'T')
} {
else if (Command == 'a') FetchNextCommandByte();
{
/* Indicate auto-address increment is supported */
WriteNextResponseByte('Y');
}
else if (Command == 'A')
{
/* Set the current address to that given by the host */
CurrAddress = (FetchNextCommandByte() << 9);
CurrAddress |= (FetchNextCommandByte() << 1);
/* Send confirmation byte back to the host */ /* Send confirmation byte back to the host */
WriteNextResponseByte('\r'); WriteNextResponseByte('\r');
} }
else if (Command == 'p') else if ((Command == 'L') || (Command == 'P'))
{ {
/* Indicate serial programmer back to the host */ /* Send confirmation byte back to the host */
WriteNextResponseByte('S'); WriteNextResponseByte('\r');
} }
else if (Command == 'S') else if (Command == 't')
{ {
/* Write the 7-byte software identifier to the endpoint */ /* Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader */
for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++) WriteNextResponseByte(0x44);
WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]); WriteNextResponseByte(0x00);
} }
else if (Command == 'V') else if (Command == 'a')
{ {
WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR); /* Indicate auto-address increment is supported */
WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR); WriteNextResponseByte('Y');
} }
else if (Command == 's') else if (Command == 'A')
{
/* Set the current address to that given by the host */
CurrAddress = (FetchNextCommandByte() << 9);
CurrAddress |= (FetchNextCommandByte() << 1);
/* Send confirmation byte back to the host */
WriteNextResponseByte('\r');
}
else if (Command == 'p')
{
/* Indicate serial programmer back to the host */
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]);
}
else if (Command == 'V')
{
WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR);
WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR);
}
else if (Command == 's')
{
WriteNextResponseByte(AVR_SIGNATURE_3);
WriteNextResponseByte(AVR_SIGNATURE_2);
WriteNextResponseByte(AVR_SIGNATURE_1);
}
else if (Command == 'e')
{
/* Clear the application section of flash */
for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < BOOT_START_ADDR; CurrFlashAddress += SPM_PAGESIZE)
{ {
WriteNextResponseByte(AVR_SIGNATURE_3); boot_page_erase(CurrFlashAddress);
WriteNextResponseByte(AVR_SIGNATURE_2); boot_spm_busy_wait();
WriteNextResponseByte(AVR_SIGNATURE_1); boot_page_write(CurrFlashAddress);
boot_spm_busy_wait();
} }
else if (Command == 'e')
{
/* Clear the application section of flash */
for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < BOOT_START_ADDR; CurrFlashAddress++)
{
boot_page_erase(CurrFlashAddress);
boot_spm_busy_wait();
boot_page_write(CurrFlashAddress);
boot_spm_busy_wait();
CurrFlashAddress += SPM_PAGESIZE;
}
/* Send confirmation byte back to the host */ /* Send confirmation byte back to the host */
WriteNextResponseByte('\r'); WriteNextResponseByte('\r');
} }
#if !defined(NO_LOCK_BYTE_SUPPORT) #if !defined(NO_LOCK_BYTE_WRITE_SUPPORT)
else if (Command == 'l') else if (Command == 'l')
{ {
/* Set the lock bits to those given by the host */ /* Set the lock bits to those given by the host */
boot_lock_bits_set(FetchNextCommandByte()); boot_lock_bits_set(FetchNextCommandByte());
/* Send confirmation byte back to the host */ /* Send confirmation byte back to the host */
WriteNextResponseByte('\r'); WriteNextResponseByte('\r');
} }
#endif #endif
else if (Command == 'r') 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') else if (Command == 'F')
{ {
WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS)); WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
} }
else if (Command == 'N') 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') else if (Command == 'Q')
{ {
WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS)); WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
} }
#if !defined(NO_BLOCK_SUPPORT) #if !defined(NO_BLOCK_SUPPORT)
else if (Command == 'b') else if (Command == 'b')
{ {
WriteNextResponseByte('Y'); WriteNextResponseByte('Y');
/* Send block size to the host */ /* Send block size to the host */
WriteNextResponseByte(SPM_PAGESIZE >> 8); WriteNextResponseByte(SPM_PAGESIZE >> 8);
WriteNextResponseByte(SPM_PAGESIZE & 0xFF); WriteNextResponseByte(SPM_PAGESIZE & 0xFF);
} }
else if ((Command == 'B') || (Command == 'g')) else if ((Command == 'B') || (Command == 'g'))
{ {
/* Delegate the block write/read to a separate function for clarity */ /* Delegate the block write/read to a separate function for clarity */
ReadWriteMemoryBlock(Command); ReadWriteMemoryBlock(Command);
} }
#endif #endif
#if !defined(NO_FLASH_BYTE_SUPPORT) #if !defined(NO_FLASH_BYTE_SUPPORT)
else if (Command == 'C') else if (Command == 'C')
{ {
/* Write the high byte to the current flash page */ /* Write the high byte to the current flash page */
boot_page_fill(CurrAddress, FetchNextCommandByte()); boot_page_fill(CurrAddress, FetchNextCommandByte());
/* Send confirmation byte back to the host */ /* Send confirmation byte back to the host */
WriteNextResponseByte('\r'); WriteNextResponseByte('\r');
} }
else if (Command == 'c') else if (Command == 'c')
{ {
/* Write the low byte to the current flash page */ /* Write the low byte to the current flash page */
boot_page_fill(CurrAddress | 0x01, FetchNextCommandByte()); boot_page_fill(CurrAddress | 0x01, FetchNextCommandByte());
/* Increment the address */ /* Increment the address */
CurrAddress += 2; CurrAddress += 2;
/* Send confirmation byte back to the host */ /* Send confirmation byte back to the host */
WriteNextResponseByte('\r'); WriteNextResponseByte('\r');
} }
else if (Command == 'm') else if (Command == 'm')
{ {
/* Commit the flash page to memory */ /* Commit the flash page to memory */
boot_page_write(CurrAddress); boot_page_write(CurrAddress);
/* Wait until write operation has completed */ /* Wait until write operation has completed */
boot_spm_busy_wait(); boot_spm_busy_wait();
/* Send confirmation byte back to the host */ /* Send confirmation byte back to the host */
WriteNextResponseByte('\r'); WriteNextResponseByte('\r');
} }
else if (Command == 'R') else if (Command == 'R')
{ {
#if (FLASHEND > 0xFFFF) #if (FLASHEND > 0xFFFF)
uint16_t ProgramWord = pgm_read_word_far(CurrAddress); uint16_t ProgramWord = pgm_read_word_far(CurrAddress);
#else #else
uint16_t ProgramWord = pgm_read_word(CurrAddress); uint16_t ProgramWord = pgm_read_word(CurrAddress);
#endif
WriteNextResponseByte(ProgramWord >> 8);
WriteNextResponseByte(ProgramWord & 0xFF);
}
#endif #endif
#if !defined(NO_EEPROM_BYTE_SUPPORT)
else if (Command == 'D')
{
/* 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 */ WriteNextResponseByte(ProgramWord >> 8);
CurrAddress += 2; WriteNextResponseByte(ProgramWord & 0xFF);
}
#endif
#if !defined(NO_EEPROM_BYTE_SUPPORT)
else if (Command == 'D')
{
/* Read the byte from the endpoint and write it to the EEPROM */
eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
/* Send confirmation byte back to the host */ /* Increment the address after use */
WriteNextResponseByte('\r'); CurrAddress += 2;
}
else if (Command == 'd')
{
/* Read the EEPROM byte and write it to the endpoint */
WriteNextResponseByte(eeprom_read_byte((uint8_t*)((intptr_t)(CurrAddress >> 1))));
/* Increment the address after use */ /* Send confirmation byte back to the host */
CurrAddress += 2; WriteNextResponseByte('\r');
} }
#endif else if (Command == 'd')
else if (Command != 27) {
{ /* Read the EEPROM byte and write it to the endpoint */
/* Unknown (non-sync) command, return fail code */ WriteNextResponseByte(eeprom_read_byte((uint8_t*)((intptr_t)(CurrAddress >> 1))));
WriteNextResponseByte('?');
}
/* Select the IN endpoint */
Endpoint_SelectEndpoint(CDC_TX_EPNUM);
/* Remember if the endpoint is completely full before clearing it */ /* Increment the address after use */
bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed()); CurrAddress += 2;
}
#endif
else if (Command != 27)
{
/* Unknown (non-sync) command, return fail code */
WriteNextResponseByte('?');
}
/* Send the endpoint data to the host */ /* Select the IN endpoint */
Endpoint_ClearIN(); Endpoint_SelectEndpoint(CDC_TX_EPNUM);
/* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal end of transfer */ /* Remember if the endpoint is completely full before clearing it */
if (IsEndpointFull) bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
{
while (!(Endpoint_IsINReady()))
{
if (USB_DeviceState == DEVICE_STATE_Unattached)
return;
}
Endpoint_ClearIN(); /* Send the endpoint data to the host */
} Endpoint_ClearIN();
/* Wait until the data has been sent to the host */ /* 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) if (USB_DeviceState == DEVICE_STATE_Unattached)
return; return;
} }
/* Select the OUT endpoint */ Endpoint_ClearIN();
Endpoint_SelectEndpoint(CDC_RX_EPNUM); }
/* Acknowledge the command from the host */ /* Wait until the data has been sent to the host */
Endpoint_ClearOUT(); while (!(Endpoint_IsINReady()))
{
if (USB_DeviceState == DEVICE_STATE_Unattached)
return;
} }
/* Select the OUT endpoint */
Endpoint_SelectEndpoint(CDC_RX_EPNUM);
/* Acknowledge the command from the host */
Endpoint_ClearOUT();
} }

@ -82,7 +82,7 @@
* to be made using the block-level commands. * to be made using the block-level commands.
* </tr> * </tr>
* <tr> * <tr>
* <td>NO_LOCK_BYTE_SUPPORT</td> * <td>NO_LOCK_BYTE_WRITE_SUPPORT</td>
* <td>Makefile LUFA_OPTS</td> * <td>Makefile LUFA_OPTS</td>
* <td>Define to disable lock byte write support in the bootloader, preventing the lock bits from being set progmatically. * <td>Define to disable lock byte write support in the bootloader, preventing the lock bits from being set progmatically.
* </tr> * </tr>

@ -127,7 +127,7 @@ LUFA_OPTS += -D NO_SOF_EVENTS
#LUFA_OPTS += -D NO_BLOCK_SUPPORT #LUFA_OPTS += -D NO_BLOCK_SUPPORT
#LUFA_OPTS += -D NO_EEPROM_BYTE_SUPPORT #LUFA_OPTS += -D NO_EEPROM_BYTE_SUPPORT
#LUFA_OPTS += -D NO_FLASH_BYTE_SUPPORT #LUFA_OPTS += -D NO_FLASH_BYTE_SUPPORT
#LUFA_OPTS += -D NO_LOCK_BYTE_SUPPORT #LUFA_OPTS += -D NO_LOCK_BYTE_WRITE_SUPPORT
# Create the LUFA source path variables by including the LUFA root makefile # Create the LUFA source path variables by including the LUFA root makefile

@ -30,9 +30,9 @@
* - Added default test tone generation mode to the Device mode AudioInput demos * - Added default test tone generation mode to the Device mode AudioInput demos
* - Added new NO_CLASS_DRIVER_AUTOFLUSH compile time option to disable automatic flushing of interfaces when the USB management * - Added new NO_CLASS_DRIVER_AUTOFLUSH compile time option to disable automatic flushing of interfaces when the USB management
* tasks for each driver is called * tasks for each driver is called
* - Added standard keyboard HID report scancode defines (thanks to László Monda) * - Added standard keyboard HID report scancode defines (thanks to Laszlo Monda)
* - Added new Pipe_GetBusyBanks(), Endpoint_GetBusyBanks() and Endpoint_AbortPendingIN() functions * - Added new Pipe_GetBusyBanks(), Endpoint_GetBusyBanks() and Endpoint_AbortPendingIN() functions
* - Added new NO_BLOCK_SUPPORT, NO_EEPROM_BYTE_SUPPORT, NO_FLASH_BYTE_SUPPORT and NO_LOCK_BYTE_SUPPORT compile time options to the * - Added new NO_BLOCK_SUPPORT, NO_EEPROM_BYTE_SUPPORT, NO_FLASH_BYTE_SUPPORT and NO_LOCK_BYTE_WRITE_SUPPORT compile time options to the
* CDC class bootloader * CDC class bootloader
* *
* <b>Changed:</b> * <b>Changed:</b>

Loading…
Cancel
Save