AVRISP programmer project now has a more robust timeout system, allowing for a doubling of the software USART speed for PDI and TPI programming.

pull/1469/head
Dean Camera 15 years ago
parent 04d40897cf
commit ce8d0424b1

@ -8,6 +8,16 @@
* *
* \section Sec_ChangeLogXXXXXX Version XXXXXX * \section Sec_ChangeLogXXXXXX Version XXXXXX
* *
* <b>New:</b>
* - (None)
*
* <b>Changed:</b>
* - AVRISP programmer project now has a more robust timeout system, allowing for a doubling of the software USART speed
* for PDI and TPI programming
*
* <b>Fixed:</b>
* - (None)
*
* \section Sec_ChangeLog100219 Version 100219 * \section Sec_ChangeLog100219 Version 100219
* *
* <b>New:</b> * <b>New:</b>

@ -13,6 +13,7 @@
* \section Sec_MigrationXXXXXX Migrating from 100219 to XXXXXX * \section Sec_MigrationXXXXXX Migrating from 100219 to XXXXXX
* *
* \section Sec_Migration100219 Migrating from 091223 to 100219 * \section Sec_Migration100219 Migrating from 091223 to 100219
* - (None)
* *
* <b>Non-USB Library Components</b> * <b>Non-USB Library Components</b>
* - Due to some ADC channels not being identical to their ADC MUX selection masks for single-ended conversions on some AVR models, * - Due to some ADC channels not being identical to their ADC MUX selection masks for single-ended conversions on some AVR models,

@ -42,14 +42,6 @@ uint32_t CurrentAddress;
/** Flag to indicate that the next read/write operation must update the device's current address */ /** Flag to indicate that the next read/write operation must update the device's current address */
bool MustSetAddress; bool MustSetAddress;
/** ISR for the management of the command execution timeout counter */
ISR(TIMER0_COMPA_vect, ISR_BLOCK)
{
if (TimeoutMSRemaining)
TimeoutMSRemaining--;
}
/** Initializes the hardware and software associated with the V2 protocol command handling. */ /** Initializes the hardware and software associated with the V2 protocol command handling. */
void V2Protocol_Init(void) void V2Protocol_Init(void)
{ {
@ -76,10 +68,6 @@ void V2Protocol_ProcessCommand(void)
{ {
uint8_t V2Command = Endpoint_Read_Byte(); uint8_t V2Command = Endpoint_Read_Byte();
/* Set total command processing timeout value, enable timeout management interrupt */
TimeoutMSRemaining = COMMAND_TIMEOUT_MS;
TIMSK0 |= (1 << OCIE0A);
switch (V2Command) switch (V2Command)
{ {
case CMD_SIGN_ON: case CMD_SIGN_ON:
@ -139,9 +127,6 @@ void V2Protocol_ProcessCommand(void)
V2Protocol_UnknownCommand(V2Command); V2Protocol_UnknownCommand(V2Command);
break; break;
} }
/* Disable timeout management interrupt once processing has completed */
TIMSK0 &= ~(1 << OCIE0A);
Endpoint_WaitUntilReady(); Endpoint_WaitUntilReady();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT); Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT);

@ -64,12 +64,6 @@
/** Programmer ID string, returned to the host during the CMD_SIGN_ON command processing */ /** Programmer ID string, returned to the host during the CMD_SIGN_ON command processing */
#define PROGRAMMER_ID "AVRISP_MK2" #define PROGRAMMER_ID "AVRISP_MK2"
/** Timeout period for each issued command from the host before it is aborted */
#define COMMAND_TIMEOUT_MS 200
/** Command timeout counter register, GPIOR for speed */
#define TimeoutMSRemaining GPIOR0
/** MUX mask for the VTARGET ADC channel number */ /** MUX mask for the VTARGET ADC channel number */
#define VTARGET_ADC_CHANNEL_MASK _GETADCMUXMASK(ADC_CHANNEL, VTARGET_ADC_CHANNEL) #define VTARGET_ADC_CHANNEL_MASK _GETADCMUXMASK(ADC_CHANNEL, VTARGET_ADC_CHANNEL)

@ -77,14 +77,19 @@ static void TINYNVM_SendWriteNVMRegister(const uint8_t Address)
bool TINYNVM_WaitWhileNVMBusBusy(void) bool TINYNVM_WaitWhileNVMBusBusy(void)
{ {
/* Poll the STATUS register to check to see if NVM access has been enabled */ /* Poll the STATUS register to check to see if NVM access has been enabled */
uint8_t TimeoutMSRemaining = 100;
while (TimeoutMSRemaining) while (TimeoutMSRemaining)
{ {
/* 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;
/* Manage software timeout */
if (TIFR0 & (1 << OCF0A))
{ {
TimeoutMSRemaining = COMMAND_TIMEOUT_MS; TIFR0 |= (1 << OCF0A);
return true; TimeoutMSRemaining--;
} }
} }
@ -99,6 +104,7 @@ bool TINYNVM_WaitWhileNVMBusBusy(void)
bool TINYNVM_WaitWhileNVMControllerBusy(void) bool TINYNVM_WaitWhileNVMControllerBusy(void)
{ {
/* Poll the STATUS register to check to see if NVM access has been enabled */ /* Poll the STATUS register to check to see if NVM access has been enabled */
uint8_t TimeoutMSRemaining = 100;
while (TimeoutMSRemaining) while (TimeoutMSRemaining)
{ {
/* Send the SIN command to read the TPI STATUS register to see the NVM bus is busy */ /* Send the SIN command to read the TPI STATUS register to see the NVM bus is busy */
@ -106,9 +112,13 @@ 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;
/* Manage software timeout */
if (TIFR0 & (1 << OCF0A))
{ {
TimeoutMSRemaining = COMMAND_TIMEOUT_MS; TIFR0 |= (1 << OCF0A);
return true; TimeoutMSRemaining--;
} }
} }

@ -72,14 +72,19 @@ static void XMEGANVM_SendNVMRegAddress(const uint8_t Register)
bool XMEGANVM_WaitWhileNVMBusBusy(void) bool XMEGANVM_WaitWhileNVMBusBusy(void)
{ {
/* Poll the STATUS register to check to see if NVM access has been enabled */ /* Poll the STATUS register to check to see if NVM access has been enabled */
uint8_t TimeoutMSRemaining = 100;
while (TimeoutMSRemaining) while (TimeoutMSRemaining)
{ {
/* 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;
/* Manage software timeout */
if (TIFR0 & (1 << OCF0A))
{ {
TimeoutMSRemaining = COMMAND_TIMEOUT_MS; TIFR0 |= (1 << OCF0A);
return true; TimeoutMSRemaining--;
} }
} }
@ -94,6 +99,7 @@ bool XMEGANVM_WaitWhileNVMBusBusy(void)
bool XMEGANVM_WaitWhileNVMControllerBusy(void) bool XMEGANVM_WaitWhileNVMControllerBusy(void)
{ {
/* Poll the NVM STATUS register while the NVM controller is busy */ /* Poll the NVM STATUS register while the NVM controller is busy */
uint8_t TimeoutMSRemaining = 100;
while (TimeoutMSRemaining) while (TimeoutMSRemaining)
{ {
/* Send a LDS command to read the NVM STATUS register to check the BUSY flag */ /* Send a LDS command to read the NVM STATUS register to check the BUSY flag */
@ -102,9 +108,13 @@ 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;
/* Manage software timeout */
if (TIFR0 & (1 << OCF0A))
{ {
TimeoutMSRemaining = COMMAND_TIMEOUT_MS; TIFR0 |= (1 << OCF0A);
return true; TimeoutMSRemaining--;
} }
} }

@ -49,50 +49,59 @@ volatile uint16_t SoftUSART_Data;
#define SoftUSART_BitCount GPIOR2 #define SoftUSART_BitCount GPIOR2
/** ISR to manage the PDI software USART when bit-banged PDI USART mode is selected. */ /** ISR to manage the rising edge of the PDI/TPI software USART when bit-banged USART mode is selected. */
ISR(TIMER1_COMPA_vect, ISR_BLOCK) ISR(TIMER1_COMPA_vect, ISR_BLOCK)
{ {
/* Toggle CLOCK pin in a single cycle (see AVR datasheet) */ /* Toggle CLOCK pin in a single cycle (see AVR datasheet) */
BITBANG_PDICLOCK_PIN |= BITBANG_PDICLOCK_MASK; BITBANG_PDICLOCK_PIN |= BITBANG_PDICLOCK_MASK;
TIFR1 |= (1 << OCF1B);
TIMSK1 = (1 << OCIE1B);
/* If not sending or receiving, just exit */ /* If not sending or receiving, just exit */
if (!(SoftUSART_BitCount)) if (!(SoftUSART_BitCount))
return; return;
/* Check to see if we are at a rising or falling edge of the clock */ /* If at rising clock edge and we are in send mode, abort */
if (BITBANG_PDICLOCK_PORT & BITBANG_PDICLOCK_MASK) if (IsSending)
{ return;
/* If at rising clock edge and we are in send mode, abort */
if (IsSending) /* Wait for the start bit when receiving */
return; if ((SoftUSART_BitCount == BITS_IN_USART_FRAME) && (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK))
return;
/* Wait for the start bit when receiving */
if ((SoftUSART_BitCount == BITS_IN_USART_FRAME) && (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK))
return;
/* Shift in the bit one less than the frame size in position, so that the start bit will eventually
* be discarded leaving the data to be byte-aligned for quick access (subtract 9 as we are ORing to the MSB) */
if (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK)
((uint8_t*)&SoftUSART_Data)[1] |= (1 << (BITS_IN_USART_FRAME - 9));
SoftUSART_Data >>= 1; /* Shift in the bit one less than the frame size in position, so that the start bit will eventually
SoftUSART_BitCount--; * be discarded leaving the data to be byte-aligned for quick access (subtract 9 as we are ORing to the MSB) */
} if (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK)
else ((uint8_t*)&SoftUSART_Data)[1] |= (1 << (BITS_IN_USART_FRAME - 9));
{
/* If at falling clock edge and we are in receive mode, abort */
if (!IsSending)
return;
/* Set the data line to the next bit value */ SoftUSART_Data >>= 1;
if (((uint8_t*)&SoftUSART_Data)[0] & 0x01) SoftUSART_BitCount--;
BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK; }
else
BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;
SoftUSART_Data >>= 1; /** ISR to manage the falling edge of the PDI/TPI software USART when bit-banged USART mode is selected. */
SoftUSART_BitCount--; ISR(TIMER1_COMPB_vect, ISR_BLOCK)
} {
/* Toggle CLOCK pin in a single cycle (see AVR datasheet) */
BITBANG_PDICLOCK_PIN |= BITBANG_PDICLOCK_MASK;
TIFR1 |= (1 << OCF1A);
TIMSK1 = (1 << OCIE1A);
/* If not sending or receiving, just exit */
if (!(SoftUSART_BitCount))
return;
/* If at falling clock edge and we are in receive mode, abort */
if (!IsSending)
return;
/* Set the data line to the next bit value */
if (((uint8_t*)&SoftUSART_Data)[0] & 0x01)
BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
else
BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;
SoftUSART_Data >>= 1;
SoftUSART_BitCount--;
} }
/** ISR to manage the TPI software USART when bit-banged TPI USART mode is selected. */ /** ISR to manage the TPI software USART when bit-banged TPI USART mode is selected. */
@ -172,7 +181,9 @@ void XPROGTarget_EnableTargetPDI(void)
/* Fire timer compare channel A ISR to manage the software USART */ /* Fire timer compare channel A ISR to manage the software USART */
OCR1A = BITS_BETWEEN_USART_CLOCKS; OCR1A = BITS_BETWEEN_USART_CLOCKS;
OCR1B = BITS_BETWEEN_USART_CLOCKS;
TCCR1B = (1 << WGM12) | (1 << CS10); TCCR1B = (1 << WGM12) | (1 << CS10);
TCCR1C = (1 << FOC1B);
TIMSK1 = (1 << OCIE1A); TIMSK1 = (1 << OCIE1A);
#endif #endif
@ -240,6 +251,10 @@ void XPROGTarget_DisableTargetPDI(void)
DDRD &= ~((1 << 5) | (1 << 3)); DDRD &= ~((1 << 5) | (1 << 3));
PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2)); PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2));
#else #else
/* Turn off software USART management timer */
TCCR1B = 0;
TCCR1C = 0;
/* Set /RESET high for a one millisecond to ensure target device is restarted */ /* Set /RESET high for a one millisecond to ensure target device is restarted */
BITBANG_PDICLOCK_PORT |= BITBANG_PDICLOCK_MASK; BITBANG_PDICLOCK_PORT |= BITBANG_PDICLOCK_MASK;
_delay_ms(1); _delay_ms(1);
@ -250,7 +265,7 @@ void XPROGTarget_DisableTargetPDI(void)
/* Tristate DATA and CLOCK lines */ /* Tristate DATA and CLOCK lines */
BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK; BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;
BITBANG_PDICLOCK_PORT &= ~BITBANG_PDICLOCK_MASK; BITBANG_PDICLOCK_PORT &= ~BITBANG_PDICLOCK_MASK;
#endif #endif
} }
@ -270,6 +285,9 @@ void XPROGTarget_DisableTargetTPI(void)
DDRD &= ~((1 << 5) | (1 << 3)); DDRD &= ~((1 << 5) | (1 << 3));
PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2)); PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2));
#else #else
/* Turn off software USART management timer */
TCCR1B = 0;
/* Set DATA and CLOCK lines to inputs */ /* Set DATA and CLOCK lines to inputs */
BITBANG_TPIDATA_DDR &= ~BITBANG_TPIDATA_MASK; BITBANG_TPIDATA_DDR &= ~BITBANG_TPIDATA_MASK;
BITBANG_TPICLOCK_DDR &= ~BITBANG_TPICLOCK_MASK; BITBANG_TPICLOCK_DDR &= ~BITBANG_TPICLOCK_MASK;
@ -332,12 +350,31 @@ uint8_t XPROGTarget_ReceiveByte(void)
#if defined(XPROG_VIA_HARDWARE_USART) #if defined(XPROG_VIA_HARDWARE_USART)
/* Wait until a byte has been received before reading */ /* Wait until a byte has been received before reading */
while (!(UCSR1A & (1 << RXC1)) && TimeoutMSRemaining); uint8_t TimeoutMSRemaining = 100;
while (!(UCSR1A & (1 << RXC1)) && TimeoutMSRemaining)
{
/* Manage software timeout */
if (TIFR0 & (1 << OCF0A))
{
TIFR0 |= (1 << OCF0A);
TimeoutMSRemaining--;
}
}
return UDR1; return UDR1;
#else #else
/* Wait until a byte has been received before reading */ /* Wait until a byte has been received before reading */
SoftUSART_BitCount = BITS_IN_USART_FRAME; SoftUSART_BitCount = BITS_IN_USART_FRAME;
while (SoftUSART_BitCount && TimeoutMSRemaining); uint8_t TimeoutMSRemaining = 100;
while (SoftUSART_BitCount && TimeoutMSRemaining)
{
/* Manage software timeout */
if (TIFR0 & (1 << OCF0A))
{
TIFR0 |= (1 << OCF0A);
TimeoutMSRemaining--;
}
}
/* Throw away the parity and stop bits to leave only the data (start bit is already discarded) */ /* Throw away the parity and stop bits to leave only the data (start bit is already discarded) */
return (uint8_t)SoftUSART_Data; return (uint8_t)SoftUSART_Data;
@ -431,7 +468,16 @@ static void XPROGTarget_SetRxMode(void)
} }
/* Wait until DATA line has been pulled up to idle by the target */ /* Wait until DATA line has been pulled up to idle by the target */
while (!(BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK) && TimeoutMSRemaining); uint8_t TimeoutMSRemaining = 100;
while (!(BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK) && TimeoutMSRemaining)
{
/* Manage software timeout */
if (TIFR0 & (1 << OCF0A))
{
TIFR0 |= (1 << OCF0A);
TimeoutMSRemaining--;
}
}
#endif #endif
IsSending = false; IsSending = false;

@ -81,7 +81,7 @@
#endif #endif
/** Number of cycles between each clock when software USART mode is used */ /** Number of cycles between each clock when software USART mode is used */
#define BITS_BETWEEN_USART_CLOCKS 200 #define BITS_BETWEEN_USART_CLOCKS 100
/** Total number of bits in a single USART frame */ /** Total number of bits in a single USART frame */
#define BITS_IN_USART_FRAME 12 #define BITS_IN_USART_FRAME 12

Loading…
Cancel
Save