Commit ab195ab1 authored by Dean Camera's avatar Dean Camera
Browse files

Added .5MHz recovery clock to the AVRISP programmer project when in ISP...

Added .5MHz recovery clock to the AVRISP programmer project when in ISP programming mode to correct mis-set fuses.

Fixed AVRISP project not extending the command delay after each successful page/word/byte program.
parent 35a0fe93
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
* do not adversely affect the code operation (currently only the LEDs driver) * do not adversely affect the code operation (currently only the LEDs driver)
* - Added keyboard modifier masks (HID_KEYBOARD_MODIFER_*) and LED report masks (KEYBOARD_LED_*) to the HID class driver and * - Added keyboard modifier masks (HID_KEYBOARD_MODIFER_*) and LED report masks (KEYBOARD_LED_*) to the HID class driver and
* Keyboard demos * Keyboard demos
* - Added .5MHz recovery clock to the AVRISP programmer project when in ISP programming mode to correct mis-set fuses
* *
* <b>Changed:</b> * <b>Changed:</b>
* - Slowed down software USART carried PDI programming in the AVRISP project to prevent transmission errors * - Slowed down software USART carried PDI programming in the AVRISP project to prevent transmission errors
...@@ -58,6 +59,7 @@ ...@@ -58,6 +59,7 @@
* - Fixed SerialStream driver blocking while waiting for characters to be received instead of returning EOF * - Fixed SerialStream driver blocking while waiting for characters to be received instead of returning EOF
* - Fixed SerialStream driver not setting stdin to the created serial stream * - Fixed SerialStream driver not setting stdin to the created serial stream
* - Fixed USB_GetHIDReportSize() returning the number of bits in the specified report instead of bytes * - Fixed USB_GetHIDReportSize() returning the number of bits in the specified report instead of bytes
* - Fixed AVRISP project not extending the command delay after each successful page/word/byte program
* *
* \section Sec_ChangeLog091223 Version 091223 * \section Sec_ChangeLog091223 Version 091223
* *
......
...@@ -110,6 +110,10 @@ ...@@ -110,6 +110,10 @@
* </tr> * </tr>
* </table> * </table>
* *
* In addition, the AVR's XCK pin will generate a .5MHz clock when SPI programming is used, to act as an external
* device clock if the fuses have been mis-set. To use the recovery clock, connect XCK to the target AVR's XTAL1
* pin, and set the ISP programming speed to 125KHz or below.
*
* <b><sup>1</sup></b> <i>Optional, see \ref SSec_Options section - for USB AVRs with ADC modules only</i> \n * <b><sup>1</sup></b> <i>Optional, see \ref SSec_Options section - for USB AVRs with ADC modules only</i> \n
* <b><sup>2</sup></b> <i>See AUX line related tokens in the \ref SSec_Options section</i> * <b><sup>2</sup></b> <i>See AUX line related tokens in the \ref SSec_Options section</i>
* *
......
...@@ -62,7 +62,14 @@ void ISPProtocol_EnterISPMode(void) ...@@ -62,7 +62,14 @@ void ISPProtocol_EnterISPMode(void)
uint8_t ResponseStatus = STATUS_CMD_FAILED; uint8_t ResponseStatus = STATUS_CMD_FAILED;
CurrentAddress = 0; CurrentAddress = 0;
/* Set up the synchronous USART to generate the recovery clock on XCK pin */
UBRR1 = (F_CPU / 500000UL);
UCSR1B = (1 << TXEN1);
UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);
DDRD |= (1 << 5);
/* Perform execution delay, initialize SPI bus */
ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS); ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS);
SPI_Init(ISPTarget_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING | SPI_SAMPLE_LEADING | SPI_MODE_MASTER); SPI_Init(ISPTarget_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING | SPI_SAMPLE_LEADING | SPI_MODE_MASTER);
...@@ -118,6 +125,12 @@ void ISPProtocol_LeaveISPMode(void) ...@@ -118,6 +125,12 @@ void ISPProtocol_LeaveISPMode(void)
SPI_ShutDown(); SPI_ShutDown();
ISPProtocol_DelayMS(Leave_ISP_Params.PostDelayMS); ISPProtocol_DelayMS(Leave_ISP_Params.PostDelayMS);
/* Turn off the synchronous USART to terminate the recovery clock on XCK pin */
UBRR1 = (F_CPU / 500000UL);
UCSR1B = (1 << TXEN1);
UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);
DDRD &= ~(1 << 5);
Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP); Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP);
Endpoint_Write_Byte(STATUS_CMD_OK); Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_ClearIN(); Endpoint_ClearIN();
......
...@@ -139,6 +139,9 @@ uint8_t ISPTarget_WaitForProgComplete(const uint8_t ProgrammingMode, const uint1 ...@@ -139,6 +139,9 @@ uint8_t ISPTarget_WaitForProgComplete(const uint8_t ProgrammingMode, const uint1
ProgrammingStatus = ISPTarget_WaitWhileTargetBusy(); ProgrammingStatus = ISPTarget_WaitWhileTargetBusy();
break; break;
} }
if (ProgrammingStatus == STATUS_CMD_OK)
TimeoutMSRemaining = COMMAND_TIMEOUT_MS;
return ProgrammingStatus; return ProgrammingStatus;
} }
...@@ -159,10 +162,7 @@ uint8_t ISPTarget_WaitWhileTargetBusy(void) ...@@ -159,10 +162,7 @@ uint8_t ISPTarget_WaitWhileTargetBusy(void)
} }
while ((SPI_ReceiveByte() & 0x01) && TimeoutMSRemaining); while ((SPI_ReceiveByte() & 0x01) && TimeoutMSRemaining);
if (!(TimeoutMSRemaining)) return ((TimeoutMSRemaining) ? STATUS_CMD_OK : STATUS_RDY_BSY_TOUT);
return STATUS_RDY_BSY_TOUT;
else
return STATUS_CMD_OK;
} }
/** Sends a low-level LOAD EXTENDED ADDRESS command to the target, for addressing of memory beyond the /** Sends a low-level LOAD EXTENDED ADDRESS command to the target, for addressing of memory beyond the
......
...@@ -82,9 +82,12 @@ bool TINYNVM_WaitWhileNVMBusBusy(void) ...@@ -82,9 +82,12 @@ bool TINYNVM_WaitWhileNVMBusBusy(void)
/* Send the SLDCS command to read the TPI STATUS register to see the NVM bus is active */ /* Send the SLDCS command to read the TPI STATUS register to see the NVM bus is active */
XPROGTarget_SendByte(TPI_CMD_SLDCS | TPI_STATUS_REG); XPROGTarget_SendByte(TPI_CMD_SLDCS | TPI_STATUS_REG);
if (XPROGTarget_ReceiveByte() & TPI_STATUS_NVM) if (XPROGTarget_ReceiveByte() & TPI_STATUS_NVM)
return true; {
TimeoutMSRemaining = COMMAND_TIMEOUT_MS;
return true;
}
} }
return false; return false;
} }
...@@ -103,9 +106,12 @@ bool TINYNVM_WaitWhileNVMControllerBusy(void) ...@@ -103,9 +106,12 @@ bool TINYNVM_WaitWhileNVMControllerBusy(void)
/* Check to see if the BUSY flag is still set */ /* Check to see if the BUSY flag is still set */
if (!(XPROGTarget_ReceiveByte() & (1 << 7))) if (!(XPROGTarget_ReceiveByte() & (1 << 7)))
return true; {
TimeoutMSRemaining = COMMAND_TIMEOUT_MS;
return true;
}
} }
return false; return false;
} }
...@@ -167,6 +173,10 @@ bool TINYNVM_WriteMemory(const uint16_t WriteAddress, uint8_t* WriteBuffer, uint ...@@ -167,6 +173,10 @@ bool TINYNVM_WriteMemory(const uint16_t WriteAddress, uint8_t* WriteBuffer, uint
while (WriteLength) while (WriteLength)
{ {
/* Wait until the NVM controller is no longer busy */
if (!(TINYNVM_WaitWhileNVMControllerBusy()))
return false;
/* Write the low byte of data to the target */ /* Write the low byte of data to the target */
XPROGTarget_SendByte(TPI_CMD_SST | TPI_POINTER_INDIRECT_PI); XPROGTarget_SendByte(TPI_CMD_SST | TPI_POINTER_INDIRECT_PI);
XPROGTarget_SendByte(*(WriteBuffer++)); XPROGTarget_SendByte(*(WriteBuffer++));
...@@ -175,10 +185,6 @@ bool TINYNVM_WriteMemory(const uint16_t WriteAddress, uint8_t* WriteBuffer, uint ...@@ -175,10 +185,6 @@ bool TINYNVM_WriteMemory(const uint16_t WriteAddress, uint8_t* WriteBuffer, uint
XPROGTarget_SendByte(TPI_CMD_SST | TPI_POINTER_INDIRECT_PI); XPROGTarget_SendByte(TPI_CMD_SST | TPI_POINTER_INDIRECT_PI);
XPROGTarget_SendByte(*(WriteBuffer++)); XPROGTarget_SendByte(*(WriteBuffer++));
/* Wait until the NVM controller is no longer busy */
if (!(TINYNVM_WaitWhileNVMControllerBusy()))
return false;
/* Need to decrement the write length twice, since we read out a whole word */ /* Need to decrement the write length twice, since we read out a whole word */
WriteLength -= 2; WriteLength -= 2;
} }
......
...@@ -77,7 +77,10 @@ bool XMEGANVM_WaitWhileNVMBusBusy(void) ...@@ -77,7 +77,10 @@ bool XMEGANVM_WaitWhileNVMBusBusy(void)
/* Send the LDCS command to read the PDI STATUS register to see the NVM bus is active */ /* Send the LDCS command to read the PDI STATUS register to see the NVM bus is active */
XPROGTarget_SendByte(PDI_CMD_LDCS | PDI_STATUS_REG); XPROGTarget_SendByte(PDI_CMD_LDCS | PDI_STATUS_REG);
if (XPROGTarget_ReceiveByte() & PDI_STATUS_NVM) if (XPROGTarget_ReceiveByte() & PDI_STATUS_NVM)
return true; {
TimeoutMSRemaining = COMMAND_TIMEOUT_MS;
return true;
}
} }
return false; return false;
...@@ -99,7 +102,10 @@ bool XMEGANVM_WaitWhileNVMControllerBusy(void) ...@@ -99,7 +102,10 @@ bool XMEGANVM_WaitWhileNVMControllerBusy(void)
/* Check to see if the BUSY flag is still set */ /* Check to see if the BUSY flag is still set */
if (!(XPROGTarget_ReceiveByte() & (1 << 7))) if (!(XPROGTarget_ReceiveByte() & (1 << 7)))
return true; {
TimeoutMSRemaining = COMMAND_TIMEOUT_MS;
return true;
}
} }
return false; return false;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment