diff --git a/LUFA/Drivers/USB/HighLevel/Events.h b/LUFA/Drivers/USB/HighLevel/Events.h index 84b951ead4..08727d749e 100644 --- a/LUFA/Drivers/USB/HighLevel/Events.h +++ b/LUFA/Drivers/USB/HighLevel/Events.h @@ -40,8 +40,8 @@ * listed here. If an event with no user-associated handler is fired within the library, it by default maps to an * internal empty stub function. * - * Each event must only have one associated event handler, but can be raised by multiple sources by calling the event - * name just like any regular C function (with any required event parameters). + * Each event must only have one associated event handler, but can be raised by multiple sources by calling the + * event handler function (with any required event parameters). * * @{ */ @@ -233,19 +233,25 @@ * \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see * \ref Group_USBManagement documentation). * + * \note This event does not exist on the series 2 USB AVRs when the NO_LIMITED_CONTROLLER_CONNECT + * compile time token is not set - see \ref EVENT_USB_Device_Disconnect. + * * \see \ref EVENT_USB_Device_WakeUp() event for accompanying Wake Up event. */ void EVENT_USB_Device_Suspend(void); /** Event for USB wake up. This event fires when a the USB interface is suspended while in device * mode, and the host wakes up the device by supplying Start Of Frame pulses. This is generally - * hooked to pull the user application out of a lowe power state and back into normal operating + * hooked to pull the user application out of a low power state and back into normal operating * mode. If the USB interface is enumerated with the \ref USB_OPT_AUTO_PLL option set, the library * will automatically restart the USB PLL before the event is fired. * * \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see * \ref Group_USBManagement documentation). * + * \note This event does not exist on the series 2 USB AVRs when the NO_LIMITED_CONTROLLER_CONNECT + * compile time token is not set - see \ref EVENT_USB_Device_Connect. + * * \see \ref EVENT_USB_Device_Suspend() event for accompanying Suspend event. */ void EVENT_USB_Device_WakeUp(void); diff --git a/Projects/AVRISP-MKII/Descriptors.c b/Projects/AVRISP-MKII/Descriptors.c index f89cfae7c3..6b4264f480 100644 --- a/Projects/AVRISP-MKII/Descriptors.c +++ b/Projects/AVRISP-MKII/Descriptors.c @@ -151,9 +151,9 @@ USB_Descriptor_String_t PROGMEM ManufacturerString = */ USB_Descriptor_String_t PROGMEM ProductString = { - .Header = {.Size = USB_STRING_LEN(33), .Type = DTYPE_String}, + .Header = {.Size = USB_STRING_LEN(22), .Type = DTYPE_String}, - .UnicodeString = L"LUFA AVRISP MkII Clone Programmer" + .UnicodeString = L"LUFA AVRISP MkII Clone" }; USB_Descriptor_String_t PROGMEM SerialString = diff --git a/Projects/AVRISP-MKII/Lib/ISP/ISPProtocol.c b/Projects/AVRISP-MKII/Lib/ISP/ISPProtocol.c index 3a7e640b4f..936c9abc9e 100644 --- a/Projects/AVRISP-MKII/Lib/ISP/ISPProtocol.c +++ b/Projects/AVRISP-MKII/Lib/ISP/ISPProtocol.c @@ -65,7 +65,9 @@ void ISPProtocol_EnterISPMode(void) ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS); SPI_Init(ISPTarget_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING | SPI_SAMPLE_LEADING | SPI_MODE_MASTER); - + + /* Continuously attempt to synchronize with the target until either the number of attempts specified + * by the host has exceeded, or the the device sends back the expected response values */ while (Enter_ISP_Params.SynchLoops-- && (ResponseStatus == STATUS_CMD_FAILED)) { uint8_t ResponseBytes[4]; @@ -110,6 +112,7 @@ void ISPProtocol_LeaveISPMode(void) Endpoint_ClearOUT(); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + /* Perform pre-exit delay, release the target /RESET, disable the SPI bus and perform the post-exit delay */ ISPProtocol_DelayMS(Leave_ISP_Params.PreDelayMS); ISPTarget_ChangeTargetResetLine(false); SPI_ShutDown(); @@ -166,6 +169,9 @@ void ISPProtocol_ProgramMemory(uint8_t V2Command) Write_Memory_Params.PollValue2; uint8_t* NextWriteByte = Write_Memory_Params.ProgData; + /* Check to see if the host has issued a SET ADDRESS command and we haven't sent a + * LOAD EXTENDED ADDRESS command (if needed, used when operating beyond the 128KB + * FLASH barrier) */ if (MustSetAddress) { if (CurrentAddress & (1UL << 31)) @@ -174,6 +180,7 @@ void ISPProtocol_ProgramMemory(uint8_t V2Command) MustSetAddress = false; } + /* Check the programming mode desired by the host, either Paged or Word memory writes */ if (Write_Memory_Params.ProgrammingMode & PROG_MODE_PAGED_WRITES_MASK) { uint16_t StartAddress = (CurrentAddress & 0xFFFF); @@ -184,16 +191,16 @@ void ISPProtocol_ProgramMemory(uint8_t V2Command) bool IsOddByte = (CurrentByte & 0x01); uint8_t ByteToWrite = *(NextWriteByte++); - if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP)) - Write_Memory_Params.ProgrammingCommands[0] |= READ_WRITE_HIGH_BYTE_MASK; - else - Write_Memory_Params.ProgrammingCommands[0] &= ~READ_WRITE_HIGH_BYTE_MASK; - SPI_SendByte(Write_Memory_Params.ProgrammingCommands[0]); SPI_SendByte(CurrentAddress >> 8); SPI_SendByte(CurrentAddress & 0xFF); SPI_SendByte(ByteToWrite); + /* AVR FLASH addressing requires us to modify the write command based on if we are writing a high + * or low byte at the current word address */ + Write_Memory_Params.ProgrammingCommands[0] ^= READ_WRITE_HIGH_BYTE_MASK; + + /* Check to see the write completion method, to see if we have a valid polling address */ if (!(PollAddress) && (ByteToWrite != PollValue)) { if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP)) @@ -289,6 +296,9 @@ void ISPProtocol_ReadMemory(uint8_t V2Command) Endpoint_Write_Byte(V2Command); Endpoint_Write_Byte(STATUS_CMD_OK); + /* Check to see if the host has issued a SET ADDRESS command and we haven't sent a + * LOAD EXTENDED ADDRESS command (if needed, used when operating beyond the 128KB + * FLASH barrier) */ if (MustSetAddress) { if (CurrentAddress & (1UL << 31)) @@ -297,28 +307,30 @@ void ISPProtocol_ReadMemory(uint8_t V2Command) MustSetAddress = false; } + /* Read each byte from the device and write them to the packet for the host */ for (uint16_t CurrentByte = 0; CurrentByte < Read_Memory_Params.BytesToRead; CurrentByte++) { - bool IsOddByte = (CurrentByte & 0x01); - - if (IsOddByte && (V2Command == CMD_READ_FLASH_ISP)) - Read_Memory_Params.ReadMemoryCommand |= READ_WRITE_HIGH_BYTE_MASK; - else - Read_Memory_Params.ReadMemoryCommand &= ~READ_WRITE_HIGH_BYTE_MASK; - + /* Read the next byte from the desired memory space in the device */ SPI_SendByte(Read_Memory_Params.ReadMemoryCommand); SPI_SendByte(CurrentAddress >> 8); SPI_SendByte(CurrentAddress & 0xFF); Endpoint_Write_Byte(SPI_ReceiveByte()); - /* Check if the endpoint bank is currently full */ + /* Check if the endpoint bank is currently full, if so send the packet */ if (!(Endpoint_IsReadWriteAllowed())) { Endpoint_ClearIN(); Endpoint_WaitUntilReady(); } - if ((IsOddByte && (V2Command == CMD_READ_FLASH_ISP)) || (V2Command == CMD_READ_EEPROM_ISP)) + /* AVR FLASH addressing requires us to modify the read command based on if we are reading a high + * or low byte at the current word address */ + if (V2Command == CMD_READ_FLASH_ISP) + Read_Memory_Params.ReadMemoryCommand ^= READ_WRITE_HIGH_BYTE_MASK; + + /* Only increment the current address if we have read both bytes in the current word when in FLASH + * read mode, or for each byte when in EEPROM read mode */ + if (((CurrentByte & 0x01) && (V2Command == CMD_READ_FLASH_ISP)) || (V2Command == CMD_READ_EEPROM_ISP)) CurrentAddress++; } @@ -353,9 +365,11 @@ void ISPProtocol_ChipErase(void) uint8_t ResponseStatus = STATUS_CMD_OK; + /* Send the chip erase commands as given by the host to the device */ for (uint8_t SByte = 0; SByte < sizeof(Erase_Chip_Params.EraseCommandBytes); SByte++) SPI_SendByte(Erase_Chip_Params.EraseCommandBytes[SByte]); + /* Use appropriate command completion check as given by the host (delay or busy polling) */ if (!(Erase_Chip_Params.PollMethod)) ISPProtocol_DelayMS(Erase_Chip_Params.EraseDelayMS); else @@ -385,7 +399,8 @@ void ISPProtocol_ReadFuseLockSigOSCCAL(uint8_t V2Command) Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); uint8_t ResponseBytes[4]; - + + /* Send the Fuse or Lock byte read commands as given by the host to the device, store response */ for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++) ResponseBytes[RByte] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]); @@ -413,6 +428,7 @@ void ISPProtocol_WriteFuseLock(uint8_t V2Command) Endpoint_ClearOUT(); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + /* Send the Fuse or Lock byte program commands as given by the host to the device */ for (uint8_t SByte = 0; SByte < sizeof(Write_FuseLockSig_Params.WriteCommandBytes); SByte++) SPI_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]); @@ -463,12 +479,29 @@ void ISPProtocol_SPIMulti(void) Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params.TxData[CurrTxPos++])); else Endpoint_Write_Byte(SPI_ReceiveByte()); + + /* Check to see if we have filled the endpoint bank and need to send the packet */ + if (!(Endpoint_IsReadWriteAllowed())) + { + Endpoint_ClearIN(); + Endpoint_WaitUntilReady(); + } CurrRxPos++; } Endpoint_Write_Byte(STATUS_CMD_OK); + + bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed()); Endpoint_ClearIN(); + + /* Ensure last packet is a short packet to terminate the transfer */ + if (IsEndpointFull) + { + Endpoint_WaitUntilReady(); + Endpoint_ClearIN(); + Endpoint_WaitUntilReady(); + } } #endif \ No newline at end of file diff --git a/Projects/AVRISP-MKII/Lib/V2Protocol.c b/Projects/AVRISP-MKII/Lib/V2Protocol.c index 093c07862e..976f24b9e3 100644 --- a/Projects/AVRISP-MKII/Lib/V2Protocol.c +++ b/Projects/AVRISP-MKII/Lib/V2Protocol.c @@ -58,6 +58,7 @@ void V2Protocol_ProcessCommand(void) { uint8_t V2Command = Endpoint_Read_Byte(); + /* Set total command processing timeout value, enable timeout management interrupt */ TimeoutMSRemaining = COMMAND_TIMEOUT_MS; TIMSK0 |= (1 << OCIE0A); @@ -121,6 +122,7 @@ void V2Protocol_ProcessCommand(void) break; } + /* Disable timeout management interrupt once processing has completed */ TIMSK0 &= ~(1 << OCIE0A); Endpoint_WaitUntilReady(); @@ -162,8 +164,8 @@ static void V2Protocol_SignOn(void) Endpoint_ClearIN(); } -/** Handler for the CMD_RESET_PROTECTION command, currently implemented as a dummy ACK function - * as no ISP short-circuit protection is currently implemented. +/** Handler for the CMD_RESET_PROTECTION command, implemented as a dummy ACK function as + * no target short-circuit protection is currently implemented. */ static void V2Protocol_ResetProtection(void) { diff --git a/Projects/AVRISP-MKII/Lib/V2ProtocolParams.c b/Projects/AVRISP-MKII/Lib/V2ProtocolParams.c index c2595e78f6..00788515dd 100644 --- a/Projects/AVRISP-MKII/Lib/V2ProtocolParams.c +++ b/Projects/AVRISP-MKII/Lib/V2ProtocolParams.c @@ -170,7 +170,7 @@ static ParameterItem_t* V2Params_GetParamFromTable(const uint8_t ParamID) ParameterItem_t* CurrTableItem = ParameterTable; /* Find the parameter in the parameter table if present */ - for (uint8_t TableIndex = 0; TableIndex < (sizeof(ParameterTable) / sizeof(ParameterTable[0])); TableIndex++) + for (uint8_t TableIndex = 0; TableIndex < TABLE_PARAM_COUNT; TableIndex++) { if (ParamID == CurrTableItem->ParamID) return CurrTableItem; diff --git a/Projects/AVRISP-MKII/Lib/V2ProtocolParams.h b/Projects/AVRISP-MKII/Lib/V2ProtocolParams.h index 04e32fe2ee..995468a4d8 100644 --- a/Projects/AVRISP-MKII/Lib/V2ProtocolParams.h +++ b/Projects/AVRISP-MKII/Lib/V2ProtocolParams.h @@ -52,10 +52,13 @@ /* Macros: */ /** Parameter privilege mask to allow the host PC to read the parameter's value */ - #define PARAM_PRIV_READ (1 << 0) + #define PARAM_PRIV_READ (1 << 0) /** Parameter privilege mask to allow the host PC to change the parameter's value */ - #define PARAM_PRIV_WRITE (1 << 1) + #define PARAM_PRIV_WRITE (1 << 1) + + /** Total number of parameters in the parameter table */ + #define TABLE_PARAM_COUNT (sizeof(ParameterTable) / sizeof(ParameterTable[0])) /* Type Defines: */ /** Type define for a parameter table entry indicating a PC readable or writable device parameter. */ diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c b/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c index c23b9d75b5..573f8fde5c 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c +++ b/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c @@ -136,24 +136,18 @@ bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest) if (!(XMEGANVM_WaitWhileNVMControllerBusy())) return false; - uint32_t MemoryCRC = 0; - - /* Read the first generated CRC byte value */ - XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2)); + /* Load the PDI pointer register with the DAT0 register start address */ + XPROGTarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES); XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT0); - MemoryCRC = XPROGTarget_ReceiveByte(); - /* Read the second generated CRC byte value */ - XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT1); - MemoryCRC |= ((uint16_t)XPROGTarget_ReceiveByte() << 8); - - /* Read the third generated CRC byte value */ - XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT2); - MemoryCRC |= ((uint32_t)XPROGTarget_ReceiveByte() << 16); + /* Send the REPEAT command to grab the CRC bytes */ + XPROGTarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE); + XPROGTarget_SendByte(XMEGA_CRC_LENGTH - 1); - *CRCDest = MemoryCRC; + /* Read in the CRC bytes from the target */ + XPROGTarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE); + for (uint8_t i = 0; i < XMEGA_CRC_LENGTH; i++) + ((uint8_t*)CRCDest)[i] = XPROGTarget_ReceiveByte(); return true; } diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.h b/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.h index 63fe05cc3f..cbd9e26f0e 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.h +++ b/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.h @@ -56,6 +56,8 @@ #endif /* Defines: */ + #define XMEGA_CRC_LENGTH 3 + #define XMEGA_NVM_REG_ADDR0 0x00 #define XMEGA_NVM_REG_ADDR1 0x01 #define XMEGA_NVM_REG_ADDR2 0x02 diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c b/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c index 9c6ee7e0c1..1be159c380 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c +++ b/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c @@ -38,7 +38,7 @@ #if defined(ENABLE_XPROG_PROTOCOL) || defined(__DOXYGEN__) /** Base absolute address for the target's NVM controller for PDI programming */ -uint32_t XPROG_Param_NVMBase = 0x010001C0; +uint32_t XPROG_Param_NVMBase = 0x010001C0; /** Size in bytes of the target's EEPROM page */ uint16_t XPROG_Param_EEPageSize; @@ -455,10 +455,10 @@ static void XPROGProtocol_SetParam(void) case XPRG_PARAM_EEPPAGESIZE: XPROG_Param_EEPageSize = Endpoint_Read_Word_BE(); break; - case XPRG_PARAM_NVMCMD: + case XPRG_PARAM_NVMCMD_REG: XPROG_Param_NVMCMDRegAddr = Endpoint_Read_Byte(); break; - case XPRG_PARAM_NVMCSR: + case XPRG_PARAM_NVMCSR_REG: XPROG_Param_NVMCSRRegAddr = Endpoint_Read_Byte(); break; default: diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.h b/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.h index 2bc7d8a50f..8e5d1b06d5 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.h +++ b/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.h @@ -98,12 +98,12 @@ #define XPRG_PARAM_NVMBASE 0x01 #define XPRG_PARAM_EEPPAGESIZE 0x02 - #define XPRG_PARAM_NVMCMD 0x03 - #define XPRG_PARAM_NVMCSR 0x04 + #define XPRG_PARAM_NVMCMD_REG 0x03 /* Undocumented, Reverse-engineered */ + #define XPRG_PARAM_NVMCSR_REG 0x04 /* Undocumented, Reverse-engineered */ #define XPRG_PROTOCOL_PDI 0x00 #define XPRG_PROTOCOL_JTAG 0x01 - #define XPRG_PROTOCOL_TPI 0x02 + #define XPRG_PROTOCOL_TPI 0x02 /* Undocumented, Reverse-engineered */ #define XPRG_PAGEMODE_WRITE (1 << 1) #define XPRG_PAGEMODE_ERASE (1 << 0)