From 42cfd157936571c70b6ba0be48fbda1ab7b450a1 Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Fri, 11 Dec 2009 00:03:10 +0000 Subject: Change over AVRISP project to have both hardware USART and software USART modes for the PDI protocol, when enabled. Fix up PDI initialisation routines. --- Projects/AVRISP/AVRISP.txt | 11 +- Projects/AVRISP/Lib/PDIProtocol.c | 27 ++--- Projects/AVRISP/Lib/PDITarget.c | 221 +++++++++++++++++++++++++++----------- Projects/AVRISP/Lib/PDITarget.h | 34 +++--- Projects/AVRISP/makefile | 2 +- 5 files changed, 194 insertions(+), 101 deletions(-) (limited to 'Projects') diff --git a/Projects/AVRISP/AVRISP.txt b/Projects/AVRISP/AVRISP.txt index c15c27fa6..9dd2f119f 100644 --- a/Projects/AVRISP/AVRISP.txt +++ b/Projects/AVRISP/AVRISP.txt @@ -109,7 +109,7 @@ * 2 See \ref SSec_Options section * * - * Connections to the device for PDI programming (when enabled): + * Connections to the device for PDI programming1 (when enabled): * * * @@ -149,6 +149,9 @@ * *
* + * 1 When PDI_VIA_HARDWARE_USART is set, the AVR's Tx and Rx become the DATA line when connected together + * via a pair of 300 ohm resistors, and the AVR's XCK pin becomes CLOCK. + * * \section SSec_Options Project Options * * The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value. @@ -192,5 +195,11 @@ * Makefile CDEFS * Define to enable XMEGA PDI programming protocol support. Ignored when compiled for the XPLAIN board. * + * + * PDI_VIA_HARDWARE_USART + * Makefile CDEFS + * Define to force the PDI protocol (when enabled) to use the hardware USART instead of bit-banging to match the official + * AVRISP pinout. Automatically set when compiled for the XPLAIN board. + * * */ diff --git a/Projects/AVRISP/Lib/PDIProtocol.c b/Projects/AVRISP/Lib/PDIProtocol.c index 864d4e9c3..c1e7bf2ee 100644 --- a/Projects/AVRISP/Lib/PDIProtocol.c +++ b/Projects/AVRISP/Lib/PDIProtocol.c @@ -104,18 +104,13 @@ static void PDIProtocol_EnterXPROGMode(void) Endpoint_ClearOUT(); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - PDIDATA_LINE_DDR |= PDIDATA_LINE_MASK; - PDICLOCK_LINE_DDR |= PDICLOCK_LINE_MASK; - - /* Must hold DATA line high for at least 90nS to enable PDI interface */ - PDIDATA_LINE_PORT |= PDIDATA_LINE_MASK; - asm volatile ("NOP"::); - asm volatile ("NOP"::); - - /* Toggle CLOCK line 16 times within 100uS of the original 90nS timeout to keep PDI interface enabled */ - for (uint8_t i = 0; i < 16; i++) - TOGGLE_PDI_CLOCK; + /* Enable PDI programming mode with the attached target */ + PDITarget_EnableTargetPDI(); + /* Store the RESET ket into the RESET PDI register to complete the handshake */ + PDITarget_SendByte(PDI_CMD_STCS | PD_RESET_REG); + PDITarget_SendByte(PDI_RESET_KEY); + /* Enable access to the XPROG NVM bus by sending the documented NVM access key to the device */ PDITarget_SendByte(PDI_CMD_KEY); for (uint8_t i = 0; i < sizeof(PDI_NVMENABLE_KEY); i++) @@ -140,14 +135,8 @@ static void PDIProtocol_LeaveXPROGMode(void) Endpoint_ClearOUT(); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - /* Set DATA and CLOCK lines to inputs */ - PDIDATA_LINE_DDR &= ~PDIDATA_LINE_MASK; - PDICLOCK_LINE_DDR &= ~PDICLOCK_LINE_MASK; - - /* Tristate DATA and CLOCK lines */ - PDIDATA_LINE_PORT &= ~PDIDATA_LINE_MASK; - PDICLOCK_LINE_PORT &= ~PDICLOCK_LINE_MASK; - + PDITarget_DisableTargetPDI(); + Endpoint_Write_Byte(CMD_XPROG); Endpoint_Write_Byte(XPRG_CMD_LEAVE_PROGMODE); Endpoint_Write_Byte(XPRG_ERR_OK); diff --git a/Projects/AVRISP/Lib/PDITarget.c b/Projects/AVRISP/Lib/PDITarget.c index a0bbf7dfa..9a94e9a4e 100644 --- a/Projects/AVRISP/Lib/PDITarget.c +++ b/Projects/AVRISP/Lib/PDITarget.c @@ -38,90 +38,191 @@ #define INCLUDE_FROM_PDITARGET_C #include "PDITarget.h" -/** Writes a given byte to the attached XMEGA device, using a RS232 frame via software through the - * PDI interface. - * - * \param[in] Byte Byte to send to the attached device - */ -void PDITarget_SendByte(uint8_t Byte) -{ - uint8_t LogicOneBits = 0; +#if !defined(PDI_VIA_HARDWARE_USART) +volatile bool IsSending; +volatile uint16_t DataBits; +volatile uint8_t BitCount; - // One Start Bit - PDIDATA_LINE_PORT &= ~PDIDATA_LINE_MASK; +ISR(TIMER0_COMPA_vect, ISR_BLOCK) +{ + BITBANG_PDICLOCK_PORT ^= BITBANG_PDICLOCK_MASK; - TOGGLE_PDI_CLOCK; + /* If not sending or receiving, just exit */ + if (!(BitCount)) + return; - // Eight Data Bits - for (uint8_t i = 0; i < 8; i++) + /* Check to see if the current clock state is on the rising or falling edge */ + bool IsRisingEdge = (BITBANG_PDICLOCK_PORT & BITBANG_PDICLOCK_MASK); + + if (IsSending && !IsRisingEdge) { - if (Byte & 0x01) - { - PDIDATA_LINE_PORT &= ~PDIDATA_LINE_MASK; - LogicOneBits++; - } + if (DataBits & 0x01) + BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK; else - { - PDIDATA_LINE_PORT |= PDIDATA_LINE_MASK; - } - - Byte >>= 1; + BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK; - TOGGLE_PDI_CLOCK; + DataBits >>= 1; + BitCount--; } + else if (!IsSending && IsRisingEdge) + { + /* Wait for the start bit when receiving */ + if ((BitCount == BITS_IN_FRAME) && (BITBANG_PDIDATA_PORT & BITBANG_PDIDATA_MASK)) + return; + + if (BITBANG_PDIDATA_PORT & BITBANG_PDIDATA_MASK) + DataBits |= (1 << (BITS_IN_FRAME - 1)); - // Even Parity Bit - if (LogicOneBits & 0x01) - PDIDATA_LINE_PORT &= ~PDIDATA_LINE_MASK; - else - PDIDATA_LINE_PORT |= PDIDATA_LINE_MASK; - - TOGGLE_PDI_CLOCK; + DataBits >>= 1; + BitCount--; + } +} - // Two Stop Bits - PDIDATA_LINE_PORT |= PDIDATA_LINE_MASK; +void PDITarget_EnableTargetPDI(void) +{ + /* Set DATA and CLOCK lines to outputs */ + BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK; + BITBANG_PDICLOCK_DDR |= BITBANG_PDICLOCK_MASK; - TOGGLE_PDI_CLOCK; - TOGGLE_PDI_CLOCK; + /* Set DATA line high for 90ns to disable /RESET functionality */ + BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK; + asm volatile ("NOP"::); + asm volatile ("NOP"::); + + /* Fire timer compare ISR every 160 cycles */ + OCR0A = 20; + TCCR0A = (1 << WGM01); + TCCR0B = (1 << CS01); + TIMSK0 = (1 << OCIE0A); } -/** Reads a given byte from the attached XMEGA device, encoded in a RS232 frame through the PDI interface. - * - * \return Received byte from the attached device - */ -uint8_t PDITarget_ReceiveByte(void) +void PDITarget_DisableTargetPDI(void) { - uint8_t ReceivedByte = 0; - - PDIDATA_LINE_DDR &= ~PDIDATA_LINE_MASK; + /* Set DATA and CLOCK lines to inputs */ + BITBANG_PDIDATA_DDR &= ~BITBANG_PDIDATA_MASK; + BITBANG_PDICLOCK_DDR &= ~BITBANG_PDICLOCK_MASK; + + /* Tristate DATA and CLOCK lines */ + BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK; + BITBANG_PDICLOCK_PORT &= ~BITBANG_PDICLOCK_MASK; - // One Start Bit - while (PDIDATA_LINE_PIN & PDIDATA_LINE_MASK); - TOGGLE_PDI_CLOCK; + TCCR0B = 0; +} - TOGGLE_PDI_CLOCK; +void PDITarget_SendByte(uint8_t Byte) +{ + bool IsOddBitsSet = false; - // Eight Data Bits + /* Compute Even parity bit */ for (uint8_t i = 0; i < 8; i++) { - if (!(PDIDATA_LINE_PIN & PDIDATA_LINE_MASK)) - ReceivedByte |= 0x80; + if (Byte & (1 << i)) + IsOddBitsSet = !(IsOddBitsSet); + } - ReceivedByte >>= 1; + /* Data shifted out LSB first, START DATA PARITY STOP STOP */ + DataBits = ((uint16_t)IsOddBitsSet << 10) | ((uint16_t)Byte << 1) | (1 << 0); - TOGGLE_PDI_CLOCK; - } + BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK; + BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK; - // Even Parity Bit (discarded) - TOGGLE_PDI_CLOCK; + IsSending = true; + BitCount = BITS_IN_FRAME; + while (BitCount); + + BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK; + BITBANG_PDIDATA_DDR &= ~BITBANG_PDIDATA_MASK; +} + +uint8_t PDITarget_ReceiveByte(void) +{ + IsSending = false; + BitCount = BITS_IN_FRAME; + while (BitCount); + + return (DataBits >> 1); +} - // Two Stop Bits - TOGGLE_PDI_CLOCK; - TOGGLE_PDI_CLOCK; +void PDITarget_SendBreak(void) +{ + DataBits = 0; + + BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK; + BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK; + + IsSending = true; + BitCount = BITS_IN_FRAME; + while (BitCount); + + BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK; + BITBANG_PDIDATA_DDR &= ~BITBANG_PDIDATA_MASK; +} +#else +void PDITarget_EnableTargetPDI(void) +{ + /* Set Tx and XCK as outputs, Rx as input */ + DDRD |= (1 << 5) | (1 << 3); + DDRD &= ~(1 << 2); - PDIDATA_LINE_DDR |= PDIDATA_LINE_MASK; + /* Set DATA line high for 90ns to disable /RESET functionality */ + PORTD |= (1 << 3); + asm volatile ("NOP"::); + asm volatile ("NOP"::); - return ReceivedByte; + /* Set up the synchronous USART for XMEGA communications - + 8 data bits, even parity, 2 stop bits */ + UBRR1 = 10; + UCSR1B = (1 << TXEN1); + UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1); + + PDITarget_SendBreak(); + PDITarget_SendBreak(); } +void PDITarget_DisableTargetPDI(void) +{ + /* Turn of receiver and transmitter of the USART, clear settings */ + UCSR1B = 0; + UCSR1C = 0; + + /* Set all USART lines as input, tristate */ + DDRD &= ~(1 << 5) | (1 << 3); + PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2)); +} + +void PDITarget_SendByte(uint8_t Byte) +{ + UCSR1B &= ~(1 << RXEN1); + UCSR1B |= (1 << TXEN1); + + UDR1 = Byte; + + while (!(UCSR1A & (1 << TXC1))); + UCSR1A |= (1 << TXC1); +} + +uint8_t PDITarget_ReceiveByte(void) +{ + UCSR1B &= ~(1 << TXEN1); + UCSR1B |= (1 << RXEN1); + + while (!(UCSR1A & (1 << RXC1))); + UCSR1A |= (1 << RXC1); + + return UDR1; +} + +void PDITarget_SendBreak(void) +{ + UCSR1B &= ~(1 << RXEN1); + UCSR1B |= (1 << TXEN1); + + for (uint8_t i = 0; i < BITS_IN_FRAME; i++) + { + while (PIND & (1 << 5)); + while (!(PIND & (1 << 5))); + } +} +#endif + #endif diff --git a/Projects/AVRISP/Lib/PDITarget.h b/Projects/AVRISP/Lib/PDITarget.h index 00ce68bb3..272655594 100644 --- a/Projects/AVRISP/Lib/PDITarget.h +++ b/Projects/AVRISP/Lib/PDITarget.h @@ -38,6 +38,7 @@ /* Includes: */ #include + #include #include #include @@ -53,25 +54,20 @@ /* Defines: */ #if BOARD == BOARD_XPLAIN - #define PDIDATA_LINE_PORT PORTD - #define PDIDATA_LINE_DDR DDRD - #define PDIDATA_LINE_PIN PIND - #define PDIDATA_LINE_MASK (1 << 2) - - #define PDICLOCK_LINE_PORT PORTD - #define PDICLOCK_LINE_DDR DDRD - #define PDICLOCK_LINE_MASK (1 << 5) + #define PDI_VIA_HARDWARE_USART #else - #define PDIDATA_LINE_PORT PORTB - #define PDIDATA_LINE_DDR DDRB - #define PDIDATA_LINE_PIN PINB - #define PDIDATA_LINE_MASK (1 << 3) + #define BITBANG_PDIDATA_PORT PORTB + #define BITBANG_PDIDATA_DDR DDRB + #define BITBANG_PDIDATA_PIN PINB + #define BITBANG_PDIDATA_MASK (1 << 3) - #define PDICLOCK_LINE_PORT RESET_LINE_PORT - #define PDICLOCK_LINE_DDR RESET_LINE_DDR - #define PDICLOCK_LINE_MASK RESET_LINE_MASK + #define BITBANG_PDICLOCK_PORT RESET_LINE_PORT + #define BITBANG_PDICLOCK_DDR RESET_LINE_DDR + #define BITBANG_PDICLOCK_MASK RESET_LINE_MASK #endif + #define BITS_IN_FRAME 12 + #define PDI_CMD_LDS 0x00 #define PDI_CMD_LD 0x20 #define PDI_CMD_STS 0x40 @@ -89,14 +85,12 @@ #define PDI_RESET_KEY 0x59 #define PDI_NVMENABLE_KEY (uint8_t[]){0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF} - - #define TOGGLE_PDI_CLOCK MACROS{ PDICLOCK_LINE_PORT ^= PDICLOCK_LINE_MASK; \ - asm volatile ("NOP" ::); \ - PDICLOCK_LINE_PORT ^= PDICLOCK_LINE_MASK; \ - asm volatile ("NOP" ::); }MACROE /* Function Prototypes: */ + void PDITarget_EnableTargetPDI(void); + void PDITarget_DisableTargetPDI(void); void PDITarget_SendByte(uint8_t Byte); uint8_t PDITarget_ReceiveByte(void); + void PDITarget_SendBreak(void); #endif diff --git a/Projects/AVRISP/makefile b/Projects/AVRISP/makefile index b215a22a2..6eebb2b33 100644 --- a/Projects/AVRISP/makefile +++ b/Projects/AVRISP/makefile @@ -60,7 +60,7 @@ # MCU name -MCU = at90usb162 +MCU = at90usb1287 # Target board (see library "Board Types" documentation, USER or blank for projects not requiring -- cgit v1.2.3