Use immediate variable expansion in the second-deepest level makefile scripts to...
[pub/USBasp.git] / Projects / AVRISP-MKII / Lib / XPROG / XMEGANVM.c
index 322f2ea..b782475 100644 (file)
@@ -1,13 +1,13 @@
 /*
              LUFA Library
 /*
              LUFA Library
-     Copyright (C) Dean Camera, 2010.
+     Copyright (C) Dean Camera, 2012.
 
   dean [at] fourwalledcubicle [dot] com
 
   dean [at] fourwalledcubicle [dot] com
-      www.fourwalledcubicle.com
+           www.lufa-lib.org
 */
 
 /*
 */
 
 /*
-  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+  Copyright 2012  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
 
   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 */
 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.
 }
 
 /** Sends the given NVM register address to the target.
@@ -96,12 +96,15 @@ bool XMEGANVM_WaitWhileNVMBusBusy(void)
  */
 bool XMEGANVM_WaitWhileNVMControllerBusy(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 (;;)
        {
        /* 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();
 
 
                uint8_t StatusRegister = XPROGTarget_ReceiveByte();
 
@@ -115,6 +118,53 @@ 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 32 USART bits */
+       XPROGTarget_SendByte(PDI_CMD_STCS | PDI_CTRL_REG);
+       XPROGTarget_SendByte(0x02);
+
+       /* 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 - must perform this until the
+        * change takes effect, as in some cases it takes multiple writes (silicon bug?).
+        */
+       do
+       {
+               /* Clear reset register */
+               XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
+               XPROGTarget_SendByte(0x00);
+
+               /* Read back the reset register, check to see if it took effect */
+               XPROGTarget_SendByte(PDI_CMD_LDCS | PDI_RESET_REG);
+       } while (XPROGTarget_ReceiveByte() != 0x00);
+
+       XPROGTarget_DisableTargetPDI();
+}
+
 /** Retrieves the CRC value of the given memory space.
  *
  *  \param[in]  CRCCommand  NVM CRC command to issue to the target
 /** Retrieves the CRC value of the given memory space.
  *
  *  \param[in]  CRCCommand  NVM CRC command to issue to the target
@@ -124,6 +174,8 @@ bool XMEGANVM_WaitWhileNVMControllerBusy(void)
  */
 bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest)
 {
  */
 bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest)
 {
+       *CRCDest = 0;
+
        /* Wait until the NVM controller is no longer busy */
        if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
          return false;
        /* Wait until the NVM controller is no longer busy */
        if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
          return false;
@@ -136,7 +188,7 @@ bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest)
        /* Set CMDEX bit in NVM CTRLA register to start the CRC generation */
        XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
        XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
        /* Set CMDEX bit in NVM CTRLA register to start the CRC generation */
        XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
        XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
-       XPROGTarget_SendByte(1 << 0);
+       XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX);
 
        /* Wait until the NVM bus is ready again */
        if (!(XMEGANVM_WaitWhileNVMBusBusy()))
 
        /* Wait until the NVM bus is ready again */
        if (!(XMEGANVM_WaitWhileNVMBusBusy()))
@@ -152,14 +204,14 @@ bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest)
 
        /* Send the REPEAT command to grab the CRC bytes */
        XPROGTarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE);
 
        /* Send the REPEAT command to grab the CRC bytes */
        XPROGTarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE);
-       XPROGTarget_SendByte(XMEGA_CRC_LENGTH - 1);
+       XPROGTarget_SendByte(XMEGA_CRC_LENGTH_BYTES - 1);
 
        /* Read in the CRC bytes from the target */
        XPROGTarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
 
        /* Read in the CRC bytes from the target */
        XPROGTarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
-       for (uint8_t i = 0; i < XMEGA_CRC_LENGTH; i++)
+       for (uint8_t i = 0; i < XMEGA_CRC_LENGTH_BYTES; i++)
          ((uint8_t*)CRCDest)[i] = XPROGTarget_ReceiveByte();
 
          ((uint8_t*)CRCDest)[i] = XPROGTarget_ReceiveByte();
 
-       return (TimeoutTicksRemaining != 0);
+       return (TimeoutTicksRemaining > 0);
 }
 
 /** Reads memory from the target's memory spaces.
 }
 
 /** Reads memory from the target's memory spaces.
@@ -194,7 +246,7 @@ bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, uint16
        while (ReadSize-- && TimeoutTicksRemaining)
          *(ReadBuffer++) = XPROGTarget_ReceiveByte();
 
        while (ReadSize-- && TimeoutTicksRemaining)
          *(ReadBuffer++) = XPROGTarget_ReceiveByte();
 
-       return (TimeoutTicksRemaining != 0);
+       return (TimeoutTicksRemaining > 0);
 }
 
 /** Writes byte addressed memory to the target's memory spaces.
 }
 
 /** Writes byte addressed memory to the target's memory spaces.
@@ -254,7 +306,7 @@ bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t Eras
                /* Set CMDEX bit in NVM CTRLA register to start the buffer erase */
                XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
                XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
                /* Set CMDEX bit in NVM CTRLA register to start the buffer erase */
                XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
                XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
-               XPROGTarget_SendByte(1 << 0);
+               XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX);
        }
 
        if (WriteSize)
        }
 
        if (WriteSize)
@@ -326,7 +378,7 @@ bool XMEGANVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address)
                /* Set CMDEX bit in NVM CTRLA register to start the erase sequence */
                XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
                XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
                /* Set CMDEX bit in NVM CTRLA register to start the erase sequence */
                XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
                XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
-               XPROGTarget_SendByte(1 << 0);
+               XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX);
        }
        else if (EraseCommand == XMEGA_NVM_CMD_ERASEEEPROM)
        {
        }
        else if (EraseCommand == XMEGA_NVM_CMD_ERASEEEPROM)
        {
@@ -338,7 +390,7 @@ bool XMEGANVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address)
                /* Set CMDEX bit in NVM CTRLA register to start the buffer erase */
                XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
                XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
                /* Set CMDEX bit in NVM CTRLA register to start the buffer erase */
                XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
                XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
-               XPROGTarget_SendByte(1 << 0);
+               XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX);
 
                /* Wait until the NVM controller is no longer busy */
                if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
 
                /* Wait until the NVM controller is no longer busy */
                if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
@@ -370,7 +422,7 @@ bool XMEGANVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address)
                /* Set CMDEX bit in NVM CTRLA register to start the EEPROM erase sequence */
                XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
                XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
                /* Set CMDEX bit in NVM CTRLA register to start the EEPROM erase sequence */
                XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
                XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
-               XPROGTarget_SendByte(1 << 0);
+               XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX);
        }
        else
        {
        }
        else
        {