/** 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_REG_RESET)); XPROGTarget_SendByte(0x00); /* Read back the reset register, check to see if it took effect */ XPROGTarget_SendByte(PDI_CMD_LDCS(PDI_REG_RESET)); } while ((XPROGTarget_ReceiveByte() != 0x00) && TimeoutTicksRemaining); XPROGTarget_DisableTargetPDI(); }
/** Busy-waits while the NVM controller is busy performing a NVM operation, such as a FLASH page read or CRC * calculation. * * \return Boolean \c true if the NVM controller became ready within the timeout period, \c false otherwise */ bool XMEGANVM_WaitWhileNVMBusBusy(void) { /* Poll the STATUS register to check to see if NVM access has been enabled */ for (;;) { /* Send the LDCS command to read the PDI STATUS register to see the NVM bus is active */ XPROGTarget_SendByte(PDI_CMD_LDCS(PDI_REG_STATUS)); uint8_t StatusRegister = XPROGTarget_ReceiveByte(); /* We might have timed out waiting for the status register read response, check here */ if (!(TimeoutTicksRemaining)) return false; /* Check the status register read response to see if the NVM bus is enabled */ if (StatusRegister & PDI_STATUS_NVM) return true; } }