aboutsummaryrefslogtreecommitdiffstats
path: root/Projects/AVRISP
diff options
context:
space:
mode:
Diffstat (limited to 'Projects/AVRISP')
-rw-r--r--Projects/AVRISP/AVRISP.txt5
-rw-r--r--Projects/AVRISP/Lib/PDIProtocol.c18
-rw-r--r--Projects/AVRISP/Lib/PDITarget.c251
-rw-r--r--Projects/AVRISP/Lib/PDITarget.h53
-rw-r--r--Projects/AVRISP/makefile1
5 files changed, 200 insertions, 128 deletions
diff --git a/Projects/AVRISP/AVRISP.txt b/Projects/AVRISP/AVRISP.txt
index 9dd2f119f..6eeef385c 100644
--- a/Projects/AVRISP/AVRISP.txt
+++ b/Projects/AVRISP/AVRISP.txt
@@ -168,6 +168,11 @@
* <td>PORT register for the programmer's target RESET line. <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr>
* <tr>
+ * <td>RESET_LINE_PIN</td>
+ * <td>Makefile CDEFS</td>
+ * <td>PIN register for the programmer's target RESET line. <i>Ignored when compiled for the XPLAIN board.</i></td>
+ * </tr>
+ * <tr>
* <td>RESET_LINE_DDR</td>
* <td>Makefile CDEFS</td>
* <td>DDR register for the programmer's target RESET line. <i>Ignored when compiled for the XPLAIN board.</i></td>
diff --git a/Projects/AVRISP/Lib/PDIProtocol.c b/Projects/AVRISP/Lib/PDIProtocol.c
index 2107e2b89..776934311 100644
--- a/Projects/AVRISP/Lib/PDIProtocol.c
+++ b/Projects/AVRISP/Lib/PDIProtocol.c
@@ -106,7 +106,7 @@ static void PDIProtocol_EnterXPROGMode(void)
PDITarget_EnableTargetPDI();
/* Store the RESET key into the RESET PDI register to keep the XMEGA in reset */
- PDITarget_SendByte(PDI_CMD_STCS | PD_RESET_REG);
+ PDITarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
PDITarget_SendByte(PDI_RESET_KEY);
/* Enable access to the XPROG NVM bus by sending the documented NVM access key to the device */
@@ -114,20 +114,12 @@ static void PDIProtocol_EnterXPROGMode(void)
for (uint8_t i = sizeof(PDI_NVMENABLE_KEY); i > 0; i--)
PDITarget_SendByte(PDI_NVMENABLE_KEY[i - 1]);
- /* Poll the STATUS register to check to see if NVM access has been enabled */
- uint8_t NVMAttemptsRemaining = 255;
- while (NVMAttemptsRemaining)
- {
- PDITarget_SendByte(PDI_CMD_LDCS | PD_STATUS_REG);
- if (PDITarget_ReceiveByte() & PDI_STATUS_NVM)
- break;
-
- NVMAttemptsRemaining--;
- }
+ /* Wait until the NVM bus becomes active */
+ bool NVMBusEnabled = PDITarget_WaitWhileNVMBusBusy();
Endpoint_Write_Byte(CMD_XPROG);
Endpoint_Write_Byte(XPRG_CMD_ENTER_PROGMODE);
- Endpoint_Write_Byte(NVMAttemptsRemaining ? XPRG_ERR_OK : XPRG_ERR_FAILED);
+ Endpoint_Write_Byte(NVMBusEnabled ? XPRG_ERR_OK : XPRG_ERR_FAILED);
Endpoint_ClearIN();
}
@@ -140,7 +132,7 @@ static void PDIProtocol_LeaveXPROGMode(void)
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
/* Clear the RESET key into the RESET PDI register to allow the XMEGA to run */
- PDITarget_SendByte(PDI_CMD_STCS | PD_RESET_REG);
+ PDITarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
PDITarget_SendByte(0x00);
PDITarget_DisableTargetPDI();
diff --git a/Projects/AVRISP/Lib/PDITarget.c b/Projects/AVRISP/Lib/PDITarget.c
index eb16e0a28..b56fe60b6 100644
--- a/Projects/AVRISP/Lib/PDITarget.c
+++ b/Projects/AVRISP/Lib/PDITarget.c
@@ -41,131 +41,54 @@
volatile bool IsSending;
#if !defined(PDI_VIA_HARDWARE_USART)
-volatile uint16_t DataBits;
-volatile uint8_t BitCount;
+volatile uint16_t SoftUSART_Data;
+volatile uint8_t SoftUSART_BitCount;
ISR(TIMER0_COMPA_vect, ISR_BLOCK)
{
- BITBANG_PDICLOCK_PORT ^= BITBANG_PDICLOCK_MASK;
+ /* Toggle CLOCK pin in a single cycle (see AVR datasheet) */
+ BITBANG_PDICLOCK_PIN |= BITBANG_PDICLOCK_MASK;
/* If not sending or receiving, just exit */
- if (!(BitCount))
+ if (!(SoftUSART_BitCount))
return;
-
+
/* 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 (DataBits & 0x01)
- BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;
+ if (SoftUSART_Data & 0x01)
+ BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
else
- BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
+ BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;
- DataBits >>= 1;
- BitCount--;
+ SoftUSART_Data >>= 1;
+ SoftUSART_BitCount--;
}
else if (!IsSending && IsRisingEdge)
{
/* Wait for the start bit when receiving */
- if ((BitCount == BITS_IN_FRAME) && (BITBANG_PDIDATA_PORT & BITBANG_PDIDATA_MASK))
+ if ((SoftUSART_BitCount == BITS_IN_FRAME) && (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK))
return;
- if (BITBANG_PDIDATA_PORT & BITBANG_PDIDATA_MASK)
- DataBits |= (1 << (BITS_IN_FRAME - 1));
+ if (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK)
+ SoftUSART_Data |= (1 << BITS_IN_FRAME);
- DataBits >>= 1;
- BitCount--;
+ SoftUSART_Data >>= 1;
+ SoftUSART_BitCount--;
}
}
+#endif
void PDITarget_EnableTargetPDI(void)
{
- /* Set DATA and CLOCK lines to outputs */
- BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_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);
-}
-
-void PDITarget_DisableTargetPDI(void)
-{
- /* 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;
-
- TCCR0B = 0;
-}
-
-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;
-}
-
-uint8_t PDITarget_ReceiveByte(void)
-{
- IsSending = false;
- BitCount = BITS_IN_FRAME;
- while (BitCount);
-
- return (DataBits >> 1);
-}
-
-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)
-{
+#if defined(PDI_VIA_HARDWARE_USART)
/* 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 */
+ /* Set DATA line high for at least 90ns to disable /RESET functionality */
PORTD |= (1 << 3);
asm volatile ("NOP"::);
asm volatile ("NOP"::);
@@ -179,10 +102,30 @@ void PDITarget_EnableTargetPDI(void)
/* Send two BREAKs of 12 bits each to enable PDI interface (need at least 16 idle bits) */
PDITarget_SendBreak();
PDITarget_SendBreak();
+#else
+ /* Set DATA and CLOCK lines to outputs */
+ BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK;
+ BITBANG_PDICLOCK_DDR |= BITBANG_PDICLOCK_MASK;
+
+ /* Set DATA line high for at least 90ns to disable /RESET functionality */
+ BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
+ asm volatile ("NOP"::);
+ asm volatile ("NOP"::);
+
+ /* Fire timer compare ISR every 50 cycles to manage the software USART */
+ OCR0A = 50;
+ TCCR0A = (1 << WGM01);
+ TCCR0B = (1 << CS00);
+ TIMSK0 = (1 << OCIE0A);
+
+ PDITarget_SendBreak();
+ PDITarget_SendBreak();
+#endif
}
void PDITarget_DisableTargetPDI(void)
{
+#if defined(PDI_VIA_HARDWARE_USART)
/* Turn off receiver and transmitter of the USART, clear settings */
UCSR1A |= (1 << TXC1) | (1 << RXC1);
UCSR1B = 0;
@@ -191,10 +134,22 @@ void PDITarget_DisableTargetPDI(void)
/* Set all USART lines as input, tristate */
DDRD &= ~((1 << 5) | (1 << 3));
PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2));
+#else
+ /* 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;
+
+ TCCR0B = 0;
+#endif
}
void PDITarget_SendByte(uint8_t Byte)
{
+#if defined(PDI_VIA_HARDWARE_USART)
/* Switch to Tx mode if currently in Rx mode */
if (!(IsSending))
{
@@ -210,10 +165,37 @@ void PDITarget_SendByte(uint8_t Byte)
/* Wait until there is space in the hardware Tx buffer before writing */
while (!(UCSR1A & (1 << UDRE1)));
UDR1 = Byte;
+#else
+ /* Switch to Tx mode if currently in Rx mode */
+ if (!(IsSending))
+ {
+ BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
+ BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK;
+
+ IsSending = true;
+ }
+
+ bool EvenParityBit = false;
+ uint8_t ParityData = Byte;
+
+ /* Compute Even parity bit */
+ for (uint8_t i = 0; i < 8; i++)
+ {
+ EvenParityBit ^= ParityData & 0x01;
+ ParityData >>= 1;
+ }
+
+ while (SoftUSART_BitCount);
+
+ /* Data shifted out LSB first, START DATA PARITY STOP STOP */
+ SoftUSART_Data = ((uint16_t)EvenParityBit << 9) | ((uint16_t)Byte << 1) | (1 << 10) | (1 << 11);
+ SoftUSART_BitCount = BITS_IN_FRAME;
+#endif
}
uint8_t PDITarget_ReceiveByte(void)
{
+#if defined(PDI_VIA_HARDWARE_USART)
/* Switch to Rx mode if currently in Tx mode */
if (IsSending)
{
@@ -232,10 +214,30 @@ uint8_t PDITarget_ReceiveByte(void)
/* Wait until a byte has been received before reading */
while (!(UCSR1A & (1 << RXC1)));
return UDR1;
+#else
+ /* Switch to Rx mode if currently in Tx mode */
+ if (IsSending)
+ {
+ while (SoftUSART_BitCount);
+
+ BITBANG_PDIDATA_DDR &= ~BITBANG_PDIDATA_MASK;
+ BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;
+
+ IsSending = false;
+ }
+
+ /* Wait until a byte has been received before reading */
+ SoftUSART_BitCount = BITS_IN_FRAME;
+ while (SoftUSART_BitCount);
+
+ /* Throw away the start, parity and stop bits to leave only the data */
+ return (uint8_t)(SoftUSART_Data >> 1);
+#endif
}
void PDITarget_SendBreak(void)
{
+#if defined(PDI_VIA_HARDWARE_USART)
/* Switch to Tx mode if currently in Rx mode */
if (!(IsSending))
{
@@ -251,13 +253,62 @@ void PDITarget_SendBreak(void)
/* Need to do nothing for a full frame to send a BREAK */
for (uint8_t i = 0; i <= BITS_IN_FRAME; i++)
{
- /* Wait for rising edge of clock */
+ /* Wait for a full cycle of the clock */
while (PIND & (1 << 5));
-
- /* Wait for falling edge of clock */
while (!(PIND & (1 << 5)));
}
-}
+#else
+ /* Switch to Tx mode if currently in Rx mode */
+ if (!(IsSending))
+ {
+ BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
+ BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK;
+
+ IsSending = true;
+ }
+
+ while (SoftUSART_BitCount);
+
+ /* Need to do nothing for a full frame to send a BREAK */
+ SoftUSART_Data = 0x0FFF;
+ SoftUSART_BitCount = BITS_IN_FRAME;
#endif
+}
+
+void PDITarget_SendAddress(uint32_t Address)
+{
+ PDITarget_SendByte(Address >> 24);
+ PDITarget_SendByte(Address >> 26);
+ PDITarget_SendByte(Address >> 8);
+ PDITarget_SendByte(Address & 0xFF);
+}
+
+bool PDITarget_WaitWhileNVMBusBusy(void)
+{
+ uint8_t AttemptsRemaining = 255;
+
+ /* Poll the STATUS register to check to see if NVM access has been enabled */
+ while (AttemptsRemaining--)
+ {
+ PDITarget_SendByte(PDI_CMD_LDCS | PDI_STATUS_REG);
+ if (PDITarget_ReceiveByte() & PDI_STATUS_NVM)
+ return true;
+ }
+
+ return false;
+}
+
+void PDITarget_WaitWhileNVMControllerBusy(void)
+{
+ /* Poll the NVM STATUS register to check to see if NVM controller is busy */
+ for (;;)
+ {
+ PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_1BYTE << 2));
+ PDITarget_SendAddress(DATAMEM_BASE | DATAMEM_NVM_BASE | 0x0F);
+
+ if (!(PDITarget_ReceiveByte() & (1 << 7)))
+ return;
+ }
+}
#endif
diff --git a/Projects/AVRISP/Lib/PDITarget.h b/Projects/AVRISP/Lib/PDITarget.h
index 272655594..85f627a6a 100644
--- a/Projects/AVRISP/Lib/PDITarget.h
+++ b/Projects/AVRISP/Lib/PDITarget.h
@@ -63,34 +63,57 @@
#define BITBANG_PDICLOCK_PORT RESET_LINE_PORT
#define BITBANG_PDICLOCK_DDR RESET_LINE_DDR
+ #define BITBANG_PDICLOCK_PIN RESET_LINE_PIN
#define BITBANG_PDICLOCK_MASK RESET_LINE_MASK
#endif
- #define BITS_IN_FRAME 12
+ #define BITS_IN_FRAME 12
- #define PDI_CMD_LDS 0x00
- #define PDI_CMD_LD 0x20
- #define PDI_CMD_STS 0x40
- #define PDI_CMD_ST 0x60
- #define PDI_CMD_LDCS 0x80
- #define PDI_CMD_REPEAT 0xA0
- #define PDI_CMD_STCS 0xC0
- #define PDI_CMD_KEY 0xE0
+ #define PDI_CMD_LDS 0x00
+ #define PDI_CMD_LD 0x20
+ #define PDI_CMD_STS 0x40
+ #define PDI_CMD_ST 0x60
+ #define PDI_CMD_LDCS 0x80
+ #define PDI_CMD_REPEAT 0xA0
+ #define PDI_CMD_STCS 0xC0
+ #define PDI_CMD_KEY 0xE0
- #define PD_STATUS_REG 0
- #define PD_RESET_REG 1
- #define PD_CTRL_REG 2
+ #define PDI_STATUS_REG 0
+ #define PDI_RESET_REG 1
+ #define PDI_CTRL_REG 2
+
+ #define PDI_STATUS_NVM (1 << 1)
+ #define PDI_RESET_KEY 0x59
+
+ #define PDI_NVMENABLE_KEY (uint8_t[]){0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF}
- #define PDI_STATUS_NVM (1 << 1)
+ #define PDI_DATSIZE_1BYTE 0
+ #define PDI_DATSIZE_2BYTES 1
+ #define PDI_DATSIZE_3BYTES 2
+ #define PDI_DATSIZE_4BYTES 3
+
+ #define PDI_POINTER_INDIRECT 0
+ #define PDI_POINTER_INDIRECT_PI 1
+ #define PDI_POINTER_DIRECT 2
- #define PDI_RESET_KEY 0x59
- #define PDI_NVMENABLE_KEY (uint8_t[]){0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF}
+ #define FLASH_BASE 0x00800000
+ #define EPPROM_BASE 0x008C0000
+ #define FUSE_BASE 0x008F0020
+ #define DATAMEM_BASE 0x01000000
+ #define PROD_SIGNATURE_BASE 0x008E0200
+ #define USER_SIGNATURE_BASE 0x008E0400
+ #define DATAMEM_NVM_BASE 0x01C0
+
/* 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);
+
+ void PDITarget_SendAddress(uint32_t Address);
+ bool PDITarget_WaitWhileNVMBusBusy(void);
+ void PDITarget_WaitWhileNVMControllerBusy(void);
#endif
diff --git a/Projects/AVRISP/makefile b/Projects/AVRISP/makefile
index 003eaa57a..e8fabc5ad 100644
--- a/Projects/AVRISP/makefile
+++ b/Projects/AVRISP/makefile
@@ -190,6 +190,7 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD) $(LUFA_OPTS)
CDEFS += -DRESET_LINE_PORT=PORTB
+CDEFS += -DRESET_LINE_PIN=PINB
CDEFS += -DRESET_LINE_DDR=DDRB
CDEFS += -DRESET_LINE_MASK="(1 << 4)"
CDEFS += -DVTARGET_ADC_CHANNEL=2