/*\r
LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
+ Copyright (C) Dean Camera, 2010.\r
\r
dean [at] fourwalledcubicle [dot] com\r
www.fourwalledcubicle.com\r
*/\r
\r
/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, distribute, and sell this \r
+ software and its documentation for any purpose is hereby granted\r
+ without fee, provided that the above copyright notice appear in \r
+ all copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting \r
+ documentation, and that the name of the author not be used in \r
+ advertising or publicity pertaining to distribution of the \r
software without specific, written prior permission.\r
\r
The author disclaim all warranties with regard to this\r
uint8_t EnterProgBytes[4];\r
} Enter_ISP_Params;\r
\r
- Endpoint_Read_Stream_LE(&Enter_ISP_Params, sizeof(Enter_ISP_Params));\r
+ Endpoint_Read_Stream_LE(&Enter_ISP_Params, sizeof(Enter_ISP_Params), NO_STREAM_CALLBACK);\r
\r
Endpoint_ClearOUT();\r
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);\r
uint8_t ResponseStatus = STATUS_CMD_FAILED;\r
\r
CurrentAddress = 0;\r
+ \r
+ /* Set up the synchronous USART to generate the recovery clock on XCK pin */\r
+ UBRR1 = (F_CPU / 500000UL);\r
+ UCSR1B = (1 << TXEN1);\r
+ UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);\r
+ DDRD |= (1 << 5);\r
\r
+ /* Perform execution delay, initialize SPI bus */\r
ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS); \r
SPI_Init(ISPTarget_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING | SPI_SAMPLE_LEADING | SPI_MODE_MASTER);\r
- \r
- while (Enter_ISP_Params.SynchLoops-- && (ResponseStatus == STATUS_CMD_FAILED))\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) && TimeoutMSRemaining)\r
{\r
uint8_t ResponseBytes[4];\r
\r
uint8_t PostDelayMS;\r
} Leave_ISP_Params;\r
\r
- Endpoint_Read_Stream_LE(&Leave_ISP_Params, sizeof(Leave_ISP_Params));\r
+ Endpoint_Read_Stream_LE(&Leave_ISP_Params, sizeof(Leave_ISP_Params), NO_STREAM_CALLBACK);\r
\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
ISPProtocol_DelayMS(Leave_ISP_Params.PostDelayMS);\r
\r
+ /* Turn off the synchronous USART to terminate the recovery clock on XCK pin */\r
+ UBRR1 = (F_CPU / 500000UL);\r
+ UCSR1B = (1 << TXEN1);\r
+ UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);\r
+ DDRD &= ~(1 << 5);\r
+\r
Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP);\r
Endpoint_Write_Byte(STATUS_CMD_OK);\r
Endpoint_ClearIN();\r
} Write_Memory_Params; // whole page and ACK the packet as fast as possible to prevent it from aborting\r
\r
Endpoint_Read_Stream_LE(&Write_Memory_Params, (sizeof(Write_Memory_Params) -\r
- sizeof(Write_Memory_Params.ProgData)));\r
+ sizeof(Write_Memory_Params.ProgData)), NO_STREAM_CALLBACK);\r
\r
\r
Write_Memory_Params.BytesToWrite = SwapEndian_16(Write_Memory_Params.BytesToWrite);\r
return;\r
}\r
\r
- Endpoint_Read_Stream_LE(&Write_Memory_Params.ProgData, Write_Memory_Params.BytesToWrite);\r
+ Endpoint_Read_Stream_LE(&Write_Memory_Params.ProgData, Write_Memory_Params.BytesToWrite, NO_STREAM_CALLBACK);\r
\r
Endpoint_ClearOUT();\r
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);\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
+ if (V2Command == CMD_PROGRAM_FLASH_ISP)\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
Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK;\r
- \r
+\r
PollAddress = (CurrentAddress & 0xFFFF); \r
} \r
\r
{\r
bool IsOddByte = (CurrentByte & 0x01);\r
uint8_t ByteToWrite = *(NextWriteByte++);\r
- \r
- if (IsOddByte && (V2Command == CMD_READ_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
+ if (V2Command == CMD_PROGRAM_FLASH_ISP)\r
+ Write_Memory_Params.ProgrammingCommands[0] ^= READ_WRITE_HIGH_BYTE_MASK;\r
+\r
if (ByteToWrite != PollValue)\r
{\r
if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP))\r
uint8_t ReadMemoryCommand;\r
} Read_Memory_Params;\r
\r
- Endpoint_Read_Stream_LE(&Read_Memory_Params, sizeof(Read_Memory_Params));\r
+ Endpoint_Read_Stream_LE(&Read_Memory_Params, sizeof(Read_Memory_Params), NO_STREAM_CALLBACK);\r
Read_Memory_Params.BytesToRead = SwapEndian_16(Read_Memory_Params.BytesToRead);\r
\r
Endpoint_ClearOUT();\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
uint8_t EraseCommandBytes[4];\r
} Erase_Chip_Params;\r
\r
- Endpoint_Read_Stream_LE(&Erase_Chip_Params, sizeof(Erase_Chip_Params));\r
+ Endpoint_Read_Stream_LE(&Erase_Chip_Params, sizeof(Erase_Chip_Params), NO_STREAM_CALLBACK);\r
\r
Endpoint_ClearOUT();\r
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);\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
uint8_t ReadCommandBytes[4];\r
} Read_FuseLockSigOSCCAL_Params;\r
\r
- Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params, sizeof(Read_FuseLockSigOSCCAL_Params));\r
+ Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params, sizeof(Read_FuseLockSigOSCCAL_Params), NO_STREAM_CALLBACK);\r
\r
Endpoint_ClearOUT();\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
uint8_t WriteCommandBytes[4];\r
} Write_FuseLockSig_Params;\r
\r
- Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params, sizeof(Write_FuseLockSig_Params));\r
+ Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params, sizeof(Write_FuseLockSig_Params), NO_STREAM_CALLBACK);\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
uint8_t TxData[255];\r
} SPI_Multi_Params;\r
\r
- Endpoint_Read_Stream_LE(&SPI_Multi_Params, sizeof(SPI_Multi_Params) - sizeof(SPI_Multi_Params.TxData));\r
- Endpoint_Read_Stream_LE(&SPI_Multi_Params.TxData, SPI_Multi_Params.TxBytes);\r
+ Endpoint_Read_Stream_LE(&SPI_Multi_Params, (sizeof(SPI_Multi_Params) - sizeof(SPI_Multi_Params.TxData)), NO_STREAM_CALLBACK);\r
+ Endpoint_Read_Stream_LE(&SPI_Multi_Params.TxData, SPI_Multi_Params.TxBytes, NO_STREAM_CALLBACK);\r
\r
Endpoint_ClearOUT();\r
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);\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
+/** Blocking delay for a given number of milliseconds.\r
+ *\r
+ * \param[in] DelayMS Number of milliseconds to delay for\r
+ */\r
+void ISPProtocol_DelayMS(uint8_t DelayMS)\r
+{\r
+ while (DelayMS-- && TimeoutMSRemaining)\r
+ {\r
+ if (TimeoutMSRemaining)\r
+ TimeoutMSRemaining--;\r
+ \r
+ _delay_ms(1);\r
+ }\r
}\r
\r
#endif
\ No newline at end of file