From 7c8f4a716f01f6598234fd60cd53345da4903fde Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Mon, 28 Dec 2009 07:17:21 +0000 Subject: Add first draft of the TPI NVM commands for reading, writing and erasing a target. Needs testing when physical access to a part is available. --- Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c | 88 ++++++++++++++++++++++---- Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.h | 10 ++- Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c | 8 +-- Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.h | 2 +- Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c | 41 ++++++++---- Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.h | 7 +- Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h | 2 +- 7 files changed, 120 insertions(+), 38 deletions(-) (limited to 'Projects/AVRISP-MKII/Lib/XPROG') diff --git a/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c b/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c index 4292faad3..4d879bd67 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c +++ b/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c @@ -39,6 +39,16 @@ #if defined(ENABLE_XPROG_PROTOCOL) || defined(__DOXYGEN__) #warning TPI Protocol support is currently incomplete and is not suitable for general use. +/** Sends the given pointer address to the target's TPI pointer register */ +void TINYNVM_SendPointerAddress(const uint16_t AbsoluteAddress) +{ + /* Send the given 16-bit address to the target, LSB first */ + XPROGTarget_SendByte(TPI_CMD_SSTPR | 0); + XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[0]); + XPROGTarget_SendByte(TPI_CMD_SSTPR | 1); + XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[1]); +} + /** Busy-waits while the NVM controller is busy performing a NVM operation, such as a FLASH page read. * * \return Boolean true if the NVM controller became ready within the timeout period, false otherwise @@ -57,17 +67,52 @@ bool TINYNVM_WaitWhileNVMBusBusy(void) return false; } +/** Waits while the target's NVM controller is busy performing an operation, exiting if the + * timeout period expires. + * + * \return Boolean true if the NVM controller became ready within the timeout period, false otherwise + */ +bool TINYNVM_WaitWhileNVMControllerBusy(void) +{ + /* Poll the STATUS register to check to see if NVM access has been enabled */ + while (TimeoutMSRemaining) + { + /* Send the SIN command to read the TPI STATUS register to see the NVM bus is active */ + XPROGTarget_SendByte(TPI_CMD_SIN | XPROG_Param_NVMCSRRegAddr); + if (XPROGTarget_ReceiveByte() & (1 << 7)) + return true; + } + + return false; +} + /** Reads memory from the target's memory spaces. * * \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 + * \param[in] ReadSize Length of the data to read from the device * * \return Boolean true if the command sequence complete successfully */ -bool TINYNVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const uint16_t ReadSize) +bool TINYNVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize) { - // TODO + /* Wait until the NVM controller is no longer busy */ + if (!(TINYNVM_WaitWhileNVMControllerBusy())) + return false; + + /* Set the NVM control register to the NO OP command for memory reading */ + XPROGTarget_SendByte(TPI_CMD_SOUT | XPROG_Param_NVMCMDRegAddr); + XPROGTarget_SendByte(TINY_NVM_CMD_NOOP); + + /* Send the address of the location to read from */ + TINYNVM_SendPointerAddress(ReadAddress); + + while (ReadSize--) + { + /* Read the byte of data from the target */ + XPROGTarget_SendByte(TPI_CMD_SLD | TPI_POINTER_INDIRECT_PI); + *(ReadBuffer++) = XPROGTarget_ReceiveByte(); + } return true; } @@ -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 * \param[in] WriteBuffer Buffer to source data from * + * * \return Boolean true if the command sequence complete successfully */ -bool TINYNVM_WriteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer) +bool TINYNVM_WriteMemory(const uint32_t WriteAddress, const uint8_t Byte) { - // TODO + /* Wait until the NVM controller is no longer busy */ + if (!(TINYNVM_WaitWhileNVMControllerBusy())) + return false; + + /* Set the NVM control register to the WORD WRITE command for memory reading */ + XPROGTarget_SendByte(TPI_CMD_SOUT | XPROG_Param_NVMCMDRegAddr); + XPROGTarget_SendByte(TINY_NVM_CMD_WORDWRITE); + + /* Send the address of the location to write to */ + TINYNVM_SendPointerAddress(WriteAddress); + + /* Write the byte of data to the target */ + XPROGTarget_SendByte(TPI_CMD_SST | TPI_POINTER_INDIRECT); + XPROGTarget_SendByte(Byte); 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 +/** Erases the target's memory space. * * \return Boolean true if the command sequence complete successfully */ -bool TINYNVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address) +bool TINYNVM_EraseMemory(void) { - // TODO + /* Wait until the NVM controller is no longer busy */ + if (!(TINYNVM_WaitWhileNVMControllerBusy())) + return false; + + /* Set the NVM control register to the CHIP ERASE command to erase the target */ + XPROGTarget_SendByte(TPI_CMD_SOUT | XPROG_Param_NVMCMDRegAddr); + XPROGTarget_SendByte(TINY_NVM_CMD_CHIPERASE); + + /* Wait until the NVM bus is ready again */ + if (!(TINYNVM_WaitWhileNVMBusBusy())) + return false; return true; } diff --git a/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.h b/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.h index ae0728af3..2d98c0d48 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.h +++ b/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.h @@ -56,18 +56,16 @@ #endif /* Defines: */ - #define TINY_NVM_REG_NVMCSR 0x32 - #define TINY_NVM_REG_NVMCMD 0x33 - #define TINY_NVM_CMD_NOOP 0x00 #define TINY_NVM_CMD_CHIPERASE 0x10 #define TINY_NVM_CMD_SECTIONERASE 0x14 #define TINY_NVM_CMD_WORDWRITE 0x1D /* Function Prototypes: */ + void TINYNVM_SendPointerAddress(const uint16_t AbsoluteAddress); bool TINYNVM_WaitWhileNVMBusBusy(void); - bool TINYNVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const uint16_t ReadSize); - bool TINYNVM_WriteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer); - bool TINYNVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address); + bool TINYNVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadLength); + bool TINYNVM_WriteMemory(const uint32_t WriteAddress, const uint8_t Byte); + bool TINYNVM_EraseMemory(void); #endif diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c b/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c index 0bdafc2ac..ea140be7b 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c +++ b/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c @@ -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. * * \param[in] WriteCommand Command to send to the device to write each memory byte - * \param[in] WriteAddress Start address to write to within the target's address space - * \param[in] WriteBuffer Buffer to source data from + * \param[in] WriteAddress Address to write to within the target's address space + * \param[in] Byte Byte to write to the target * * \return Boolean true if the command sequence complete successfully */ -bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer) +bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t Byte) { /* Wait until the NVM controller is no longer busy */ if (!(XMEGANVM_WaitWhileNVMControllerBusy())) @@ -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 */ XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); XMEGANVM_SendAddress(WriteAddress); - XPROGTarget_SendByte(*(WriteBuffer++)); + XPROGTarget_SendByte(Byte); return true; } diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.h b/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.h index bc5772657..608f5ab79 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.h +++ b/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.h @@ -110,7 +110,7 @@ bool XMEGANVM_WaitWhileNVMControllerBusy(void); bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest); bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize); - bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer); + bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t Byte); bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t EraseBuffCommand, const uint8_t WritePageCommand, const uint8_t PageMode, const uint32_t WriteAddress, const uint8_t* WriteBuffer, uint16_t WriteSize); diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c b/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c index f3f888e1c..39f82a0df 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c +++ b/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c @@ -37,11 +37,17 @@ #include "XPROGProtocol.h" #if defined(ENABLE_XPROG_PROTOCOL) || defined(__DOXYGEN__) -/** Base absolute address for the target's NVM controller */ +/** Base absolute address for the target's NVM controller for PDI programming */ uint32_t XPROG_Param_NVMBase = 0x010001C0; /** Size in bytes of the target's EEPROM page */ -uint32_t XPROG_Param_EEPageSize; +uint16_t XPROG_Param_EEPageSize; + +/** Address of the TPI device's NVMCMD register for TPI programming */ +uint8_t XPROG_Param_NVMCMDRegAddr; + +/** Address of the TPI device's NVMCSR register for TPI programming */ +uint8_t XPROG_Param_NVMCSRRegAddr; /** Currently selected XPROG programming protocol */ uint8_t XPROG_SelectedProtocol = XPRG_PROTOCOL_PDI; @@ -222,7 +228,9 @@ static void XPROGProtocol_Erase(void) } else { - // TODO + /* Erase the target memory, indicate timeout if ocurred */ + if (!(TINYNVM_EraseMemory())) + ReturnStatus = XPRG_ERR_TIMEOUT; } Endpoint_Write_Byte(CMD_XPROG); @@ -294,18 +302,20 @@ static void XPROGProtocol_WriteMemory(void) } /* Send the appropriate memory write commands to the device, indicate timeout if occurred */ - if ((PagedMemory && !XMEGANVM_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand, + if ((PagedMemory && !(XMEGANVM_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand, WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address, - WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length)) || - (!PagedMemory && !XMEGANVM_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address, - WriteMemory_XPROG_Params.ProgData))) + WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length))) || + (!PagedMemory && !(XMEGANVM_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address, + WriteMemory_XPROG_Params.ProgData[0])))) { ReturnStatus = XPRG_ERR_TIMEOUT; } } else { - // TODO + /* Send write command to the TPI device, indicate timeout if occurred */ + if (!(TINYNVM_WriteMemory(WriteMemory_XPROG_Params.Address, WriteMemory_XPROG_Params.ProgData[0]))) + ReturnStatus = XPRG_ERR_TIMEOUT; } Endpoint_Write_Byte(CMD_XPROG); @@ -339,13 +349,15 @@ static void XPROGProtocol_ReadMemory(void) if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI) { - /* Read the target's memory, indicate timeout if occurred */ + /* Read the PDI target's memory, indicate timeout if occurred */ if (!(XMEGANVM_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length))) ReturnStatus = XPRG_ERR_TIMEOUT; } else { - // TODO + /* Read the TPI target's memory, indicate timeout if occurred */ + if (!(TINYNVM_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length))) + ReturnStatus = XPRG_ERR_TIMEOUT; } Endpoint_Write_Byte(CMD_XPROG); @@ -428,9 +440,12 @@ static void XPROGProtocol_SetParam(void) case XPRG_PARAM_EEPPAGESIZE: XPROG_Param_EEPageSize = Endpoint_Read_Word_BE(); break; - case XPRG_PARAM_UNDOC_1: - case XPRG_PARAM_UNDOC_2: - break; // Undocumented TPI parameter, just accept and discard + case XPRG_PARAM_NVMCMD: + XPROG_Param_NVMCMDRegAddr = Endpoint_Read_Byte(); + break; + case XPRG_PARAM_NVMCSR: + XPROG_Param_NVMCSRRegAddr = Endpoint_Read_Byte(); + break; default: ReturnStatus = XPRG_ERR_FAILED; break; diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.h b/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.h index e42e50cec..a95e5b851 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.h +++ b/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.h @@ -97,8 +97,8 @@ #define XPRG_PARAM_NVMBASE 0x01 #define XPRG_PARAM_EEPPAGESIZE 0x02 - #define XPRG_PARAM_UNDOC_1 0x03 - #define XPRG_PARAM_UNDOC_2 0x04 + #define XPRG_PARAM_NVMCMD 0x03 + #define XPRG_PARAM_NVMCSR 0x04 #define XPRG_PROTOCOL_PDI 0x00 #define XPRG_PROTOCOL_JTAG 0x01 @@ -109,6 +109,9 @@ /* External Variables: */ extern uint32_t XPROG_Param_NVMBase; + extern uint16_t XPROG_Param_EEPageSize; + extern uint8_t XPROG_Param_NVMCSRRegAddr; + extern uint8_t XPROG_Param_NVMCMDRegAddr; /* Function Prototypes: */ void XPROGProtocol_SetMode(void); diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h b/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h index a892829c1..f4c3b7b1d 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h +++ b/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h @@ -99,8 +99,8 @@ #define PDI_CTRL_REG 2 #define PDI_STATUS_NVM (1 << 1) - #define PDI_RESET_KEY 0x59 + #define PDI_RESET_KEY 0x59 #define PDI_NVMENABLE_KEY (uint8_t[]){0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF} #define PDI_DATSIZE_1BYTE 0 -- cgit v1.2.3