/*
LUFA Library
Copyright (C) Dean Camera, 2010.
-
+
dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
+ www.lufa-lib.org
*/
/*
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
uint8_t PollIndex;
uint8_t EnterProgBytes[4];
} Enter_ISP_Params;
-
+
Endpoint_Read_Stream_LE(&Enter_ISP_Params, sizeof(Enter_ISP_Params), NO_STREAM_CALLBACK);
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t ResponseStatus = STATUS_CMD_FAILED;
-
+
CurrentAddress = 0;
-
- /* Set up the synchronous USART to generate the .5MHz recovery clock on XCK pin */
- UBRR1 = (F_CPU / 500000UL);
- UCSR1B = (1 << TXEN1);
- UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);
- DDRD |= (1 << 5);
/* Perform execution delay, initialize SPI bus */
- ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS);
+ ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS);
ISPTarget_Init();
/* Continuously attempt to synchronize with the target until either the number of attempts specified
ISPProtocol_DelayMS(Enter_ISP_Params.ByteDelay);
ResponseBytes[RByte] = ISPTarget_TransferByte(Enter_ISP_Params.EnterProgBytes[RByte]);
}
-
+
/* Check if polling disabled, or if the polled value matches the expected value */
if (!(Enter_ISP_Params.PollIndex) || (ResponseBytes[Enter_ISP_Params.PollIndex - 1] == Enter_ISP_Params.PollValue))
{
} Leave_ISP_Params;
Endpoint_Read_Stream_LE(&Leave_ISP_Params, sizeof(Leave_ISP_Params), NO_STREAM_CALLBACK);
-
+
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
ISPTarget_ShutDown();
ISPProtocol_DelayMS(Leave_ISP_Params.PostDelayMS);
- /* Turn off the synchronous USART to terminate the recovery clock on XCK pin */
- UBRR1 = (F_CPU / 500000UL);
- UCSR1B = (1 << TXEN1);
- UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);
- DDRD &= ~(1 << 5);
-
Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_ClearIN();
uint8_t PollValue2;
uint8_t ProgData[256]; // Note, the Jungo driver has a very short ACK timeout period, need to buffer the
} Write_Memory_Params; // whole page and ACK the packet as fast as possible to prevent it from aborting
-
+
Endpoint_Read_Stream_LE(&Write_Memory_Params, (sizeof(Write_Memory_Params) -
sizeof(Write_Memory_Params.ProgData)), NO_STREAM_CALLBACK);
Write_Memory_Params.BytesToWrite = SwapEndian_16(Write_Memory_Params.BytesToWrite);
-
+
if (Write_Memory_Params.BytesToWrite > sizeof(Write_Memory_Params.ProgData))
{
Endpoint_ClearOUT();
Endpoint_ClearIN();
return;
}
-
+
Endpoint_Read_Stream_LE(&Write_Memory_Params.ProgData, Write_Memory_Params.BytesToWrite, NO_STREAM_CALLBACK);
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
- uint8_t ProgrammingStatus = STATUS_CMD_OK;
+ uint8_t ProgrammingStatus = STATUS_CMD_OK;
uint16_t PollAddress = 0;
uint8_t PollValue = (V2Command == CMD_PROGRAM_FLASH_ISP) ? Write_Memory_Params.PollValue1 :
Write_Memory_Params.PollValue2;
- uint8_t* NextWriteByte = Write_Memory_Params.ProgData;
+ uint8_t* NextWriteByte = Write_Memory_Params.ProgData;
/* 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);
-
+
/* Check to see if we need to send a LOAD EXTENDED ADDRESS command to the target */
if (MustLoadExtendedAddress)
{
{
bool IsOddByte = (CurrentByte & 0x01);
uint8_t ByteToWrite = *(NextWriteByte++);
-
+
ISPTarget_SendByte(Write_Memory_Params.ProgrammingCommands[0]);
ISPTarget_SendByte(CurrentAddress >> 8);
ISPTarget_SendByte(CurrentAddress & 0xFF);
ISPTarget_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 */
if (V2Command == CMD_PROGRAM_FLASH_ISP)
if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP))
Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK;
- PollAddress = (CurrentAddress & 0xFFFF);
- }
+ PollAddress = (CurrentAddress & 0xFFFF);
+ }
/* EEPROM increments the address on each byte, flash needs to increment on each word */
if (IsOddByte || (V2Command == CMD_PROGRAM_EEPROM_ISP))
CurrentAddress++;
}
-
+
/* If the current page must be committed, send the PROGRAM PAGE command to the target */
if (Write_Memory_Params.ProgrammingMode & PROG_MODE_COMMIT_PAGE_MASK)
{
ISPTarget_SendByte(StartAddress >> 8);
ISPTarget_SendByte(StartAddress & 0xFF);
ISPTarget_SendByte(0x00);
-
- /* Check if polling is possible, if not switch to timed delay mode */
- if (!(PollAddress))
+
+ /* Check if polling is possible and enabled, if not switch to timed delay mode */
+ if (!(PollAddress) && (Write_Memory_Params.ProgrammingMode & PROG_MODE_PAGED_VALUE_MASK))
{
Write_Memory_Params.ProgrammingMode &= ~PROG_MODE_PAGED_VALUE_MASK;
- Write_Memory_Params.ProgrammingMode |= PROG_MODE_PAGED_TIMEDELAY_MASK;
+ Write_Memory_Params.ProgrammingMode |= PROG_MODE_PAGED_TIMEDELAY_MASK;
}
ProgrammingStatus = ISPTarget_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue,
/* Check to see if the FLASH address has crossed the extended address boundary */
if ((V2Command == CMD_PROGRAM_FLASH_ISP) && !(CurrentAddress & 0xFFFF))
- MustLoadExtendedAddress = true;
+ MustLoadExtendedAddress = true;
}
}
else
{
bool IsOddByte = (CurrentByte & 0x01);
uint8_t ByteToWrite = *(NextWriteByte++);
-
+
/* Check to see if we need to send a LOAD EXTENDED ADDRESS command to the target */
if (MustLoadExtendedAddress)
{
ISPTarget_SendByte(CurrentAddress >> 8);
ISPTarget_SendByte(CurrentAddress & 0xFF);
ISPTarget_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 */
if (V2Command == CMD_PROGRAM_FLASH_ISP)
Write_Memory_Params.ProgrammingCommands[0] ^= READ_WRITE_HIGH_BYTE_MASK;
+ /* Save previous programming mode in case we modify it for the current word */
+ uint8_t PreviousProgrammingMode = Write_Memory_Params.ProgrammingMode;
+
if (ByteToWrite != PollValue)
{
if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP))
Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK;
-
+
PollAddress = (CurrentAddress & 0xFFFF);
}
-
+ else if (!(Write_Memory_Params.ProgrammingMode & PROG_MODE_WORD_READYBUSY_MASK))
+ {
+ Write_Memory_Params.ProgrammingMode &= ~PROG_MODE_WORD_VALUE_MASK;
+ Write_Memory_Params.ProgrammingMode |= PROG_MODE_WORD_TIMEDELAY_MASK;
+ }
+
ProgrammingStatus = ISPTarget_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue,
Write_Memory_Params.DelayMS, Write_Memory_Params.ProgrammingCommands[2]);
-
+
+ /* Restore previous programming mode mask in case the current word needed to change it */
+ Write_Memory_Params.ProgrammingMode = PreviousProgrammingMode;
+
/* Abort the programming loop early if the byte/word programming failed */
if (ProgrammingStatus != STATUS_CMD_OK)
break;
if ((CurrentByte & 0x01) || (V2Command == CMD_PROGRAM_EEPROM_ISP))
{
CurrentAddress++;
-
+
if ((V2Command != CMD_PROGRAM_EEPROM_ISP) && !(CurrentAddress & 0xFFFF))
- MustLoadExtendedAddress = true;
+ MustLoadExtendedAddress = true;
}
}
}
uint16_t BytesToRead;
uint8_t ReadMemoryCommand;
} Read_Memory_Params;
-
+
Endpoint_Read_Stream_LE(&Read_Memory_Params, sizeof(Read_Memory_Params), NO_STREAM_CALLBACK);
Read_Memory_Params.BytesToRead = SwapEndian_16(Read_Memory_Params.BytesToRead);
-
+
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
-
+
Endpoint_Write_Byte(V2Command);
Endpoint_Write_Byte(STATUS_CMD_OK);
ISPTarget_SendByte(CurrentAddress >> 8);
ISPTarget_SendByte(CurrentAddress & 0xFF);
Endpoint_Write_Byte(ISPTarget_ReceiveByte());
-
+
/* Check if the endpoint bank is currently full, if so send the packet */
if (!(Endpoint_IsReadWriteAllowed()))
{
Endpoint_ClearIN();
Endpoint_WaitUntilReady();
}
-
+
/* 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;
-
+
/* EEPROM just increments the address each byte, flash needs to increment on each word and
* also check to ensure that a LOAD EXTENDED ADDRESS command is issued each time the extended
* address boundary has been crossed */
if ((CurrentByte & 0x01) || (V2Command == CMD_READ_EEPROM_ISP))
{
CurrentAddress++;
-
+
if ((V2Command != CMD_READ_EEPROM_ISP) && !(CurrentAddress & 0xFFFF))
- MustLoadExtendedAddress = true;
+ MustLoadExtendedAddress = true;
}
}
bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
Endpoint_ClearIN();
-
+
/* Ensure last packet is a short packet to terminate the transfer */
if (IsEndpointFull)
{
- Endpoint_WaitUntilReady();
+ Endpoint_WaitUntilReady();
Endpoint_ClearIN();
- Endpoint_WaitUntilReady();
+ Endpoint_WaitUntilReady();
}
}
uint8_t PollMethod;
uint8_t EraseCommandBytes[4];
} Erase_Chip_Params;
-
+
Endpoint_Read_Stream_LE(&Erase_Chip_Params, sizeof(Erase_Chip_Params), NO_STREAM_CALLBACK);
-
+
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
-
+
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++)
ISPTarget_SendByte(Erase_Chip_Params.EraseCommandBytes[SByte]);
ISPProtocol_DelayMS(Erase_Chip_Params.EraseDelayMS);
else
ResponseStatus = ISPTarget_WaitWhileTargetBusy();
-
+
Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP);
Endpoint_Write_Byte(ResponseStatus);
Endpoint_ClearIN();
uint8_t RetByte;
uint8_t ReadCommandBytes[4];
} Read_FuseLockSigOSCCAL_Params;
-
+
Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params, sizeof(Read_FuseLockSigOSCCAL_Params), NO_STREAM_CALLBACK);
Endpoint_ClearOUT();
/* 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] = ISPTarget_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]);
-
+
Endpoint_Write_Byte(V2Command);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_Write_Byte(ResponseBytes[Read_FuseLockSigOSCCAL_Params.RetByte - 1]);
{
uint8_t WriteCommandBytes[4];
} Write_FuseLockSig_Params;
-
+
Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params, sizeof(Write_FuseLockSig_Params), NO_STREAM_CALLBACK);
Endpoint_ClearOUT();
/* 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++)
ISPTarget_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]);
-
+
Endpoint_Write_Byte(V2Command);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_Write_Byte(STATUS_CMD_OK);
uint8_t RxStartAddr;
uint8_t TxData[255];
} SPI_Multi_Params;
-
+
Endpoint_Read_Stream_LE(&SPI_Multi_Params, (sizeof(SPI_Multi_Params) - sizeof(SPI_Multi_Params.TxData)), NO_STREAM_CALLBACK);
Endpoint_Read_Stream_LE(&SPI_Multi_Params.TxData, SPI_Multi_Params.TxBytes, NO_STREAM_CALLBACK);
-
+
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
-
+
Endpoint_Write_Byte(CMD_SPI_MULTI);
Endpoint_Write_Byte(STATUS_CMD_OK);
ISPTarget_SendByte(SPI_Multi_Params.TxData[CurrTxPos]);
else
ISPTarget_SendByte(0);
-
+
CurrTxPos++;
}
Endpoint_Write_Byte(ISPTarget_TransferByte(SPI_Multi_Params.TxData[CurrTxPos++]));
else
Endpoint_Write_Byte(ISPTarget_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_WaitUntilReady();
Endpoint_ClearIN();
- Endpoint_WaitUntilReady();
+ Endpoint_WaitUntilReady();
}
}
_delay_ms(1);
}
-#endif
\ No newline at end of file
+#endif