forked from mfulz_github/qmk_firmware
Clean up and add more comments to the AVRISP-MKII project. Make sure the SPI_MULTI command handler supports multiple packet responses. Use slightly smaller/faster repeated indirect-load commands when retrieving the PDI target's memory CRCs.
This commit is contained in:
parent
b0ce1eab66
commit
f3d370a777
|
@ -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
|
* 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.
|
* internal empty stub function.
|
||||||
*
|
*
|
||||||
* Each event must only have one associated event handler, but can be raised by multiple sources by calling the event
|
* Each event must only have one associated event handler, but can be raised by multiple sources by calling the
|
||||||
* name just like any regular C function (with any required event parameters).
|
* 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
|
* \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see
|
||||||
* \ref Group_USBManagement documentation).
|
* \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.
|
* \see \ref EVENT_USB_Device_WakeUp() event for accompanying Wake Up event.
|
||||||
*/
|
*/
|
||||||
void EVENT_USB_Device_Suspend(void);
|
void EVENT_USB_Device_Suspend(void);
|
||||||
|
|
||||||
/** Event for USB wake up. This event fires when a the USB interface is suspended while in device
|
/** 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
|
* 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
|
* 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.
|
* 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
|
* \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see
|
||||||
* \ref Group_USBManagement documentation).
|
* \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.
|
* \see \ref EVENT_USB_Device_Suspend() event for accompanying Suspend event.
|
||||||
*/
|
*/
|
||||||
void EVENT_USB_Device_WakeUp(void);
|
void EVENT_USB_Device_WakeUp(void);
|
||||||
|
|
|
@ -151,9 +151,9 @@ USB_Descriptor_String_t PROGMEM ManufacturerString =
|
||||||
*/
|
*/
|
||||||
USB_Descriptor_String_t PROGMEM ProductString =
|
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 =
|
USB_Descriptor_String_t PROGMEM SerialString =
|
||||||
|
|
|
@ -66,6 +66,8 @@ void ISPProtocol_EnterISPMode(void)
|
||||||
ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS);
|
ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS);
|
||||||
SPI_Init(ISPTarget_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING | SPI_SAMPLE_LEADING | SPI_MODE_MASTER);
|
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))
|
while (Enter_ISP_Params.SynchLoops-- && (ResponseStatus == STATUS_CMD_FAILED))
|
||||||
{
|
{
|
||||||
uint8_t ResponseBytes[4];
|
uint8_t ResponseBytes[4];
|
||||||
|
@ -110,6 +112,7 @@ void ISPProtocol_LeaveISPMode(void)
|
||||||
Endpoint_ClearOUT();
|
Endpoint_ClearOUT();
|
||||||
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
|
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);
|
ISPProtocol_DelayMS(Leave_ISP_Params.PreDelayMS);
|
||||||
ISPTarget_ChangeTargetResetLine(false);
|
ISPTarget_ChangeTargetResetLine(false);
|
||||||
SPI_ShutDown();
|
SPI_ShutDown();
|
||||||
|
@ -166,6 +169,9 @@ void ISPProtocol_ProgramMemory(uint8_t V2Command)
|
||||||
Write_Memory_Params.PollValue2;
|
Write_Memory_Params.PollValue2;
|
||||||
uint8_t* NextWriteByte = Write_Memory_Params.ProgData;
|
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 (MustSetAddress)
|
||||||
{
|
{
|
||||||
if (CurrentAddress & (1UL << 31))
|
if (CurrentAddress & (1UL << 31))
|
||||||
|
@ -174,6 +180,7 @@ void ISPProtocol_ProgramMemory(uint8_t V2Command)
|
||||||
MustSetAddress = false;
|
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)
|
if (Write_Memory_Params.ProgrammingMode & PROG_MODE_PAGED_WRITES_MASK)
|
||||||
{
|
{
|
||||||
uint16_t StartAddress = (CurrentAddress & 0xFFFF);
|
uint16_t StartAddress = (CurrentAddress & 0xFFFF);
|
||||||
|
@ -184,16 +191,16 @@ void ISPProtocol_ProgramMemory(uint8_t V2Command)
|
||||||
bool IsOddByte = (CurrentByte & 0x01);
|
bool IsOddByte = (CurrentByte & 0x01);
|
||||||
uint8_t ByteToWrite = *(NextWriteByte++);
|
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(Write_Memory_Params.ProgrammingCommands[0]);
|
||||||
SPI_SendByte(CurrentAddress >> 8);
|
SPI_SendByte(CurrentAddress >> 8);
|
||||||
SPI_SendByte(CurrentAddress & 0xFF);
|
SPI_SendByte(CurrentAddress & 0xFF);
|
||||||
SPI_SendByte(ByteToWrite);
|
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 (!(PollAddress) && (ByteToWrite != PollValue))
|
||||||
{
|
{
|
||||||
if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP))
|
if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP))
|
||||||
|
@ -289,6 +296,9 @@ void ISPProtocol_ReadMemory(uint8_t V2Command)
|
||||||
Endpoint_Write_Byte(V2Command);
|
Endpoint_Write_Byte(V2Command);
|
||||||
Endpoint_Write_Byte(STATUS_CMD_OK);
|
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 (MustSetAddress)
|
||||||
{
|
{
|
||||||
if (CurrentAddress & (1UL << 31))
|
if (CurrentAddress & (1UL << 31))
|
||||||
|
@ -297,28 +307,30 @@ void ISPProtocol_ReadMemory(uint8_t V2Command)
|
||||||
MustSetAddress = false;
|
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++)
|
for (uint16_t CurrentByte = 0; CurrentByte < Read_Memory_Params.BytesToRead; CurrentByte++)
|
||||||
{
|
{
|
||||||
bool IsOddByte = (CurrentByte & 0x01);
|
/* Read the next byte from the desired memory space in the device */
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
SPI_SendByte(Read_Memory_Params.ReadMemoryCommand);
|
SPI_SendByte(Read_Memory_Params.ReadMemoryCommand);
|
||||||
SPI_SendByte(CurrentAddress >> 8);
|
SPI_SendByte(CurrentAddress >> 8);
|
||||||
SPI_SendByte(CurrentAddress & 0xFF);
|
SPI_SendByte(CurrentAddress & 0xFF);
|
||||||
Endpoint_Write_Byte(SPI_ReceiveByte());
|
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()))
|
if (!(Endpoint_IsReadWriteAllowed()))
|
||||||
{
|
{
|
||||||
Endpoint_ClearIN();
|
Endpoint_ClearIN();
|
||||||
Endpoint_WaitUntilReady();
|
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++;
|
CurrentAddress++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,9 +365,11 @@ void ISPProtocol_ChipErase(void)
|
||||||
|
|
||||||
uint8_t ResponseStatus = STATUS_CMD_OK;
|
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++)
|
for (uint8_t SByte = 0; SByte < sizeof(Erase_Chip_Params.EraseCommandBytes); SByte++)
|
||||||
SPI_SendByte(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))
|
if (!(Erase_Chip_Params.PollMethod))
|
||||||
ISPProtocol_DelayMS(Erase_Chip_Params.EraseDelayMS);
|
ISPProtocol_DelayMS(Erase_Chip_Params.EraseDelayMS);
|
||||||
else
|
else
|
||||||
|
@ -386,6 +400,7 @@ void ISPProtocol_ReadFuseLockSigOSCCAL(uint8_t V2Command)
|
||||||
|
|
||||||
uint8_t ResponseBytes[4];
|
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++)
|
for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
|
||||||
ResponseBytes[RByte] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]);
|
ResponseBytes[RByte] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]);
|
||||||
|
|
||||||
|
@ -413,6 +428,7 @@ void ISPProtocol_WriteFuseLock(uint8_t V2Command)
|
||||||
Endpoint_ClearOUT();
|
Endpoint_ClearOUT();
|
||||||
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
|
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++)
|
for (uint8_t SByte = 0; SByte < sizeof(Write_FuseLockSig_Params.WriteCommandBytes); SByte++)
|
||||||
SPI_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]);
|
SPI_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]);
|
||||||
|
|
||||||
|
@ -464,11 +480,28 @@ void ISPProtocol_SPIMulti(void)
|
||||||
else
|
else
|
||||||
Endpoint_Write_Byte(SPI_ReceiveByte());
|
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++;
|
CurrRxPos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Endpoint_Write_Byte(STATUS_CMD_OK);
|
Endpoint_Write_Byte(STATUS_CMD_OK);
|
||||||
|
|
||||||
|
bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
|
||||||
Endpoint_ClearIN();
|
Endpoint_ClearIN();
|
||||||
|
|
||||||
|
/* Ensure last packet is a short packet to terminate the transfer */
|
||||||
|
if (IsEndpointFull)
|
||||||
|
{
|
||||||
|
Endpoint_WaitUntilReady();
|
||||||
|
Endpoint_ClearIN();
|
||||||
|
Endpoint_WaitUntilReady();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -58,6 +58,7 @@ void V2Protocol_ProcessCommand(void)
|
||||||
{
|
{
|
||||||
uint8_t V2Command = Endpoint_Read_Byte();
|
uint8_t V2Command = Endpoint_Read_Byte();
|
||||||
|
|
||||||
|
/* Set total command processing timeout value, enable timeout management interrupt */
|
||||||
TimeoutMSRemaining = COMMAND_TIMEOUT_MS;
|
TimeoutMSRemaining = COMMAND_TIMEOUT_MS;
|
||||||
TIMSK0 |= (1 << OCIE0A);
|
TIMSK0 |= (1 << OCIE0A);
|
||||||
|
|
||||||
|
@ -121,6 +122,7 @@ void V2Protocol_ProcessCommand(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable timeout management interrupt once processing has completed */
|
||||||
TIMSK0 &= ~(1 << OCIE0A);
|
TIMSK0 &= ~(1 << OCIE0A);
|
||||||
|
|
||||||
Endpoint_WaitUntilReady();
|
Endpoint_WaitUntilReady();
|
||||||
|
@ -162,8 +164,8 @@ static void V2Protocol_SignOn(void)
|
||||||
Endpoint_ClearIN();
|
Endpoint_ClearIN();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Handler for the CMD_RESET_PROTECTION command, currently implemented as a dummy ACK function
|
/** Handler for the CMD_RESET_PROTECTION command, implemented as a dummy ACK function as
|
||||||
* as no ISP short-circuit protection is currently implemented.
|
* no target short-circuit protection is currently implemented.
|
||||||
*/
|
*/
|
||||||
static void V2Protocol_ResetProtection(void)
|
static void V2Protocol_ResetProtection(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -170,7 +170,7 @@ static ParameterItem_t* V2Params_GetParamFromTable(const uint8_t ParamID)
|
||||||
ParameterItem_t* CurrTableItem = ParameterTable;
|
ParameterItem_t* CurrTableItem = ParameterTable;
|
||||||
|
|
||||||
/* Find the parameter in the parameter table if present */
|
/* 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)
|
if (ParamID == CurrTableItem->ParamID)
|
||||||
return CurrTableItem;
|
return CurrTableItem;
|
||||||
|
|
|
@ -52,10 +52,13 @@
|
||||||
|
|
||||||
/* Macros: */
|
/* Macros: */
|
||||||
/** Parameter privilege mask to allow the host PC to read the parameter's value */
|
/** 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 */
|
/** 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 Defines: */
|
||||||
/** Type define for a parameter table entry indicating a PC readable or writable device parameter. */
|
/** Type define for a parameter table entry indicating a PC readable or writable device parameter. */
|
||||||
|
|
|
@ -136,24 +136,18 @@ bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest)
|
||||||
if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
|
if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint32_t MemoryCRC = 0;
|
/* Load the PDI pointer register with the DAT0 register start address */
|
||||||
|
XPROGTarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES);
|
||||||
/* Read the first generated CRC byte value */
|
|
||||||
XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
|
|
||||||
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT0);
|
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT0);
|
||||||
MemoryCRC = XPROGTarget_ReceiveByte();
|
|
||||||
|
|
||||||
/* Read the second generated CRC byte value */
|
/* Send the REPEAT command to grab the CRC bytes */
|
||||||
XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
|
XPROGTarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE);
|
||||||
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT1);
|
XPROGTarget_SendByte(XMEGA_CRC_LENGTH - 1);
|
||||||
MemoryCRC |= ((uint16_t)XPROGTarget_ReceiveByte() << 8);
|
|
||||||
|
|
||||||
/* Read the third generated CRC byte value */
|
/* Read in the CRC bytes from the target */
|
||||||
XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
|
XPROGTarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
|
||||||
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT2);
|
for (uint8_t i = 0; i < XMEGA_CRC_LENGTH; i++)
|
||||||
MemoryCRC |= ((uint32_t)XPROGTarget_ReceiveByte() << 16);
|
((uint8_t*)CRCDest)[i] = XPROGTarget_ReceiveByte();
|
||||||
|
|
||||||
*CRCDest = MemoryCRC;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Defines: */
|
/* Defines: */
|
||||||
|
#define XMEGA_CRC_LENGTH 3
|
||||||
|
|
||||||
#define XMEGA_NVM_REG_ADDR0 0x00
|
#define XMEGA_NVM_REG_ADDR0 0x00
|
||||||
#define XMEGA_NVM_REG_ADDR1 0x01
|
#define XMEGA_NVM_REG_ADDR1 0x01
|
||||||
#define XMEGA_NVM_REG_ADDR2 0x02
|
#define XMEGA_NVM_REG_ADDR2 0x02
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
#if defined(ENABLE_XPROG_PROTOCOL) || defined(__DOXYGEN__)
|
#if defined(ENABLE_XPROG_PROTOCOL) || defined(__DOXYGEN__)
|
||||||
/** Base absolute address for the target's NVM controller for PDI programming */
|
/** 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 */
|
/** Size in bytes of the target's EEPROM page */
|
||||||
uint16_t XPROG_Param_EEPageSize;
|
uint16_t XPROG_Param_EEPageSize;
|
||||||
|
@ -455,10 +455,10 @@ static void XPROGProtocol_SetParam(void)
|
||||||
case XPRG_PARAM_EEPPAGESIZE:
|
case XPRG_PARAM_EEPPAGESIZE:
|
||||||
XPROG_Param_EEPageSize = Endpoint_Read_Word_BE();
|
XPROG_Param_EEPageSize = Endpoint_Read_Word_BE();
|
||||||
break;
|
break;
|
||||||
case XPRG_PARAM_NVMCMD:
|
case XPRG_PARAM_NVMCMD_REG:
|
||||||
XPROG_Param_NVMCMDRegAddr = Endpoint_Read_Byte();
|
XPROG_Param_NVMCMDRegAddr = Endpoint_Read_Byte();
|
||||||
break;
|
break;
|
||||||
case XPRG_PARAM_NVMCSR:
|
case XPRG_PARAM_NVMCSR_REG:
|
||||||
XPROG_Param_NVMCSRRegAddr = Endpoint_Read_Byte();
|
XPROG_Param_NVMCSRRegAddr = Endpoint_Read_Byte();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -98,12 +98,12 @@
|
||||||
|
|
||||||
#define XPRG_PARAM_NVMBASE 0x01
|
#define XPRG_PARAM_NVMBASE 0x01
|
||||||
#define XPRG_PARAM_EEPPAGESIZE 0x02
|
#define XPRG_PARAM_EEPPAGESIZE 0x02
|
||||||
#define XPRG_PARAM_NVMCMD 0x03
|
#define XPRG_PARAM_NVMCMD_REG 0x03 /* Undocumented, Reverse-engineered */
|
||||||
#define XPRG_PARAM_NVMCSR 0x04
|
#define XPRG_PARAM_NVMCSR_REG 0x04 /* Undocumented, Reverse-engineered */
|
||||||
|
|
||||||
#define XPRG_PROTOCOL_PDI 0x00
|
#define XPRG_PROTOCOL_PDI 0x00
|
||||||
#define XPRG_PROTOCOL_JTAG 0x01
|
#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_WRITE (1 << 1)
|
||||||
#define XPRG_PAGEMODE_ERASE (1 << 0)
|
#define XPRG_PAGEMODE_ERASE (1 << 0)
|
||||||
|
|
Loading…
Reference in New Issue