aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Projects/AVRISP/AVRISP.txt11
-rw-r--r--Projects/AVRISP/Lib/PDIProtocol.c27
-rw-r--r--Projects/AVRISP/Lib/PDITarget.c221
-rw-r--r--Projects/AVRISP/Lib/PDITarget.h34
-rw-r--r--Projects/AVRISP/makefile2
5 files changed, 194 insertions, 101 deletions
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 @@
* <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>
* <tr>
@@ -149,6 +149,9 @@
* </tr>
* </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
*
* 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>Define to enable XMEGA PDI programming protocol support. <i>Ignored when compiled for the XPLAIN board.</i></td>
* </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>
*/
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 <avr/io.h>
+ #include <avr/interrupt.h>
#include <stdbool.h>
#include <LUFA/Common/Common.h>
@@ -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