From ce8d0424b1a59bb2b0bd3ab8f69f4e4cf8c9930b Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Fri, 19 Feb 2010 05:17:41 +0000 Subject: [PATCH] AVRISP programmer project now has a more robust timeout system, allowing for a doubling of the software USART speed for PDI and TPI programming. --- LUFA/ManPages/ChangeLog.txt | 10 ++ LUFA/ManPages/MigrationInformation.txt | 1 + Projects/AVRISP-MKII/Lib/V2Protocol.c | 15 --- Projects/AVRISP-MKII/Lib/V2Protocol.h | 6 - Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c | 18 ++- Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c | 18 ++- Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.c | 118 +++++++++++++------ Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h | 2 +- 8 files changed, 122 insertions(+), 66 deletions(-) diff --git a/LUFA/ManPages/ChangeLog.txt b/LUFA/ManPages/ChangeLog.txt index 9b3154f049..5e2241d428 100644 --- a/LUFA/ManPages/ChangeLog.txt +++ b/LUFA/ManPages/ChangeLog.txt @@ -8,6 +8,16 @@ * * \section Sec_ChangeLogXXXXXX Version XXXXXX * + * New: + * - (None) + * + * Changed: + * - AVRISP programmer project now has a more robust timeout system, allowing for a doubling of the software USART speed + * for PDI and TPI programming + * + * Fixed: + * - (None) + * * \section Sec_ChangeLog100219 Version 100219 * * New: diff --git a/LUFA/ManPages/MigrationInformation.txt b/LUFA/ManPages/MigrationInformation.txt index 169b7870a6..2623640701 100644 --- a/LUFA/ManPages/MigrationInformation.txt +++ b/LUFA/ManPages/MigrationInformation.txt @@ -13,6 +13,7 @@ * \section Sec_MigrationXXXXXX Migrating from 100219 to XXXXXX * * \section Sec_Migration100219 Migrating from 091223 to 100219 + * - (None) * * Non-USB Library Components * - Due to some ADC channels not being identical to their ADC MUX selection masks for single-ended conversions on some AVR models, diff --git a/Projects/AVRISP-MKII/Lib/V2Protocol.c b/Projects/AVRISP-MKII/Lib/V2Protocol.c index 8d8f2003f3..cea42eae5f 100644 --- a/Projects/AVRISP-MKII/Lib/V2Protocol.c +++ b/Projects/AVRISP-MKII/Lib/V2Protocol.c @@ -42,14 +42,6 @@ uint32_t CurrentAddress; /** Flag to indicate that the next read/write operation must update the device's current address */ 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. */ void V2Protocol_Init(void) { @@ -76,10 +68,6 @@ void V2Protocol_ProcessCommand(void) { 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) { case CMD_SIGN_ON: @@ -139,9 +127,6 @@ void V2Protocol_ProcessCommand(void) V2Protocol_UnknownCommand(V2Command); break; } - - /* Disable timeout management interrupt once processing has completed */ - TIMSK0 &= ~(1 << OCIE0A); Endpoint_WaitUntilReady(); Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT); diff --git a/Projects/AVRISP-MKII/Lib/V2Protocol.h b/Projects/AVRISP-MKII/Lib/V2Protocol.h index d67fb3dada..97fea471b7 100644 --- a/Projects/AVRISP-MKII/Lib/V2Protocol.h +++ b/Projects/AVRISP-MKII/Lib/V2Protocol.h @@ -64,12 +64,6 @@ /** Programmer ID string, returned to the host during the CMD_SIGN_ON command processing */ #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 */ #define VTARGET_ADC_CHANNEL_MASK _GETADCMUXMASK(ADC_CHANNEL, VTARGET_ADC_CHANNEL) diff --git a/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c b/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c index 0ab297538e..428469df74 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c +++ b/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c @@ -77,14 +77,19 @@ static void TINYNVM_SendWriteNVMRegister(const uint8_t Address) bool TINYNVM_WaitWhileNVMBusBusy(void) { /* Poll the STATUS register to check to see if NVM access has been enabled */ + uint8_t TimeoutMSRemaining = 100; while (TimeoutMSRemaining) { /* 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); if (XPROGTarget_ReceiveByte() & TPI_STATUS_NVM) + return true; + + /* Manage software timeout */ + if (TIFR0 & (1 << OCF0A)) { - TimeoutMSRemaining = COMMAND_TIMEOUT_MS; - return true; + TIFR0 |= (1 << OCF0A); + TimeoutMSRemaining--; } } @@ -99,6 +104,7 @@ bool TINYNVM_WaitWhileNVMBusBusy(void) bool TINYNVM_WaitWhileNVMControllerBusy(void) { /* Poll the STATUS register to check to see if NVM access has been enabled */ + uint8_t TimeoutMSRemaining = 100; while (TimeoutMSRemaining) { /* 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 */ if (!(XPROGTarget_ReceiveByte() & (1 << 7))) + return true; + + /* Manage software timeout */ + if (TIFR0 & (1 << OCF0A)) { - TimeoutMSRemaining = COMMAND_TIMEOUT_MS; - return true; + TIFR0 |= (1 << OCF0A); + TimeoutMSRemaining--; } } diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c b/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c index fc98cfceb9..6ef59db377 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c +++ b/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c @@ -72,14 +72,19 @@ static void XMEGANVM_SendNVMRegAddress(const uint8_t Register) bool XMEGANVM_WaitWhileNVMBusBusy(void) { /* Poll the STATUS register to check to see if NVM access has been enabled */ + uint8_t TimeoutMSRemaining = 100; while (TimeoutMSRemaining) { /* 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); if (XPROGTarget_ReceiveByte() & PDI_STATUS_NVM) + return true; + + /* Manage software timeout */ + if (TIFR0 & (1 << OCF0A)) { - TimeoutMSRemaining = COMMAND_TIMEOUT_MS; - return true; + TIFR0 |= (1 << OCF0A); + TimeoutMSRemaining--; } } @@ -94,6 +99,7 @@ bool XMEGANVM_WaitWhileNVMBusBusy(void) bool XMEGANVM_WaitWhileNVMControllerBusy(void) { /* Poll the NVM STATUS register while the NVM controller is busy */ + uint8_t TimeoutMSRemaining = 100; while (TimeoutMSRemaining) { /* 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 */ if (!(XPROGTarget_ReceiveByte() & (1 << 7))) + return true; + + /* Manage software timeout */ + if (TIFR0 & (1 << OCF0A)) { - TimeoutMSRemaining = COMMAND_TIMEOUT_MS; - return true; + TIFR0 |= (1 << OCF0A); + TimeoutMSRemaining--; } } diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.c b/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.c index e77d77bd5b..45c1d225de 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.c +++ b/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.c @@ -49,50 +49,59 @@ volatile uint16_t SoftUSART_Data; #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) { /* Toggle CLOCK pin in a single cycle (see AVR datasheet) */ BITBANG_PDICLOCK_PIN |= BITBANG_PDICLOCK_MASK; + TIFR1 |= (1 << OCF1B); + TIMSK1 = (1 << OCIE1B); /* If not sending or receiving, just exit */ if (!(SoftUSART_BitCount)) return; - /* Check to see if we are at a rising or falling edge of the clock */ - if (BITBANG_PDICLOCK_PORT & BITBANG_PDICLOCK_MASK) - { - /* If at rising clock edge and we are in send mode, abort */ - if (IsSending) - 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)); + /* If at rising clock edge and we are in send mode, abort */ + if (IsSending) + return; + + /* Wait for the start bit when receiving */ + if ((SoftUSART_BitCount == BITS_IN_USART_FRAME) && (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK)) + return; - SoftUSART_Data >>= 1; - SoftUSART_BitCount--; - } - else - { - /* If at falling clock edge and we are in receive mode, abort */ - if (!IsSending) - 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)); - /* 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--; +} - SoftUSART_Data >>= 1; - SoftUSART_BitCount--; - } +/** ISR to manage the falling edge of the PDI/TPI software USART when bit-banged USART mode is selected. */ +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. */ @@ -172,7 +181,9 @@ void XPROGTarget_EnableTargetPDI(void) /* Fire timer compare channel A ISR to manage the software USART */ OCR1A = BITS_BETWEEN_USART_CLOCKS; + OCR1B = BITS_BETWEEN_USART_CLOCKS; TCCR1B = (1 << WGM12) | (1 << CS10); + TCCR1C = (1 << FOC1B); TIMSK1 = (1 << OCIE1A); #endif @@ -240,6 +251,10 @@ void XPROGTarget_DisableTargetPDI(void) DDRD &= ~((1 << 5) | (1 << 3)); PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2)); #else + /* Turn off software USART management timer */ + TCCR1B = 0; + TCCR1C = 0; + /* Set /RESET high for a one millisecond to ensure target device is restarted */ BITBANG_PDICLOCK_PORT |= BITBANG_PDICLOCK_MASK; _delay_ms(1); @@ -250,7 +265,7 @@ void XPROGTarget_DisableTargetPDI(void) /* Tristate DATA and CLOCK lines */ BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK; - BITBANG_PDICLOCK_PORT &= ~BITBANG_PDICLOCK_MASK; + BITBANG_PDICLOCK_PORT &= ~BITBANG_PDICLOCK_MASK; #endif } @@ -270,6 +285,9 @@ void XPROGTarget_DisableTargetTPI(void) DDRD &= ~((1 << 5) | (1 << 3)); PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2)); #else + /* Turn off software USART management timer */ + TCCR1B = 0; + /* Set DATA and CLOCK lines to inputs */ BITBANG_TPIDATA_DDR &= ~BITBANG_TPIDATA_MASK; BITBANG_TPICLOCK_DDR &= ~BITBANG_TPICLOCK_MASK; @@ -332,12 +350,31 @@ uint8_t XPROGTarget_ReceiveByte(void) #if defined(XPROG_VIA_HARDWARE_USART) /* 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; #else /* Wait until a byte has been received before reading */ 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) */ 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 */ - 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 IsSending = false; diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h b/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h index bc2953dd2a..d08a8b653b 100644 --- a/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h +++ b/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h @@ -81,7 +81,7 @@ #endif /** 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 */ #define BITS_IN_USART_FRAME 12