Rename AVRISP project folder to AVRISP-MKII.

This commit is contained in:
Dean Camera 2009-12-27 12:28:29 +00:00
commit 8ecdc2b144
24 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,134 @@
/*
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
*
* Main source file for the AVRISP project. This file contains the main tasks of
* the project and is responsible for the initial application hardware configuration.
*/
#include "AVRISP.h"
/** Main program entry point. This routine contains the overall program flow, including initial
* setup of all components and the main program loop.
*/
int main(void)
{
SetupHardware();
V2Params_LoadNonVolatileParamValues();
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
for (;;)
{
Process_AVRISP_Commands();
V2Params_UpdateParamValues();
USB_USBTask();
}
}
/** Configures the board hardware and chip peripherals for the demo's functionality. */
void SetupHardware(void)
{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Disable clock division */
clock_prescale_set(clock_div_1);
/* Hardware Initialization */
LEDs_Init();
USB_Init();
#if defined(ADC)
/* Initialize the ADC converter for VTARGET level detection on supported AVR models */
ADC_Init(ADC_FREE_RUNNING | ADC_PRESCALE_128);
ADC_SetupChannel(VTARGET_ADC_CHANNEL);
ADC_StartReading(VTARGET_ADC_CHANNEL | ADC_RIGHT_ADJUSTED | ADC_REFERENCE_AVCC);
#endif
/* Millisecond timer initialization for managing the command timeout counter */
OCR0A = ((F_CPU / 64) / 1000);
TCCR0A = (1 << WGM01);
TCCR0B = ((1 << CS01) | (1 << CS00));
}
/** Event handler for the library USB Connection event. */
void EVENT_USB_Device_Connect(void)
{
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}
/** Event handler for the library USB Disconnection event. */
void EVENT_USB_Device_Disconnect(void)
{
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
/** Event handler for the library USB Configuration Changed event. */
void EVENT_USB_Device_ConfigurationChanged(void)
{
/* Indicate USB connected and ready */
LEDs_SetAllLEDs(LEDMASK_USB_READY);
/* Setup AVRISP data Endpoints */
if (!(Endpoint_ConfigureEndpoint(AVRISP_DATA_EPNUM, EP_TYPE_BULK,
ENDPOINT_DIR_OUT, AVRISP_DATA_EPSIZE,
ENDPOINT_BANK_SINGLE)))
{
LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
}
/** Processes incoming V2 Protocol commands from the host, returning a response when required. */
void Process_AVRISP_Commands(void)
{
/* Device must be connected and configured for the task to run */
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
Endpoint_SelectEndpoint(AVRISP_DATA_EPNUM);
/* Check to see if a V2 Protocol command has been received */
if (Endpoint_IsOUTReceived())
{
LEDs_SetAllLEDs(LEDMASK_BUSY);
/* Pass off processing of the V2 Protocol command to the V2 Protocol handler */
V2Protocol_ProcessCommand();
LEDs_SetAllLEDs(LEDMASK_USB_READY);
}
}

View file

@ -0,0 +1,82 @@
/*
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 AVRISP.c.
*/
#ifndef _AVRISP_H_
#define _AVRISP_H_
/* Includes: */
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include "Descriptors.h"
#include <LUFA/Version.h>
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Drivers/USB/USB.h>
#if defined(ADC)
#include <LUFA/Drivers/Peripheral/ADC.h>
#endif
#include "Lib/V2Protocol.h"
/* Macros: */
/** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
#define LEDMASK_USB_NOTREADY LEDS_LED1
/** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
#define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
/** LED mask for the library LED driver, to indicate that the USB interface is ready. */
#define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
#define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
/** LED mask for the library LED driver, to indicate that the USB interface is busy. */
#define LEDMASK_BUSY (LEDS_LED1 | LEDS_LED2)
/* Function Prototypes: */
void SetupHardware(void);
void EVENT_USB_Device_Connect(void);
void EVENT_USB_Device_Disconnect(void);
void EVENT_USB_Device_ConfigurationChanged(void);
void Process_AVRISP_Commands(void);
#endif

View file

@ -0,0 +1,259 @@
/** \file
*
* This file contains special DoxyGen information for the generation of the main page and other special
* documentation pages. It is not a project source file.
*/
/** \mainpage AVRISP MKII Programmer Project
*
* \section SSec_Compat Project Compatibility:
*
* The following list indicates what microcontrollers are compatible with this project.
*
* - Series 7 USB AVRs
* - Series 6 USB AVRs
* - Series 4 USB AVRs
* - Series 2 USB AVRs (8KB versions with reduced features only)
*
* \section SSec_Info USB Information:
*
* The following table gives a rundown of the USB utilization of this project.
*
* <table>
* <tr>
* <td><b>USB Mode:</b></td>
* <td>Device</td>
* </tr>
* <tr>
* <td><b>USB Class:</b></td>
* <td>Vendor Specific Class</td>
* </tr>
* <tr>
* <td><b>USB Subclass:</b></td>
* <td>N/A</td>
* </tr>
* <tr>
* <td><b>Relevant Standards:</b></td>
* <td>Atmel AVRISP MKII Protocol Specification</td>
* </tr>
* <tr>
* <td><b>Usable Speeds:</b></td>
* <td>Full Speed Mode</td>
* </tr>
* </table>
*
* \section SSec_Description Project Description:
*
* Firmware for an AVRStudio compatible AVRISP-MKII clone programmer. This project will enable the USB AVR series of
* microcontrollers to act as a clone of the official Atmel AVRISP-MKII programmer, usable within AVRStudio. In its
* most basic form, it allows for the programming of 5V AVRs from within AVRStudio with no special hardware other than
* the USB AVR and the parts needed for the USB interface. If the user desires, more advanced circuits incorporating
* level conversion can be made to allow for the programming of 3.3V AVR designs.
*
* This device spoofs Atmel's official AVRISP-MKII device PID so that it remains compatible with Atmel's AVRISP-MKII
* drivers. When prompted, direct your OS to install Atmel's AVRISP-MKII drivers provided with AVRStudio.
*
* Note that this design currently has several limitations:
* - Minimum ISP target clock speed of 500KHz due to hardware SPI used
* - No reversed/shorted target connector detection and notification
*
* On AVR models with an ADC converter, AVCC should be tied to 5V (e.g. VBUS) and the VTARGET_ADC_CHANNEL token should be
* set to an appropriate ADC channel number in the project makefile for VTARGET detection to operate correctly. On models
* without an ADC converter, VTARGET will report at a fixed 5V level.
*
* When compiled for the XPLAIN board target, this will automatically configure itself for the correct connections to the
* XPLAIN's XMEGA AVR, and will enable PDI only programming support (since ISP and TPI modes are not needed).
*
* While this application can be compiled for USB AVRs with as little as 8KB of FLASH, for full functionality 16KB or more
* of FLASH is required. On 8KB devices, ISP, PDI or TPI programming support can be disabled to reduce program size.
*
* \section Sec_ISP ISP Connections
* Connections to the device for SPI programming (when enabled):
*
* <table>
* <tr>
* <td><b>Programmer Pin:</b></td>
* <td><b>Target Device Pin:</b></td>
* <td><b>ISP 6 Pin Layout:</b></td>
* </tr>
* <tr>
* <td>MISO</td>
* <td>PDO</td>
* <td>1</td>
* </tr>
* <tr>
* <td>ADCx <b><sup>1</sup></b></td>
* <td>VTARGET</td>
* <td>2</td>
* </tr>
* <tr>
* <td>SCLK</td>
* <td>SCLK</td>
* <td>3</td>
* </tr>
* <tr>
* <td>MOSI</td>
* <td>PDI</td>
* <td>4</td>
* </tr>
* <tr>
* <td>PORTx.y <b><sup>2</sup></b></td>
* <td>/RESET</td>
* <td>5</td>
* </tr>
* <tr>
* <td>GND</td>
* <td>GND</td>
* <td>6</td>
* </tr>
* </table>
*
* <b><sup>1</sup></b> <i>Optional, see \ref SSec_Options section - for USB AVRs with ADC modules only</i> \n
* <b><sup>2</sup></b> <i>See \ref SSec_Options section</i>
*
* \section Sec_PDI PDI Connections
* Connections to the device for PDI programming<b><sup>1</sup></b> (when enabled):
*
* <table>
* <tr>
* <td><b>Programmer Pin:</b></td>
* <td><b>Target Device Pin:</b></td>
* <td><b>PDI 6 Pin Layout:</b></td>
* </tr>
* <tr>
* <td>MISO</td>
* <td>DATA</td>
* <td>1</td>
* </tr>
* <tr>
* <td>ADCx <b><sup>1</sup></b></td>
* <td>VTARGET</td>
* <td>2</td>
* </tr>
* <tr>
* <td>N/A</td>
* <td>N/A</td>
* <td>3</td>
* </tr>
* <tr>
* <td>N/A</td>
* <td>N/A</td>
* <td>4</td>
* </tr>
* <tr>
* <td>PORTx.y <b><sup>2</sup></b></td>
* <td>CLOCK</td>
* <td>5</td>
* </tr>
* <tr>
* <td>GND</td>
* <td>GND</td>
* <td>6</td>
* </tr>
* </table>
*
* <b><sup>1</sup></b> <i>When XPROG_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.</i>
*
* \section Sec_TPI TPI Connections
* Connections to the device for TPI programming<b><sup>1</sup></b> (when enabled):
*
* <table>
* <tr>
* <td><b>Programmer Pin:</b></td>
* <td><b>Target Device Pin:</b></td>
* <td><b>TPI 6 Pin Layout:</b></td>
* </tr>
* <tr>
* <td>MISO</td>
* <td>DATA</td>
* <td>1</td>
* </tr>
* <tr>
* <td>ADCx <b><sup>1</sup></b></td>
* <td>VTARGET</td>
* <td>2</td>
* </tr>
* <tr>
* <td>SCLK</td>
* <td>CLOCK</td>
* <td>3</td>
* </tr>
* <tr>
* <td>N/A</td>
* <td>N/A</td>
* <td>4</td>
* </tr>
* <tr>
* <td>PORTx.y <b><sup>2</sup></b></td>
* <td>/RESET</td>
* <td>5</td>
* </tr>
* <tr>
* <td>GND</td>
* <td>GND</td>
* <td>6</td>
* </tr>
* </table>
*
* <b><sup>1</sup></b> <i>When XPROG_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.</i>
*
* \section SSec_Options Project Options
*
* The following defines can be found in this project, which can control the project behaviour when defined, or changed in value.
*
* <table>
* <tr>
* <td><b>Define Name:</b></td>
* <td><b>Location:</b></td>
* <td><b>Description:</b></td>
* </tr>
* <tr>
* <td>RESET_LINE_PORT</td>
* <td>Makefile CDEFS</td>
* <td>PORT register for the programmer's target RESET line. <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr>
* <tr>
* <td>RESET_LINE_PIN</td>
* <td>Makefile CDEFS</td>
* <td>PIN register for the programmer's target RESET line. <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr>
* <tr>
* <td>RESET_LINE_DDR</td>
* <td>Makefile CDEFS</td>
* <td>DDR register for the programmer's target RESET line. <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr>
* <tr>
* <td>RESET_LINE_MASK</td>
* <td>Makefile CDEFS</td>
* <td>Mask for the programmer's target RESET line on the chosen port. <b>Must not be the AVR's /SS pin</b>, as the
* target pins are tri-stated when not in use, and low signals on the /SS pin will force SPI slave mode when the
* pin is configured as an input. When in PDI programming mode, this is the target clock pin.
* <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr>
* <tr>
* <td>VTARGET_ADC_CHANNEL</td>
* <td>Makefile CDEFS</td>
* <td>ADC channel number (on supported AVRs) to use for VTARGET level detection.</td>
* </tr>
* <tr>
* <td>ENABLE_ISP_PROTOCOL</td>
* <td>Makefile CDEFS</td>
* <td>Define to enable SPI programming protocol support. <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr>
* <tr>
* <td>ENABLE_XPROG_PROTOCOL</td>
* <td>Makefile CDEFS</td>
* <td>Define to enable PDI and TPI programming protocol support. <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr>
* <tr>
* <td>XPROG_VIA_HARDWARE_USART</td>
* <td>Makefile CDEFS</td>
* <td>Define to force the PDI and TPI protocols (when enabled) to use the much faster hardware USART instead of bit-banging to
* match the official AVRISP pinout. This breaks pinout compatibility with the official AVRISP MKII (and requires
* seperate ISP and PDI/TPI programming headers) but increases programming speed dramatically.
* <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr>
* </table>
*/

View file

@ -0,0 +1,216 @@
/*
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
*
* USB Device Descriptors, for library use when in USB device mode. Descriptors are special
* computer-readable structures which the host requests upon device enumeration, to determine
* the device's capabilities and functions.
*/
#include "Descriptors.h"
/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
* device characteristics, including the supported USB version, control endpoint size and the
* number of device configurations. The descriptor is read out by the USB host when the enumeration
* process begins.
*/
USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
{
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
.USBSpecification = VERSION_BCD(01.10),
.Class = 0xFF,
.SubClass = 0x00,
.Protocol = 0x00,
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
.VendorID = 0x03EB,
.ProductID = 0x2104,
.ReleaseNumber = VERSION_BCD(02.00),
.ManufacturerStrIndex = 0x01,
.ProductStrIndex = 0x02,
.SerialNumStrIndex = 0x03,
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
};
/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
* of the device in one of its supported configurations, including information about any device interfaces
* and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
* a configuration so that the host may correctly communicate with the USB device.
*/
USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
{
.Config =
{
.Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
.TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
.TotalInterfaces = 1,
.ConfigurationNumber = 1,
.ConfigurationStrIndex = NO_DESCRIPTOR,
.ConfigAttributes = USB_CONFIG_ATTR_SELFPOWERED,
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
},
.AVRISPInterface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = 0,
.AlternateSetting = 0,
.TotalEndpoints = 2,
.Class = 0xFF,
.SubClass = 0x00,
.Protocol = 0x00,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.DataInEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_IN | AVRISP_DATA_EPNUM),
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = AVRISP_DATA_EPSIZE,
.PollingIntervalMS = 0x00
},
.DataOutEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_OUT | AVRISP_DATA_EPNUM),
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = AVRISP_DATA_EPSIZE,
.PollingIntervalMS = 0x00
},
};
/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
* the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
* via the language ID table available at USB.org what languages the device supports for its string descriptors.
*/
USB_Descriptor_String_t PROGMEM LanguageString =
{
.Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
.UnicodeString = {LANGUAGE_ID_ENG}
};
/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
* form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
* Descriptor.
*/
USB_Descriptor_String_t PROGMEM ManufacturerString =
{
.Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
.UnicodeString = L"Dean Camera"
};
/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
* and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
* Descriptor.
*/
USB_Descriptor_String_t PROGMEM ProductString =
{
.Header = {.Size = USB_STRING_LEN(33), .Type = DTYPE_String},
.UnicodeString = L"LUFA AVRISP MkII Clone Programmer"
};
USB_Descriptor_String_t PROGMEM SerialString =
{
.Header = {.Size = USB_STRING_LEN(13), .Type = DTYPE_String},
.UnicodeString = L"0000A00128255"
};
/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
* documentation) by the application code so that the address and size of a requested descriptor can be given
* to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
* is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
* USB host.
*/
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
{
const uint8_t DescriptorType = (wValue >> 8);
const uint8_t DescriptorNumber = (wValue & 0xFF);
void* Address = NULL;
uint16_t Size = NO_DESCRIPTOR;
switch (DescriptorType)
{
case DTYPE_Device:
Address = (void*)&DeviceDescriptor;
Size = sizeof(USB_Descriptor_Device_t);
break;
case DTYPE_Configuration:
Address = (void*)&ConfigurationDescriptor;
Size = sizeof(USB_Descriptor_Configuration_t);
break;
case DTYPE_String:
switch (DescriptorNumber)
{
case 0x00:
Address = (void*)&LanguageString;
Size = pgm_read_byte(&LanguageString.Header.Size);
break;
case 0x01:
Address = (void*)&ManufacturerString;
Size = pgm_read_byte(&ManufacturerString.Header.Size);
break;
case 0x02:
Address = (void*)&ProductString;
Size = pgm_read_byte(&ProductString.Header.Size);
break;
case 0x03:
Address = (void*)&SerialString;
Size = pgm_read_byte(&SerialString.Header.Size);
break;
}
break;
}
*DescriptorAddress = Address;
return Size;
}

View file

@ -0,0 +1,68 @@
/*
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 Descriptors.c.
*/
#ifndef _DESCRIPTORS_H_
#define _DESCRIPTORS_H_
/* Includes: */
#include <avr/pgmspace.h>
#include <LUFA/Drivers/USB/USB.h>
/* Macros: */
/** Endpoint number of the AVRISP bidirectional data endpoint. */
#define AVRISP_DATA_EPNUM 2
/** Size in bytes of the AVRISP data endpoint. */
#define AVRISP_DATA_EPSIZE 64
/* Type Defines: */
/** Type define for the device configuration descriptor structure. This must be defined in the
* application code, as the configuration descriptor contains several sub-descriptors which
* vary between devices, and which describe the device's usage to the host.
*/
typedef struct
{
USB_Descriptor_Configuration_Header_t Config;
USB_Descriptor_Interface_t AVRISPInterface;
USB_Descriptor_Endpoint_t DataInEndpoint;
USB_Descriptor_Endpoint_t DataOutEndpoint;
} USB_Descriptor_Configuration_t;
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,474 @@
/*
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
*
* ISP Protocol handler, to process V2 Protocol wrapped ISP commands used in Atmel programmer devices.
*/
#include "ISPProtocol.h"
#if defined(ENABLE_ISP_PROTOCOL) || defined(__DOXYGEN__)
/** Handler for the CMD_ENTER_PROGMODE_ISP command, which attempts to enter programming mode on
* the attached device, returning success or failure back to the host.
*/
void ISPProtocol_EnterISPMode(void)
{
struct
{
uint8_t TimeoutMS;
uint8_t PinStabDelayMS;
uint8_t ExecutionDelayMS;
uint8_t SynchLoops;
uint8_t ByteDelay;
uint8_t PollValue;
uint8_t PollIndex;
uint8_t EnterProgBytes[4];
} Enter_ISP_Params;
Endpoint_Read_Stream_LE(&Enter_ISP_Params, sizeof(Enter_ISP_Params));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t ResponseStatus = STATUS_CMD_FAILED;
CurrentAddress = 0;
ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS);
SPI_Init(ISPTarget_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING | SPI_SAMPLE_LEADING | SPI_MODE_MASTER);
while (Enter_ISP_Params.SynchLoops-- && (ResponseStatus == STATUS_CMD_FAILED))
{
uint8_t ResponseBytes[4];
ISPTarget_ChangeTargetResetLine(true);
ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS);
for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
{
ISPProtocol_DelayMS(Enter_ISP_Params.ByteDelay);
ResponseBytes[RByte] = SPI_TransferByte(Enter_ISP_Params.EnterProgBytes[RByte]);
}
/* Check if polling disabled, or if the polled value matches the expected value */
if (!(Enter_ISP_Params.PollIndex) || (ResponseBytes[Enter_ISP_Params.PollIndex - 1] == Enter_ISP_Params.PollValue))
{
ResponseStatus = STATUS_CMD_OK;
}
else
{
ISPTarget_ChangeTargetResetLine(false);
ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS);
}
}
Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP);
Endpoint_Write_Byte(ResponseStatus);
Endpoint_ClearIN();
}
/** Handler for the CMD_LEAVE_ISP command, which releases the target from programming mode. */
void ISPProtocol_LeaveISPMode(void)
{
struct
{
uint8_t PreDelayMS;
uint8_t PostDelayMS;
} Leave_ISP_Params;
Endpoint_Read_Stream_LE(&Leave_ISP_Params, sizeof(Leave_ISP_Params));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
ISPProtocol_DelayMS(Leave_ISP_Params.PreDelayMS);
ISPTarget_ChangeTargetResetLine(false);
SPI_ShutDown();
ISPProtocol_DelayMS(Leave_ISP_Params.PostDelayMS);
Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_ClearIN();
}
/** Handler for the CMD_PROGRAM_FLASH_ISP and CMD_PROGRAM_EEPROM_ISP commands, writing out bytes,
* words or pages of data to the attached device.
*
* \param[in] V2Command Issued V2 Protocol command byte from the host
*/
void ISPProtocol_ProgramMemory(uint8_t V2Command)
{
struct
{
uint16_t BytesToWrite;
uint8_t ProgrammingMode;
uint8_t DelayMS;
uint8_t ProgrammingCommands[3];
uint8_t PollValue1;
uint8_t PollValue2;
uint8_t ProgData[256]; // Note, the Jungo driver has a very short ACK timeout period, need to buffer the
} Write_Memory_Params; // whole page and ACK the packet as fast as possible to prevent it from aborting
Endpoint_Read_Stream_LE(&Write_Memory_Params, (sizeof(Write_Memory_Params) -
sizeof(Write_Memory_Params.ProgData)));
Write_Memory_Params.BytesToWrite = SwapEndian_16(Write_Memory_Params.BytesToWrite);
if (Write_Memory_Params.BytesToWrite > sizeof(Write_Memory_Params.ProgData))
{
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_Byte(V2Command);
Endpoint_Write_Byte(STATUS_CMD_FAILED);
Endpoint_ClearIN();
return;
}
Endpoint_Read_Stream_LE(&Write_Memory_Params.ProgData, Write_Memory_Params.BytesToWrite);
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t ProgrammingStatus = STATUS_CMD_OK;
uint16_t PollAddress = 0;
uint8_t PollValue = (V2Command == CMD_PROGRAM_FLASH_ISP) ? Write_Memory_Params.PollValue1 :
Write_Memory_Params.PollValue2;
uint8_t* NextWriteByte = Write_Memory_Params.ProgData;
if (MustSetAddress)
{
if (CurrentAddress & (1UL << 31))
ISPTarget_LoadExtendedAddress();
MustSetAddress = false;
}
if (Write_Memory_Params.ProgrammingMode & PROG_MODE_PAGED_WRITES_MASK)
{
uint16_t StartAddress = (CurrentAddress & 0xFFFF);
/* Paged mode memory programming */
for (uint16_t CurrentByte = 0; CurrentByte < Write_Memory_Params.BytesToWrite; CurrentByte++)
{
bool IsOddByte = (CurrentByte & 0x01);
uint8_t ByteToWrite = *(NextWriteByte++);
if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP))
Write_Memory_Params.ProgrammingCommands[0] |= READ_WRITE_HIGH_BYTE_MASK;
else
Write_Memory_Params.ProgrammingCommands[0] &= ~READ_WRITE_HIGH_BYTE_MASK;
SPI_SendByte(Write_Memory_Params.ProgrammingCommands[0]);
SPI_SendByte(CurrentAddress >> 8);
SPI_SendByte(CurrentAddress & 0xFF);
SPI_SendByte(ByteToWrite);
if (!(PollAddress) && (ByteToWrite != PollValue))
{
if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP))
Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK;
PollAddress = (CurrentAddress & 0xFFFF);
}
if (IsOddByte || (V2Command == CMD_PROGRAM_EEPROM_ISP))
CurrentAddress++;
}
/* If the current page must be committed, send the PROGRAM PAGE command to the target */
if (Write_Memory_Params.ProgrammingMode & PROG_MODE_COMMIT_PAGE_MASK)
{
SPI_SendByte(Write_Memory_Params.ProgrammingCommands[1]);
SPI_SendByte(StartAddress >> 8);
SPI_SendByte(StartAddress & 0xFF);
SPI_SendByte(0x00);
/* Check if polling is possible, if not switch to timed delay mode */
if (!(PollAddress))
{
Write_Memory_Params.ProgrammingMode &= ~PROG_MODE_PAGED_VALUE_MASK;
Write_Memory_Params.ProgrammingMode |= PROG_MODE_PAGED_TIMEDELAY_MASK;
}
ProgrammingStatus = ISPTarget_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue,
Write_Memory_Params.DelayMS, Write_Memory_Params.ProgrammingCommands[2]);
}
}
else
{
/* Word/byte mode memory programming */
for (uint16_t CurrentByte = 0; CurrentByte < Write_Memory_Params.BytesToWrite; CurrentByte++)
{
bool IsOddByte = (CurrentByte & 0x01);
uint8_t ByteToWrite = *(NextWriteByte++);
if (IsOddByte && (V2Command == CMD_READ_FLASH_ISP))
Write_Memory_Params.ProgrammingCommands[0] |= READ_WRITE_HIGH_BYTE_MASK;
else
Write_Memory_Params.ProgrammingCommands[0] &= ~READ_WRITE_HIGH_BYTE_MASK;
SPI_SendByte(Write_Memory_Params.ProgrammingCommands[0]);
SPI_SendByte(CurrentAddress >> 8);
SPI_SendByte(CurrentAddress & 0xFF);
SPI_SendByte(ByteToWrite);
if (ByteToWrite != PollValue)
{
if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP))
Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK;
PollAddress = (CurrentAddress & 0xFFFF);
}
if (IsOddByte || (V2Command == CMD_PROGRAM_EEPROM_ISP))
CurrentAddress++;
ProgrammingStatus = ISPTarget_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue,
Write_Memory_Params.DelayMS, Write_Memory_Params.ProgrammingCommands[2]);
if (ProgrammingStatus != STATUS_CMD_OK)
break;
}
}
Endpoint_Write_Byte(V2Command);
Endpoint_Write_Byte(ProgrammingStatus);
Endpoint_ClearIN();
}
/** Handler for the CMD_READ_FLASH_ISP and CMD_READ_EEPROM_ISP commands, reading in bytes,
* words or pages of data from the attached device.
*
* \param[in] V2Command Issued V2 Protocol command byte from the host
*/
void ISPProtocol_ReadMemory(uint8_t V2Command)
{
struct
{
uint16_t BytesToRead;
uint8_t ReadMemoryCommand;
} Read_Memory_Params;
Endpoint_Read_Stream_LE(&Read_Memory_Params, sizeof(Read_Memory_Params));
Read_Memory_Params.BytesToRead = SwapEndian_16(Read_Memory_Params.BytesToRead);
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_Byte(V2Command);
Endpoint_Write_Byte(STATUS_CMD_OK);
if (MustSetAddress)
{
if (CurrentAddress & (1UL << 31))
ISPTarget_LoadExtendedAddress();
MustSetAddress = false;
}
for (uint16_t CurrentByte = 0; CurrentByte < Read_Memory_Params.BytesToRead; CurrentByte++)
{
bool IsOddByte = (CurrentByte & 0x01);
if (IsOddByte && (V2Command == CMD_READ_FLASH_ISP))
Read_Memory_Params.ReadMemoryCommand |= READ_WRITE_HIGH_BYTE_MASK;
else
Read_Memory_Params.ReadMemoryCommand &= ~READ_WRITE_HIGH_BYTE_MASK;
SPI_SendByte(Read_Memory_Params.ReadMemoryCommand);
SPI_SendByte(CurrentAddress >> 8);
SPI_SendByte(CurrentAddress & 0xFF);
Endpoint_Write_Byte(SPI_ReceiveByte());
/* Check if the endpoint bank is currently full */
if (!(Endpoint_IsReadWriteAllowed()))
{
Endpoint_ClearIN();
Endpoint_WaitUntilReady();
}
if ((IsOddByte && (V2Command == CMD_READ_FLASH_ISP)) || (V2Command == CMD_READ_EEPROM_ISP))
CurrentAddress++;
}
Endpoint_Write_Byte(STATUS_CMD_OK);
bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
Endpoint_ClearIN();
/* Ensure last packet is a short packet to terminate the transfer */
if (IsEndpointFull)
{
Endpoint_WaitUntilReady();
Endpoint_ClearIN();
Endpoint_WaitUntilReady();
}
}
/** Handler for the CMD_CHI_ERASE_ISP command, clearing the target's FLASH memory. */
void ISPProtocol_ChipErase(void)
{
struct
{
uint8_t EraseDelayMS;
uint8_t PollMethod;
uint8_t EraseCommandBytes[4];
} Erase_Chip_Params;
Endpoint_Read_Stream_LE(&Erase_Chip_Params, sizeof(Erase_Chip_Params));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t ResponseStatus = STATUS_CMD_OK;
for (uint8_t SByte = 0; SByte < sizeof(Erase_Chip_Params.EraseCommandBytes); SByte++)
SPI_SendByte(Erase_Chip_Params.EraseCommandBytes[SByte]);
if (!(Erase_Chip_Params.PollMethod))
ISPProtocol_DelayMS(Erase_Chip_Params.EraseDelayMS);
else
ResponseStatus = ISPTarget_WaitWhileTargetBusy();
Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP);
Endpoint_Write_Byte(ResponseStatus);
Endpoint_ClearIN();
}
/** Handler for the CMD_READ_FUSE_ISP, CMD_READ_LOCK_ISP, CMD_READ_SIGNATURE_ISP and CMD_READ_OSCCAL commands,
* reading the requested configuration byte from the device.
*
* \param[in] V2Command Issued V2 Protocol command byte from the host
*/
void ISPProtocol_ReadFuseLockSigOSCCAL(uint8_t V2Command)
{
struct
{
uint8_t RetByte;
uint8_t ReadCommandBytes[4];
} Read_FuseLockSigOSCCAL_Params;
Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params, sizeof(Read_FuseLockSigOSCCAL_Params));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t ResponseBytes[4];
for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
ResponseBytes[RByte] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]);
Endpoint_Write_Byte(V2Command);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_Write_Byte(ResponseBytes[Read_FuseLockSigOSCCAL_Params.RetByte - 1]);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_ClearIN();
}
/** Handler for the CMD_WRITE_FUSE_ISP and CMD_WRITE_LOCK_ISP commands, writing the requested configuration
* byte to the device.
*
* \param[in] V2Command Issued V2 Protocol command byte from the host
*/
void ISPProtocol_WriteFuseLock(uint8_t V2Command)
{
struct
{
uint8_t WriteCommandBytes[4];
} Write_FuseLockSig_Params;
Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params, sizeof(Write_FuseLockSig_Params));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
for (uint8_t SByte = 0; SByte < sizeof(Write_FuseLockSig_Params.WriteCommandBytes); SByte++)
SPI_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]);
Endpoint_Write_Byte(V2Command);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_ClearIN();
}
/** Handler for the CMD_SPI_MULTI command, writing and reading arbitrary SPI data to and from the attached device. */
void ISPProtocol_SPIMulti(void)
{
struct
{
uint8_t TxBytes;
uint8_t RxBytes;
uint8_t RxStartAddr;
uint8_t TxData[255];
} SPI_Multi_Params;
Endpoint_Read_Stream_LE(&SPI_Multi_Params, sizeof(SPI_Multi_Params) - sizeof(SPI_Multi_Params.TxData));
Endpoint_Read_Stream_LE(&SPI_Multi_Params.TxData, SPI_Multi_Params.TxBytes);
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_Byte(CMD_SPI_MULTI);
Endpoint_Write_Byte(STATUS_CMD_OK);
uint8_t CurrTxPos = 0;
uint8_t CurrRxPos = 0;
/* Write out bytes to transmit until the start of the bytes to receive is met */
while (CurrTxPos < SPI_Multi_Params.RxStartAddr)
{
if (CurrTxPos < SPI_Multi_Params.TxBytes)
SPI_SendByte(SPI_Multi_Params.TxData[CurrTxPos]);
else
SPI_SendByte(0);
CurrTxPos++;
}
/* Transmit remaining bytes with padding as needed, read in response bytes */
while (CurrRxPos < SPI_Multi_Params.RxBytes)
{
if (CurrTxPos < SPI_Multi_Params.TxBytes)
Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params.TxData[CurrTxPos++]));
else
Endpoint_Write_Byte(SPI_ReceiveByte());
CurrRxPos++;
}
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_ClearIN();
}
#endif

View file

@ -0,0 +1,90 @@
/*
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 ISPProtocol.c.
*/
#ifndef _ISP_PROTOCOL_
#define _ISP_PROTOCOL_
/* Includes: */
#include <avr/io.h>
#include <util/delay.h>
#include <LUFA/Drivers/USB/USB.h>
#include "../V2Protocol.h"
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
#undef ENABLE_ISP_PROTOCOL
#if !defined(ENABLE_XPROG_PROTOCOL)
#define ENABLE_XPROG_PROTOCOL
#endif
#endif
/* Macros: */
/** Mask for the reading or writing of the high byte in a FLASH word when issuing a low-level programming command */
#define READ_WRITE_HIGH_BYTE_MASK (1 << 3)
#define PROG_MODE_PAGED_WRITES_MASK (1 << 0)
#define PROG_MODE_WORD_TIMEDELAY_MASK (1 << 1)
#define PROG_MODE_WORD_VALUE_MASK (1 << 2)
#define PROG_MODE_WORD_READYBUSY_MASK (1 << 3)
#define PROG_MODE_PAGED_TIMEDELAY_MASK (1 << 4)
#define PROG_MODE_PAGED_VALUE_MASK (1 << 5)
#define PROG_MODE_PAGED_READYBUSY_MASK (1 << 6)
#define PROG_MODE_COMMIT_PAGE_MASK (1 << 7)
/* Inline Functions: */
/** Blocking delay for a given number of milliseconds.
*
* \param[in] DelayMS Number of milliseconds to delay for
*/
static inline void ISPProtocol_DelayMS(uint8_t DelayMS)
{
while (DelayMS--)
_delay_ms(1);
}
/* Function Prototypes: */
void ISPProtocol_EnterISPMode(void);
void ISPProtocol_LeaveISPMode(void);
void ISPProtocol_ProgramMemory(const uint8_t V2Command);
void ISPProtocol_ReadMemory(const uint8_t V2Command);
void ISPProtocol_ChipErase(void);
void ISPProtocol_ReadFuseLockSigOSCCAL(const uint8_t V2Command);
void ISPProtocol_WriteFuseLock(const uint8_t V2Command);
void ISPProtocol_SPIMulti(void);
#endif

View file

@ -0,0 +1,180 @@
/*
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 ISP Protocol decoder.
*/
#include "ISPTarget.h"
#if defined(ENABLE_ISP_PROTOCOL) || defined(__DOXYGEN__)
/** Converts the given AVR Studio SCK duration parameter (set by a SET PARAM command from the host) to the nearest
* possible SPI clock prescaler mask for passing to the SPI_Init() routine.
*
* \return Nearest SPI prescaler mask for the given SCK frequency
*/
uint8_t ISPTarget_GetSPIPrescalerMask(void)
{
static const uint8_t SPIMaskFromSCKDuration[] =
{
#if (F_CPU == 8000000)
SPI_SPEED_FCPU_DIV_2, // AVRStudio = 8MHz SPI, Actual = 4MHz SPI
SPI_SPEED_FCPU_DIV_2, // AVRStudio = 4MHz SPI, Actual = 4MHz SPI
SPI_SPEED_FCPU_DIV_4, // AVRStudio = 2MHz SPI, Actual = 2MHz SPI
SPI_SPEED_FCPU_DIV_8, // AVRStudio = 1MHz SPI, Actual = 1MHz SPI
SPI_SPEED_FCPU_DIV_16, // AVRStudio = 500KHz SPI, Actual = 500KHz SPI
SPI_SPEED_FCPU_DIV_32, // AVRStudio = 250KHz SPI, Actual = 250KHz SPI
SPI_SPEED_FCPU_DIV_64 // AVRStudio = 125KHz SPI, Actual = 125KHz SPI
#elif (F_CPU == 16000000)
SPI_SPEED_FCPU_DIV_2, // AVRStudio = 8MHz SPI, Actual = 8MHz SPI
SPI_SPEED_FCPU_DIV_4, // AVRStudio = 4MHz SPI, Actual = 4MHz SPI
SPI_SPEED_FCPU_DIV_8, // AVRStudio = 2MHz SPI, Actual = 2MHz SPI
SPI_SPEED_FCPU_DIV_16, // AVRStudio = 1MHz SPI, Actual = 1MHz SPI
SPI_SPEED_FCPU_DIV_32, // AVRStudio = 500KHz SPI, Actual = 500KHz SPI
SPI_SPEED_FCPU_DIV_64, // AVRStudio = 250KHz SPI, Actual = 250KHz SPI
SPI_SPEED_FCPU_DIV_128 // AVRStudio = 125KHz SPI, Actual = 125KHz SPI
#else
#error No SPI prescaler masks for chosen F_CPU speed.
#endif
};
uint8_t SCKDuration = V2Params_GetParameterValue(PARAM_SCK_DURATION);
if (SCKDuration >= sizeof(SPIMaskFromSCKDuration))
SCKDuration = (sizeof(SPIMaskFromSCKDuration) - 1);
return SPIMaskFromSCKDuration[SCKDuration];
}
/** Asserts or deasserts the target's reset line, using the correct polarity as set by the host using a SET PARAM command.
* When not asserted, the line is tristated so as not to interfere with normal device operation.
*
* \param[in] ResetTarget Boolean true when the target should be held in reset, false otherwise
*/
void ISPTarget_ChangeTargetResetLine(const bool ResetTarget)
{
if (ResetTarget)
{
RESET_LINE_DDR |= RESET_LINE_MASK;
if (!(V2Params_GetParameterValue(PARAM_RESET_POLARITY)))
RESET_LINE_PORT |= RESET_LINE_MASK;
}
else
{
RESET_LINE_DDR &= ~RESET_LINE_MASK;
RESET_LINE_PORT &= ~RESET_LINE_MASK;
}
}
/** Waits until the last issued target memory programming command has completed, via the check mode given and using
* the given parameters.
*
* \param[in] ProgrammingMode Programming mode used and completion check to use, a mask of PROG_MODE_* constants
* \param[in] PollAddress Memory address to poll for completion if polling check mode used
* \param[in] PollValue Poll value to check against if polling check mode used
* \param[in] DelayMS Milliseconds to delay before returning if delay check mode used
* \param[in] ReadMemCommand Device low-level READ MEMORY command to send if value check mode used
*
* \return V2 Protocol status \ref STATUS_CMD_OK if the no timeout occurred, \ref STATUS_RDY_BSY_TOUT or
* \ref STATUS_CMD_TOUT otherwise
*/
uint8_t ISPTarget_WaitForProgComplete(const uint8_t ProgrammingMode, const uint16_t PollAddress, const uint8_t PollValue,
const uint8_t DelayMS, const uint8_t ReadMemCommand)
{
uint8_t ProgrammingStatus = STATUS_CMD_OK;
/* Determine method of Programming Complete check */
switch (ProgrammingMode & ~(PROG_MODE_PAGED_WRITES_MASK | PROG_MODE_COMMIT_PAGE_MASK))
{
case PROG_MODE_WORD_TIMEDELAY_MASK:
case PROG_MODE_PAGED_TIMEDELAY_MASK:
ISPProtocol_DelayMS(DelayMS);
break;
case PROG_MODE_WORD_VALUE_MASK:
case PROG_MODE_PAGED_VALUE_MASK:
do
{
SPI_SendByte(ReadMemCommand);
SPI_SendByte(PollAddress >> 8);
SPI_SendByte(PollAddress & 0xFF);
}
while ((SPI_TransferByte(0x00) != PollValue) && TimeoutMSRemaining);
if (!(TimeoutMSRemaining))
ProgrammingStatus = STATUS_CMD_TOUT;
break;
case PROG_MODE_WORD_READYBUSY_MASK:
case PROG_MODE_PAGED_READYBUSY_MASK:
ProgrammingStatus = ISPTarget_WaitWhileTargetBusy();
break;
}
return ProgrammingStatus;
}
/** Waits until the target has completed the last operation, by continuously polling the device's
* BUSY flag until it is cleared, or until the \ref TARGET_BUSY_TIMEOUT_MS timeout period has expired.
*
* \return V2 Protocol status \ref STATUS_CMD_OK if the no timeout occurred, \ref STATUS_RDY_BSY_TOUT otherwise
*/
uint8_t ISPTarget_WaitWhileTargetBusy(void)
{
do
{
SPI_SendByte(0xF0);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
}
while ((SPI_ReceiveByte() & 0x01) && TimeoutMSRemaining);
if (!(TimeoutMSRemaining))
return STATUS_RDY_BSY_TOUT;
else
return STATUS_CMD_OK;
}
/** Sends a low-level LOAD EXTENDED ADDRESS command to the target, for addressing of memory beyond the
* 64KB boundary. This sends the command with the correct address as indicated by the current address
* pointer variable set by the host when a SET ADDRESS command is issued.
*/
void ISPTarget_LoadExtendedAddress(void)
{
SPI_SendByte(0x4D);
SPI_SendByte(0x00);
SPI_SendByte((CurrentAddress & 0x00FF0000) >> 16);
SPI_SendByte(0x00);
}
#endif

View file

@ -0,0 +1,70 @@
/*
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 ISPTarget.c.
*/
#ifndef _ISP_TARGET_
#define _ISP_TARGET_
/* Includes: */
#include <avr/io.h>
#include <util/delay.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/Peripheral/SPI.h>
#include "../V2ProtocolParams.h"
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
#undef ENABLE_ISP_PROTOCOL
#if !defined(ENABLE_XPROG_PROTOCOL)
#define ENABLE_XPROG_PROTOCOL
#endif
#endif
/* Macros: */
/** Total number of allowable ISP programming speeds supported by the device */
#define TOTAL_ISP_PROGRAMMING_SPEEDS 7
/* Function Prototypes: */
uint8_t ISPTarget_GetSPIPrescalerMask(void);
void ISPTarget_ChangeTargetResetLine(const bool ResetTarget);
uint8_t ISPTarget_WaitForProgComplete(const uint8_t ProgrammingMode, const uint16_t PollAddress,
const uint8_t PollValue, const uint8_t DelayMS,
const uint8_t ReadMemCommand);
uint8_t ISPTarget_WaitWhileTargetBusy(void);
void ISPTarget_LoadExtendedAddress(void);
#endif

View file

@ -0,0 +1,233 @@
/*
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
*
* V2Protocol handler, to process V2 Protocol commands used in Atmel programmer devices.
*/
#define INCLUDE_FROM_V2PROTOCOL_C
#include "V2Protocol.h"
/** Current memory address for FLASH/EEPROM memory read/write commands */
uint32_t CurrentAddress;
/** Flag to indicate that the next read/write operation must update the device's current address */
bool MustSetAddress;
/** ISR for the management of the command execution timeout counter */
ISR(TIMER0_COMPA_vect, ISR_BLOCK)
{
if (TimeoutMSRemaining)
TimeoutMSRemaining--;
}
/** Master V2 Protocol packet handler, for received V2 Protocol packets from a connected host.
* This routine decodes the issued command and passes off the handling of the command to the
* appropriate function.
*/
void V2Protocol_ProcessCommand(void)
{
uint8_t V2Command = Endpoint_Read_Byte();
TimeoutMSRemaining = COMMAND_TIMEOUT_MS;
TIMSK0 |= (1 << OCIE0A);
switch (V2Command)
{
case CMD_SIGN_ON:
V2Protocol_SignOn();
break;
case CMD_SET_PARAMETER:
case CMD_GET_PARAMETER:
V2Protocol_GetSetParam(V2Command);
break;
case CMD_LOAD_ADDRESS:
V2Protocol_LoadAddress();
break;
case CMD_RESET_PROTECTION:
V2Protocol_ResetProtection();
break;
#if defined(ENABLE_ISP_PROTOCOL)
case CMD_ENTER_PROGMODE_ISP:
ISPProtocol_EnterISPMode();
break;
case CMD_LEAVE_PROGMODE_ISP:
ISPProtocol_LeaveISPMode();
break;
case CMD_PROGRAM_FLASH_ISP:
case CMD_PROGRAM_EEPROM_ISP:
ISPProtocol_ProgramMemory(V2Command);
break;
case CMD_READ_FLASH_ISP:
case CMD_READ_EEPROM_ISP:
ISPProtocol_ReadMemory(V2Command);
break;
case CMD_CHIP_ERASE_ISP:
ISPProtocol_ChipErase();
break;
case CMD_READ_FUSE_ISP:
case CMD_READ_LOCK_ISP:
case CMD_READ_SIGNATURE_ISP:
case CMD_READ_OSCCAL_ISP:
ISPProtocol_ReadFuseLockSigOSCCAL(V2Command);
break;
case CMD_PROGRAM_FUSE_ISP:
case CMD_PROGRAM_LOCK_ISP:
ISPProtocol_WriteFuseLock(V2Command);
break;
case CMD_SPI_MULTI:
ISPProtocol_SPIMulti();
break;
#endif
#if defined(ENABLE_XPROG_PROTOCOL)
case CMD_XPROG_SETMODE:
XPROGProtocol_SetMode();
break;
case CMD_XPROG:
XPROGProtocol_Command();
break;
#endif
default:
V2Protocol_UnknownCommand(V2Command);
break;
}
TIMSK0 &= ~(1 << OCIE0A);
Endpoint_WaitUntilReady();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT);
}
/** Handler for unknown V2 protocol commands. This discards all sent data and returns a
* STATUS_CMD_UNKNOWN status back to the host.
*
* \param[in] V2Command Issued V2 Protocol command byte from the host
*/
static void V2Protocol_UnknownCommand(const uint8_t V2Command)
{
/* Discard all incoming data */
while (Endpoint_BytesInEndpoint() == AVRISP_DATA_EPSIZE)
{
Endpoint_ClearOUT();
Endpoint_WaitUntilReady();
}
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_Byte(V2Command);
Endpoint_Write_Byte(STATUS_CMD_UNKNOWN);
Endpoint_ClearIN();
}
/** Handler for the CMD_SIGN_ON command, returning the programmer ID string to the host. */
static void V2Protocol_SignOn(void)
{
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_Byte(CMD_SIGN_ON);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_Write_Byte(sizeof(PROGRAMMER_ID) - 1);
Endpoint_Write_Stream_LE(PROGRAMMER_ID, (sizeof(PROGRAMMER_ID) - 1));
Endpoint_ClearIN();
}
/** Handler for the CMD_RESET_PROTECTION command, currently implemented as a dummy ACK function
* as no ISP short-circuit protection is currently implemented.
*/
static void V2Protocol_ResetProtection(void)
{
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_Byte(CMD_RESET_PROTECTION);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_ClearIN();
}
/** Handler for the CMD_SET_PARAMETER and CMD_GET_PARAMETER commands from the host, setting or
* getting a device parameter's value from the parameter table.
*
* \param[in] V2Command Issued V2 Protocol command byte from the host
*/
static void V2Protocol_GetSetParam(const uint8_t V2Command)
{
uint8_t ParamID = Endpoint_Read_Byte();
uint8_t ParamValue;
if (V2Command == CMD_SET_PARAMETER)
ParamValue = Endpoint_Read_Byte();
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_Byte(V2Command);
uint8_t ParamPrivs = V2Params_GetParameterPrivileges(ParamID);
if ((V2Command == CMD_SET_PARAMETER) && (ParamPrivs & PARAM_PRIV_WRITE))
{
Endpoint_Write_Byte(STATUS_CMD_OK);
V2Params_SetParameterValue(ParamID, ParamValue);
}
else if ((V2Command == CMD_GET_PARAMETER) && (ParamPrivs & PARAM_PRIV_READ))
{
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_Write_Byte(V2Params_GetParameterValue(ParamID));
}
else
{
Endpoint_Write_Byte(STATUS_CMD_FAILED);
}
Endpoint_ClearIN();
}
/** Handler for the CMD_LOAD_ADDRESS command, loading the given device address into a
* global storage variable for later use, and issuing LOAD EXTENDED ADDRESS commands
* to the attached device as required.
*/
static void V2Protocol_LoadAddress(void)
{
Endpoint_Read_Stream_BE(&CurrentAddress, sizeof(CurrentAddress));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
MustSetAddress = true;
Endpoint_Write_Byte(CMD_LOAD_ADDRESS);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_ClearIN();
}

View file

@ -0,0 +1,84 @@
/*
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 V2Protocol.c.
*/
#ifndef _V2_PROTOCOL_
#define _V2_PROTOCOL_
/* Includes: */
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/Peripheral/SPI.h>
#include "../Descriptors.h"
#include "V2ProtocolConstants.h"
#include "V2ProtocolParams.h"
#include "ISP/ISPProtocol.h"
#include "XPROG/XPROGProtocol.h"
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
#undef ENABLE_ISP_PROTOCOL
#if !defined(ENABLE_XPROG_PROTOCOL)
#define ENABLE_XPROG_PROTOCOL
#endif
#endif
/* Macros: */
/** Programmer ID string, returned to the host during the CMD_SIGN_ON command processing */
#define PROGRAMMER_ID "AVRISP_MK2"
/** Timeout period for each issued command from the host before it is aborted */
#define COMMAND_TIMEOUT_MS 200
/** Command timeout counter register, GPIOR for speed */
#define TimeoutMSRemaining GPIOR0
/* External Variables: */
extern uint32_t CurrentAddress;
extern bool MustSetAddress;
/* Function Prototypes: */
void V2Protocol_ProcessCommand(void);
#if defined(INCLUDE_FROM_V2PROTOCOL_C)
static void V2Protocol_UnknownCommand(uint8_t V2Command);
static void V2Protocol_SignOn(void);
static void V2Protocol_GetSetParam(uint8_t V2Command);
static void V2Protocol_ResetProtection(void);
static void V2Protocol_LoadAddress(void);
#endif
#endif

View file

@ -0,0 +1,88 @@
/*
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
*
* Macros for the V2 Protocol Packet Commands and Responses.
*/
#ifndef _V2_PROTOCOL_CONSTANTS_
#define _V2_PROTOCOL_CONSTANTS_
/* Macros: */
#define CMD_SIGN_ON 0x01
#define CMD_SET_PARAMETER 0x02
#define CMD_GET_PARAMETER 0x03
#define CMD_OSCCAL 0x05
#define CMD_LOAD_ADDRESS 0x06
#define CMD_FIRMWARE_UPGRADE 0x07
#define CMD_RESET_PROTECTION 0x0A
#define CMD_ENTER_PROGMODE_ISP 0x10
#define CMD_LEAVE_PROGMODE_ISP 0x11
#define CMD_CHIP_ERASE_ISP 0x12
#define CMD_PROGRAM_FLASH_ISP 0x13
#define CMD_READ_FLASH_ISP 0x14
#define CMD_PROGRAM_EEPROM_ISP 0x15
#define CMD_READ_EEPROM_ISP 0x16
#define CMD_PROGRAM_FUSE_ISP 0x17
#define CMD_READ_FUSE_ISP 0x18
#define CMD_PROGRAM_LOCK_ISP 0x19
#define CMD_READ_LOCK_ISP 0x1A
#define CMD_READ_SIGNATURE_ISP 0x1B
#define CMD_READ_OSCCAL_ISP 0x1C
#define CMD_SPI_MULTI 0x1D
#define CMD_XPROG 0x50
#define CMD_XPROG_SETMODE 0x51
#define STATUS_CMD_OK 0x00
#define STATUS_CMD_TOUT 0x80
#define STATUS_RDY_BSY_TOUT 0x81
#define STATUS_SET_PARAM_MISSING 0x82
#define STATUS_CMD_FAILED 0xC0
#define STATUS_CMD_UNKNOWN 0xC9
#define STATUS_ISP_READY 0x00
#define STATUS_CONN_FAIL_MOSI 0x01
#define STATUS_CONN_FAIL_RST 0x02
#define STATUS_CONN_FAIL_SCK 0x04
#define STATUS_TGT_NOT_DETECTED 0x10
#define STATUS_TGT_REVERSE_INSERTED 0x20
#define PARAM_BUILD_NUMBER_LOW 0x80
#define PARAM_BUILD_NUMBER_HIGH 0x81
#define PARAM_HW_VER 0x90
#define PARAM_SW_MAJOR 0x91
#define PARAM_SW_MINOR 0x92
#define PARAM_VTARGET 0x94
#define PARAM_SCK_DURATION 0x98
#define PARAM_RESET_POLARITY 0x9E
#define PARAM_STATUS_TGT_CONN 0xA1
#define PARAM_DISCHARGEDELAY 0xA4
#endif

View file

@ -0,0 +1,182 @@
/*
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
*
* V2Protocol parameter handler, to process V2 Protocol device parameters.
*/
#define INCLUDE_FROM_V2PROTOCOL_PARAMS_C
#include "V2ProtocolParams.h"
/* Non-Volatile Parameter Values for EEPROM storage */
uint8_t EEMEM EEPROM_Rest_Polarity = 0x00;
/* Volatile Parameter Values for RAM storage */
static ParameterItem_t ParameterTable[] =
{
{ .ParamID = PARAM_BUILD_NUMBER_LOW,
.ParamPrivileges = PARAM_PRIV_READ,
.ParamValue = (LUFA_VERSION_INTEGER >> 8) },
{ .ParamID = PARAM_BUILD_NUMBER_HIGH,
.ParamPrivileges = PARAM_PRIV_READ,
.ParamValue = (LUFA_VERSION_INTEGER & 0xFF), },
{ .ParamID = PARAM_HW_VER,
.ParamPrivileges = PARAM_PRIV_READ,
.ParamValue = 0x00 },
{ .ParamID = PARAM_SW_MAJOR,
.ParamPrivileges = PARAM_PRIV_READ,
.ParamValue = 0x01 },
{ .ParamID = PARAM_SW_MINOR,
.ParamPrivileges = PARAM_PRIV_READ,
.ParamValue = 0x0D },
{ .ParamID = PARAM_VTARGET,
.ParamPrivileges = PARAM_PRIV_READ,
.ParamValue = 0x32 },
{ .ParamID = PARAM_SCK_DURATION,
.ParamPrivileges = PARAM_PRIV_READ | PARAM_PRIV_WRITE,
.ParamValue = (TOTAL_ISP_PROGRAMMING_SPEEDS - 1) },
{ .ParamID = PARAM_RESET_POLARITY,
.ParamPrivileges = PARAM_PRIV_WRITE,
.ParamValue = 0x00 },
{ .ParamID = PARAM_STATUS_TGT_CONN,
.ParamPrivileges = PARAM_PRIV_READ,
.ParamValue = 0x00 },
{ .ParamID = PARAM_DISCHARGEDELAY,
.ParamPrivileges = PARAM_PRIV_WRITE,
.ParamValue = 0x00 },
};
/** Loads saved non-volatile parameter values from the EEPROM into the parameter table, as needed. */
void V2Params_LoadNonVolatileParamValues(void)
{
/* Target RESET line polarity is a non-volatile value, retrieve current parameter value from EEPROM -
* NB: Cannot call V2Protocol_SetParameterValue() here, as that will cause another EEPROM write! */
V2Params_GetParamFromTable(PARAM_RESET_POLARITY)->ParamValue = eeprom_read_byte(&EEPROM_Rest_Polarity);
}
/** Updates any parameter values that are sourced from hardware rather than explicitly set by the host, such as
* VTARGET levels from the ADC on supported AVR models.
*/
void V2Params_UpdateParamValues(void)
{
#if defined(ADC)
/* Update VTARGET parameter with the latest ADC conversion of VTARGET on supported AVR models */
V2Params_GetParamFromTable(PARAM_VTARGET)->ParamValue = ((5 * 10 * ADC_GetResult()) / 1024);
#endif
}
/** Retrieves the host PC read/write privileges for a given parameter in the parameter table. This should
* be called before calls to \ref V2Params_GetParameterValue() or \ref V2Params_SetParameterValue() when
* getting or setting parameter values in response to requests from the host.
*
* \param[in] ParamID Parameter ID whose privileges are to be retrieved from the table
*
* \return Privileges for the requested parameter, as a mask of PARAM_PRIV_* masks
*/
uint8_t V2Params_GetParameterPrivileges(const uint8_t ParamID)
{
ParameterItem_t* ParamInfo = V2Params_GetParamFromTable(ParamID);
if (ParamInfo == NULL)
return 0;
return ParamInfo->ParamPrivileges;
}
/** Retrieves the current value for a given parameter in the parameter table.
*
* \param[in] ParamID Parameter ID whose value is to be retrieved from the table
*
* \return Current value of the parameter in the table, or 0 if not found
*/
uint8_t V2Params_GetParameterValue(const uint8_t ParamID)
{
ParameterItem_t* ParamInfo = V2Params_GetParamFromTable(ParamID);
if (ParamInfo == NULL)
return 0;
return ParamInfo->ParamValue;
}
/** Sets the value for a given parameter in the parameter table.
*
* \param[in] ParamID Parameter ID whose value is to be set in the table
* \param[in] Value New value to set the parameter to
*
* \return Pointer to the associated parameter information from the parameter table if found, NULL otherwise
*/
void V2Params_SetParameterValue(const uint8_t ParamID, const uint8_t Value)
{
ParameterItem_t* ParamInfo = V2Params_GetParamFromTable(ParamID);
if (ParamInfo == NULL)
return;
ParamInfo->ParamValue = Value;
/* The target RESET line polarity is a non-volatile parameter, save to EEPROM when changed */
if (ParamID == PARAM_RESET_POLARITY)
eeprom_write_byte(&EEPROM_Rest_Polarity, Value);
}
/** Retrieves a parameter entry (including ID, value and privileges) from the parameter table that matches the given
* parameter ID.
*
* \param[in] ParamID Parameter ID to find in the table
*
* \return Pointer to the associated parameter information from the parameter table if found, NULL otherwise
*/
static ParameterItem_t* V2Params_GetParamFromTable(const uint8_t ParamID)
{
ParameterItem_t* CurrTableItem = ParameterTable;
/* Find the parameter in the parameter table if present */
for (uint8_t TableIndex = 0; TableIndex < (sizeof(ParameterTable) / sizeof(ParameterTable[0])); TableIndex++)
{
if (ParamID == CurrTableItem->ParamID)
return CurrTableItem;
CurrTableItem++;
}
return NULL;
}

View file

@ -0,0 +1,82 @@
/*
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 V2ProtocolParams.c.
*/
#ifndef _V2_PROTOCOL_PARAMS_
#define _V2_PROTOCOL_PARAMS_
/* Includes: */
#include <avr/io.h>
#include <avr/eeprom.h>
#include <LUFA/Version.h>
#if defined(ADC)
#include <LUFA/Drivers/Peripheral/ADC.h>
#endif
#include "V2Protocol.h"
#include "V2ProtocolConstants.h"
#include "ISP/ISPTarget.h"
/* Macros: */
/** Parameter privilege mask to allow the host PC to read the parameter's value */
#define PARAM_PRIV_READ (1 << 0)
/** Parameter privilege mask to allow the host PC to change the parameter's value */
#define PARAM_PRIV_WRITE (1 << 1)
/* Type Defines: */
/** Type define for a parameter table entry indicating a PC readable or writable device parameter. */
typedef struct
{
const uint8_t ParamID; /**< Parameter ID number to uniquely identify the parameter within the device */
const uint8_t ParamPrivileges; /**< Parameter privileges to allow the host to read or write the parameter's value */
uint8_t ParamValue; /**< Current parameter's value within the device */
} ParameterItem_t;
/* Function Prototypes: */
void V2Params_LoadNonVolatileParamValues(void);
void V2Params_UpdateParamValues(void);
uint8_t V2Params_GetParameterPrivileges(const uint8_t ParamID);
uint8_t V2Params_GetParameterValue(const uint8_t ParamID);
void V2Params_SetParameterValue(const uint8_t ParamID, const uint8_t Value);
#if defined(INCLUDE_FROM_V2PROTOCOL_PARAMS_C)
static ParameterItem_t* V2Params_GetParamFromTable(const uint8_t ParamID);
#endif
#endif

View file

@ -0,0 +1,104 @@
/*
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_XPROG_PROTOCOL) || defined(__DOXYGEN__)
#warning TPI Protocol support is currently incomplete and is not suitable for general use.
/** Busy-waits while the NVM controller is busy performing a NVM operation, such as a FLASH page read.
*
* \return Boolean true if the NVM controller became ready within the timeout period, false otherwise
*/
bool TINYNVM_WaitWhileNVMBusBusy(void)
{
/* Poll the STATUS register to check to see if NVM access has been enabled */
while (TimeoutMSRemaining)
{
/* Send the SLDCS command to read the TPI STATUS register to see the NVM bus is active */
XPROGTarget_SendByte(TPI_CMD_SLDCS | TPI_STATUS_REG);
if (XPROGTarget_ReceiveByte() & TPI_STATUS_NVM)
return true;
}
return false;
}
/** 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 TINYNVM_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 TINYNVM_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 TINYNVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address)
{
// TODO
return true;
}
#endif

View file

@ -0,0 +1,73 @@
/*
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 "XPROGProtocol.h"
#include "XPROGTarget.h"
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
#undef ENABLE_ISP_PROTOCOL
#if !defined(ENABLE_XPROG_PROTOCOL)
#define ENABLE_XPROG_PROTOCOL
#endif
#endif
/* Defines: */
#define TINY_NVM_REG_NVMCSR 0x32
#define TINY_NVM_REG_NVMCMD 0x33
#define TINY_NVM_CMD_NOOP 0x00
#define TINY_NVM_CMD_CHIPERASE 0x10
#define TINY_NVM_CMD_SECTIONERASE 0x14
#define TINY_NVM_CMD_WORDWRITE 0x1D
/* Function Prototypes: */
bool TINYNVM_WaitWhileNVMBusBusy(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);
#endif

View file

@ -0,0 +1,342 @@
/*
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_XPROG_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 */
XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[0]);
XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[1]);
XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[2]);
XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[3]);
}
/** 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)
{
/* Poll the STATUS register to check to see if NVM access has been enabled */
while (TimeoutMSRemaining)
{
/* 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;
}
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)
{
/* Poll the NVM STATUS register while the NVM controller is busy */
while (TimeoutMSRemaining)
{
/* Send a LDS command to read the NVM STATUS register to check the BUSY flag */
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 (!(XPROGTarget_ReceiveByte() & (1 << 7)))
return true;
}
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 */
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
XPROGTarget_SendByte(CRCCommand);
/* Set CMDEX bit in NVM CTRLA register to start the CRC generation */
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
XPROGTarget_SendByte(1 << 0);
/* Wait until the NVM bus is ready again */
if (!(XMEGANVM_WaitWhileNVMBusBusy()))
return false;
/* Wait until the NVM controller is no longer busy */
if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
return false;
uint32_t MemoryCRC = 0;
/* Read the first generated CRC byte value */
XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT0);
MemoryCRC = XPROGTarget_ReceiveByte();
/* Read the second generated CRC byte value */
XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT1);
MemoryCRC |= ((uint16_t)XPROGTarget_ReceiveByte() << 8);
/* Read the third generated CRC byte value */
XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT2);
MemoryCRC |= ((uint32_t)XPROGTarget_ReceiveByte() << 16);
*CRCDest = MemoryCRC;
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, 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 */
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
XPROGTarget_SendByte(XMEGA_NVM_CMD_READNVM);
/* Load the PDI pointer register with the start address we want to read from */
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 */
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 */
XPROGTarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
while (ReadSize--)
*(ReadBuffer++) = XPROGTarget_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 */
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
XPROGTarget_SendByte(WriteCommand);
/* Send new memory byte to the memory to the target */
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendAddress(WriteAddress);
XPROGTarget_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, 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 */
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
XPROGTarget_SendByte(EraseBuffCommand);
/* Set CMDEX bit in NVM CTRLA register to start the buffer erase */
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
XPROGTarget_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 */
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
XPROGTarget_SendByte(WriteBuffCommand);
/* Load the PDI pointer register with the start address we want to write to */
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 */
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 */
XPROGTarget_SendByte(PDI_CMD_ST | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
while (WriteSize--)
XPROGTarget_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 */
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
XPROGTarget_SendByte(WritePageCommand);
/* Send the address of the first page location to write the memory page */
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendAddress(WriteAddress);
XPROGTarget_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 */
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
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 */
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
XPROGTarget_SendByte(1 << 0);
}
else
{
/* Other erase modes just need us to address a byte within the target memory space */
XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
XMEGANVM_SendAddress(Address);
XPROGTarget_SendByte(0x00);
}
/* Wait until the NVM bus is ready again */
if (!(XMEGANVM_WaitWhileNVMBusBusy()))
return false;
return true;
}
#endif

View file

@ -0,0 +1,119 @@
/*
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 "XPROGProtocol.h"
#include "XPROGTarget.h"
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
#undef ENABLE_ISP_PROTOCOL
#if !defined(ENABLE_XPROG_PROTOCOL)
#define ENABLE_XPROG_PROTOCOL
#endif
#endif
/* Defines: */
#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_WaitWhileNVMBusBusy(void);
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, 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, uint16_t WriteSize);
bool XMEGANVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address);
#endif

View file

@ -0,0 +1,439 @@
/*
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
*
* XPROG Protocol handler, to process V2 Protocol wrapped XPROG commands used in Atmel programmer devices.
*/
#define INCLUDE_FROM_XPROGPROTOCOL_C
#include "XPROGProtocol.h"
#if defined(ENABLE_XPROG_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;
/** Currently selected XPROG programming protocol */
uint8_t XPROG_SelectedProtocol = XPRG_PROTOCOL_PDI;
/** Handler for the CMD_XPROG_SETMODE command, which sets the programmer-to-target protocol used for PDI/TPI
* programming.
*/
void XPROGProtocol_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);
XPROG_SelectedProtocol = SetMode_XPROG_Params.Protocol;
Endpoint_Write_Byte(CMD_XPROG_SETMODE);
Endpoint_Write_Byte((SetMode_XPROG_Params.Protocol != XPRG_PROTOCOL_JTAG) ? 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 XPROGProtocol_Command(void)
{
uint8_t XPROGCommand = Endpoint_Read_Byte();
switch (XPROGCommand)
{
case XPRG_CMD_ENTER_PROGMODE:
XPROGProtocol_EnterXPROGMode();
break;
case XPRG_CMD_LEAVE_PROGMODE:
XPROGProtocol_LeaveXPROGMode();
break;
case XPRG_CMD_ERASE:
XPROGProtocol_Erase();
break;
case XPRG_CMD_WRITE_MEM:
XPROGProtocol_WriteMemory();
break;
case XPRG_CMD_READ_MEM:
XPROGProtocol_ReadMemory();
break;
case XPRG_CMD_CRC:
XPROGProtocol_ReadCRC();
break;
case XPRG_CMD_SET_PARAM:
XPROGProtocol_SetParam();
break;
}
}
/** Handler for the XPROG ENTER_PROGMODE command to establish a connection with the attached device. */
static void XPROGProtocol_EnterXPROGMode(void)
{
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
bool NVMBusEnabled;
if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
{
/* Enable PDI programming mode with the attached target */
XPROGTarget_EnableTargetPDI();
/* Store the RESET key into the RESET PDI register to keep the XMEGA in reset */
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 */
XPROGTarget_SendByte(PDI_CMD_KEY);
for (uint8_t i = sizeof(PDI_NVMENABLE_KEY); i > 0; i--)
XPROGTarget_SendByte(PDI_NVMENABLE_KEY[i - 1]);
/* Wait until the NVM bus becomes active */
NVMBusEnabled = XMEGANVM_WaitWhileNVMBusBusy();
}
else
{
/* Enable TPI programming mode with the attached target */
XPROGTarget_EnableTargetTPI();
/* Enable access to the XPROG NVM bus by sending the documented NVM access key to the device */
XPROGTarget_SendByte(TPI_CMD_SKEY);
for (uint8_t i = sizeof(TPI_NVMENABLE_KEY); i > 0; i--)
XPROGTarget_SendByte(TPI_NVMENABLE_KEY[i - 1]);
/* Wait until the NVM bus becomes active */
NVMBusEnabled = TINYNVM_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 XPROGProtocol_LeaveXPROGMode(void)
{
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
{
/* Clear the RESET key in the RESET PDI register to allow the XMEGA to run */
XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
XPROGTarget_SendByte(0x00);
XPROGTarget_DisableTargetPDI();
}
else
{
/* Clear the NVMEN bit in the TPI CONTROL register to disable TPI mode */
XPROGTarget_SendByte(TPI_CMD_SSTCS | TPI_CTRL_REG);
XPROGTarget_SendByte(0x00);
XPROGTarget_DisableTargetTPI();
}
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 XPROGProtocol_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;
if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
{
/* 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;
}
else
{
// TODO
}
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 XPROGProtocol_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 (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
{
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;
}
}
else
{
// TODO
}
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 XPROGProtocol_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];
if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
{
/* 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;
}
else
{
// TODO
}
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 XPROGProtocol_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;
if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
{
/* 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;
}
else
{
/* TPI does not support memory CRC */
ReturnStatus = XPRG_ERR_FAILED;
}
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 XPROG parameter for use when communicating with the
* attached device.
*/
static void XPROGProtocol_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 XPROGProtocol.c.
*/
#ifndef _XPROG_PROTOCOL_
#define _XPROG_PROTOCOL_
/* Includes: */
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <LUFA/Drivers/USB/USB.h>
#include "../V2Protocol.h"
#include "XPROGTarget.h"
#include "XMEGANVM.h"
#include "TINYNVM.h"
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
#undef ENABLE_ISP_PROTOCOL
#if !defined(ENABLE_XPROG_PROTOCOL)
#define ENABLE_XPROG_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 XPROGProtocol_SetMode(void);
void XPROGProtocol_Command(void);
#if defined(INCLUDE_FROM_XPROGPROTOCOL_C)
static void XPROGProtocol_EnterXPROGMode(void);
static void XPROGProtocol_LeaveXPROGMode(void);
static void XPROGProtocol_SetParam(void);
static void XPROGProtocol_Erase(void);
static void XPROGProtocol_WriteMemory(void);
static void XPROGProtocol_ReadMemory(void);
static void XPROGProtocol_ReadCRC(void);
#endif
#endif

View file

@ -0,0 +1,420 @@
/*
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_XPROGTARGET_C
#include "XPROGTarget.h"
#if defined(ENABLE_XPROG_PROTOCOL) || defined(__DOXYGEN__)
/** Flag to indicate if the USART is currently in Tx or Rx mode. */
volatile bool IsSending;
#if !defined(XPROG_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 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) */
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_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)
((uint8_t*)&SoftUSART_Data)[1] |= (1 << (BITS_IN_USART_FRAME - 9));
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 (((uint8_t*)&SoftUSART_Data)[0] & 0x01)
BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
else
BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;
SoftUSART_Data >>= 1;
SoftUSART_BitCount--;
}
}
/** ISR to manage the TPI software USART when bit-banged TPI USART mode is selected. */
ISR(TIMER1_COMPB_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)
((uint8_t*)&SoftUSART_Data)[1] |= (1 << (BITS_IN_USART_FRAME - 9));
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 (((uint8_t*)&SoftUSART_Data)[0] & 0x01)
BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK;
else
BITBANG_TPIDATA_PORT &= ~BITBANG_TPIDATA_MASK;
SoftUSART_Data >>= 1;
SoftUSART_BitCount--;
}
}
#endif
/** Enables the target's PDI interface, holding the target in reset until PDI mode is exited. */
void XPROGTarget_EnableTargetPDI(void)
{
#if defined(XPROG_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) */
XPROGTarget_SendBreak();
XPROGTarget_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 channel A ISR every 90 cycles to manage the software USART */
OCR1A = 90;
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) */
XPROGTarget_SendBreak();
XPROGTarget_SendBreak();
#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 channel B ISR every 90 cycles to manage the software USART */
OCR1B = 9;
TCCR1B = (1 << WGM12) | (1 << CS10);
TIMSK1 = (1 << OCIE1B);
/* Send two BREAKs of 12 bits each to enable TPI interface (need at least 16 idle bits) */
XPROGTarget_SendBreak();
XPROGTarget_SendBreak();
#endif
}
/** Disables the target's PDI interface, exits programming mode and starts the target's application. */
void XPROGTarget_DisableTargetPDI(void)
{
#if defined(XPROG_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
}
/** Disables the target's TPI interface, exits programming mode and starts the target's application. */
void XPROGTarget_DisableTargetTPI(void)
{
#if defined(XPROG_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 XPROGTarget_SendByte(const uint8_t Byte)
{
#if defined(XPROG_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_USART_FRAME;
#endif
}
/** Receives a byte via the software USART, blocking until data is received.
*
* \return Received byte from the USART
*/
uint8_t XPROGTarget_ReceiveByte(void)
{
#if defined(XPROG_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)) && TimeoutMSRemaining);
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_USART_FRAME;
while (SoftUSART_BitCount && TimeoutMSRemaining);
/* 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 XPROGTarget_SendBreak(void)
{
#if defined(XPROG_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_USART_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_USART_FRAME;
#endif
}
#endif

View file

@ -0,0 +1,164 @@
/*
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>
#include "../V2Protocol.h"
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
#undef ENABLE_ISP_PROTOCOL
#if !defined(ENABLE_XPROG_PROTOCOL)
#define ENABLE_XPROG_PROTOCOL
#endif
#endif
/* Defines: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
// #define XPROG_VIA_HARDWARE_USART
#define BITBANG_PDIDATA_PORT PORTD
#define BITBANG_PDIDATA_DDR DDRD
#define BITBANG_PDIDATA_PIN PIND
#define BITBANG_PDIDATA_MASK (1 << 3)
#define BITBANG_PDICLOCK_PORT PORTD
#define BITBANG_PDICLOCK_DDR DDRD
#define BITBANG_PDICLOCK_PIN PIND
#define BITBANG_PDICLOCK_MASK (1 << 5)
#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)
#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
#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)
#endif
/** Total number of bits in a single USART frame */
#define BITS_IN_USART_FRAME 12
#define PDI_CMD_LDS 0x00
#define PDI_CMD_LD 0x20
#define PDI_CMD_STS 0x40
#define PDI_CMD_ST 0x60
#define PDI_CMD_LDCS 0x80
#define PDI_CMD_REPEAT 0xA0
#define PDI_CMD_STCS 0xC0
#define PDI_CMD_KEY 0xE0
#define PDI_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
#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 XPROGTarget_EnableTargetPDI(void);
void XPROGTarget_EnableTargetTPI(void);
void XPROGTarget_DisableTargetPDI(void);
void XPROGTarget_DisableTargetTPI(void);
void XPROGTarget_SendByte(const uint8_t Byte);
uint8_t XPROGTarget_ReceiveByte(void);
void XPROGTarget_SendBreak(void);
bool XPROGTarget_WaitWhileNVMBusBusy(void);
#endif

View file

@ -0,0 +1,752 @@
# Hey Emacs, this is a -*- makefile -*-
#----------------------------------------------------------------------------
# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
# >> Modified for use with the LUFA project. <<
#
# Released to the Public Domain
#
# Additional material for this makefile was written by:
# Peter Fleury
# Tim Henigan
# Colin O'Flynn
# Reiner Patommel
# Markus Pfaff
# Sander Pool
# Frederik Rouleau
# Carlos Lamas
# Dean Camera
# Opendous Inc.
# Denver Gingerich
#
#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device, using avrdude.
# Please customize the avrdude settings below first!
#
# make dfu = Download the hex file to the device, using dfu-programmer (must
# have dfu-programmer installed).
#
# make flip = Download the hex file to the device, using Atmel FLIP (must
# have Atmel FLIP installed).
#
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
# (must have dfu-programmer installed).
#
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
# (must have Atmel FLIP installed).
#
# make doxygen = Generate DoxyGen documentation for the project (must have
# DoxyGen installed)
#
# make debug = Start either simulavr or avarice as specified for debugging,
# with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
# bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------
# MCU name
MCU = at90usb1287
# Target board (see library "Board Types" documentation, USER or blank for projects not requiring
# LUFA board drivers). If USER is selected, put custom board drivers in a directory called
# "Board" inside the application directory.
BOARD = USBKEY
# Processor frequency.
# This will define a symbol, F_CPU, in all source code files equal to the
# processor frequency in Hz. You can then use this symbol in your source code to
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
# automatically to create a 32-bit value in your source code.
#
# This will be an integer division of F_CLOCK below, as it is sourced by
# F_CLOCK after it has run through any CPU prescalers. Note that this value
# does not *change* the processor frequency - it should merely be updated to
# reflect the processor speed set externally so that the code can use accurate
# software delays.
F_CPU = 8000000
# Input clock frequency.
# This will define a symbol, F_CLOCK, in all source code files equal to the
# input clock frequency (before any prescaling is performed) in Hz. This value may
# differ from F_CPU if prescaling is used on the latter, and is required as the
# raw input clock is fed directly to the PLL sections of the AVR for high speed
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
# at the end, this will be done automatically to create a 32-bit value in your
# source code.
#
# If no clock division is performed on the input clock inside the AVR (via the
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
F_CLOCK = $(F_CPU)
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
# Target file name (without extension).
TARGET = AVRISP
# Object files directory
# To put object files in current directory, use a dot (.), do NOT make
# this an empty or blank macro!
OBJDIR = .
# Path to the LUFA library
LUFA_PATH = ../../
# LUFA library compile-time options
LUFA_OPTS = -D USB_DEVICE_ONLY
LUFA_OPTS += -D FIXED_CONTROL_ENDPOINT_SIZE=16
LUFA_OPTS += -D FIXED_NUM_CONFIGURATIONS=1
LUFA_OPTS += -D NO_STREAM_CALLBACKS
LUFA_OPTS += -D USE_FLASH_DESCRIPTORS
LUFA_OPTS += -D USE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c \
Descriptors.c \
Lib/V2Protocol.c \
Lib/V2ProtocolParams.c \
Lib/ISP/ISPProtocol.c \
Lib/ISP/ISPTarget.c \
Lib/XPROG/XPROGProtocol.c \
Lib/XPROG/XPROGTarget.c \
Lib/XPROG/XMEGANVM.c \
Lib/XPROG/TINYNVM.c \
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Host.c \
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/HostChapter9.c \
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/LowLevel.c \
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Pipe.c \
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/Events.c \
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \
$(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \
# List C++ source files here. (C dependencies are automatically generated.)
CPPSRC =
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC =
# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s
# Debugging format.
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
# AVR Studio 4.10 requires dwarf-2.
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
DEBUG = dwarf-2
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
EXTRAINCDIRS = $(LUFA_PATH)/
# Compiler flag to set the C Standard level.
# c89 = "ANSI" C
# gnu89 = c89 plus GCC extensions
# c99 = ISO C99 standard (not yet fully implemented)
# gnu99 = c99 plus GCC extensions
CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD) $(LUFA_OPTS)
CDEFS += -DRESET_LINE_PORT=PORTB
CDEFS += -DRESET_LINE_PIN=PINB
CDEFS += -DRESET_LINE_DDR=DDRB
CDEFS += -DRESET_LINE_MASK="(1 << 4)"
CDEFS += -DVTARGET_ADC_CHANNEL=2
CDEFS += -DENABLE_ISP_PROTOCOL
CDEFS += -DENABLE_XPROG_PROTOCOL
# Place -D or -U options here for ASM sources
ADEFS = -DF_CPU=$(F_CPU)
# Place -D or -U options here for C++ sources
CPPDEFS = -DF_CPU=$(F_CPU)UL
#CPPDEFS += -D__STDC_LIMIT_MACROS
#CPPDEFS += -D__STDC_CONSTANT_MACROS
#---------------- Compiler Options C ----------------
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char
CFLAGS += -funsigned-bitfields
CFLAGS += -ffunction-sections
CFLAGS += -fno-inline-small-functions
CFLAGS += -fpack-struct
CFLAGS += -fshort-enums
CFLAGS += -Wall
CFLAGS += -Wstrict-prototypes
CFLAGS += -Wundef
#CFLAGS += -fno-unit-at-a-time
#CFLAGS += -Wunreachable-code
#CFLAGS += -Wsign-compare
CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
#---------------- Compiler Options C++ ----------------
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CPPFLAGS = -g$(DEBUG)
CPPFLAGS += $(CPPDEFS)
CPPFLAGS += -O$(OPT)
CPPFLAGS += -funsigned-char
CPPFLAGS += -funsigned-bitfields
CPPFLAGS += -fpack-struct
CPPFLAGS += -fshort-enums
CPPFLAGS += -fno-exceptions
CPPFLAGS += -Wall
CFLAGS += -Wundef
#CPPFLAGS += -mshort-calls
#CPPFLAGS += -fno-unit-at-a-time
#CPPFLAGS += -Wstrict-prototypes
#CPPFLAGS += -Wunreachable-code
#CPPFLAGS += -Wsign-compare
CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
#CPPFLAGS += $(CSTANDARD)
#---------------- Assembler Options ----------------
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
# -listing-cont-lines: Sets the maximum number of continuation lines of hex
# dump that will be displayed for a given single line of source input.
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100
#---------------- Library Options ----------------
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
# If this is left blank, then it will use the Standard printf version.
PRINTF_LIB =
#PRINTF_LIB = $(PRINTF_LIB_MIN)
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
# If this is left blank, then it will use the Standard scanf version.
SCANF_LIB =
#SCANF_LIB = $(SCANF_LIB_MIN)
#SCANF_LIB = $(SCANF_LIB_FLOAT)
MATH_LIB = -lm
# List any extra directories to look for libraries here.
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
EXTRALIBDIRS =
#---------------- External Memory Options ----------------
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
EXTMEMOPTS =
#---------------- Linker Options ----------------
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += -Wl,--relax
LDFLAGS += -Wl,--gc-sections
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
#LDFLAGS += -T linker_script.x
#---------------- Programming Options (avrdude) ----------------
# Programming hardware: alf avr910 avrisp bascom bsd
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
#
# Type: avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER = jtagmkII
# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = usb
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
#---------------- Debugging Options ----------------
# For simulavr only - target MCU frequency.
DEBUG_MFREQ = $(F_CPU)
# Set the DEBUG_UI to either gdb or insight.
# DEBUG_UI = gdb
DEBUG_UI = insight
# Set the debugging back-end to either avarice, simulavr.
DEBUG_BACKEND = avarice
#DEBUG_BACKEND = simulavr
# GDB Init Filename.
GDBINIT_FILE = __avr_gdbinit
# When using avarice settings for the JTAG
JTAG_DEV = /dev/com1
# Debugging port used to communicate between GDB / avarice / simulavr.
DEBUG_PORT = 4242
# Debugging host used to communicate between GDB / avarice / simulavr, normally
# just set to localhost unless doing some sort of crazy debugging when
# avarice is running on a different computer.
DEBUG_HOST = localhost
#============================================================================
# Define programs and commands.
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
AR = avr-ar rcs
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
REMOVEDIR = rm -rf
COPY = cp
WINSHELL = cmd
# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = -------- end --------
MSG_SIZE_BEFORE = Size before:
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling C:
MSG_COMPILING_CPP = Compiling C++:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
MSG_CREATING_LIBRARY = Creating library:
# Define all object files.
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o)
# Define all listing files.
LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst)
# Compiler flags to generate dependency files.
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: begin gccversion sizebefore build checkinvalidevents showliboptions showtarget sizeafter end
# Change the build target to build a HEX file or a library.
build: elf hex eep lss sym
#build: lib
elf: $(TARGET).elf
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
LIBNAME=lib$(TARGET).a
lib: $(LIBNAME)
# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
@echo
@echo $(MSG_BEGIN)
end:
@echo $(MSG_END)
@echo
# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) $(MCU_FLAG) $(FORMAT_FLAG) $(TARGET).elf
MCU_FLAG = $(shell $(SIZE) --help | grep -- --mcu > /dev/null && echo --mcu=$(MCU) )
FORMAT_FLAG = $(shell $(SIZE) --help | grep -- --format=.*avr > /dev/null && echo --format=avr )
sizebefore:
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
2>/dev/null; echo; fi
sizeafter:
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
2>/dev/null; echo; fi
$(LUFA_PATH)/LUFA/LUFA_Events.lst:
@make -C $(LUFA_PATH)/LUFA/ LUFA_Events.lst
checkinvalidevents: $(LUFA_PATH)/LUFA/LUFA_Events.lst
@echo
@echo Checking for invalid events...
@$(shell) avr-nm $(OBJ) | sed -n -e 's/^.*EVENT_/EVENT_/p' | \
grep -F -v --file=$(LUFA_PATH)/LUFA/LUFA_Events.lst > InvalidEvents.tmp || true
@sed -n -e 's/^/ WARNING - INVALID EVENT NAME: /p' InvalidEvents.tmp
@if test -s InvalidEvents.tmp; then exit 1; fi
showliboptions:
@echo
@echo ---- Compile Time Library Options ----
@for i in $(LUFA_OPTS:-D%=%); do \
echo $$i; \
done
@echo --------------------------------------
showtarget:
@echo
@echo --------- Target Information ---------
@echo AVR Model: $(MCU)
@echo Board: $(BOARD)
@echo Clock: $(F_CPU)Hz CPU, $(F_CLOCK)Hz Master
@echo --------------------------------------
# Display compiler version information.
gccversion :
@$(CC) --version
# Program the device.
program: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
flip: $(TARGET).hex
batchisp -hardware usb -device $(MCU) -operation erase f
batchisp -hardware usb -device $(MCU) -operation loadbuffer $(TARGET).hex program
batchisp -hardware usb -device $(MCU) -operation start reset 0
dfu: $(TARGET).hex
dfu-programmer $(MCU) erase
dfu-programmer $(MCU) flash --debug 1 $(TARGET).hex
dfu-programmer $(MCU) reset
flip-ee: $(TARGET).hex $(TARGET).eep
$(COPY) $(TARGET).eep $(TARGET)eep.hex
batchisp -hardware usb -device $(MCU) -operation memory EEPROM erase
batchisp -hardware usb -device $(MCU) -operation memory EEPROM loadbuffer $(TARGET)eep.hex program
batchisp -hardware usb -device $(MCU) -operation start reset 0
$(REMOVE) $(TARGET)eep.hex
dfu-ee: $(TARGET).hex $(TARGET).eep
dfu-programmer $(MCU) flash-eeprom --debug 1 --suppress-bootloader-mem $(TARGET).eep
dfu-programmer $(MCU) reset
# Generate avr-gdb config/init file which does the following:
# define the reset signal, load the target file, connect to target, and set
# a breakpoint at main().
gdb-config:
@$(REMOVE) $(GDBINIT_FILE)
@echo define reset >> $(GDBINIT_FILE)
@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
@echo end >> $(GDBINIT_FILE)
@echo file $(TARGET).elf >> $(GDBINIT_FILE)
@echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
ifeq ($(DEBUG_BACKEND),simulavr)
@echo load >> $(GDBINIT_FILE)
endif
@echo break main >> $(GDBINIT_FILE)
debug: gdb-config $(TARGET).elf
ifeq ($(DEBUG_BACKEND), avarice)
@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
@$(WINSHELL) /c pause
else
@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
$(DEBUG_MFREQ) --port $(DEBUG_PORT)
endif
@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT = $(OBJCOPY) --debugging
COFFCONVERT += --change-section-address .data-0x800000
COFFCONVERT += --change-section-address .bss-0x800000
COFFCONVERT += --change-section-address .noinit-0x800000
COFFCONVERT += --change-section-address .eeprom-0x810000
coff: $(TARGET).elf
@echo
@echo $(MSG_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
extcoff: $(TARGET).elf
@echo
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
@echo
@echo $(MSG_FLASH) $@
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
%.eep: %.elf
@echo
@echo $(MSG_EEPROM) $@
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0
# Create extended listing file from ELF output file.
%.lss: %.elf
@echo
@echo $(MSG_EXTENDED_LISTING) $@
$(OBJDUMP) -h -z -S $< > $@
# Create a symbol table from ELF output file.
%.sym: %.elf
@echo
@echo $(MSG_SYMBOL_TABLE) $@
$(NM) -n $< > $@
# Create library from object files.
.SECONDARY : $(TARGET).a
.PRECIOUS : $(OBJ)
%.a: $(OBJ)
@echo
@echo $(MSG_CREATING_LIBRARY) $@
$(AR) $@ $(OBJ)
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
@echo
@echo $(MSG_LINKING) $@
$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
# Compile: create object files from C source files.
$(OBJDIR)/%.o : %.c
@echo
@echo $(MSG_COMPILING) $<
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create object files from C++ source files.
$(OBJDIR)/%.o : %.cpp
@echo
@echo $(MSG_COMPILING_CPP) $<
$(CC) -c $(ALL_CPPFLAGS) $< -o $@
# Compile: create assembler files from C source files.
%.s : %.c
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C++ source files.
%.s : %.cpp
$(CC) -S $(ALL_CPPFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
$(OBJDIR)/%.o : %.S
@echo
@echo $(MSG_ASSEMBLING) $<
$(CC) -c $(ALL_ASFLAGS) $< -o $@
# Create preprocessed source for use in sending a bug report.
%.i : %.c
$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@
# Target: clean project.
clean: begin clean_list clean_binary end
clean_binary:
$(REMOVE) $(TARGET).hex
clean_list:
@echo $(MSG_CLEANING)
$(REMOVE) $(TARGET).eep
$(REMOVE) $(TARGET)eep.hex
$(REMOVE) $(TARGET).cof
$(REMOVE) $(TARGET).elf
$(REMOVE) $(TARGET).map
$(REMOVE) $(TARGET).sym
$(REMOVE) $(TARGET).lss
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o)
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)
$(REMOVE) $(SRC:.c=.i)
$(REMOVE) InvalidEvents.tmp
$(REMOVEDIR) .dep
doxygen:
@echo Generating Project Documentation...
@doxygen Doxygen.conf
@echo Documentation Generation Complete.
clean_doxygen:
rm -rf Documentation
# Create object files directory
$(shell mkdir $(OBJDIR) 2>/dev/null)
# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# Listing of phony targets.
.PHONY : all checkinvalidevents showliboptions \
showtarget begin finish end sizebefore sizeafter \
gccversion build elf hex eep lss sym coff extcoff \
program dfu flip flip-ee dfu-ee clean debug \
clean_list clean_binary gdb-config doxygen