Update UC3 platform driver support to use the bitmasks defined in the header files...
[pub/USBasp.git] / Projects / AVRISP-MKII / Lib / XPROG / XMEGANVM.c
index 322f2ea..e4f1186 100644 (file)
@@ -1,13 +1,13 @@
 /*
              LUFA Library
-     Copyright (C) Dean Camera, 2010.
+     Copyright (C) Dean Camera, 2011.
 
   dean [at] fourwalledcubicle [dot] com
-      www.fourwalledcubicle.com
+           www.lufa-lib.org
 */
 
 /*
-  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+  Copyright 2011  Dean Camera (dean [at] fourwalledcubicle [dot] com)
 
   Permission to use, copy, modify, distribute, and sell this
   software and its documentation for any purpose is hereby granted
 static void XMEGANVM_SendAddress(const uint32_t AbsoluteAddress)
 {
        /* Send the given 32-bit address to the target, LSB first */
-       XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[0]);
-       XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[1]);
-       XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[2]);
-       XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[3]);
+       XPROGTarget_SendByte(AbsoluteAddress &  0xFF);
+       XPROGTarget_SendByte(AbsoluteAddress >> 8);
+       XPROGTarget_SendByte(AbsoluteAddress >> 16);
+       XPROGTarget_SendByte(AbsoluteAddress >> 24);
 }
 
 /** Sends the given NVM register address to the target.
@@ -80,7 +80,7 @@ bool XMEGANVM_WaitWhileNVMBusBusy(void)
                uint8_t StatusRegister = XPROGTarget_ReceiveByte();
 
                /* We might have timed out waiting for the status register read response, check here */
-               if (!(TimeoutTicksRemaining))
+               if (TimeoutExpired)
                  return false;
 
                /* Check the status register read response to see if the NVM bus is enabled */
@@ -96,17 +96,20 @@ bool XMEGANVM_WaitWhileNVMBusBusy(void)
  */
 bool XMEGANVM_WaitWhileNVMControllerBusy(void)
 {
+       /* Preload the pointer register with the NVM STATUS register address to check the BUSY flag */
+       XPROGTarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES);
+       XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_STATUS);
+
        /* Poll the NVM STATUS register while the NVM controller is busy */
        for (;;)
        {
-               /* Send a LDS command to read the NVM STATUS register to check the BUSY flag */
-               XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
-               XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_STATUS);
+               /* Fetch the current status value via the pointer register (without auto-increment afterwards) */
+               XPROGTarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT << 2) | PDI_DATSIZE_1BYTE);
 
                uint8_t StatusRegister = XPROGTarget_ReceiveByte();
 
                /* We might have timed out waiting for the status register read response, check here */
-               if (!(TimeoutTicksRemaining))
+               if (TimeoutExpired)
                  return false;
 
                /* Check to see if the BUSY flag is still set */
@@ -115,6 +118,48 @@ bool XMEGANVM_WaitWhileNVMControllerBusy(void)
        }
 }
 
+/** Enables the physical PDI interface on the target and enables access to the internal NVM controller.
+ *
+ *  \return Boolean true if the PDI interface was enabled successfully, false otherwise
+ */
+bool XMEGANVM_EnablePDI(void)
+{
+       /* Enable PDI programming mode with the attached target */
+       XPROGTarget_EnableTargetPDI();
+
+       /* Store the RESET key into the RESET PDI register to keep the XMEGA in reset */
+       XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
+       XPROGTarget_SendByte(PDI_RESET_KEY);
+
+       /* Lower direction change guard time to 0 USART bits */
+       XPROGTarget_SendByte(PDI_CMD_STCS | PDI_CTRL_REG);
+       XPROGTarget_SendByte(0x07);
+
+       /* Enable access to the XPROG NVM bus by sending the documented NVM access key to the device */
+       XPROGTarget_SendByte(PDI_CMD_KEY);
+       for (uint8_t i = sizeof(PDI_NVMENABLE_KEY); i > 0; i--)
+         XPROGTarget_SendByte(PDI_NVMENABLE_KEY[i - 1]);
+
+       /* Wait until the NVM bus becomes active */
+       return XMEGANVM_WaitWhileNVMBusBusy();
+}
+
+/** Removes access to the target's NVM controller and physically disables the target's physical PDI interface. */
+void XMEGANVM_DisablePDI(void)
+{
+       XMEGANVM_WaitWhileNVMBusBusy();
+
+       /* Clear the RESET key in the RESET PDI register to allow the XMEGA to run */
+       XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
+       XPROGTarget_SendByte(0x00);
+
+       /* Do it twice to make sure it takes effect (silicon bug?) */
+       XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
+       XPROGTarget_SendByte(0x00);
+
+       XPROGTarget_DisableTargetPDI();
+}
+
 /** Retrieves the CRC value of the given memory space.
  *
  *  \param[in]  CRCCommand  NVM CRC command to issue to the target
@@ -159,7 +204,7 @@ bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest)
        for (uint8_t i = 0; i < XMEGA_CRC_LENGTH; i++)
          ((uint8_t*)CRCDest)[i] = XPROGTarget_ReceiveByte();
 
-       return (TimeoutTicksRemaining != 0);
+       return (TimeoutExpired == false);
 }
 
 /** Reads memory from the target's memory spaces.
@@ -191,10 +236,10 @@ bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, uint16
 
        /* Send a LD command with indirect access and post-increment to read out the bytes */
        XPROGTarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
-       while (ReadSize-- && TimeoutTicksRemaining)
+       while (ReadSize-- && !(TimeoutExpired))
          *(ReadBuffer++) = XPROGTarget_ReceiveByte();
 
-       return (TimeoutTicksRemaining != 0);
+       return (TimeoutExpired == false);
 }
 
 /** Writes byte addressed memory to the target's memory spaces.