Commit 7c8f4a71 authored by Dean Camera's avatar Dean Camera
Browse files

Add first draft of the TPI NVM commands for reading, writing and erasing a...

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.
parent 3222f21b
......@@ -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;
}
......
......@@ -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
......@@ -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;
}
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment