Fix error in AVRISP programmer when repeatedly using PDI mode via the hardware USART...
[pub/USBasp.git] / Projects / AVRISP / Lib / NVMTarget.c
index 85de130..c2ed92d 100644 (file)
@@ -93,16 +93,17 @@ bool NVMTarget_WaitWhileNVMControllerBusy(void)
 \r
 /** Retrieves the CRC value of the given memory space.\r
  *\r
- *  \param[in] CRCCommand  NVM CRC command to issue to the target\r
+ *  \param[in]  CRCCommand  NVM CRC command to issue to the target\r
+ *  \param[out] CRCDest     CRC Destination when read from the target\r
  *\r
- *  \return 24-bit CRC value for the given address space\r
+ *  \return Boolean true if the command sequence complete sucessfully\r
  */\r
-uint32_t NVMTarget_GetMemoryCRC(uint8_t CRCCommand)\r
+bool NVMTarget_GetMemoryCRC(uint8_t CRCCommand, uint32_t* CRCDest)\r
 {\r
-       uint32_t MemoryCRC;\r
-\r
-       NVMTarget_WaitWhileNVMControllerBusy();\r
-\r
+       /* Wait until the NVM controller is no longer busy */\r
+       if (!(NVMTarget_WaitWhileNVMControllerBusy()))\r
+         return false;\r
+         \r
        /* Set the NVM command to the correct CRC read command */\r
        PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));\r
        NVMTarget_SendNVMRegAddress(NVM_REG_CMD);\r
@@ -113,26 +114,28 @@ uint32_t NVMTarget_GetMemoryCRC(uint8_t CRCCommand)
        NVMTarget_SendNVMRegAddress(NVM_REG_CTRLA);\r
        PDITarget_SendByte(1 << 0);\r
 \r
-       /* Wait until the NVM bus and controller is no longer busy */\r
-       PDITarget_WaitWhileNVMBusBusy();\r
-       NVMTarget_WaitWhileNVMControllerBusy();\r
+       /* Wait until the NVM controller is no longer busy */\r
+       if (!(NVMTarget_WaitWhileNVMControllerBusy()))\r
+         return false;\r
+       \r
+       *CRCDest = 0;\r
        \r
        /* Read the first generated CRC byte value */\r
        PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));\r
        NVMTarget_SendNVMRegAddress(NVM_REG_DAT0);\r
-       MemoryCRC  = PDITarget_ReceiveByte();\r
+       *CRCDest  = PDITarget_ReceiveByte();\r
 \r
        /* Read the second generated CRC byte value */\r
        PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));\r
        NVMTarget_SendNVMRegAddress(NVM_REG_DAT1);\r
-       MemoryCRC |= ((uint16_t)PDITarget_ReceiveByte() << 8);\r
+       *CRCDest |= ((uint16_t)PDITarget_ReceiveByte() << 8);\r
 \r
        /* Read the third generated CRC byte value */\r
        PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));\r
        NVMTarget_SendNVMRegAddress(NVM_REG_DAT2);\r
-       MemoryCRC |= ((uint32_t)PDITarget_ReceiveByte() << 16);\r
+       *CRCDest |= ((uint32_t)PDITarget_ReceiveByte() << 16);\r
        \r
-       return MemoryCRC;\r
+       return true;\r
 }\r
 \r
 /** Reads memory from the target's memory spaces.\r
@@ -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\r
  *  \param[out] ReadBuffer   Buffer to store read data into\r
  *  \param[in]  ReadSize     Number of bytes to read\r
+ *\r
+ *  \return Boolean true if the command sequence complete sucessfully\r
  */\r
-void NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize)\r
+bool NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize)\r
 {\r
-       NVMTarget_WaitWhileNVMControllerBusy();\r
+       /* Wait until the NVM controller is no longer busy */\r
+       if (!(NVMTarget_WaitWhileNVMControllerBusy()))\r
+         return false;\r
        \r
        /* Send the READNVM command to the NVM controller for reading of an aribtrary location */\r
        PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));\r
@@ -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 */\r
        PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));\r
        NVMTarget_SendAddress(ReadAddress);\r
-       *(ReadBuffer++) = PDITarget_ReceiveByte();\r
+       *ReadBuffer = PDITarget_ReceiveByte();\r
 \r
        /* Check to see if we are reading more than a single byte */\r
        if (ReadSize > 1)\r
        {\r
-               /* Decrement the ReadSize counter as we have already read once byte of memory */\r
-               ReadSize--;\r
-       \r
                /* Send the REPEAT command with the specified number of bytes remaining to read */\r
                PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_2BYTES);\r
                PDITarget_SendByte(ReadSize &  0xFF);\r
@@ -169,20 +173,27 @@ void NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t Re
                \r
                /* Send a LD command with indirect access and postincrement to read out the remaining bytes */\r
                PDITarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);\r
-               for (uint16_t i = 1; i < ReadSize; i++)\r
+               for (uint16_t i = 0; i < ReadSize; i++)\r
                  *(ReadBuffer++) = PDITarget_ReceiveByte();\r
        }\r
+       \r
+       return true;\r
 }\r
 \r
 /** Erases a specific memory space of the target.\r
  *\r
  *  \param[in] EraseCommand  NVM erase command to send to the device\r
  *  \param[in] Address  Address inside the memory space to erase\r
+ *\r
+ *  \return Boolean true if the command sequence complete sucessfully\r
  */\r
-void NVMTarget_EraseMemory(uint8_t EraseCommand, uint32_t Address)\r
+bool NVMTarget_EraseMemory(uint8_t EraseCommand, uint32_t Address)\r
 {\r
-       NVMTarget_WaitWhileNVMControllerBusy();\r
-\r
+       /* Wait until the NVM controller is no longer busy */\r
+       if (!(NVMTarget_WaitWhileNVMControllerBusy()))\r
+         return false;\r
+         \r
+       /* Send the memory erase command to the target */\r
        PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));\r
        NVMTarget_SendNVMRegAddress(NVM_REG_CMD);\r
        PDITarget_SendByte(EraseCommand);\r
@@ -203,9 +214,11 @@ void NVMTarget_EraseMemory(uint8_t EraseCommand, uint32_t Address)
                PDITarget_SendByte(0x00);\r
        }\r
        \r
-       /* Wait until both the NVM bus and NVM controller are ready again */\r
-       PDITarget_WaitWhileNVMBusBusy();\r
-       NVMTarget_WaitWhileNVMControllerBusy();\r
+       /* Wait until the NVM bus is ready again */\r
+       if (!(PDITarget_WaitWhileNVMBusBusy()))\r
+         return false;\r
+         \r
+       return true;\r
 }\r
 \r
 #endif\r