Use _delay_us() function in the XPROGTarget.c file to ensure timing requirements...
[pub/USBasp.git] / Projects / AVRISP-MKII / Lib / XPROG / TINYNVM.c
index 3ddd2ed..e751303 100644 (file)
@@ -1,21 +1,21 @@
 /*\r
              LUFA Library\r
-     Copyright (C) Dean Camera, 2009.\r
+     Copyright (C) Dean Camera, 2010.\r
               \r
   dean [at] fourwalledcubicle [dot] com\r
       www.fourwalledcubicle.com\r
 */\r
 \r
 /*\r
-  Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
-  Permission to use, copy, modify, and distribute this software\r
-  and its documentation for any purpose and without fee is hereby\r
-  granted, provided that the above copyright notice appear in all\r
-  copies and that both that the copyright notice and this\r
-  permission notice and warranty disclaimer appear in supporting\r
-  documentation, and that the name of the author not be used in\r
-  advertising or publicity pertaining to distribution of the\r
+  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+  Permission to use, copy, modify, distribute, and sell this \r
+  software and its documentation for any purpose is hereby granted\r
+  without fee, provided that the above copyright notice appear in \r
+  all copies and that both that the copyright notice and this\r
+  permission notice and warranty disclaimer appear in supporting \r
+  documentation, and that the name of the author not be used in \r
+  advertising or publicity pertaining to distribution of the \r
   software without specific, written prior permission.\r
 \r
   The author disclaim all warranties with regard to this\r
 #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
+static 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
+/** Sends a SIN command to the target with the specified I/O address, ready for the data byte to be written.\r
+ *\r
+ *  \param[in] Address  6-bit I/O address to write to in the target's I/O memory space\r
+ */\r
+static void TINYNVM_SendReadNVMRegister(uint8_t Address)\r
+{\r
+       /* The TPI command for reading from the I/O space uses strange addressing, where the I/O address's upper\r
+        * two bits of the 6-bit address are shifted left once */\r
+       XPROGTarget_SendByte(TPI_CMD_SIN | ((Address & 0x30) << 1) | (Address & 0x0F));\r
+}\r
+\r
+/** Sends a SOUT command to the target with the specified I/O address, ready for the data byte to be read.\r
+ *\r
+ *  \param[in] Address  6-bit I/O address to read from in the target's I/O memory space\r
+ */\r
+static void TINYNVM_SendWriteNVMRegister(uint8_t Address)\r
+{\r
+       /* The TPI command for writing to the I/O space uses wierd addressing, where the I/O address's upper\r
+        * two bits of the 6-bit address are shifted left once */\r
+       XPROGTarget_SendByte(TPI_CMD_SOUT | ((Address & 0x30) << 1) | (Address & 0x0F));\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,46 +89,106 @@ 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 busy */\r
+               TINYNVM_SendReadNVMRegister(XPROG_Param_NVMCSRRegAddr);\r
+\r
+               /* Check to see if the BUSY flag is still set */\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 uint16_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
+       TINYNVM_SendWriteNVMRegister(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
 \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]  WriteLength   Total number of bytes to write to the device\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 uint16_t WriteAddress, const uint8_t* WriteBuffer, uint16_t WriteLength)\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
+       TINYNVM_SendWriteNVMRegister(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
+       while (WriteLength--)\r
+       {\r
+               /* Write the byte of data to the target */\r
+               XPROGTarget_SendByte(TPI_CMD_SST | TPI_POINTER_INDIRECT_PI);\r
+               XPROGTarget_SendByte(*(WriteBuffer++));\r
+       }\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
+       TINYNVM_SendWriteNVMRegister(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