/** Handler for the XPROG ENTER_PROGMODE command to establish a PDI connection with the attached device. */\r
static void PDIProtocol_EnterXPROGMode(void)\r
{\r
- uint8_t ReturnStatus = XPRG_ERR_OK;\r
-\r
Endpoint_ClearOUT();\r
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);\r
\r
/* Enable PDI programming mode with the attached target */\r
PDITarget_EnableTargetPDI();\r
\r
- /* Store the RESET ket into the RESET PDI register to complete the handshake */\r
+ /* Store the RESET key into the RESET PDI register to keep the XMEGA in reset */\r
PDITarget_SendByte(PDI_CMD_STCS | PD_RESET_REG); \r
PDITarget_SendByte(PDI_RESET_KEY);\r
\r
for (uint8_t i = 0; i < sizeof(PDI_NVMENABLE_KEY); i++)\r
PDITarget_SendByte(PDI_NVMENABLE_KEY[i]);\r
\r
- /* Read out the STATUS register to check that NVM access was successfully enabled */\r
- PDITarget_SendByte(PDI_CMD_LDCS | PD_STATUS_REG); \r
- if (!(PDITarget_ReceiveByte() & PDI_STATUS_NVM))\r
- ReturnStatus = XPRG_ERR_FAILED;\r
+ /* Poll the STATUS register to check to see if NVM access has been enabled */\r
+ uint8_t NVMAttemptsRemaining = 200;\r
+ while (NVMAttemptsRemaining--)\r
+ {\r
+ _delay_ms(1);\r
+ PDITarget_SendByte(PDI_CMD_LDCS | PD_STATUS_REG);\r
+\r
+ if (PDITarget_ReceiveByte() & PDI_STATUS_NVM)\r
+ break;\r
+ }\r
\r
Endpoint_Write_Byte(CMD_XPROG);\r
Endpoint_Write_Byte(XPRG_CMD_ENTER_PROGMODE);\r
- Endpoint_Write_Byte(ReturnStatus);\r
+ Endpoint_Write_Byte(NVMAttemptsRemaining ? XPRG_ERR_OK : XPRG_ERR_FAILED);\r
Endpoint_ClearIN();\r
}\r
\r
Endpoint_ClearOUT();\r
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);\r
\r
+ /* Clear the RESET key into the RESET PDI register to allow the XMEGA to run */\r
+ PDITarget_SendByte(PDI_CMD_STCS | PD_RESET_REG); \r
+ PDITarget_SendByte(0x00);\r
+\r
PDITarget_DisableTargetPDI();\r
\r
Endpoint_Write_Byte(CMD_XPROG);\r
/* Set up the synchronous USART for XMEGA communications - \r
8 data bits, even parity, 2 stop bits */\r
UBRR1 = 10;\r
- UCSR1B = (1 << TXEN1);\r
UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);\r
\r
+ /* Send two BREAKs of 12 bits each to enable PDI interface (need at least 16 idle bits) */\r
PDITarget_SendBreak();\r
PDITarget_SendBreak();\r
}\r
UCSR1C = 0;\r
\r
/* Set all USART lines as input, tristate */\r
- DDRD &= ~(1 << 5) | (1 << 3);\r
+ DDRD &= ~((1 << 5) | (1 << 3));\r
PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2));\r
}\r
\r
void PDITarget_SendBreak(void)\r
{\r
UCSR1B &= ~(1 << RXEN1);\r
- UCSR1B |= (1 << TXEN1);\r
+ UCSR1B |= (1 << TXEN1);\r
\r
- for (uint8_t i = 0; i < BITS_IN_FRAME; i++)\r
+ for (uint8_t i = 0; i <= BITS_IN_FRAME; i++)\r
{\r
+ /* Wait for rising edge of clock */\r
while (PIND & (1 << 5));\r
+ \r
+ /* Wait for falling edge of clock */\r
while (!(PIND & (1 << 5)));\r
}\r
}\r