Combine AVRISP project TPI and PDI lib directories - these protocols use the same underlying XPROG wrapper for the host-to-programmer command wrapping.

This commit is contained in:
Dean Camera 2009-12-24 01:55:53 +00:00
parent 26bc1f3cfd
commit ce044844ea
20 changed files with 19 additions and 11 deletions

View file

@ -0,0 +1,378 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* PDI Protocol handler, to process V2 Protocol wrapped PDI commands used in Atmel programmer devices.
*/
#define INCLUDE_FROM_PDIPROTOCOL_C
#include "PDIProtocol.h"
#if defined(ENABLE_PDI_PROTOCOL) || defined(__DOXYGEN__)
/** Base absolute address for the target's NVM controller */
uint32_t XPROG_Param_NVMBase = 0x010001C0;
/** Size in bytes of the target's EEPROM page */
uint32_t XPROG_Param_EEPageSize;
/** Handler for the CMD_XPROG_SETMODE command, which sets the programmer-to-target protocol used for PDI
* XMEGA programming (either PDI or JTAG). Only PDI programming is supported.
*/
void PDIProtocol_XPROG_SetMode(void)
{
struct
{
uint8_t Protocol;
} SetMode_XPROG_Params;
Endpoint_Read_Stream_LE(&SetMode_XPROG_Params, sizeof(SetMode_XPROG_Params));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Serial_TxByte(SetMode_XPROG_Params.Protocol);
Endpoint_Write_Byte(CMD_XPROG_SETMODE);
Endpoint_Write_Byte((SetMode_XPROG_Params.Protocol == XPRG_PROTOCOL_PDI) ? STATUS_CMD_OK : STATUS_CMD_FAILED);
Endpoint_ClearIN();
}
/** Handler for the CMD_XPROG command, which wraps up XPROG commands in a V2 wrapper which need to be
* removed and processed so that the underlying XPROG command can be handled.
*/
void PDIProtocol_XPROG_Command(void)
{
uint8_t XPROGCommand = Endpoint_Read_Byte();
switch (XPROGCommand)
{
case XPRG_CMD_ENTER_PROGMODE:
PDIProtocol_EnterXPROGMode();
break;
case XPRG_CMD_LEAVE_PROGMODE:
PDIProtocol_LeaveXPROGMode();
break;
case XPRG_CMD_ERASE:
PDIProtocol_Erase();
break;
case XPRG_CMD_WRITE_MEM:
PDIProtocol_WriteMemory();
break;
case XPRG_CMD_READ_MEM:
PDIProtocol_ReadMemory();
break;
case XPRG_CMD_CRC:
PDIProtocol_ReadCRC();
break;
case XPRG_CMD_SET_PARAM:
PDIProtocol_SetParam();
break;
}
}
/** Handler for the XPROG ENTER_PROGMODE command to establish a PDI connection with the attached device. */
static void PDIProtocol_EnterXPROGMode(void)
{
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
/* Enable PDI programming mode with the attached target */
PDITarget_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);
/* 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 = sizeof(PDI_NVMENABLE_KEY); i > 0; i--)
PDITarget_SendByte(PDI_NVMENABLE_KEY[i - 1]);
/* 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(NVMBusEnabled ? XPRG_ERR_OK : XPRG_ERR_FAILED);
Endpoint_ClearIN();
}
/** Handler for the XPROG LEAVE_PROGMODE command to terminate the PDI programming connection with
* the attached device.
*/
static void PDIProtocol_LeaveXPROGMode(void)
{
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
/* 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);
PDITarget_DisableTargetPDI();
Endpoint_Write_Byte(CMD_XPROG);
Endpoint_Write_Byte(XPRG_CMD_LEAVE_PROGMODE);
Endpoint_Write_Byte(XPRG_ERR_OK);
Endpoint_ClearIN();
}
/** Handler for the XPRG ERASE command to erase a specific memory address space in the attached device. */
static void PDIProtocol_Erase(void)
{
uint8_t ReturnStatus = XPRG_ERR_OK;
struct
{
uint8_t MemoryType;
uint32_t Address;
} Erase_XPROG_Params;
Endpoint_Read_Stream_LE(&Erase_XPROG_Params, sizeof(Erase_XPROG_Params));
Erase_XPROG_Params.Address = SwapEndian_32(Erase_XPROG_Params.Address);
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t EraseCommand = XMEGA_NVM_CMD_NOOP;
/* Determine which NVM command to send to the device depending on the memory to erase */
if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_CHIP)
EraseCommand = XMEGA_NVM_CMD_CHIPERASE;
else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_APP)
EraseCommand = XMEGA_NVM_CMD_ERASEAPPSEC;
else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_BOOT)
EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSEC;
else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_EEPROM)
EraseCommand = XMEGA_NVM_CMD_ERASEEEPROM;
else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_APP_PAGE)
EraseCommand = XMEGA_NVM_CMD_ERASEAPPSECPAGE;
else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_BOOT_PAGE)
EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSECPAGE;
else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_EEPROM_PAGE)
EraseCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGE;
else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_USERSIG)
EraseCommand = XMEGA_NVM_CMD_ERASEUSERSIG;
/* Erase the target memory, indicate timeout if ocurred */
if (!(XMEGANVM_EraseMemory(EraseCommand, Erase_XPROG_Params.Address)))
ReturnStatus = XPRG_ERR_TIMEOUT;
Endpoint_Write_Byte(CMD_XPROG);
Endpoint_Write_Byte(XPRG_CMD_ERASE);
Endpoint_Write_Byte(ReturnStatus);
Endpoint_ClearIN();
}
/** Handler for the XPROG WRITE_MEMORY command to write to a specific memory space within the attached device. */
static void PDIProtocol_WriteMemory(void)
{
uint8_t ReturnStatus = XPRG_ERR_OK;
struct
{
uint8_t MemoryType;
uint8_t PageMode;
uint32_t Address;
uint16_t Length;
uint8_t ProgData[256];
} WriteMemory_XPROG_Params;
Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params, (sizeof(WriteMemory_XPROG_Params) -
sizeof(WriteMemory_XPROG_Params).ProgData));
WriteMemory_XPROG_Params.Address = SwapEndian_32(WriteMemory_XPROG_Params.Address);
WriteMemory_XPROG_Params.Length = SwapEndian_16(WriteMemory_XPROG_Params.Length);
Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length);
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
/* Assume FLASH page programming by default, as it is the common case */
uint8_t WriteCommand = XMEGA_NVM_CMD_WRITEFLASHPAGE;
uint8_t WriteBuffCommand = XMEGA_NVM_CMD_LOADFLASHPAGEBUFF;
uint8_t EraseBuffCommand = XMEGA_NVM_CMD_ERASEFLASHPAGEBUFF;
bool PagedMemory = true;
if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_APPL)
{
WriteCommand = XMEGA_NVM_CMD_WRITEAPPSECPAGE;
}
else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_BOOT)
{
WriteCommand = XMEGA_NVM_CMD_WRITEBOOTSECPAGE;
}
else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_EEPROM)
{
WriteCommand = XMEGA_NVM_CMD_WRITEEEPROMPAGE;
WriteBuffCommand = XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF;
EraseBuffCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF;
}
else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_USERSIG)
{
/* User signature is paged, but needs us to manually indicate the mode bits since the host doesn't set them */
WriteMemory_XPROG_Params.PageMode = (XPRG_PAGEMODE_ERASE | XPRG_PAGEMODE_WRITE);
WriteCommand = XMEGA_NVM_CMD_WRITEUSERSIG;
}
else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_FUSE)
{
WriteCommand = XMEGA_NVM_CMD_WRITEFUSE;
PagedMemory = false;
}
else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_LOCKBITS)
{
WriteCommand = XMEGA_NVM_CMD_WRITELOCK;
PagedMemory = false;
}
/* Send the appropriate memory write commands to the device, indicate timeout if occurred */
if ((PagedMemory && !XMEGANVM_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand,
WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address,
WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length)) ||
(!PagedMemory && !XMEGANVM_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address,
WriteMemory_XPROG_Params.ProgData)))
{
ReturnStatus = XPRG_ERR_TIMEOUT;
}
Endpoint_Write_Byte(CMD_XPROG);
Endpoint_Write_Byte(XPRG_CMD_WRITE_MEM);
Endpoint_Write_Byte(ReturnStatus);
Endpoint_ClearIN();
}
/** Handler for the XPROG READ_MEMORY command to read data from a specific address space within the
* attached device.
*/
static void PDIProtocol_ReadMemory(void)
{
uint8_t ReturnStatus = XPRG_ERR_OK;
struct
{
uint8_t MemoryType;
uint32_t Address;
uint16_t Length;
} ReadMemory_XPROG_Params;
Endpoint_Read_Stream_LE(&ReadMemory_XPROG_Params, sizeof(ReadMemory_XPROG_Params));
ReadMemory_XPROG_Params.Address = SwapEndian_32(ReadMemory_XPROG_Params.Address);
ReadMemory_XPROG_Params.Length = SwapEndian_16(ReadMemory_XPROG_Params.Length);
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t ReadBuffer[256];
/* Read the target's memory, indicate timeout if occurred */
if (!(XMEGANVM_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length)))
ReturnStatus = XPRG_ERR_TIMEOUT;
Endpoint_Write_Byte(CMD_XPROG);
Endpoint_Write_Byte(XPRG_CMD_READ_MEM);
Endpoint_Write_Byte(ReturnStatus);
if (ReturnStatus == XPRG_ERR_OK)
Endpoint_Write_Stream_LE(ReadBuffer, ReadMemory_XPROG_Params.Length);
Endpoint_ClearIN();
}
/** Handler for the XPROG CRC command to read a specific memory space's CRC value for comparison between the
* attached device's memory and a data set on the host.
*/
static void PDIProtocol_ReadCRC(void)
{
uint8_t ReturnStatus = XPRG_ERR_OK;
struct
{
uint8_t CRCType;
} ReadCRC_XPROG_Params;
Endpoint_Read_Stream_LE(&ReadCRC_XPROG_Params, sizeof(ReadCRC_XPROG_Params));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t CRCCommand = XMEGA_NVM_CMD_NOOP;
uint32_t MemoryCRC;
/* Determine which NVM command to send to the device depending on the memory to CRC */
if (ReadCRC_XPROG_Params.CRCType == XPRG_CRC_APP)
CRCCommand = XMEGA_NVM_CMD_APPCRC;
else if (ReadCRC_XPROG_Params.CRCType == XPRG_CRC_BOOT)
CRCCommand = XMEGA_NVM_CMD_BOOTCRC;
else
CRCCommand = XMEGA_NVM_CMD_FLASHCRC;
/* Perform and retrieve the memory CRC, indicate timeout if occurred */
if (!(XMEGANVM_GetMemoryCRC(CRCCommand, &MemoryCRC)))
ReturnStatus = XPRG_ERR_TIMEOUT;
Endpoint_Write_Byte(CMD_XPROG);
Endpoint_Write_Byte(XPRG_CMD_CRC);
Endpoint_Write_Byte(ReturnStatus);
if (ReturnStatus == XPRG_ERR_OK)
{
Endpoint_Write_Byte(MemoryCRC >> 16);
Endpoint_Write_Word_LE(MemoryCRC & 0xFFFF);
}
Endpoint_ClearIN();
}
/** Handler for the XPROG SET_PARAM command to set a PDI parameter for use when communicating with the
* attached device.
*/
static void PDIProtocol_SetParam(void)
{
uint8_t ReturnStatus = XPRG_ERR_OK;
uint8_t XPROGParam = Endpoint_Read_Byte();
/* Determine which parameter is being set, store the new parameter value */
if (XPROGParam == XPRG_PARAM_NVMBASE)
XPROG_Param_NVMBase = Endpoint_Read_DWord_BE();
else if (XPROGParam == XPRG_PARAM_EEPPAGESIZE)
XPROG_Param_EEPageSize = Endpoint_Read_Word_BE();
else
ReturnStatus = XPRG_ERR_FAILED;
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_Byte(CMD_XPROG);
Endpoint_Write_Byte(XPRG_CMD_SET_PARAM);
Endpoint_Write_Byte(ReturnStatus);
Endpoint_ClearIN();
}
#endif

View file

@ -0,0 +1,125 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for PDIProtocol.c.
*/
#ifndef _PDI_PROTOCOL_
#define _PDI_PROTOCOL_
/* Includes: */
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <LUFA/Drivers/USB/USB.h>
#include "../V2Protocol.h"
#include "PDITarget.h"
#include "XMEGANVM.h"
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
#undef ENABLE_ISP_PROTOCOL
#undef ENABLE_TPI_PROTOCOL
#if !defined(ENABLE_PDI_PROTOCOL)
#define ENABLE_PDI_PROTOCOL
#endif
#endif
/* Macros: */
#define XPRG_CMD_ENTER_PROGMODE 0x01
#define XPRG_CMD_LEAVE_PROGMODE 0x02
#define XPRG_CMD_ERASE 0x03
#define XPRG_CMD_WRITE_MEM 0x04
#define XPRG_CMD_READ_MEM 0x05
#define XPRG_CMD_CRC 0x06
#define XPRG_CMD_SET_PARAM 0x07
#define XPRG_MEM_TYPE_APPL 1
#define XPRG_MEM_TYPE_BOOT 2
#define XPRG_MEM_TYPE_EEPROM 3
#define XPRG_MEM_TYPE_FUSE 4
#define XPRG_MEM_TYPE_LOCKBITS 5
#define XPRG_MEM_TYPE_USERSIG 6
#define XPRG_MEM_TYPE_FACTORY_CALIBRATION 7
#define XPRG_ERASE_CHIP 1
#define XPRG_ERASE_APP 2
#define XPRG_ERASE_BOOT 3
#define XPRG_ERASE_EEPROM 4
#define XPRG_ERASE_APP_PAGE 5
#define XPRG_ERASE_BOOT_PAGE 6
#define XPRG_ERASE_EEPROM_PAGE 7
#define XPRG_ERASE_USERSIG 8
#define XPRG_MEM_WRITE_ERASE 0
#define XPRG_MEM_WRITE_WRITE 1
#define XPRG_CRC_APP 1
#define XPRG_CRC_BOOT 2
#define XPRG_CRC_FLASH 3
#define XPRG_ERR_OK 0
#define XPRG_ERR_FAILED 1
#define XPRG_ERR_COLLISION 2
#define XPRG_ERR_TIMEOUT 3
#define XPRG_PARAM_NVMBASE 0x01
#define XPRG_PARAM_EEPPAGESIZE 0x02
#define XPRG_PROTOCOL_PDI 0x00
#define XPRG_PROTOCOL_JTAG 0x01
#define XPRG_PROTOCOL_TPI 0x02
#define XPRG_PAGEMODE_WRITE (1 << 1)
#define XPRG_PAGEMODE_ERASE (1 << 0)
/* External Variables: */
extern uint32_t XPROG_Param_NVMBase;
/* Function Prototypes: */
void PDIProtocol_XPROG_SetMode(void);
void PDIProtocol_XPROG_Command(void);
#if defined(INCLUDE_FROM_PDIPROTOCOL_C)
static void PDIProtocol_EnterXPROGMode(void);
static void PDIProtocol_LeaveXPROGMode(void);
static void PDIProtocol_SetParam(void);
static void PDIProtocol_Erase(void);
static void PDIProtocol_WriteMemory(void);
static void PDIProtocol_ReadMemory(void);
static void PDIProtocol_ReadCRC(void);
#endif
#endif

View file

@ -0,0 +1,335 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Target-related functions for the PDI Protocol decoder.
*/
#define INCLUDE_FROM_PDITARGET_C
#include "PDITarget.h"
#if defined(ENABLE_PDI_PROTOCOL) || defined(__DOXYGEN__)
/** Flag to indicate if the USART is currently in Tx or Rx mode. */
volatile bool IsSending;
#if !defined(PDI_VIA_HARDWARE_USART)
/** Software USART raw frame bits for transmission/reception. */
volatile uint16_t SoftUSART_Data;
/** Bits remaining to be sent or received via the software USART - set as a GPIOR for speed. */
#define SoftUSART_BitCount GPIOR2
/** ISR to manage the software USART when bit-banged USART mode is selected. */
ISR(TIMER1_COMPA_vect, ISR_BLOCK)
{
/* Toggle CLOCK pin in a single cycle (see AVR datasheet) */
BITBANG_PDICLOCK_PIN |= BITBANG_PDICLOCK_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_PDICLOCK_PORT & BITBANG_PDICLOCK_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_PDI_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;
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_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
else
BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;
SoftUSART_Data >>= 1;
SoftUSART_BitCount--;
}
}
#endif
/** Enables the target's PDI interface, holding the target in reset until PDI mode is exited. */
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 at least 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 = (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 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 100 cycles to manage the software USART */
OCR1A = 80;
TCCR1B = (1 << WGM12) | (1 << CS10);
TIMSK1 = (1 << OCIE1A);
/* Send two BREAKs of 12 bits each to enable TPI interface (need at least 16 idle bits) */
PDITarget_SendBreak();
PDITarget_SendBreak();
#endif
}
/** Disables the target's PDI interface, exits programming mode and starts the target's application. */
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;
UCSR1C = 0;
/* 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;
#endif
}
/** Sends a byte via the USART.
*
* \param[in] Byte Byte to send through the USART
*/
void PDITarget_SendByte(const uint8_t Byte)
{
#if defined(PDI_VIA_HARDWARE_USART)
/* Switch to Tx mode if currently in Rx mode */
if (!(IsSending))
{
PORTD |= (1 << 3);
DDRD |= (1 << 3);
UCSR1B |= (1 << TXEN1);
UCSR1B &= ~(1 << RXEN1);
IsSending = true;
}
/* Wait until there is space in the hardware Tx buffer before writing */
while (!(UCSR1A & (1 << UDRE1)));
UCSR1A |= (1 << TXC1);
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;
}
/* Calculate the new USART frame data here while while we wait for a previous byte (if any) to finish sending */
uint16_t NewUSARTData = ((1 << 11) | (1 << 10) | (0 << 9) | ((uint16_t)Byte << 1) | (0 << 0));
/* Compute Even parity - while a bit is still set, chop off lowest bit and toggle parity bit */
uint8_t ParityData = Byte;
while (ParityData)
{
NewUSARTData ^= (1 << 9);
ParityData &= (ParityData - 1);
}
/* Wait until transmitter is idle before writing new data */
while (SoftUSART_BitCount);
/* Data shifted out LSB first, START DATA PARITY STOP STOP */
SoftUSART_Data = NewUSARTData;
SoftUSART_BitCount = BITS_IN_PDI_FRAME;
#endif
}
/** Receives a byte via the software USART, blocking until data is received.
*
* \return Received byte from the USART
*/
uint8_t PDITarget_ReceiveByte(void)
{
#if defined(PDI_VIA_HARDWARE_USART)
/* Switch to Rx mode if currently in Tx mode */
if (IsSending)
{
while (!(UCSR1A & (1 << TXC1)));
UCSR1A |= (1 << TXC1);
UCSR1B &= ~(1 << TXEN1);
UCSR1B |= (1 << RXEN1);
DDRD &= ~(1 << 3);
PORTD &= ~(1 << 3);
IsSending = false;
}
/* 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_PDI_FRAME;
while (SoftUSART_BitCount);
/* Throw away the parity and stop bits to leave only the data (start bit is already discarded) */
return (uint8_t)SoftUSART_Data;
#endif
}
/** Sends a BREAK via the USART to the attached target, consisting of a full frame of idle bits. */
void PDITarget_SendBreak(void)
{
#if defined(PDI_VIA_HARDWARE_USART)
/* Switch to Tx mode if currently in Rx mode */
if (!(IsSending))
{
PORTD |= (1 << 3);
DDRD |= (1 << 3);
UCSR1B &= ~(1 << RXEN1);
UCSR1B |= (1 << TXEN1);
IsSending = true;
}
/* Need to do nothing for a full frame to send a BREAK */
for (uint8_t i = 0; i < BITS_IN_PDI_FRAME; i++)
{
/* Wait for a full cycle of the clock */
while (PIND & (1 << 5));
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_PDI_FRAME;
#endif
}
/** 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 PDITarget_WaitWhileNVMBusBusy(void)
{
TCNT0 = 0;
TIFR0 = (1 << OCF1A);
uint8_t TimeoutMS = PDI_NVM_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 */
PDITarget_SendByte(PDI_CMD_LDCS | PDI_STATUS_REG);
if (PDITarget_ReceiveByte() & PDI_STATUS_NVM)
return true;
if (TIFR0 & (1 << OCF1A))
{
TIFR0 = (1 << OCF1A);
TimeoutMS--;
}
}
return false;
}
#endif

View file

@ -0,0 +1,112 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for PDITarget.c.
*/
#ifndef _PDI_TARGET_
#define _PDI_TARGET_
/* Includes: */
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include <LUFA/Common/Common.h>
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
#undef ENABLE_ISP_PROTOCOL
#undef ENABLE_TPI_PROTOCOL
#if !defined(ENABLE_PDI_PROTOCOL)
#define ENABLE_PDI_PROTOCOL
#endif
#endif
/* Defines: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
#define PDI_VIA_HARDWARE_USART
#else
#define BITBANG_PDIDATA_PORT PORTB
#define BITBANG_PDIDATA_DDR DDRB
#define BITBANG_PDIDATA_PIN PINB
#define BITBANG_PDIDATA_MASK (1 << 3)
#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
/** Total number of bits in a single USART frame */
#define BITS_IN_PDI_FRAME 12
/** Timeout in milliseconds of a PDI busy-wait command */
#define PDI_NVM_TIMEOUT_MS 100
#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_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_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
/* Function Prototypes: */
void PDITarget_EnableTargetPDI(void);
void PDITarget_DisableTargetPDI(void);
void PDITarget_SendByte(const uint8_t Byte);
uint8_t PDITarget_ReceiveByte(void);
void PDITarget_SendBreak(void);
bool PDITarget_WaitWhileNVMBusBusy(void);
#endif

View file

@ -0,0 +1,43 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Target-related functions for the TINY target's NVM module.
*/
#define INCLUDE_FROM_TINYNVM_C
#include "TINYNVM.h"
#if defined(ENABLE_TPI_PROTOCOL) || defined(__DOXYGEN__)
// TODO
#endif

View file

@ -0,0 +1,62 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for TINYNVM.c.
*/
#ifndef _TINY_NVM_
#define _TINY_NVM_
/* Includes: */
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include <LUFA/Common/Common.h>
#include "TPIProtocol.h"
#include "TPITarget.h"
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
#undef ENABLE_ISP_PROTOCOL
#undef ENABLE_TPI_PROTOCOL
#if !defined(ENABLE_PDI_PROTOCOL)
#define ENABLE_PDI_PROTOCOL
#endif
#endif
/* Defines: */
#define TINY_NVM_BUSY_TIMEOUT_MS 100
#endif

View file

@ -0,0 +1,44 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* TPI Protocol handler, to process V2 Protocol wrapped TPI commands used in Atmel programmer devices.
*/
#define INCLUDE_FROM_TPIPROTOCOL_C
#include "TPIProtocol.h"
#if defined(ENABLE_TPI_PROTOCOL) || defined(__DOXYGEN__)
#warning TPI Programming Protocol is currently incomplete and is not suitable for general use.
// TODO
#endif

View file

@ -0,0 +1,59 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for TPIProtocol.c.
*/
#ifndef _TPI_PROTOCOL_
#define _TPI_PROTOCOL_
/* Includes: */
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <LUFA/Drivers/USB/USB.h>
#include "TPITarget.h"
#include "TINYNVM.h"
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
#undef ENABLE_ISP_PROTOCOL
#undef ENABLE_TPI_PROTOCOL
#if !defined(ENABLE_PDI_PROTOCOL)
#define ENABLE_PDI_PROTOCOL
#endif
#endif
#endif

View file

@ -0,0 +1,338 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Target-related functions for the TPI Protocol decoder.
*/
#define INCLUDE_FROM_TPITARGET_C
#include "TPITarget.h"
#if defined(ENABLE_TPI_PROTOCOL) || defined(__DOXYGEN__)
/** Flag to indicate if the USART is currently in Tx or Rx mode. */
volatile bool IsSending;
#if !defined(TPI_VIA_HARDWARE_USART)
/** Software USART raw frame bits for transmission/reception. */
volatile uint16_t SoftUSART_Data;
/** Bits remaining to be sent or received via the software USART - set as a GPIOR for speed. */
#define SoftUSART_BitCount GPIOR2
/** ISR to manage the software USART when bit-banged 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_TPI_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_TPI_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--;
}
}
#endif
/** Enables the target's TPI interface, holding the target in reset until TPI mode is exited. */
void TPITarget_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(TPI_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) */
TPITarget_SendBreak();
TPITarget_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) */
TPITarget_SendBreak();
TPITarget_SendBreak();
#endif
}
/** Disables the target's TPI interface, exits programming mode and starts the target's application. */
void TPITarget_DisableTargetTPI(void)
{
#if defined(TPI_VIA_HARDWARE_USART)
/* Turn off receiver and transmitter of the USART, clear settings */
UCSR1A |= (1 << TXC1) | (1 << RXC1);
UCSR1B = 0;
UCSR1C = 0;
/* 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_TPIDATA_DDR &= ~BITBANG_TPIDATA_MASK;
BITBANG_TPICLOCK_DDR &= ~BITBANG_TPICLOCK_MASK;
/* Tristate DATA and CLOCK lines */
BITBANG_TPIDATA_PORT &= ~BITBANG_TPIDATA_MASK;
BITBANG_TPICLOCK_PORT &= ~BITBANG_TPICLOCK_MASK;
#endif
/* Tristate target /RESET line */
RESET_LINE_DDR &= ~RESET_LINE_MASK;
RESET_LINE_PORT &= ~RESET_LINE_MASK;
}
/** Sends a byte via the USART.
*
* \param[in] Byte Byte to send through the USART
*/
void TPITarget_SendByte(const uint8_t Byte)
{
#if defined(TPI_VIA_HARDWARE_USART)
/* Switch to Tx mode if currently in Rx mode */
if (!(IsSending))
{
PORTD |= (1 << 3);
DDRD |= (1 << 3);
UCSR1B |= (1 << TXEN1);
UCSR1B &= ~(1 << RXEN1);
IsSending = true;
}
/* Wait until there is space in the hardware Tx buffer before writing */
while (!(UCSR1A & (1 << UDRE1)));
UCSR1A |= (1 << TXC1);
UDR1 = Byte;
#else
/* Switch to Tx mode if currently in Rx mode */
if (!(IsSending))
{
BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK;
BITBANG_TPIDATA_DDR |= BITBANG_TPIDATA_MASK;
IsSending = true;
}
/* Calculate the new USART frame data here while while we wait for a previous byte (if any) to finish sending */
uint16_t NewUSARTData = ((1 << 11) | (1 << 10) | (0 << 9) | ((uint16_t)Byte << 1) | (0 << 0));
/* Compute Even parity - while a bit is still set, chop off lowest bit and toggle parity bit */
uint8_t ParityData = Byte;
while (ParityData)
{
NewUSARTData ^= (1 << 9);
ParityData &= (ParityData - 1);
}
/* Wait until transmitter is idle before writing new data */
while (SoftUSART_BitCount);
/* Data shifted out LSB first, START DATA PARITY STOP STOP */
SoftUSART_Data = NewUSARTData;
SoftUSART_BitCount = BITS_IN_TPI_FRAME;
#endif
}
/** Receives a byte via the software USART, blocking until data is received.
*
* \return Received byte from the USART
*/
uint8_t TPITarget_ReceiveByte(void)
{
#if defined(TPI_VIA_HARDWARE_USART)
/* Switch to Rx mode if currently in Tx mode */
if (IsSending)
{
while (!(UCSR1A & (1 << TXC1)));
UCSR1A |= (1 << TXC1);
UCSR1B &= ~(1 << TXEN1);
UCSR1B |= (1 << RXEN1);
DDRD &= ~(1 << 3);
PORTD &= ~(1 << 3);
IsSending = false;
}
/* 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_TPIDATA_DDR &= ~BITBANG_TPIDATA_MASK;
BITBANG_TPIDATA_PORT &= ~BITBANG_TPIDATA_MASK;
IsSending = false;
}
/* Wait until a byte has been received before reading */
SoftUSART_BitCount = BITS_IN_TPI_FRAME;
while (SoftUSART_BitCount);
/* Throw away the parity and stop bits to leave only the data (start bit is already discarded) */
return (uint8_t)SoftUSART_Data;
#endif
}
/** Sends a BREAK via the USART to the attached target, consisting of a full frame of idle bits. */
void TPITarget_SendBreak(void)
{
#if defined(TPI_VIA_HARDWARE_USART)
/* Switch to Tx mode if currently in Rx mode */
if (!(IsSending))
{
PORTD |= (1 << 3);
DDRD |= (1 << 3);
UCSR1B &= ~(1 << RXEN1);
UCSR1B |= (1 << TXEN1);
IsSending = true;
}
/* Need to do nothing for a full frame to send a BREAK */
for (uint8_t i = 0; i < BITS_IN_TPI_FRAME; i++)
{
/* Wait for a full cycle of the clock */
while (PIND & (1 << 5));
while (!(PIND & (1 << 5)));
}
#else
/* Switch to Tx mode if currently in Rx mode */
if (!(IsSending))
{
BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK;
BITBANG_TPIDATA_DDR |= BITBANG_TPIDATA_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_TPI_FRAME;
#endif
}
/** 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 TPITarget_WaitWhileNVMBusBusy(void)
{
TCNT0 = 0;
TIFR0 = (1 << OCF1A);
uint8_t TimeoutMS = TPI_NVM_TIMEOUT_MS;
/* Poll the STATUS register to check to see if NVM access has been enabled */
while (TimeoutMS)
{
/* Send the SLDCS command to read the TPI STATUS register to see the NVM bus is active */
TPITarget_SendByte(TPI_CMD_SLDCS | TPI_STATUS_REG);
if (TPITarget_ReceiveByte() & TPI_STATUS_NVM)
return true;
if (TIFR0 & (1 << OCF1A))
{
TIFR0 = (1 << OCF1A);
TimeoutMS--;
}
}
return false;
}
#endif

View file

@ -0,0 +1,101 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for TPITarget.c.
*/
#ifndef _TPI_TARGET_
#define _TPI_TARGET_
/* Includes: */
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include <LUFA/Common/Common.h>
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
#undef ENABLE_ISP_PROTOCOL
#undef ENABLE_TPI_PROTOCOL
#if !defined(ENABLE_PDI_PROTOCOL)
#define ENABLE_PDI_PROTOCOL
#endif
#endif
/* Defines: */
#define BITBANG_TPIDATA_PORT PORTB
#define BITBANG_TPIDATA_DDR DDRB
#define BITBANG_TPIDATA_PIN PINB
#define BITBANG_TPIDATA_MASK (1 << 3)
#define BITBANG_TPICLOCK_PORT PORTB
#define BITBANG_TPICLOCK_DDR DDRB
#define BITBANG_TPICLOCK_PIN PINB
#define BITBANG_TPICLOCK_MASK (1 << 1)
/** Total number of bits in a single USART frame */
#define BITS_IN_TPI_FRAME 12
/** Timeout in milliseconds of a PDI busy-wait command */
#define TPI_NVM_TIMEOUT_MS 100
#define TPI_CMD_SLD 0x20
#define TPI_CMD_SST 0x60
#define TPI_CMD_SSTPR 0x68
#define TPI_CMD_SIN 0x10
#define TPI_CMD_SOUT 0x90
#define TPI_CMD_SLDCS 0x80
#define TPI_CMD_SSTCS 0xC0
#define TPI_CMD_SKEY 0xE0
#define TPI_STATUS_REG 0x00
#define TPI_CTRL_REG 0x02
#define TPI_ID_REG 0x0F
#define TPI_STATUS_NVM (1 << 1)
#define TPI_NVMENABLE_KEY (uint8_t[]){0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF}
#define TPI_POINTER_INDIRECT 0
#define TPI_POINTER_INDIRECT_PI (1 << 2)
/* Function Prototypes: */
void TPITarget_EnableTargetTPI(void);
void TPITarget_DisableTargetTPI(void);
void TPITarget_SendByte(const uint8_t Byte);
uint8_t TPITarget_ReceiveByte(void);
void TPITarget_SendBreak(void);
bool TPITarget_WaitWhileNVMBusBusy(void);
#endif

View file

@ -0,0 +1,332 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Target-related functions for the XMEGA target's NVM module.
*/
#define INCLUDE_FROM_XMEGA_NVM_C
#include "XMEGANVM.h"
#if defined(ENABLE_PDI_PROTOCOL) || defined(__DOXYGEN__)
/** Sends the given NVM register address to the target.
*
* \param[in] Register NVM register whose absolute address is to be sent
*/
void XMEGANVM_SendNVMRegAddress(const uint8_t Register)
{
/* Determine the absolute register address from the NVM base memory address and the NVM register address */
uint32_t Address = XPROG_Param_NVMBase | Register;
/* Send the calculated 32-bit address to the target, LSB first */
XMEGANVM_SendAddress(Address);
}
/** Sends the given 32-bit absolute address to the target.
*
* \param[in] AbsoluteAddress Absolute address to send to the target
*/
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);
}
/** 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)
{
TCNT0 = 0;
TIFR0 = (1 << OCF1A);
uint8_t TimeoutMS = XMEGA_NVM_BUSY_TIMEOUT_MS;
/* Poll the NVM STATUS register while the NVM controller is busy */
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));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_STATUS);
/* Check to see if the BUSY flag is still set */
if (!(PDITarget_ReceiveByte() & (1 << 7)))
return true;
if (TIFR0 & (1 << OCF1A))
{
TIFR0 = (1 << OCF1A);
TimeoutMS--;
}
}
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)
{
/* Wait until the NVM controller is no longer busy */
if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
return false;
/* Set the NVM command to the correct CRC read command */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
PDITarget_SendByte(CRCCommand);
/* Set CMDEX bit in NVM CTRLA register to start the CRC generation */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
PDITarget_SendByte(1 << 0);
/* Wait until the NVM bus is ready again */
if (!(PDITarget_WaitWhileNVMBusBusy()))
return false;
/* Wait until the NVM controller is no longer busy */
if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
return false;
*CRCDest = 0;
/* Read the first generated CRC byte value */
PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT0);
*CRCDest = PDITarget_ReceiveByte();
/* Read the second generated CRC byte value */
PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT1);
*CRCDest |= ((uint16_t)PDITarget_ReceiveByte() << 8);
/* Read the third generated CRC byte value */
PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT2);
*CRCDest |= ((uint32_t)PDITarget_ReceiveByte() << 16);
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)
{
/* Wait until the NVM controller is no longer busy */
if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
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));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
PDITarget_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);
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);
/* 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);
for (uint16_t i = 0; i < ReadSize; i++)
*(ReadBuffer++) = PDITarget_ReceiveByte();
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_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer)
{
/* Wait until the NVM controller is no longer busy */
if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
return false;
/* Send the memory write command to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
PDITarget_SendByte(WriteCommand);
/* Send new memory byte to the memory to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendAddress(WriteAddress);
PDITarget_SendByte(*(WriteBuffer++));
return true;
}
/** Writes page addressed memory to the target's memory spaces.
*
* \param[in] WriteBuffCommand Command to send to the device to write a byte to the memory page buffer
* \param[in] EraseBuffCommand Command to send to the device to erase the memory page buffer
* \param[in] WritePageCommand Command to send to the device to write the page buffer to the destination memory
* \param[in] PageMode Bitfield indicating what operations need to be executed on the specified page
* \param[in] WriteAddress Start address to write the page data to within the target's address space
* \param[in] WriteBuffer Buffer to source data from
* \param[in] WriteSize Number of bytes to write
*
* \return Boolean true if the command sequence complete successfully
*/
bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t EraseBuffCommand,
const uint8_t WritePageCommand, const uint8_t PageMode, const uint32_t WriteAddress,
const uint8_t* WriteBuffer, const uint16_t WriteSize)
{
if (PageMode & XPRG_PAGEMODE_ERASE)
{
/* Wait until the NVM controller is no longer busy */
if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
return false;
/* Send the memory buffer erase command to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
PDITarget_SendByte(EraseBuffCommand);
/* Set CMDEX bit in NVM CTRLA register to start the buffer erase */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
PDITarget_SendByte(1 << 0);
}
if (WriteSize)
{
/* Wait until the NVM controller is no longer busy */
if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
return false;
/* Send the memory buffer write command to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
PDITarget_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);
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);
/* 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);
for (uint16_t i = 0; i < WriteSize; i++)
PDITarget_SendByte(*(WriteBuffer++));
}
if (PageMode & XPRG_PAGEMODE_WRITE)
{
/* Wait until the NVM controller is no longer busy */
if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
return false;
/* Send the memory write command to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
PDITarget_SendByte(WritePageCommand);
/* Send the address of the first page location to write the memory page */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendAddress(WriteAddress);
PDITarget_SendByte(0x00);
}
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)
{
/* Wait until the NVM controller is no longer busy */
if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
return false;
/* Send the memory erase command to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
PDITarget_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));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
PDITarget_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));
XMEGANVM_SendAddress(Address);
PDITarget_SendByte(0x00);
}
/* Wait until the NVM bus is ready again */
if (!(PDITarget_WaitWhileNVMBusBusy()))
return false;
return true;
}
#endif

View file

@ -0,0 +1,121 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for XMEGANVM.c.
*/
#ifndef _XMEGA_NVM__
#define _XMEGA_NVM_
/* Includes: */
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include <LUFA/Common/Common.h>
#include "PDIProtocol.h"
#include "PDITarget.h"
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
#undef ENABLE_ISP_PROTOCOL
#undef ENABLE_TPI_PROTOCOL
#if !defined(ENABLE_PDI_PROTOCOL)
#define ENABLE_PDI_PROTOCOL
#endif
#endif
/* Defines: */
#define XMEGA_NVM_BUSY_TIMEOUT_MS 200
#define XMEGA_NVM_REG_ADDR0 0x00
#define XMEGA_NVM_REG_ADDR1 0x01
#define XMEGA_NVM_REG_ADDR2 0x02
#define XMEGA_NVM_REG_DAT0 0x04
#define XMEGA_NVM_REG_DAT1 0x05
#define XMEGA_NVM_REG_DAT2 0x06
#define XMEGA_NVM_REG_CMD 0x0A
#define XMEGA_NVM_REG_CTRLA 0x0B
#define XMEGA_NVM_REG_CTRLB 0x0C
#define XMEGA_NVM_REG_INTCTRL 0x0D
#define XMEGA_NVM_REG_STATUS 0x0F
#define XMEGA_NVM_REG_LOCKBITS 0x10
#define XMEGA_NVM_CMD_NOOP 0x00
#define XMEGA_NVM_CMD_CHIPERASE 0x40
#define XMEGA_NVM_CMD_READNVM 0x43
#define XMEGA_NVM_CMD_LOADFLASHPAGEBUFF 0x23
#define XMEGA_NVM_CMD_ERASEFLASHPAGEBUFF 0x26
#define XMEGA_NVM_CMD_ERASEFLASHPAGE 0x2B
#define XMEGA_NVM_CMD_WRITEFLASHPAGE 0x2E
#define XMEGA_NVM_CMD_ERASEWRITEFLASH 0x2F
#define XMEGA_NVM_CMD_FLASHCRC 0x78
#define XMEGA_NVM_CMD_ERASEAPPSEC 0x20
#define XMEGA_NVM_CMD_ERASEAPPSECPAGE 0x22
#define XMEGA_NVM_CMD_WRITEAPPSECPAGE 0x24
#define XMEGA_NVM_CMD_ERASEWRITEAPPSECPAGE 0x25
#define XMEGA_NVM_CMD_APPCRC 0x38
#define XMEGA_NVM_CMD_ERASEBOOTSEC 0x68
#define XMEGA_NVM_CMD_ERASEBOOTSECPAGE 0x2A
#define XMEGA_NVM_CMD_WRITEBOOTSECPAGE 0x2C
#define XMEGA_NVM_CMD_ERASEWRITEBOOTSECPAGE 0x2D
#define XMEGA_NVM_CMD_BOOTCRC 0x39
#define XMEGA_NVM_CMD_READUSERSIG 0x03
#define XMEGA_NVM_CMD_ERASEUSERSIG 0x18
#define XMEGA_NVM_CMD_WRITEUSERSIG 0x1A
#define XMEGA_NVM_CMD_READCALIBRATION 0x02
#define XMEGA_NVM_CMD_READFUSE 0x07
#define XMEGA_NVM_CMD_WRITEFUSE 0x4C
#define XMEGA_NVM_CMD_WRITELOCK 0x08
#define XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF 0x33
#define XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF 0x36
#define XMEGA_NVM_CMD_ERASEEEPROM 0x30
#define XMEGA_NVM_CMD_ERASEEEPROMPAGE 0x32
#define XMEGA_NVM_CMD_WRITEEEPROMPAGE 0x34
#define XMEGA_NVM_CMD_ERASEWRITEEEPROMPAGE 0x35
#define XMEGA_NVM_CMD_READEEPROM 0x06
/* Function Prototypes: */
void XMEGANVM_SendNVMRegAddress(const uint8_t Register);
void XMEGANVM_SendAddress(const uint32_t AbsoluteAddress);
bool XMEGANVM_WaitWhileNVMControllerBusy(void);
bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest);
bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const uint16_t ReadSize);
bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer);
bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t EraseBuffCommand,
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);
#endif