From a7880ac1cdbfe8ddaf957173bc08f334aad8bca7 Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Tue, 15 Dec 2009 00:14:17 +0000 Subject: [PATCH] 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. --- Projects/AVRISP/Lib/NVMTarget.c | 67 ++++++++++++++++++------------- Projects/AVRISP/Lib/NVMTarget.h | 12 +++--- Projects/AVRISP/Lib/PDIProtocol.c | 10 +++-- Projects/AVRISP/Lib/PDITarget.c | 7 ++-- 4 files changed, 57 insertions(+), 39 deletions(-) diff --git a/Projects/AVRISP/Lib/NVMTarget.c b/Projects/AVRISP/Lib/NVMTarget.c index 85de130694..c2ed92d2e2 100644 --- a/Projects/AVRISP/Lib/NVMTarget.c +++ b/Projects/AVRISP/Lib/NVMTarget.c @@ -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 diff --git a/Projects/AVRISP/Lib/NVMTarget.h b/Projects/AVRISP/Lib/NVMTarget.h index b43967f996..dae55ed121 100644 --- a/Projects/AVRISP/Lib/NVMTarget.h +++ b/Projects/AVRISP/Lib/NVMTarget.h @@ -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 diff --git a/Projects/AVRISP/Lib/PDIProtocol.c b/Projects/AVRISP/Lib/PDIProtocol.c index 24ce26cb65..46d6dd417e 100644 --- a/Projects/AVRISP/Lib/PDIProtocol.c +++ b/Projects/AVRISP/Lib/PDIProtocol.c @@ -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); diff --git a/Projects/AVRISP/Lib/PDITarget.c b/Projects/AVRISP/Lib/PDITarget.c index c774fdab81..28df55021c 100644 --- a/Projects/AVRISP/Lib/PDITarget.c +++ b/Projects/AVRISP/Lib/PDITarget.c @@ -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))