Commit a7880ac1 authored by Dean Camera's avatar Dean Camera
Browse files

Fix error in AVRISP programmer when repeatedly using PDI mode via the hardware...

Fix error in AVRISP programmer when repeatedly using PDI mode via the hardware USART due to the SendByte routine not clearing the Transmit Complete USART flag.
parent bb387933
......@@ -93,16 +93,17 @@ bool NVMTarget_WaitWhileNVMControllerBusy(void)
/** Retrieves the CRC value of the given memory space.
*
* \param[in] CRCCommand NVM CRC command to issue to the target
* \param[in] CRCCommand NVM CRC command to issue to the target
* \param[out] CRCDest CRC Destination when read from the target
*
* \return 24-bit CRC value for the given address space
* \return Boolean true if the command sequence complete sucessfully
*/
uint32_t NVMTarget_GetMemoryCRC(uint8_t CRCCommand)
bool NVMTarget_GetMemoryCRC(uint8_t CRCCommand, uint32_t* CRCDest)
{
uint32_t MemoryCRC;
NVMTarget_WaitWhileNVMControllerBusy();
/* Wait until the NVM controller is no longer busy */
if (!(NVMTarget_WaitWhileNVMControllerBusy()))
return false;
/* Set the NVM command to the correct CRC read command */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
......@@ -113,26 +114,28 @@ uint32_t NVMTarget_GetMemoryCRC(uint8_t CRCCommand)
NVMTarget_SendNVMRegAddress(NVM_REG_CTRLA);
PDITarget_SendByte(1 << 0);
/* Wait until the NVM bus and controller is no longer busy */
PDITarget_WaitWhileNVMBusBusy();
NVMTarget_WaitWhileNVMControllerBusy();
/* Wait until the NVM controller is no longer busy */
if (!(NVMTarget_WaitWhileNVMControllerBusy()))
return false;
*CRCDest = 0;
/* Read the first generated CRC byte value */
PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
NVMTarget_SendNVMRegAddress(NVM_REG_DAT0);
MemoryCRC = PDITarget_ReceiveByte();
*CRCDest = PDITarget_ReceiveByte();
/* Read the second generated CRC byte value */
PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
NVMTarget_SendNVMRegAddress(NVM_REG_DAT1);
MemoryCRC |= ((uint16_t)PDITarget_ReceiveByte() << 8);
*CRCDest |= ((uint16_t)PDITarget_ReceiveByte() << 8);
/* Read the third generated CRC byte value */
PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
NVMTarget_SendNVMRegAddress(NVM_REG_DAT2);
MemoryCRC |= ((uint32_t)PDITarget_ReceiveByte() << 16);
*CRCDest |= ((uint32_t)PDITarget_ReceiveByte() << 16);
return MemoryCRC;
return true;
}
/** Reads memory from the target's memory spaces.
......@@ -140,10 +143,14 @@ uint32_t NVMTarget_GetMemoryCRC(uint8_t CRCCommand)
* \param[in] ReadAddress Start address to read from within the target's address space
* \param[out] ReadBuffer Buffer to store read data into
* \param[in] ReadSize Number of bytes to read
*
* \return Boolean true if the command sequence complete sucessfully
*/
void NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize)
bool NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize)
{
NVMTarget_WaitWhileNVMControllerBusy();
/* Wait until the NVM controller is no longer busy */
if (!(NVMTarget_WaitWhileNVMControllerBusy()))
return false;
/* Send the READNVM command to the NVM controller for reading of an aribtrary location */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
......@@ -154,14 +161,11 @@ void NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t Re
* counters so that we can use the REPEAT command later to save on overhead for multiple bytes */
PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
NVMTarget_SendAddress(ReadAddress);
*(ReadBuffer++) = PDITarget_ReceiveByte();
*ReadBuffer = PDITarget_ReceiveByte();
/* Check to see if we are reading more than a single byte */
if (ReadSize > 1)
{
/* Decrement the ReadSize counter as we have already read once byte of memory */
ReadSize--;
/* Send the REPEAT command with the specified number of bytes remaining to read */
PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_2BYTES);
PDITarget_SendByte(ReadSize & 0xFF);
......@@ -169,20 +173,27 @@ void NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t Re
/* Send a LD command with indirect access and postincrement to read out the remaining bytes */
PDITarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
for (uint16_t i = 1; i < ReadSize; i++)
for (uint16_t i = 0; i < ReadSize; i++)
*(ReadBuffer++) = PDITarget_ReceiveByte();
}
return true;
}
/** Erases a specific memory space of the target.
*
* \param[in] EraseCommand NVM erase command to send to the device
* \param[in] Address Address inside the memory space to erase
*
* \return Boolean true if the command sequence complete sucessfully
*/
void NVMTarget_EraseMemory(uint8_t EraseCommand, uint32_t Address)
bool NVMTarget_EraseMemory(uint8_t EraseCommand, uint32_t Address)
{
NVMTarget_WaitWhileNVMControllerBusy();
/* Wait until the NVM controller is no longer busy */
if (!(NVMTarget_WaitWhileNVMControllerBusy()))
return false;
/* Send the memory erase command to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
PDITarget_SendByte(EraseCommand);
......@@ -203,9 +214,11 @@ void NVMTarget_EraseMemory(uint8_t EraseCommand, uint32_t Address)
PDITarget_SendByte(0x00);
}
/* Wait until both the NVM bus and NVM controller are ready again */
PDITarget_WaitWhileNVMBusBusy();
NVMTarget_WaitWhileNVMControllerBusy();
/* Wait until the NVM bus is ready again */
if (!(PDITarget_WaitWhileNVMBusBusy()))
return false;
return true;
}
#endif
......@@ -106,11 +106,11 @@
#define NVM_CMD_READEEPROM 0x06
/* Function Prototypes: */
void NVMTarget_SendNVMRegAddress(uint8_t Register);
void NVMTarget_SendAddress(uint32_t AbsoluteAddress);
bool NVMTarget_WaitWhileNVMControllerBusy(void);
uint32_t NVMTarget_GetMemoryCRC(uint8_t CRCCommand);
void NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize);
void NVMTarget_EraseMemory(uint8_t EraseCommand, uint32_t Address);
void NVMTarget_SendNVMRegAddress(uint8_t Register);
void NVMTarget_SendAddress(uint32_t AbsoluteAddress);
bool NVMTarget_WaitWhileNVMControllerBusy(void);
bool NVMTarget_GetMemoryCRC(uint8_t CRCCommand, uint32_t* CRCDest);
bool NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize);
bool NVMTarget_EraseMemory(uint8_t EraseCommand, uint32_t Address);
#endif
......@@ -181,7 +181,8 @@ static void PDIProtocol_Erase(void)
else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_USERSIG)
EraseCommand = NVM_CMD_ERASEUSERSIG;
NVMTarget_EraseMemory(EraseCommand, Erase_XPROG_Params.Address);
if (!(NVMTarget_EraseMemory(EraseCommand, Erase_XPROG_Params.Address)))
ReturnStatus = XPRG_ERR_TIMEOUT;
Endpoint_Write_Byte(CMD_XPROG);
Endpoint_Write_Byte(XPRG_CMD_ERASE);
......@@ -241,7 +242,9 @@ static void PDIProtocol_ReadMemory(void)
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t ReadBuffer[ReadMemory_XPROG_Params.Length];
NVMTarget_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length);
if (!(NVMTarget_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length)))
ReturnStatus = XPRG_ERR_TIMEOUT;
Endpoint_Write_Byte(CMD_XPROG);
Endpoint_Write_Byte(XPRG_CMD_READ_MEM);
......@@ -279,7 +282,8 @@ static void PDIProtocol_ReadCRC(void)
else
CRCCommand = NVM_CMD_FLASHCRC;
MemoryCRC = NVMTarget_GetMemoryCRC(CRCCommand);
if (!(NVMTarget_GetMemoryCRC(CRCCommand, &MemoryCRC)))
ReturnStatus = XPRG_ERR_TIMEOUT;
Endpoint_Write_Byte(CMD_XPROG);
Endpoint_Write_Byte(XPRG_CMD_CRC);
......
......@@ -102,7 +102,7 @@ void PDITarget_EnableTargetPDI(void)
/* Set up the synchronous USART for XMEGA communications -
8 data bits, even parity, 2 stop bits */
UBRR1 = 10;
UBRR1 = (F_CPU / 1000000UL);
UCSR1B = (1 << TXEN1);
UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);
......@@ -167,15 +167,16 @@ void PDITarget_SendByte(uint8_t Byte)
PORTD |= (1 << 3);
DDRD |= (1 << 3);
UCSR1B &= ~(1 << RXEN1);
UCSR1B |= (1 << TXEN1);
UCSR1B &= ~(1 << RXEN1);
IsSending = true;
}
/* Wait until there is space in the hardware Tx buffer before writing */
while (!(UCSR1A & (1 << UDRE1)));
UDR1 = Byte;
UCSR1A |= (1 << TXC1);
UDR1 = Byte;
#else
/* Switch to Tx mode if currently in Rx mode */
if (!(IsSending))
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment