Change over AVRISP project to have both hardware USART and software USART modes for the PDI protocol, when enabled. Fix up PDI initialisation routines.

pull/1469/head
Dean Camera 15 years ago
parent 7aecda6fda
commit 42cfd15793

@ -109,7 +109,7 @@
* <b><sup>2</sup></b> <i>See \ref SSec_Options section</i> * <b><sup>2</sup></b> <i>See \ref SSec_Options section</i>
* *
* *
* Connections to the device for PDI programming (when enabled): * Connections to the device for PDI programming<b><sup>1</sup></b> (when enabled):
* *
* <table> * <table>
* <tr> * <tr>
@ -149,6 +149,9 @@
* </tr> * </tr>
* </table> * </table>
* *
* <b><sup>1</sup></b> 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 * \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. * 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 @@
* <td>Makefile CDEFS</td> * <td>Makefile CDEFS</td>
* <td>Define to enable XMEGA PDI programming protocol support. <i>Ignored when compiled for the XPLAIN board.</i></td> * <td>Define to enable XMEGA PDI programming protocol support. <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr> * </tr>
* <tr>
* <td>PDI_VIA_HARDWARE_USART</td>
* <td>Makefile CDEFS</td>
* <td>Define to force the PDI protocol (when enabled) to use the hardware USART instead of bit-banging to match the official
* AVRISP pinout. <i>Automatically set when compiled for the XPLAIN board.</i></td>
* </tr>
* </table> * </table>
*/ */

@ -104,17 +104,12 @@ static void PDIProtocol_EnterXPROGMode(void)
Endpoint_ClearOUT(); Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
PDIDATA_LINE_DDR |= PDIDATA_LINE_MASK; /* Enable PDI programming mode with the attached target */
PDICLOCK_LINE_DDR |= PDICLOCK_LINE_MASK; PDITarget_EnableTargetPDI();
/* Must hold DATA line high for at least 90nS to enable PDI interface */ /* Store the RESET ket into the RESET PDI register to complete the handshake */
PDIDATA_LINE_PORT |= PDIDATA_LINE_MASK; PDITarget_SendByte(PDI_CMD_STCS | PD_RESET_REG);
asm volatile ("NOP"::); PDITarget_SendByte(PDI_RESET_KEY);
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 access to the XPROG NVM bus by sending the documented NVM access key to the device */ /* Enable access to the XPROG NVM bus by sending the documented NVM access key to the device */
PDITarget_SendByte(PDI_CMD_KEY); PDITarget_SendByte(PDI_CMD_KEY);
@ -140,13 +135,7 @@ static void PDIProtocol_LeaveXPROGMode(void)
Endpoint_ClearOUT(); Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
/* Set DATA and CLOCK lines to inputs */ PDITarget_DisableTargetPDI();
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;
Endpoint_Write_Byte(CMD_XPROG); Endpoint_Write_Byte(CMD_XPROG);
Endpoint_Write_Byte(XPRG_CMD_LEAVE_PROGMODE); Endpoint_Write_Byte(XPRG_CMD_LEAVE_PROGMODE);

@ -38,90 +38,191 @@
#define INCLUDE_FROM_PDITARGET_C #define INCLUDE_FROM_PDITARGET_C
#include "PDITarget.h" #include "PDITarget.h"
/** Writes a given byte to the attached XMEGA device, using a RS232 frame via software through the #if !defined(PDI_VIA_HARDWARE_USART)
* PDI interface. volatile bool IsSending;
* volatile uint16_t DataBits;
* \param[in] Byte Byte to send to the attached device volatile uint8_t BitCount;
*/
void PDITarget_SendByte(uint8_t Byte) ISR(TIMER0_COMPA_vect, ISR_BLOCK)
{ {
uint8_t LogicOneBits = 0; BITBANG_PDICLOCK_PORT ^= BITBANG_PDICLOCK_MASK;
// One Start Bit /* If not sending or receiving, just exit */
PDIDATA_LINE_PORT &= ~PDIDATA_LINE_MASK; if (!(BitCount))
return;
TOGGLE_PDI_CLOCK; /* Check to see if the current clock state is on the rising or falling edge */
bool IsRisingEdge = (BITBANG_PDICLOCK_PORT & BITBANG_PDICLOCK_MASK);
// Eight Data Bits if (IsSending && !IsRisingEdge)
for (uint8_t i = 0; i < 8; i++)
{ {
if (Byte & 0x01) if (DataBits & 0x01)
{ BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;
PDIDATA_LINE_PORT &= ~PDIDATA_LINE_MASK;
LogicOneBits++;
}
else else
{ BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
PDIDATA_LINE_PORT |= PDIDATA_LINE_MASK;
}
Byte >>= 1; 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;
TOGGLE_PDI_CLOCK; if (BITBANG_PDIDATA_PORT & BITBANG_PDIDATA_MASK)
DataBits |= (1 << (BITS_IN_FRAME - 1));
DataBits >>= 1;
BitCount--;
} }
}
// Even Parity Bit void PDITarget_EnableTargetPDI(void)
if (LogicOneBits & 0x01) {
PDIDATA_LINE_PORT &= ~PDIDATA_LINE_MASK; /* Set DATA and CLOCK lines to outputs */
else BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK;
PDIDATA_LINE_PORT |= PDIDATA_LINE_MASK; BITBANG_PDICLOCK_DDR |= BITBANG_PDICLOCK_MASK;
/* 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);
}
TOGGLE_PDI_CLOCK; void PDITarget_DisableTargetPDI(void)
{
/* Set DATA and CLOCK lines to inputs */
BITBANG_PDIDATA_DDR &= ~BITBANG_PDIDATA_MASK;
BITBANG_PDICLOCK_DDR &= ~BITBANG_PDICLOCK_MASK;
// Two Stop Bits /* Tristate DATA and CLOCK lines */
PDIDATA_LINE_PORT |= PDIDATA_LINE_MASK; BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;
BITBANG_PDICLOCK_PORT &= ~BITBANG_PDICLOCK_MASK;
TOGGLE_PDI_CLOCK; TCCR0B = 0;
TOGGLE_PDI_CLOCK; }
void PDITarget_SendByte(uint8_t Byte)
{
bool IsOddBitsSet = false;
/* Compute Even parity bit */
for (uint8_t i = 0; i < 8; i++)
{
if (Byte & (1 << i))
IsOddBitsSet = !(IsOddBitsSet);
}
/* Data shifted out LSB first, START DATA PARITY STOP STOP */
DataBits = ((uint16_t)IsOddBitsSet << 10) | ((uint16_t)Byte << 1) | (1 << 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;
} }
/** 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) uint8_t PDITarget_ReceiveByte(void)
{ {
uint8_t ReceivedByte = 0; IsSending = false;
BitCount = BITS_IN_FRAME;
while (BitCount);
PDIDATA_LINE_DDR &= ~PDIDATA_LINE_MASK; return (DataBits >> 1);
}
// One Start Bit void PDITarget_SendBreak(void)
while (PDIDATA_LINE_PIN & PDIDATA_LINE_MASK); {
TOGGLE_PDI_CLOCK; DataBits = 0;
TOGGLE_PDI_CLOCK; BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK;
// Eight Data Bits IsSending = true;
for (uint8_t i = 0; i < 8; i++) BitCount = BITS_IN_FRAME;
{ while (BitCount);
if (!(PDIDATA_LINE_PIN & PDIDATA_LINE_MASK))
ReceivedByte |= 0x80;
ReceivedByte >>= 1; 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);
/* Set DATA line high for 90ns to disable /RESET functionality */
PORTD |= (1 << 3);
asm volatile ("NOP"::);
asm volatile ("NOP"::);
/* 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();
}
TOGGLE_PDI_CLOCK; void PDITarget_DisableTargetPDI(void)
} {
/* Turn of receiver and transmitter of the USART, clear settings */
UCSR1B = 0;
UCSR1C = 0;
// Even Parity Bit (discarded) /* Set all USART lines as input, tristate */
TOGGLE_PDI_CLOCK; DDRD &= ~(1 << 5) | (1 << 3);
PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2));
}
// Two Stop Bits void PDITarget_SendByte(uint8_t Byte)
TOGGLE_PDI_CLOCK; {
TOGGLE_PDI_CLOCK; UCSR1B &= ~(1 << RXEN1);
UCSR1B |= (1 << TXEN1);
PDIDATA_LINE_DDR |= PDIDATA_LINE_MASK; UDR1 = Byte;
return ReceivedByte; 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 #endif

@ -38,6 +38,7 @@
/* Includes: */ /* Includes: */
#include <avr/io.h> #include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h> #include <stdbool.h>
#include <LUFA/Common/Common.h> #include <LUFA/Common/Common.h>
@ -53,25 +54,20 @@
/* Defines: */ /* Defines: */
#if BOARD == BOARD_XPLAIN #if BOARD == BOARD_XPLAIN
#define PDIDATA_LINE_PORT PORTD #define PDI_VIA_HARDWARE_USART
#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)
#else #else
#define PDIDATA_LINE_PORT PORTB #define BITBANG_PDIDATA_PORT PORTB
#define PDIDATA_LINE_DDR DDRB #define BITBANG_PDIDATA_DDR DDRB
#define PDIDATA_LINE_PIN PINB #define BITBANG_PDIDATA_PIN PINB
#define PDIDATA_LINE_MASK (1 << 3) #define BITBANG_PDIDATA_MASK (1 << 3)
#define PDICLOCK_LINE_PORT RESET_LINE_PORT #define BITBANG_PDICLOCK_PORT RESET_LINE_PORT
#define PDICLOCK_LINE_DDR RESET_LINE_DDR #define BITBANG_PDICLOCK_DDR RESET_LINE_DDR
#define PDICLOCK_LINE_MASK RESET_LINE_MASK #define BITBANG_PDICLOCK_MASK RESET_LINE_MASK
#endif #endif
#define BITS_IN_FRAME 12
#define PDI_CMD_LDS 0x00 #define PDI_CMD_LDS 0x00
#define PDI_CMD_LD 0x20 #define PDI_CMD_LD 0x20
#define PDI_CMD_STS 0x40 #define PDI_CMD_STS 0x40
@ -90,13 +86,11 @@
#define PDI_RESET_KEY 0x59 #define PDI_RESET_KEY 0x59
#define PDI_NVMENABLE_KEY (uint8_t[]){0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF} #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: */ /* Function Prototypes: */
void PDITarget_EnableTargetPDI(void);
void PDITarget_DisableTargetPDI(void);
void PDITarget_SendByte(uint8_t Byte); void PDITarget_SendByte(uint8_t Byte);
uint8_t PDITarget_ReceiveByte(void); uint8_t PDITarget_ReceiveByte(void);
void PDITarget_SendBreak(void);
#endif #endif

@ -60,7 +60,7 @@
# MCU name # MCU name
MCU = at90usb162 MCU = at90usb1287
# Target board (see library "Board Types" documentation, USER or blank for projects not requiring # Target board (see library "Board Types" documentation, USER or blank for projects not requiring

Loading…
Cancel
Save