Add first draft of the TPI NVM commands for reading, writing and erasing a target...
authorDean Camera <dean@fourwalledcubicle.com>
Mon, 28 Dec 2009 07:17:21 +0000 (07:17 +0000)
committerDean Camera <dean@fourwalledcubicle.com>
Mon, 28 Dec 2009 07:17:21 +0000 (07:17 +0000)
Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c
Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.h
Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c
Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.h
Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c
Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.h
Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h

index 4292faa..4d879bd 100644 (file)
 #if defined(ENABLE_XPROG_PROTOCOL) || defined(__DOXYGEN__)\r
 #warning TPI Protocol support is currently incomplete and is not suitable for general use.\r
 \r
+/** Sends the given pointer address to the target's TPI pointer register */\r
+void TINYNVM_SendPointerAddress(const uint16_t AbsoluteAddress)\r
+{\r
+       /* Send the given 16-bit address to the target, LSB first */\r
+       XPROGTarget_SendByte(TPI_CMD_SSTPR | 0);\r
+       XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[0]);\r
+       XPROGTarget_SendByte(TPI_CMD_SSTPR | 1);\r
+       XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[1]);\r
+}\r
+\r
 /** Busy-waits while the NVM controller is busy performing a NVM operation, such as a FLASH page read.\r
  *\r
  *  \return Boolean true if the NVM controller became ready within the timeout period, false otherwise\r
@@ -57,17 +67,52 @@ bool TINYNVM_WaitWhileNVMBusBusy(void)
        return false;\r
 }\r
 \r
+/** Waits while the target's NVM controller is busy performing an operation, exiting if the\r
+ *  timeout period expires.\r
+ *\r
+ *  \return Boolean true if the NVM controller became ready within the timeout period, false otherwise\r
+ */\r
+bool TINYNVM_WaitWhileNVMControllerBusy(void)\r
+{\r
+       /* Poll the STATUS register to check to see if NVM access has been enabled */\r
+       while (TimeoutMSRemaining)\r
+       {\r
+               /* Send the SIN command to read the TPI STATUS register to see the NVM bus is active */\r
+               XPROGTarget_SendByte(TPI_CMD_SIN | XPROG_Param_NVMCSRRegAddr);\r
+               if (XPROGTarget_ReceiveByte() & (1 << 7))\r
+                 return true;\r
+       }\r
+       \r
+       return false;\r
+}\r
+\r
 /** Reads memory from the target's memory spaces.\r
  *\r
  *  \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
+ *  \param[in]  ReadSize     Length of the data to read from the device\r
  *\r
  *  \return Boolean true if the command sequence complete successfully\r
  */\r
-bool TINYNVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const uint16_t ReadSize)\r
+bool TINYNVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize)\r
 {\r
-       // TODO\r
+       /* Wait until the NVM controller is no longer busy */\r
+       if (!(TINYNVM_WaitWhileNVMControllerBusy()))\r
+         return false;\r
+\r
+       /* Set the NVM control register to the NO OP command for memory reading */\r
+       XPROGTarget_SendByte(TPI_CMD_SOUT | XPROG_Param_NVMCMDRegAddr);\r
+       XPROGTarget_SendByte(TINY_NVM_CMD_NOOP);\r
+       \r
+       /* Send the address of the location to read from */\r
+       TINYNVM_SendPointerAddress(ReadAddress);\r
+       \r
+       while (ReadSize--)\r
+       {\r
+               /* Read the byte of data from the target */\r
+               XPROGTarget_SendByte(TPI_CMD_SLD | TPI_POINTER_INDIRECT_PI);\r
+               *(ReadBuffer++) = XPROGTarget_ReceiveByte();\r
+       }\r
        \r
        return true;\r
 }\r
@@ -78,25 +123,46 @@ bool TINYNVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const u
  *  \param[in]  WriteAddress  Start address to write to within the target's address space\r
  *  \param[in]  WriteBuffer   Buffer to source data from\r
  *\r
+ *\r
  *  \return Boolean true if the command sequence complete successfully\r
  */\r
-bool TINYNVM_WriteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer)\r
+bool TINYNVM_WriteMemory(const uint32_t WriteAddress, const uint8_t Byte)\r
 {\r
-       // TODO\r
+       /* Wait until the NVM controller is no longer busy */\r
+       if (!(TINYNVM_WaitWhileNVMControllerBusy()))\r
+         return false;\r
+\r
+       /* Set the NVM control register to the WORD WRITE command for memory reading */\r
+       XPROGTarget_SendByte(TPI_CMD_SOUT | XPROG_Param_NVMCMDRegAddr);\r
+       XPROGTarget_SendByte(TINY_NVM_CMD_WORDWRITE);\r
+       \r
+       /* Send the address of the location to write to */\r
+       TINYNVM_SendPointerAddress(WriteAddress);\r
+       \r
+       /* Write the byte of data to the target */\r
+       XPROGTarget_SendByte(TPI_CMD_SST | TPI_POINTER_INDIRECT);\r
+       XPROGTarget_SendByte(Byte);\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
+/** Erases the target's memory space.\r
  *\r
  *  \return Boolean true if the command sequence complete successfully\r
  */\r
-bool TINYNVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address)\r
+bool TINYNVM_EraseMemory(void)\r
 {\r
-       // TODO\r
+       /* Wait until the NVM controller is no longer busy */\r
+       if (!(TINYNVM_WaitWhileNVMControllerBusy()))\r
+         return false;\r
+\r
+       /* Set the NVM control register to the CHIP ERASE command to erase the target */\r
+       XPROGTarget_SendByte(TPI_CMD_SOUT | XPROG_Param_NVMCMDRegAddr);\r
+       XPROGTarget_SendByte(TINY_NVM_CMD_CHIPERASE);   \r
+\r
+       /* Wait until the NVM bus is ready again */\r
+       if (!(TINYNVM_WaitWhileNVMBusBusy()))\r
+         return false;\r
        \r
        return true;\r
 }\r
index ae0728a..2d98c0d 100644 (file)
                #endif\r
 \r
        /* Defines: */\r
-               #define TINY_NVM_REG_NVMCSR            0x32\r
-               #define TINY_NVM_REG_NVMCMD            0x33\r
-\r
                #define TINY_NVM_CMD_NOOP              0x00\r
                #define TINY_NVM_CMD_CHIPERASE         0x10\r
                #define TINY_NVM_CMD_SECTIONERASE      0x14\r
                #define TINY_NVM_CMD_WORDWRITE         0x1D\r
 \r
        /* Function Prototypes: */\r
+               void TINYNVM_SendPointerAddress(const uint16_t AbsoluteAddress);\r
                bool TINYNVM_WaitWhileNVMBusBusy(void);\r
-               bool TINYNVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const uint16_t ReadSize);\r
-               bool TINYNVM_WriteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer);\r
-               bool TINYNVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address);\r
+               bool TINYNVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadLength);\r
+               bool TINYNVM_WriteMemory(const uint32_t WriteAddress, const uint8_t Byte);\r
+               bool TINYNVM_EraseMemory(void);\r
 \r
 #endif\r
index 0bdafc2..ea140be 100644 (file)
@@ -196,12 +196,12 @@ bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, uint16
 /** Writes byte addressed memory to the target's memory spaces.\r
  *\r
  *  \param[in]  WriteCommand  Command to send to the device to write each memory byte\r
- *  \param[in]  WriteAddress  Start address to write to within the target's address space\r
- *  \param[in]  WriteBuffer   Buffer to source data from\r
+ *  \param[in]  WriteAddress  Address to write to within the target's address space\r
+ *  \param[in]  Byte          Byte to write to the target\r
  *\r
  *  \return Boolean true if the command sequence complete successfully\r
  */\r
-bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer)\r
+bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t Byte)\r
 {\r
        /* Wait until the NVM controller is no longer busy */\r
        if (!(XMEGANVM_WaitWhileNVMControllerBusy()))\r
@@ -215,7 +215,7 @@ bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAd
        /* Send new memory byte to the memory to the target */\r
        XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));\r
        XMEGANVM_SendAddress(WriteAddress);\r
-       XPROGTarget_SendByte(*(WriteBuffer++));\r
+       XPROGTarget_SendByte(Byte);\r
        \r
        return true;\r
 }\r
index bc57726..608f5ab 100644 (file)
                bool XMEGANVM_WaitWhileNVMControllerBusy(void);\r
                bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest);\r
                bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize);\r
-               bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer);\r
+               bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t Byte);\r
                bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t EraseBuffCommand,\r
                                              const uint8_t WritePageCommand, const uint8_t PageMode, const uint32_t WriteAddress,\r
                                              const uint8_t* WriteBuffer, uint16_t WriteSize);\r
index f3f888e..39f82a0 100644 (file)
 #include "XPROGProtocol.h"\r
 \r
 #if defined(ENABLE_XPROG_PROTOCOL) || defined(__DOXYGEN__)\r
-/** Base absolute address for the target's NVM controller */\r
+/** Base absolute address for the target's NVM controller for PDI programming */\r
 uint32_t XPROG_Param_NVMBase    = 0x010001C0;\r
 \r
 /** Size in bytes of the target's EEPROM page */\r
-uint32_t XPROG_Param_EEPageSize;\r
+uint16_t XPROG_Param_EEPageSize;\r
+\r
+/** Address of the TPI device's NVMCMD register for TPI programming */\r
+uint8_t  XPROG_Param_NVMCMDRegAddr;\r
+\r
+/** Address of the TPI device's NVMCSR register for TPI programming */\r
+uint8_t  XPROG_Param_NVMCSRRegAddr;\r
 \r
 /** Currently selected XPROG programming protocol */\r
 uint8_t  XPROG_SelectedProtocol = XPRG_PROTOCOL_PDI;\r
@@ -222,7 +228,9 @@ static void XPROGProtocol_Erase(void)
        }\r
        else\r
        {\r
-               // TODO\r
+               /* Erase the target memory, indicate timeout if ocurred */\r
+               if (!(TINYNVM_EraseMemory()))\r
+                 ReturnStatus = XPRG_ERR_TIMEOUT;\r
        }\r
        \r
        Endpoint_Write_Byte(CMD_XPROG);\r
@@ -294,18 +302,20 @@ static void XPROGProtocol_WriteMemory(void)
                }\r
                \r
                /* Send the appropriate memory write commands to the device, indicate timeout if occurred */\r
-               if ((PagedMemory && !XMEGANVM_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand, \r
+               if ((PagedMemory && !(XMEGANVM_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand, \r
                                                                                                           WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address,\r
-                                                                                                          WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length)) ||\r
-                  (!PagedMemory && !XMEGANVM_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address,\r
-                                                                                                          WriteMemory_XPROG_Params.ProgData)))\r
+                                                                                                          WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length))) ||\r
+                  (!PagedMemory && !(XMEGANVM_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address,\r
+                                                                                                          WriteMemory_XPROG_Params.ProgData[0]))))\r
                {\r
                        ReturnStatus = XPRG_ERR_TIMEOUT;\r
                }\r
        }\r
        else\r
        {\r
-               // TODO\r
+               /* Send write command to the TPI device, indicate timeout if occurred */\r
+               if (!(TINYNVM_WriteMemory(WriteMemory_XPROG_Params.Address, WriteMemory_XPROG_Params.ProgData[0])))\r
+                 ReturnStatus = XPRG_ERR_TIMEOUT;\r
        }\r
        \r
        Endpoint_Write_Byte(CMD_XPROG);\r
@@ -339,13 +349,15 @@ static void XPROGProtocol_ReadMemory(void)
        \r
        if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)\r
        {\r
-               /* Read the target's memory, indicate timeout if occurred */\r
+               /* Read the PDI target's memory, indicate timeout if occurred */\r
                if (!(XMEGANVM_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length)))\r
                  ReturnStatus = XPRG_ERR_TIMEOUT;\r
        }\r
        else\r
        {\r
-               // TODO\r
+               /* Read the TPI target's memory, indicate timeout if occurred */\r
+               if (!(TINYNVM_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length)))\r
+                 ReturnStatus = XPRG_ERR_TIMEOUT;\r
        }\r
 \r
        Endpoint_Write_Byte(CMD_XPROG);\r
@@ -428,9 +440,12 @@ static void XPROGProtocol_SetParam(void)
                case XPRG_PARAM_EEPPAGESIZE:\r
                        XPROG_Param_EEPageSize = Endpoint_Read_Word_BE();\r
                        break;\r
-               case XPRG_PARAM_UNDOC_1:\r
-               case XPRG_PARAM_UNDOC_2:\r
-                       break; // Undocumented TPI parameter, just accept and discard\r
+               case XPRG_PARAM_NVMCMD:\r
+                       XPROG_Param_NVMCMDRegAddr = Endpoint_Read_Byte();\r
+                       break;\r
+               case XPRG_PARAM_NVMCSR:\r
+                       XPROG_Param_NVMCSRRegAddr = Endpoint_Read_Byte();\r
+                       break;\r
                default:\r
                        ReturnStatus = XPRG_ERR_FAILED;\r
                        break;\r
index e42e50c..a95e5b8 100644 (file)
@@ -97,8 +97,8 @@
 \r
                #define XPRG_PARAM_NVMBASE                  0x01\r
                #define XPRG_PARAM_EEPPAGESIZE              0x02\r
-               #define XPRG_PARAM_UNDOC_1                  0x03\r
-               #define XPRG_PARAM_UNDOC_2                  0x04\r
+               #define XPRG_PARAM_NVMCMD                   0x03\r
+               #define XPRG_PARAM_NVMCSR                   0x04\r
                \r
                #define XPRG_PROTOCOL_PDI                   0x00\r
                #define XPRG_PROTOCOL_JTAG                  0x01\r
        \r
        /* External Variables: */\r
                extern uint32_t XPROG_Param_NVMBase;\r
+               extern uint16_t XPROG_Param_EEPageSize;\r
+               extern uint8_t  XPROG_Param_NVMCSRRegAddr;\r
+               extern uint8_t  XPROG_Param_NVMCMDRegAddr;\r
                \r
        /* Function Prototypes: */\r
                void XPROGProtocol_SetMode(void);\r
index a892829..f4c3b7b 100644 (file)
@@ -99,8 +99,8 @@
                #define PDI_CTRL_REG               2\r
                \r
                #define PDI_STATUS_NVM             (1 << 1)\r
-               #define PDI_RESET_KEY              0x59\r
 \r
+               #define PDI_RESET_KEY              0x59\r
                #define PDI_NVMENABLE_KEY          (uint8_t[]){0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF}\r
 \r
                #define PDI_DATSIZE_1BYTE          0\r