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