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.
pull/1469/head
Dean Camera 15 years ago
parent 35a0fe9384
commit ab195ab1da

@ -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 @@
* - 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 @@
* </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>
* *

@ -63,6 +63,13 @@ void ISPProtocol_EnterISPMode(void)
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)
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();

@ -140,6 +140,9 @@ uint8_t ISPTarget_WaitForProgComplete(const uint8_t ProgrammingMode, const uint1
break; break;
} }
if (ProgrammingStatus == STATUS_CMD_OK)
TimeoutMSRemaining = COMMAND_TIMEOUT_MS;
return ProgrammingStatus; return ProgrammingStatus;
} }
@ -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,7 +82,10 @@ 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,7 +106,10 @@ 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
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
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)
/* 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)
/* 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;

Loading…
Cancel
Save