Commit 65fcebf4 authored by Dean Camera's avatar Dean Camera
Browse files

Complete combining of PDI and TPI target communication code files, stub out...

Complete combining of PDI and TPI target communication code files, stub out TINY NVM controller functions.
parent cfdab42d
This diff is collapsed.
......@@ -38,6 +38,86 @@
#if defined(ENABLE_XPROG_PROTOCOL) || defined(__DOXYGEN__)
// TODO
/** Busy-waits while the NVM controller is busy performing a NVM operation, such as a FLASH page read or CRC
* calculation.
*
* \return Boolean true if the NVM controller became ready within the timeout period, false otherwise
*/
bool XMEGANVM_WaitWhileNVMBusBusy(void)
{
// TODO
return false;
}
/** Waits while the target's NVM controller is busy performing an operation, exiting if the
* timeout period expires.
*
* \return Boolean true if the NVM controller became ready within the timeout period, false otherwise
*/
bool XMEGANVM_WaitWhileNVMControllerBusy(void)
{
// TODO
return false;
}
/** Retrieves the CRC value of the given memory space.
*
* \param[in] CRCCommand NVM CRC command to issue to the target
* \param[out] CRCDest CRC Destination when read from the target
*
* \return Boolean true if the command sequence complete successfully
*/
bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest)
{
// TODO
return true;
}
/** Reads memory from the target's memory spaces.
*
* \param[in] ReadAddress Start address to read from within the target's address space
* \param[out] ReadBuffer Buffer to store read data into
* \param[in] ReadSize Number of bytes to read
*
* \return Boolean true if the command sequence complete successfully
*/
bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const uint16_t ReadSize)
{
// TODO
return true;
}
/** Writes byte addressed memory to the target's memory spaces.
*
* \param[in] WriteCommand Command to send to the device to write each memory byte
* \param[in] WriteAddress Start address to write to within the target's address space
* \param[in] WriteBuffer Buffer to source data from
*
* \return Boolean true if the command sequence complete successfully
*/
bool XMEGANVM_WriteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer)
{
// TODO
return true;
}
/** Erases a specific memory space of the target.
*
* \param[in] EraseCommand NVM erase command to send to the device
* \param[in] Address Address inside the memory space to erase
*
* \return Boolean true if the command sequence complete successfully
*/
bool XMEGANVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address)
{
// TODO
return true;
}
#endif
......@@ -44,7 +44,7 @@
#include <LUFA/Common/Common.h>
#include "XPROGProtocol.h"
#include "TPITarget.h"
#include "XPROGTarget.h"
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
......@@ -58,4 +58,11 @@
/* Defines: */
#define TINY_NVM_BUSY_TIMEOUT_MS 100
/* Function Prototypes: */
bool TINYNVM_WaitWhileNVMControllerBusy(void);
bool TINYNVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const uint16_t ReadSize);
bool TINYNVM_WriteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer);
bool TINYNVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address);
bool TINYNVM_WaitWhileNVMBusBusy(void);
#endif
......@@ -58,10 +58,40 @@ void XMEGANVM_SendNVMRegAddress(const uint8_t Register)
void XMEGANVM_SendAddress(const uint32_t AbsoluteAddress)
{
/* Send the given 32-bit address to the target, LSB first */
PDITarget_SendByte(AbsoluteAddress & 0xFF);
PDITarget_SendByte(AbsoluteAddress >> 8);
PDITarget_SendByte(AbsoluteAddress >> 16);
PDITarget_SendByte(AbsoluteAddress >> 24);
XPROGTarget_SendByte(AbsoluteAddress & 0xFF);
XPROGTarget_SendByte(AbsoluteAddress >> 8);
XPROGTarget_SendByte(AbsoluteAddress >> 16);
XPROGTarget_SendByte(AbsoluteAddress >> 24);
}
/** Busy-waits while the NVM controller is busy performing a NVM operation, such as a FLASH page read or CRC
* calculation.
*
* \return Boolean true if the NVM controller became ready within the timeout period, false otherwise
*/
bool XMEGANVM_WaitWhileNVMBusBusy(void)
{
TCNT0 = 0;
TIFR0 = (1 << OCF1A);
uint8_t TimeoutMS = XMEGA_NVM_BUSY_TIMEOUT_MS;
/* Poll the STATUS register to check to see if NVM access has been enabled */
while (TimeoutMS)
{
/* Send the LDCS command to read the PDI STATUS register to see the NVM bus is active */
XPROGTarget_SendByte(PDI_CMD_LDCS | PDI_STATUS_REG);
if (XPROGTarget_ReceiveByte() & PDI_STATUS_NVM)
return true;
if (TIFR0 & (1 << OCF1A))
{
TIFR0 = (1 << OCF1A);
TimeoutMS--;
}
}
return false;
}
/** Waits while the target's NVM controller is busy performing an operation, exiting if the
......@@ -80,11 +110,11 @@ bool XMEGANVM_WaitWhileNVMControllerBusy(void)
while (TimeoutMS)
{
/* Send a LDS command to read the NVM STATUS register to check the BUSY flag */
PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_STATUS);
/* Check to see if the BUSY flag is still set */
if (!(PDITarget_ReceiveByte() & (1 << 7)))
if (!(XPROGTarget_ReceiveByte() & (1 << 7)))
return true;
if (TIFR0 & (1 << OCF1A))
......@@ -111,17 +141,17 @@ bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest)
return false;
/* Set the NVM command to the correct CRC read command */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
PDITarget_SendByte(CRCCommand);
XPROGTarget_SendByte(CRCCommand);
/* Set CMDEX bit in NVM CTRLA register to start the CRC generation */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
PDITarget_SendByte(1 << 0);
XPROGTarget_SendByte(1 << 0);
/* Wait until the NVM bus is ready again */
if (!(PDITarget_WaitWhileNVMBusBusy()))
if (!(XMEGANVM_WaitWhileNVMBusBusy()))
return false;
/* Wait until the NVM controller is no longer busy */
......@@ -131,19 +161,19 @@ bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest)
*CRCDest = 0;
/* Read the first generated CRC byte value */
PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT0);
*CRCDest = PDITarget_ReceiveByte();
*CRCDest = XPROGTarget_ReceiveByte();
/* Read the second generated CRC byte value */
PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT1);
*CRCDest |= ((uint16_t)PDITarget_ReceiveByte() << 8);
*CRCDest |= ((uint16_t)XPROGTarget_ReceiveByte() << 8);
/* Read the third generated CRC byte value */
PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT2);
*CRCDest |= ((uint32_t)PDITarget_ReceiveByte() << 16);
*CRCDest |= ((uint32_t)XPROGTarget_ReceiveByte() << 16);
return true;
}
......@@ -163,22 +193,22 @@ bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const
return false;
/* Send the READNVM command to the NVM controller for reading of an arbitrary location */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
PDITarget_SendByte(XMEGA_NVM_CMD_READNVM);
XPROGTarget_SendByte(XMEGA_NVM_CMD_READNVM);
/* Load the PDI pointer register with the start address we want to read from */
PDITarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES);
XPROGTarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES);
XMEGANVM_SendAddress(ReadAddress);
/* Send the REPEAT command with the specified number of bytes to read */
PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE);
PDITarget_SendByte(ReadSize - 1);
XPROGTarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE);
XPROGTarget_SendByte(ReadSize - 1);
/* Send a LD command with indirect access and postincrement to read out the bytes */
PDITarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
XPROGTarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
for (uint16_t i = 0; i < ReadSize; i++)
*(ReadBuffer++) = PDITarget_ReceiveByte();
*(ReadBuffer++) = XPROGTarget_ReceiveByte();
return true;
}
......@@ -198,14 +228,14 @@ bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAd
return false;
/* Send the memory write command to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
PDITarget_SendByte(WriteCommand);
XPROGTarget_SendByte(WriteCommand);
/* Send new memory byte to the memory to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendAddress(WriteAddress);
PDITarget_SendByte(*(WriteBuffer++));
XPROGTarget_SendByte(*(WriteBuffer++));
return true;
}
......@@ -233,14 +263,14 @@ bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t Eras
return false;
/* Send the memory buffer erase command to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
PDITarget_SendByte(EraseBuffCommand);
XPROGTarget_SendByte(EraseBuffCommand);
/* Set CMDEX bit in NVM CTRLA register to start the buffer erase */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
PDITarget_SendByte(1 << 0);
XPROGTarget_SendByte(1 << 0);
}
if (WriteSize)
......@@ -250,22 +280,22 @@ bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t Eras
return false;
/* Send the memory buffer write command to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
PDITarget_SendByte(WriteBuffCommand);
XPROGTarget_SendByte(WriteBuffCommand);
/* Load the PDI pointer register with the start address we want to write to */
PDITarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES);
XPROGTarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES);
XMEGANVM_SendAddress(WriteAddress);
/* Send the REPEAT command with the specified number of bytes to write */
PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE);
PDITarget_SendByte(WriteSize - 1);
XPROGTarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE);
XPROGTarget_SendByte(WriteSize - 1);
/* Send a ST command with indirect access and postincrement to write the bytes */
PDITarget_SendByte(PDI_CMD_ST | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
XPROGTarget_SendByte(PDI_CMD_ST | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
for (uint16_t i = 0; i < WriteSize; i++)
PDITarget_SendByte(*(WriteBuffer++));
XPROGTarget_SendByte(*(WriteBuffer++));
}
if (PageMode & XPRG_PAGEMODE_WRITE)
......@@ -275,14 +305,14 @@ bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t Eras
return false;
/* Send the memory write command to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
PDITarget_SendByte(WritePageCommand);
XPROGTarget_SendByte(WritePageCommand);
/* Send the address of the first page location to write the memory page */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendAddress(WriteAddress);
PDITarget_SendByte(0x00);
XPROGTarget_SendByte(0x00);
}
return true;
......@@ -302,28 +332,28 @@ bool XMEGANVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address)
return false;
/* Send the memory erase command to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
PDITarget_SendByte(EraseCommand);
XPROGTarget_SendByte(EraseCommand);
/* Chip erase is handled separately, since it's procedure is different to other erase types */
if (EraseCommand == XMEGA_NVM_CMD_CHIPERASE)
{
/* Set CMDEX bit in NVM CTRLA register to start the chip erase */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
PDITarget_SendByte(1 << 0);
XPROGTarget_SendByte(1 << 0);
}
else
{
/* Other erase modes just need us to address a byte within the target memory space */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendAddress(Address);
PDITarget_SendByte(0x00);
XPROGTarget_SendByte(0x00);
}
/* Wait until the NVM bus is ready again */
if (!(PDITarget_WaitWhileNVMBusBusy()))
if (!(XMEGANVM_WaitWhileNVMBusBusy()))
return false;
return true;
......
......@@ -44,7 +44,7 @@
#include <LUFA/Common/Common.h>
#include "XPROGProtocol.h"
#include "PDITarget.h"
#include "XPROGTarget.h"
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
......@@ -56,7 +56,7 @@
#endif
/* Defines: */
#define XMEGA_NVM_BUSY_TIMEOUT_MS 200
#define XMEGA_NVM_BUSY_TIMEOUT_MS 100
#define XMEGA_NVM_REG_ADDR0 0x00
#define XMEGA_NVM_REG_ADDR1 0x01
......@@ -116,5 +116,6 @@
const uint8_t WritePageCommand, const uint8_t PageMode, const uint32_t WriteAddress,
const uint8_t* WriteBuffer, const uint16_t WriteSize);
bool XMEGANVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address);
bool XMEGANVM_WaitWhileNVMBusBusy(void);
#endif
......@@ -113,23 +113,26 @@ static void XPROGProtocol_EnterXPROGMode(void)
if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
{
/* Enable PDI programming mode with the attached target */
PDITarget_EnableTargetPDI();
XPROGTarget_EnableTargetPDI();
/* Store the RESET key into the RESET PDI register to keep the XMEGA in reset */
PDITarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
PDITarget_SendByte(PDI_RESET_KEY);
XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
XPROGTarget_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);
XPROGTarget_SendByte(PDI_CMD_KEY);
for (uint8_t i = sizeof(PDI_NVMENABLE_KEY); i > 0; i--)
PDITarget_SendByte(PDI_NVMENABLE_KEY[i - 1]);
XPROGTarget_SendByte(PDI_NVMENABLE_KEY[i - 1]);
/* Wait until the NVM bus becomes active */
NVMBusEnabled = PDITarget_WaitWhileNVMBusBusy();
NVMBusEnabled = XMEGANVM_WaitWhileNVMBusBusy();
}
else
{
// TODO
/* Enable TPI programming mode with the attached target */
XPROGTarget_EnableTargetTPI();
// TODO - enable NVM bus via KEY
}
Endpoint_Write_Byte(CMD_XPROG);
......@@ -149,14 +152,16 @@ static void XPROGProtocol_LeaveXPROGMode(void)
if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
{
/* Clear the RESET key in the RESET PDI register to allow the XMEGA to run */
PDITarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
PDITarget_SendByte(0x00);
XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
XPROGTarget_SendByte(0x00);
PDITarget_DisableTargetPDI();
XPROGTarget_DisableTargetPDI();
}
else
{
// TODO
// TODO - Disable TPI via register
XPROGTarget_DisableTargetTPI();
}
Endpoint_Write_Byte(CMD_XPROG);
......@@ -381,7 +386,8 @@ static void XPROGProtocol_ReadCRC(void)
}
else
{
// TODO
/* TPI does not support memory CRC */
ReturnStatus = XPRG_ERR_FAILED;
}
Endpoint_Write_Byte(CMD_XPROG);
......
......@@ -44,9 +44,8 @@
#include <LUFA/Drivers/USB/USB.h>
#include "../V2Protocol.h"
#include "PDITarget.h"
#include "XPROGTarget.h"
#include "XMEGANVM.h"
#include "TPITarget.h"
#include "TINYNVM.h"
/* Preprocessor Checks: */
......
......@@ -33,8 +33,8 @@
* Target-related functions for the PDI Protocol decoder.
*/
#define INCLUDE_FROM_PDITARGET_C
#include "PDITarget.h"
#define INCLUDE_FROM_XPROGTARGET_C
#include "XPROGTarget.h"
#if defined(ENABLE_XPROG_PROTOCOL) || defined(__DOXYGEN__)
......@@ -49,7 +49,53 @@ volatile uint16_t SoftUSART_Data;
#define SoftUSART_BitCount GPIOR2
/** ISR to manage the software USART when bit-banged USART mode is selected. */
/** ISR to manage the TPI software USART when bit-banged TPI USART mode is selected. */
ISR(TIMER1_CAPT_vect, ISR_BLOCK)
{
/* Toggle CLOCK pin in a single cycle (see AVR datasheet) */
BITBANG_TPICLOCK_PIN |= BITBANG_TPICLOCK_MASK;
/* If not sending or receiving, just exit */
if (!(SoftUSART_BitCount))
return;
/* Check to see if we are at a rising or falling edge of the clock */
if (BITBANG_TPICLOCK_PORT & BITBANG_TPICLOCK_MASK)
{
/* If at rising clock edge and we are in send mode, abort */
if (IsSending)
return;
/* Wait for the start bit when receiving */
if ((SoftUSART_BitCount == BITS_IN_USART_FRAME) && (BITBANG_TPIDATA_PIN & BITBANG_TPIDATA_MASK))
return;
/* Shift in the bit one less than the frame size in position, so that the start bit will eventually
* be discarded leaving the data to be byte-aligned for quick access */
if (BITBANG_TPIDATA_PIN & BITBANG_TPIDATA_MASK)
SoftUSART_Data |= (1 << (BITS_IN_USART_FRAME - 1));
SoftUSART_Data >>= 1;
SoftUSART_BitCount--;
}
else
{
/* If at falling clock edge and we are in receive mode, abort */
if (!IsSending)
return;
/* Set the data line to the next bit value */
if (SoftUSART_Data & 0x01)
BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK;
else
BITBANG_TPIDATA_PORT &= ~BITBANG_TPIDATA_MASK;
SoftUSART_Data >>= 1;
SoftUSART_BitCount--;
}
}
/** ISR to manage the PDI software USART when bit-banged PDI USART mode is selected. */
ISR(TIMER1_COMPA_vect, ISR_BLOCK)
{
/* Toggle CLOCK pin in a single cycle (see AVR datasheet) */
......@@ -67,13 +113,13 @@ ISR(TIMER1_COMPA_vect, ISR_BLOCK)
return;
/* Wait for the start bit when receiving */
if ((SoftUSART_BitCount == BITS_IN_PDI_FRAME) && (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK))
if ((SoftUSART_BitCount == BITS_IN_USART_FRAME) && (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK))
return;
/* Shift in the bit one less than the frame size in position, so that the start bit will eventually
* be discarded leaving the data to be byte-aligned for quick access */
if (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK)
SoftUSART_Data |= (1 << (BITS_IN_PDI_FRAME - 1));
SoftUSART_Data |= (1 << (BITS_IN_USART_FRAME - 1));
SoftUSART_Data >>= 1;
SoftUSART_BitCount--;
......@@ -96,8 +142,50 @@ ISR(TIMER1_COMPA_vect, ISR_BLOCK)
}
#endif
/** Enables the target's TPI interface, holding the target in reset until TPI mode is exited. */
void XPROGTarget_EnableTargetTPI(void)
{
/* Set /RESET line low for at least 90ns to enable TPI functionality */
RESET_LINE_DDR |= RESET_LINE_MASK;
RESET_LINE_PORT &= ~RESET_LINE_MASK;
asm volatile ("NOP"::);
asm volatile ("NOP"::);
#if defined(XPROG_VIA_HARDWARE_USART)
/* Set Tx and XCK as outputs, Rx as input */
DDRD |= (1 << 5) | (1 << 3);
DDRD &= ~(1 << 2);
/* Set up the synchronous USART for XMEGA communications -
8 data bits, even parity, 2 stop bits */
UBRR1 = (F_CPU / 1000000UL);
UCSR1B = (1 << TXEN1);
UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);
/* Send two BREAKs of 12 bits each to enable TPI interface (need at least 16 idle bits) */
XPROGTarget_SendBreak();
XPROGTarget_SendBreak();
#else
/* Set DATA and CLOCK lines to outputs */
BITBANG_TPIDATA_DDR |= BITBANG_TPIDATA_MASK;
BITBANG_TPICLOCK_DDR |= BITBANG_TPICLOCK_MASK;
/* Set DATA line high for idle state */
BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK;
/* Fire timer capture ISR every 100 cycles to manage the software USART */
OCR1A = 80;
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);
TIMSK1 = (1 << ICIE1);
/* Send two BREAKs of 12 bits each to enable TPI interface (need at least 16 idle bits) */
XPROGTarget_SendBreak();
XPROGTarget_SendBreak();
#endif
}
/** Enables the target's PDI interface, holding the target in reset until PDI mode is exited. */
void PDITarget_EnableTargetPDI(void)
void XPROGTarget_EnableTargetPDI(void)
{
#if defined(XPROG_VIA_HARDWARE_USART)
/* Set Tx and XCK as outputs, Rx as input */
......@@ -116,8 +204,8 @@ void PDITarget_EnableTargetPDI(void)
UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);
/* Send two BREAKs of 12 bits each to enable PDI interface (need at least 16 idle bits) */
PDITarget_SendBreak();
PDITarget_SendBreak();
XPROGTarget_SendBreak();
XPROGTarget_SendBreak();
#else
/* Set DATA and CLOCK lines to outputs */
BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK;
......@@ -134,13 +222,40 @@ void PDITarget_EnableTargetPDI(void)
TIMSK1 = (1 << OCIE1A);
/* Send two BREAKs of 12 bits each to enable TPI interface (need at least 16 idle bits) */
PDITarget_SendBreak();
PDITarget_SendBreak();
XPROGTarget_SendBreak();
XPROGTarget_SendBreak();
#endif