#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
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
* \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
#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
/** 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
/* 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
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
#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
}\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
}\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
\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
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
\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
#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