X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/5a4def747897c1c6ffbe465506d846c7c686d3e9..3c1b28cf5ff16fede61f2abf37d5616f3e661036:/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c b/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c index 322f2ea80..b78247583 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c +++ b/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c @@ -1,13 +1,13 @@ /* LUFA Library - Copyright (C) Dean Camera, 2010. + Copyright (C) Dean Camera, 2012. 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 @@ -45,10 +45,10 @@ 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. @@ -96,12 +96,15 @@ 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(); @@ -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 @@ -124,6 +174,8 @@ bool XMEGANVM_WaitWhileNVMControllerBusy(void) */ 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; @@ -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); - XPROGTarget_SendByte(1 << 0); + XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX); /* 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); - 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); - 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(); - return (TimeoutTicksRemaining != 0); + return (TimeoutTicksRemaining > 0); } /** 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(); - return (TimeoutTicksRemaining != 0); + return (TimeoutTicksRemaining > 0); } /** 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); - XPROGTarget_SendByte(1 << 0); + XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX); } 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); - XPROGTarget_SendByte(1 << 0); + XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX); } 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); - XPROGTarget_SendByte(1 << 0); + XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX); /* 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); - XPROGTarget_SendByte(1 << 0); + XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX); } else {