forked from mfulz_github/qmk_firmware
Change over AVRISP project to have both hardware USART and software USART modes for the PDI protocol, when enabled. Fix up PDI initialisation routines.
This commit is contained in:
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,18 +104,13 @@ 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 */
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
/* 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 */
|
/* 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);
|
||||||
for (uint8_t i = 0; i < sizeof(PDI_NVMENABLE_KEY); i++)
|
for (uint8_t i = 0; i < sizeof(PDI_NVMENABLE_KEY); i++)
|
||||||
|
@ -140,14 +135,8 @@ 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);
|
||||||
Endpoint_Write_Byte(XPRG_ERR_OK);
|
Endpoint_Write_Byte(XPRG_ERR_OK);
|
||||||
|
|
|
@ -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;
|
||||||
*/
|
|
||||||
|
ISR(TIMER0_COMPA_vect, ISR_BLOCK)
|
||||||
|
{
|
||||||
|
BITBANG_PDICLOCK_PORT ^= BITBANG_PDICLOCK_MASK;
|
||||||
|
|
||||||
|
/* If not sending or receiving, just exit */
|
||||||
|
if (!(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;
|
||||||
|
else
|
||||||
|
BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
DataBits >>= 1;
|
||||||
|
BitCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
void PDITarget_SendByte(uint8_t Byte)
|
||||||
{
|
{
|
||||||
uint8_t LogicOneBits = 0;
|
bool IsOddBitsSet = false;
|
||||||
|
|
||||||
// One Start Bit
|
|
||||||
PDIDATA_LINE_PORT &= ~PDIDATA_LINE_MASK;
|
|
||||||
|
|
||||||
TOGGLE_PDI_CLOCK;
|
|
||||||
|
|
||||||
// Eight Data Bits
|
/* Compute Even parity bit */
|
||||||
for (uint8_t i = 0; i < 8; i++)
|
for (uint8_t i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if (Byte & 0x01)
|
if (Byte & (1 << i))
|
||||||
{
|
IsOddBitsSet = !(IsOddBitsSet);
|
||||||
PDIDATA_LINE_PORT &= ~PDIDATA_LINE_MASK;
|
|
||||||
LogicOneBits++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PDIDATA_LINE_PORT |= PDIDATA_LINE_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Byte >>= 1;
|
|
||||||
|
|
||||||
TOGGLE_PDI_CLOCK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Even Parity Bit
|
/* Data shifted out LSB first, START DATA PARITY STOP STOP */
|
||||||
if (LogicOneBits & 0x01)
|
DataBits = ((uint16_t)IsOddBitsSet << 10) | ((uint16_t)Byte << 1) | (1 << 0);
|
||||||
PDIDATA_LINE_PORT &= ~PDIDATA_LINE_MASK;
|
|
||||||
else
|
|
||||||
PDIDATA_LINE_PORT |= PDIDATA_LINE_MASK;
|
|
||||||
|
|
||||||
TOGGLE_PDI_CLOCK;
|
BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
|
||||||
|
BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK;
|
||||||
|
|
||||||
// Two Stop Bits
|
IsSending = true;
|
||||||
PDIDATA_LINE_PORT |= PDIDATA_LINE_MASK;
|
BitCount = BITS_IN_FRAME;
|
||||||
|
while (BitCount);
|
||||||
TOGGLE_PDI_CLOCK;
|
|
||||||
TOGGLE_PDI_CLOCK;
|
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
|
|
||||||
while (PDIDATA_LINE_PIN & PDIDATA_LINE_MASK);
|
|
||||||
TOGGLE_PDI_CLOCK;
|
|
||||||
|
|
||||||
TOGGLE_PDI_CLOCK;
|
|
||||||
|
|
||||||
// Eight Data Bits
|
|
||||||
for (uint8_t i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
if (!(PDIDATA_LINE_PIN & PDIDATA_LINE_MASK))
|
|
||||||
ReceivedByte |= 0x80;
|
|
||||||
|
|
||||||
ReceivedByte >>= 1;
|
|
||||||
|
|
||||||
TOGGLE_PDI_CLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Even Parity Bit (discarded)
|
|
||||||
TOGGLE_PDI_CLOCK;
|
|
||||||
|
|
||||||
// Two Stop Bits
|
|
||||||
TOGGLE_PDI_CLOCK;
|
|
||||||
TOGGLE_PDI_CLOCK;
|
|
||||||
|
|
||||||
PDIDATA_LINE_DDR |= PDIDATA_LINE_MASK;
|
|
||||||
|
|
||||||
return ReceivedByte;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
#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
|
||||||
|
@ -89,14 +85,12 @@
|
||||||
|
|
||||||
#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…
Reference in New Issue