diff options
-rw-r--r-- | Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c | 88 | ||||
-rw-r--r-- | Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.h | 10 | ||||
-rw-r--r-- | Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c | 8 | ||||
-rw-r--r-- | Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.h | 2 | ||||
-rw-r--r-- | Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c | 41 | ||||
-rw-r--r-- | Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.h | 7 | ||||
-rw-r--r-- | Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h | 2 |
7 files changed, 120 insertions, 38 deletions
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
|