1
0
Fork 0

Squashed 'tmk_core/' changes from caca2c0..dc0e46e

dc0e46e Rename LUFA to LUFA-git
3bfa7fa Remove LUFA-120730
215b764 Merge commit 'afa0f22a9299686fd88f58ce09c5b521ac917e8f' as 'protocol/lufa/LUFA'
afa0f22 Squashed 'protocol/lufa/LUFA/' content from commit def7fca
c0c42fa Remove submodule of LUFA
30f897d Merge commit '87ced33feb74e79c3281dda36eb6d6d153399b41' as 'protocol/usb_hid/USB_Host_Shield_2.0'
87ced33 Squashed 'protocol/usb_hid/USB_Host_Shield_2.0/' content from commit aab4a69
14f6d49 Remove submodule of USB_Host_Shield_2.0

git-subtree-dir: tmk_core
git-subtree-split: dc0e46eaa4367d4e218f8816e3c117895820f07c
This commit is contained in:
tmk 2015-05-13 11:13:10 +09:00
parent 4d116a04e9
commit f6d56675f9
1575 changed files with 421901 additions and 63190 deletions

View file

@ -0,0 +1,156 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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-MKII.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();
V2Protocol_Init();
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
GlobalInterruptEnable();
for (;;)
{
#if (BOARD == BOARD_USBTINYMKII)
/* On the USBTINY-MKII target, there is a secondary LED which indicates the current selected power
mode - either VBUS, or sourced from the VTARGET pin of the programming connectors */
LEDs_ChangeLEDs(LEDMASK_VBUSPOWER, (PIND & (1 << 0)) ? 0 : LEDMASK_VBUSPOWER);
#endif
AVRISP_Task();
USB_USBTask();
}
}
/** Configures the board hardware and chip peripherals for the demo's functionality. */
void SetupHardware(void)
{
#if (ARCH == ARCH_AVR8)
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Disable clock division */
clock_prescale_set(clock_div_1);
#endif
/* Hardware Initialization */
LEDs_Init();
#if defined(RESET_TOGGLES_LIBUSB_COMPAT)
UpdateCurrentCompatibilityMode();
#endif
/* USB Stack Initialization */
USB_Init();
}
/** 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)
{
bool ConfigSuccess = true;
/* Setup AVRISP Data OUT endpoint */
ConfigSuccess &= Endpoint_ConfigureEndpoint(AVRISP_DATA_OUT_EPADDR, EP_TYPE_BULK, AVRISP_DATA_EPSIZE, 1);
/* Setup AVRISP Data IN endpoint if it is using a physically different endpoint */
if ((AVRISP_DATA_IN_EPADDR & ENDPOINT_EPNUM_MASK) != (AVRISP_DATA_OUT_EPADDR & ENDPOINT_EPNUM_MASK))
ConfigSuccess &= Endpoint_ConfigureEndpoint(AVRISP_DATA_IN_EPADDR, EP_TYPE_BULK, AVRISP_DATA_EPSIZE, 1);
/* Indicate endpoint configuration success or failure */
LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
}
/** Processes incoming V2 Protocol commands from the host, returning a response when required. */
void AVRISP_Task(void)
{
/* Device must be connected and configured for the task to run */
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
V2Params_UpdateParamValues();
Endpoint_SelectEndpoint(AVRISP_DATA_OUT_EPADDR);
/* 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);
}
}
/** 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.
*
* \param[in] wValue Descriptor type and index to retrieve
* \param[in] wIndex Sub-index to retrieve (such as a localized string language)
* \param[out] DescriptorAddress Address of the retrieved descriptor
* \param[out] DescriptorMemorySpace Memory space that the descriptor is stored in
*
* \return Length of the retrieved descriptor in bytes, or NO_DESCRIPTOR if the descriptor was not found
*/
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const uint8_t wIndex,
const void** const DescriptorAddress,
uint8_t* DescriptorMemorySpace)
{
return AVRISP_GetDescriptor(wValue, wIndex, DescriptorAddress, DescriptorMemorySpace);
}

View file

@ -0,0 +1,91 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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 <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Platform/Platform.h>
#if defined(ADC)
#include <LUFA/Drivers/Peripheral/ADC.h>
#endif
#include "AVRISPDescriptors.h"
#include "Lib/V2Protocol.h"
#include "Config/AppConfig.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_LED1 | LEDS_LED2)
/** LED mask for the library LED driver, to indicate that the USB interface is ready. */
#define LEDMASK_USB_READY LEDS_LED2
/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
#define LEDMASK_USB_ERROR LEDS_LED1
/** LED mask for the library LED driver, to indicate that the USB interface is busy. */
#define LEDMASK_BUSY (LEDS_LED1 | LEDS_LED2)
/** LED mask for the library LED driver, to indicate that the target is being powered by VBUS. */
#define LEDMASK_VBUSPOWER LEDS_LED3
/* Function Prototypes: */
void SetupHardware(void);
void AVRISP_Task(void);
void EVENT_USB_Device_Connect(void);
void EVENT_USB_Device_Disconnect(void);
void EVENT_USB_Device_ConfigurationChanged(void);
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const uint8_t wIndex,
const void** const DescriptorAddress,
uint8_t* const DescriptorMemorySpace)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3) ATTR_NON_NULL_PTR_ARG(4);
#endif

View file

@ -0,0 +1,385 @@
/** \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 Sec_Compat Project Compatibility
*
* The following list indicates what microcontrollers are compatible with this project.
*
* \li Series 7 USB AVRs (AT90USBxxx7)
* \li Series 6 USB AVRs (AT90USBxxx6)
* \li Series 4 USB AVRs (ATMEGAxxU4)
* \li Series 2 USB AVRs (AT90USBxx2, ATMEGAxxU2) - <i>8KB versions with reduced features only</i>
*
* \section Sec_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>Supported USB Speeds:</b></td>
* <td>Full Speed Mode</td>
* </tr>
* </table>
*
* \section Sec_Description Project Description
*
* Firmware for an Atmel Studio/AVR Studio 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
* Atmel Studio/AVR Studio or with any software capable of driving a real Atmel AVRISP-MKII programmer. In its most
* basic form, it allows for the programming of AVR TINY, MEGA and XMEGA devices aat the programmer's VCC voltage from
* within Atmel Studio/AVR Studio 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 target AVRs running at a different voltage to the programmer.
*
* 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 Atmel Studio/AVR Studio.
*
* Note that this design currently has the following limitations:
* - No reversed/shorted target connector detection and notification
* - A separate header is required for each of the ISP, PDI and TPI programming protocols that the user wishes to use
*
* On AVR models with an ADC converter, the USB AVR's AVCC pin should be tied to 5V (e.g. VBUS) and the
* \c 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 a fixed 3.3V level at all times
* which should allow the programmer to remain compatible at the protocol level with all AVR devices.
*
* 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 or PDI/TPI protocol programming support can be disabled to reduce program size.
*
* \section Sec_KnownIssues Known Issues:
*
* \par Incompatible with newer AVRDUDE releases.
* Due to <a href="http://savannah.nongnu.org/bugs/index.php?40831">a change in 6.0.1 and never AVRDUDE releases</a>,
* these builds are incompatible with the AVRISP-MKII clone project. Use an older 5.x release until AVRDUDE is patched.
*
* \par XMEGA EEPROM programming fails in some cases.
* Several users have reported that XMEGA EEPROM programming fails unless the chip is erased first. If a non-blank EEPROM
* is present, writing further EEPROM data causes corruption.
* <a href="https://github.com/abcminiuser/lufa/issues/25">LUFA issue tracker entry</a>.
*
* \section Sec_Installation Installation
* The programmer supports multiple platforms, both Windows and Linux.
*
* \subsection SSec_LinuxInstallation Linux Installation
* On Linux systems, the programmer should be usable out of the box with no special setup other than (on some systems)
* editing of the system permissions to allow the programmer to be used from a non-elevated (root) context. The programmer
* is compatible with the free open source AVRDude programming software project.
*
* \subsection SSec_WindowsInstallation Windows Installation
* On Windows systems, due to an unfortunate limitation of the USB AVR devices and the driver used in the official AVR
* Studio/Atmel Studio platform, the programmer cannot be made compatible with AVRDude and AVR Studio/Atmel Studio at the
* same time. Instead, the programmer will be compatible with the official Atmel software by default, with a recompilation
* with the \c LIBUSB_DRIVER_COMPAT token (see \ref Sec_Options) being required to use the alternative libUSB driver
* compatibility mode that will allow the programmer to work under AVRDude on Windows.
*
* If compiled for Atmel Studio/AVR Studio compatibility, install the Jungo device drivers that ship with the Atmel software.
* If compiled in the alternative libUSB compatibility mode for AVRDude use, install the libUSB drivers that are included
* with your compiled copy of AVRDude, or create them using the libUSB-Win32 (http://sourceforge.net/projects/libusb-win32)
* project.
*
* For convenience, the programmer will report two different serial numbers depending on the firmware compatibility mode, so
* that the correct driver can be installed for the matching firmware. If the \c RESET_TOGGLES_LIBUSB_COMPAT compile option
* is used (see \ref Sec_Options) this allows for an easy way to automatically switch device drivers along with the firmware
* compatibility mode. The serials are:
*
* <table>
* <tr>
* <th><b>Serial Number:</b></th>
* <th><b>Compatibility Mode:</b></th>
* </tr>
* <tr>
* <td>000200012345</td>
* <td>Jungo (Atmel Studio) Compatibility</td>
* </tr>
* <tr>
* <td>000200112345</td>
* <td>libUSB Compatibility</td>
* </tr>
* </table>
*
* \section Sec_ISP ISP Connections
* Connections to the device for SPI programming (when enabled):
*
* <table>
* <tr>
* <th><b>Programmer Pin:</b></th>
* <th><b>Target Device Pin:</b></th>
* <th><b>ISP 6 Pin Layout:</b></th>
* </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>
*
* In addition, the AVR's OCR1A pin will generate a 4MHz clock, to act as an external rescue device clock if the
* fuses have been mis-set. To use the recovery clock, connect the OCR1A pin of the USB AVR to the target AVR's
* XTAL1 pin, and set the ISP programming speed to 125KHz (note: other ISP speeds will not work correctly).
*
* <b><sup>1</sup></b> <i>Optional, see \ref Sec_Options section - for USB AVRs with ADC modules only</i> \n
* <b><sup>2</sup></b> <i>See AUX line related tokens in the \ref Sec_Options section</i>
*
* \section Sec_PDI PDI Connections
* Connections to the device for PDI programming (when enabled):
*
* <table>
* <tr>
* <th><b>Programmer Pin:</b></th>
* <th><b>Target Device Pin:</b></th>
* <th><b>PDI 6 Pin Layout:</b></th>
* </tr>
* <tr>
* <td>Tx/Rx <b><sup>2</sup></b></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>XCK</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>Optional, see \ref Sec_Options section - for USB AVRs with ADC modules only</i> \n
* <b><sup>2</sup></b> <i>The AVR's Tx and Rx become the DATA line when connected together via a pair of 220 ohm resistors</i> \n
*
* \section Sec_TPI TPI Connections
* Connections to the device for TPI programming (when enabled):
*
* <table>
* <tr>
* <th><b>Programmer Pin:</b></th>
* <th><b>Target Device Pin:</b></th>
* <th><b>TPI 6 Pin Layout:</b></th>
* </tr>
* <tr>
* <td>Tx/Rx <b><sup>2</sup></b></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>XCK <b><sup>2</sup></b></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>3</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 Sec_Options section - for USB AVRs with ADC modules only</i> \n
* <b><sup>2</sup></b> <i>The AVR's Tx and Rx become the DATA line when connected together via a pair of 220 ohm resistors</i> \n
* <b><sup>3</sup></b> <i>See AUX line related tokens in the \ref Sec_Options section</i>
*
* \section Sec_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>
* <th><b>Define Name:</b></th>
* <th><b>Location:</b></th>
* <th><b>Description:</b></th>
* </tr>
* <tr>
* <td>AUX_LINE_PORT</td>
* <td>AppConfig.h</td>
* <td>PORT register for the programmer's AUX target line. The use of this line varies between the programming protocols,
* but is generally used for the target's /RESET line.
* \n \n <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr>
* <tr>
* <td>AUX_LINE_PIN</td>
* <td>AppConfig.h</td>
* <td>PIN register for the programmer's AUX target line. The use of this line varies between the programming protocols,
* but is generally used for the target's /RESET line.
* \n \n <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr>
* <tr>
* <td>AUX_LINE_DDR</td>
* <td>AppConfig.h</td>
* <td>DDR register for the programmer's AUX target line. The use of this line varies between the programming protocols,
* but is generally used for the target's /RESET line.
* \n \n <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr>
* <tr>
* <td>AUX_LINE_MASK</td>
* <td>AppConfig.h</td>
* <td>Mask for the programmer's AUX target line. The use of this line varies between the programming protocols,
* but is generally used for the target's /RESET line. <b>Must not be the AVR's /SS pin</b>.
* \n \n <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr>
* <tr>
* <td>VTARGET_ADC_CHANNEL</td>
* <td>AppConfig.h</td>
* <td>ADC channel number (on supported AVRs) to use for VTARGET level detection, if NO_VTARGET_DETECT is not defined.
* \n \n <i>Ignored when compiled for targets lacking an ADC.</i></td>
* </tr>
* <tr>
* <td>ENABLE_ISP_PROTOCOL</td>
* <td>AppConfig.h</td>
* <td>Define to enable SPI programming protocol support.
* \n \n <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr>
* <tr>
* <td>ENABLE_XPROG_PROTOCOL</td>
* <td>AppConfig.h</td>
* <td>Define to enable PDI and TPI programming protocol support.
* \n \n <i>Ignored when compiled for the XPLAIN board.</i></td>
* </tr>
* <tr>
* <td>NO_VTARGET_DETECT</td>
* <td>AppConfig.h</td>
* <td>Define to disable VTARGET sampling and reporting on AVR models with an ADC converter. This will cause the programmer
* to report a fixed 3.3V target voltage to the host regardless of the real target voltage.
* \n \n <i>Ignored when compiled for targets lacking an ADC.</i></td>
* </tr>
* <tr>
* <td>VTARGET_REF_VOLTS</td>
* <td>AppConfig.h</td>
* <td>Indicates the programmer AVR's AVCC reference voltage when measuring the target's supply voltage. Note that the supply
* voltage should never exceed the reference voltage on the programmer AVR without some form of protection to prevent damage
* to the ADC.
* \n \n <i>Ignored when compiled for targets lacking an ADC, or when NO_VTARGET_DETECT is defined.</i></td>
* </tr>
* <tr>
* <td>VTARGET_USE_INTERNAL_REF</td>
* <td>AppConfig.h</td>
* <td>Selects the internal 2.56V ADC reference voltage, instead of using the AVR's VREF pin. When enabled, this option will
* override the VTARGET_REF_VOLTS configuration option.
* \n \n <i>Ignored when compiled for targets lacking an ADC, or when NO_VTARGET_DETECT is defined.</i></td>
* </tr>
* <tr>
* <td>VTARGET_SCALE_FACTOR</td>
* <td>AppConfig.h</td>
* <td>Indicates the target's supply voltage scale factor when applied to the ADC. A simple resistive divider can be used on the
* ADC pin for measuring the target's supply voltage, so that voltages above the programmer AVR's AVCC reference voltage can be
* measured. This should be the reciprocal of the division performed - e.g. if the VTARGET voltage is halved, this should be set
* to 2.
* \n \n <i>Ignored when compiled for targets lacking an ADC, or when NO_VTARGET_DETECT is defined.</i></td>
* </tr>
* <tr>
* <td>LIBUSB_DRIVER_COMPAT</td>
* <td>AppConfig.h</td>
* <td>Define to switch to a non-standard endpoint scheme, breaking compatibility with Atmel Studio/AVR Studio under Windows but
* making the code compatible with software such as avrdude (all platforms) that use the libUSB driver.
*
* \note This option is incompatible with \c RESET_TOGGLES_LIBUSB_COMPAT.</td>
* </tr>
* <tr>
* <td>RESET_TOGGLES_LIBUSB_COMPAT</td>
* <td>AppConfig.h</td>
* <td>Define to make the /RESET line of the AVR toggle between Jungo and libUSB driver compatibility modes. Each time the AVR is
* reset externally via the reset pin, the compatibility mode will be toggled. The compatibility mode is preserved between
* power cycles and is not toggled via other forms of reset such as Watchdog or Brown Out.
*
* When this option is enabled, all board LEDs will flash twice on startup for Jungo compatibility mode, and five times for
* libUSB compatibility mode.
*
* \note This option is incompatible with \c LIBUSB_DRIVER_COMPAT.</td>
* </tr>
* <tr>
* <td>XCK_RESCUE_CLOCK_ENABLE</td>
* <td>AppConfig.h</td>
* <td>Define to move the ISP rescue clock to the AVR's XCK pin instead of the OCR1A output pin. This is useful for existing programming
* hardware that does not expose the OCR1A pin of the AVR, but <i>may</i> cause some issues with PDI programming mode.</td>
* </tr>
* <tr>
* <td>INVERTED_ISP_MISO</td>
* <td>AppConfig.h</td>
* <td>Define to invert the received data on the ISP MISO line. This is sometimes needed depending on the level translation hardware used,
* if the translator hardware inverts the received logic level.</td>
* </tr>
* <tr>
* <td>FIRMWARE_VERSION_MINOR</td>
* <td>AppConfig.h</td>
* <td>Define to set the minor firmware revision nunber reported to the host on request. By default this will use a firmware version compatible
* with the latest Atmel IDE version, however if desired the reported minor value can be adjusted here.</td>
* </tr>
* </table>
*/

View file

@ -0,0 +1,302 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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 "AVRISPDescriptors.h"
#if defined(RESET_TOGGLES_LIBUSB_COMPAT) || defined(__DOXYGEN__)
/** Indicates if an external reset has occurred and the compatibility mode needs to be altered */
static bool AVRISP_NeedCompatibilitySwitch ATTR_NO_INIT;
/** Current AVRISP data IN endpoint address. */
uint8_t AVRISP_CurrDataINEndpointAddress;
/** Saved AVRISP data IN endpoint address in EEPROM. */
uint8_t AVRISP_CurrDataINEndpointAddress_EEPROM EEMEM;
#endif
/** 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.
*/
const USB_Descriptor_Device_t PROGMEM AVRISP_DeviceDescriptor =
{
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
.USBSpecification = VERSION_BCD(1,1,0),
.Class = USB_CSCP_VendorSpecificClass,
.SubClass = USB_CSCP_NoDeviceSubclass,
.Protocol = USB_CSCP_NoDeviceProtocol,
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
.VendorID = 0x03EB,
.ProductID = 0x2104,
.ReleaseNumber = VERSION_BCD(2,0,0),
.ManufacturerStrIndex = AVRISP_STRING_ID_Manufacturer,
.ProductStrIndex = AVRISP_STRING_ID_Product,
.SerialNumStrIndex = AVRISP_STRING_ID_Serial,
.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.
*/
AVRISP_USB_Descriptor_Configuration_t AVRISP_ConfigurationDescriptor =
{
.Config =
{
.Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
.TotalConfigurationSize = sizeof(AVRISP_USB_Descriptor_Configuration_t),
.TotalInterfaces = 1,
.ConfigurationNumber = 1,
.ConfigurationStrIndex = NO_DESCRIPTOR,
.ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED),
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
},
.AVRISP_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = INTERFACE_ID_AVRISP,
.AlternateSetting = 0,
.TotalEndpoints = 2,
.Class = USB_CSCP_VendorSpecificClass,
.SubClass = USB_CSCP_NoDeviceSubclass,
.Protocol = USB_CSCP_NoDeviceProtocol,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.AVRISP_DataInEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
#if defined(RESET_TOGGLES_LIBUSB_COMPAT)
.EndpointAddress = 0,
#else
.EndpointAddress = AVRISP_DATA_IN_EPADDR,
#endif
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = AVRISP_DATA_EPSIZE,
.PollingIntervalMS = 0x0A
},
.AVRISP_DataOutEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = AVRISP_DATA_OUT_EPADDR,
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = AVRISP_DATA_EPSIZE,
.PollingIntervalMS = 0x0A
},
};
/** 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.
*/
const USB_Descriptor_String_t PROGMEM AVRISP_LanguageString = USB_STRING_DESCRIPTOR_ARRAY(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.
*/
const USB_Descriptor_String_t PROGMEM AVRISP_ManufacturerString = USB_STRING_DESCRIPTOR(L"ATMEL");
/** 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.
*/
const USB_Descriptor_String_t PROGMEM AVRISP_ProductString = USB_STRING_DESCRIPTOR(L"AVRISP mkII");
/** Serial number string. This is a Unicode string containing the device's unique serial number, expressed as a
* series of uppercase hexadecimal digits.
*/
USB_Descriptor_String_t AVRISP_SerialString = USB_STRING_DESCRIPTOR(L"000200012345\0"
// Note: Real AVRISP-MKII has the embedded NUL byte, bug in firmware?
);
/** 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 AVRISP_GetDescriptor(const uint16_t wValue,
const uint8_t wIndex,
const void** const DescriptorAddress,
uint8_t* DescriptorMemorySpace)
{
const uint8_t DescriptorType = (wValue >> 8);
const uint8_t DescriptorNumber = (wValue & 0xFF);
const void* Address = NULL;
uint16_t Size = NO_DESCRIPTOR;
*DescriptorMemorySpace = MEMSPACE_FLASH;
switch (DescriptorType)
{
case DTYPE_Device:
Address = &AVRISP_DeviceDescriptor;
Size = sizeof(USB_Descriptor_Device_t);
break;
case DTYPE_Configuration:
*DescriptorMemorySpace = MEMSPACE_RAM;
#if defined(RESET_TOGGLES_LIBUSB_COMPAT)
/* Update the configuration descriptor with the current endpoint address */
AVRISP_ConfigurationDescriptor.AVRISP_DataInEndpoint.EndpointAddress = AVRISP_CurrDataINEndpointAddress;
#endif
Address = &AVRISP_ConfigurationDescriptor;
Size = sizeof(AVRISP_USB_Descriptor_Configuration_t);
break;
case DTYPE_String:
switch (DescriptorNumber)
{
case AVRISP_STRING_ID_Language:
Address = &AVRISP_LanguageString;
Size = pgm_read_byte(&AVRISP_LanguageString.Header.Size);
break;
case AVRISP_STRING_ID_Manufacturer:
Address = &AVRISP_ManufacturerString;
Size = pgm_read_byte(&AVRISP_ManufacturerString.Header.Size);
break;
case AVRISP_STRING_ID_Product:
Address = &AVRISP_ProductString;
Size = pgm_read_byte(&AVRISP_ProductString.Header.Size);
break;
case AVRISP_STRING_ID_Serial:
Address = &AVRISP_SerialString;
Size = AVRISP_SerialString.Header.Size;
/* Update serial number to have a different serial based on the current endpoint address */
((uint16_t*)&AVRISP_SerialString.UnicodeString)[6] = cpu_to_le16('0' + (AVRISP_DATA_IN_EPADDR & ENDPOINT_EPNUM_MASK));
*DescriptorMemorySpace = MEMSPACE_RAM;
break;
}
break;
}
*DescriptorAddress = Address;
return Size;
}
#if defined(RESET_TOGGLES_LIBUSB_COMPAT) || defined(__DOXYGEN__)
/** Checks the state of the system status register MCUSR and indicates via a flag if
* the current AVRISP driver compatibility mode needs to be reset.
*
* When the \c RESET_TOGGLES_LIBUSB_COMPAT compile time option is enabled, pulling
* the reset line of the AVR low will toggle between Jungo and libUSB compatibility
* modes. Other forms of reset (such as power on or watchdog) will not force a mode
* change.
*/
void CheckExternalReset(void)
{
/* If an external reset occurred, we need to change compatibility mode */
AVRISP_NeedCompatibilitySwitch = (MCUSR == (1 << EXTRF));
MCUSR = 0;
}
/** Updates the device descriptors so that the correct compatibility mode is used
* when the \c RESET_TOGGLES_LIBUSB_COMPAT compile time option is enabled. This
* configures the programmer for either Jungo or libUSB driver compatibility. Each
* time the AVR is reset via pulling the reset line low the compatibility mode will
* be toggled. The current mode is stored in EEPROM and preserved through power
* cycles of the AVR.
*/
void UpdateCurrentCompatibilityMode(void)
{
/* Load the current IN endpoint address stored in EEPROM */
AVRISP_CurrDataINEndpointAddress = eeprom_read_byte(&AVRISP_CurrDataINEndpointAddress_EEPROM);
/* Check if we need to switch compatibility modes */
if (AVRISP_NeedCompatibilitySwitch)
{
/* Toggle between compatibility modes */
AVRISP_CurrDataINEndpointAddress = (AVRISP_CurrDataINEndpointAddress == AVRISP_DATA_IN_EPADDR_LIBUSB) ?
AVRISP_DATA_IN_EPADDR_JUNGO : AVRISP_DATA_IN_EPADDR_LIBUSB;
/* Save the new mode into EEPROM */
eeprom_update_byte(&AVRISP_CurrDataINEndpointAddress_EEPROM, AVRISP_CurrDataINEndpointAddress);
}
LEDs_SetAllLEDs(LEDS_NO_LEDS);
/* Validate IN endpoint address and indicate current mode via LED flashes */
switch (AVRISP_CurrDataINEndpointAddress)
{
default:
/* Default to Jungo compatibility mode if saved EEPROM is invalid */
AVRISP_CurrDataINEndpointAddress = AVRISP_DATA_IN_EPADDR_JUNGO;
case AVRISP_DATA_IN_EPADDR_JUNGO:
/* Two flashes for Jungo compatibility mode */
for (uint8_t i = 0; i < 4; i++)
{
LEDs_ToggleLEDs(LEDS_ALL_LEDS);
Delay_MS(100);
}
break;
case AVRISP_DATA_IN_EPADDR_LIBUSB:
/* Five flashes for libUSB compatibility mode */
for (uint8_t i = 0; i < 10; i++)
{
LEDs_ToggleLEDs(LEDS_ALL_LEDS);
Delay_MS(100);
}
break;
}
Delay_MS(500);
}
#endif

View file

@ -0,0 +1,128 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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>
#include <LUFA/Drivers/Board/LEDs.h>
#include "Config/AppConfig.h"
/* Preprocessor Checks: */
#if defined(LIBUSB_DRIVER_COMPAT) && defined(RESET_TOGGLES_LIBUSB_COMPAT)
#error LIBUSB_DRIVER_COMPAT and RESET_TOGGLES_LIBUSB_COMPAT are mutually exclusive.
#endif
/* Macros: */
/** Endpoint address of the AVRISP data OUT endpoint. */
#define AVRISP_DATA_OUT_EPADDR (ENDPOINT_DIR_OUT | 2)
/** Endpoint address of the AVRISP data IN endpoint, when in Jungo driver compatibility mode. */
#define AVRISP_DATA_IN_EPADDR_JUNGO (ENDPOINT_DIR_IN | 2)
/** Endpoint address of the AVRISP data IN endpoint, when in LibUSB driver compatibility mode. */
#define AVRISP_DATA_IN_EPADDR_LIBUSB (ENDPOINT_DIR_IN | 3)
#if defined(RESET_TOGGLES_LIBUSB_COMPAT)
#define AVRISP_DATA_IN_EPADDR AVRISP_CurrDataINEndpointAddress
#elif defined(LIBUSB_DRIVER_COMPAT)
#define AVRISP_DATA_IN_EPADDR AVRISP_DATA_IN_EPADDR_LIBUSB
#else
/** Endpoint address of the AVRISP data IN endpoint. */
#define AVRISP_DATA_IN_EPADDR AVRISP_DATA_IN_EPADDR_JUNGO
#endif
/** 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;
// Atmel AVRISP-MKII Interface
USB_Descriptor_Interface_t AVRISP_Interface;
USB_Descriptor_Endpoint_t AVRISP_DataInEndpoint;
USB_Descriptor_Endpoint_t AVRISP_DataOutEndpoint;
} AVRISP_USB_Descriptor_Configuration_t;
/** Enum for the device interface descriptor IDs within the device. Each interface descriptor
* should have a unique ID index associated with it, which can be used to refer to the
* interface from other descriptors.
*/
enum InterfaceDescriptors_t
{
INTERFACE_ID_AVRISP = 0, /**< AVRISP interface descriptor ID */
};
/** Enum for the device string descriptor IDs within the device. Each string descriptor should
* have a unique ID index associated with it, which can be used to refer to the string from
* other descriptors.
*/
enum AVRISP_StringDescriptors_t
{
AVRISP_STRING_ID_Language = 0, /**< Supported Languages string descriptor ID (must be zero) */
AVRISP_STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
AVRISP_STRING_ID_Product = 2, /**< Product string ID */
AVRISP_STRING_ID_Serial = 3, /**< Serial number string ID */
};
/* External Variables: */
#if defined(RESET_TOGGLES_LIBUSB_COMPAT)
extern uint8_t AVRISP_CurrDataINEndpointAddress;
#endif
/* Function Prototypes: */
uint16_t AVRISP_GetDescriptor(const uint16_t wValue,
const uint8_t wIndex,
const void** const DescriptorAddress,
uint8_t* const DescriptorMemorySpace)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3) ATTR_NON_NULL_PTR_ARG(4);
#if defined(RESET_TOGGLES_LIBUSB_COMPAT)
void CheckExternalReset(void) ATTR_NAKED ATTR_INIT_SECTION(3);
void UpdateCurrentCompatibilityMode(void);
#endif
#endif

View file

@ -0,0 +1,70 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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
* \brief Application Configuration Header File
*
* This is a header file which is be used to configure some of
* the application's compile time options, as an alternative to
* specifying the compile time constants supplied through a
* makefile or build system.
*
* For information on what each token does, refer to the
* \ref Sec_Options section of the application documentation.
*/
#ifndef _APP_CONFIG_H_
#define _APP_CONFIG_H_
#define AUX_LINE_PORT PORTB
#define AUX_LINE_PIN PINB
#define AUX_LINE_DDR DDRB
#if (BOARD == BOARD_U2S)
#define AUX_LINE_MASK (1 << 0)
#else
#define AUX_LINE_MASK (1 << 4)
#endif
#define ENABLE_ISP_PROTOCOL
#define ENABLE_XPROG_PROTOCOL
#define VTARGET_ADC_CHANNEL 2
#define VTARGET_REF_VOLTS 5
#define VTARGET_SCALE_FACTOR 1
// #define VTARGET_USE_INTERNAL_REF
// #define NO_VTARGET_DETECT
// #define XCK_RESCUE_CLOCK_ENABLE
// #define INVERTED_ISP_MISO
#define LIBUSB_DRIVER_COMPAT
// #define RESET_TOGGLES_LIBUSB_COMPAT
// #define FIRMWARE_VERSION_MINOR 0x11
#endif

View file

@ -0,0 +1,93 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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
* \brief LUFA Library Configuration Header File
*
* This header file is used to configure LUFA's compile time options,
* as an alternative to the compile time constants supplied through
* a makefile.
*
* For information on what each token does, refer to the LUFA
* manual section "Summary of Compile Tokens".
*/
#ifndef _LUFA_CONFIG_H_
#define _LUFA_CONFIG_H_
#if (ARCH == ARCH_AVR8)
/* Non-USB Related Configuration Tokens: */
// #define DISABLE_TERMINAL_CODES
/* USB Class Driver Related Tokens: */
// #define HID_HOST_BOOT_PROTOCOL_ONLY
// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
// #define HID_MAX_COLLECTIONS {Insert Value Here}
// #define HID_MAX_REPORTITEMS {Insert Value Here}
// #define HID_MAX_REPORT_IDS {Insert Value Here}
// #define NO_CLASS_DRIVER_AUTOFLUSH
/* General USB Driver Related Tokens: */
#define ORDERED_EP_CONFIG
#define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
#define USB_DEVICE_ONLY
// #define USB_HOST_ONLY
// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
// #define NO_LIMITED_CONTROLLER_CONNECT
#define NO_SOF_EVENTS
/* USB Device Mode Driver Related Tokens: */
// #define USE_RAM_DESCRIPTORS
// #define USE_FLASH_DESCRIPTORS
// #define USE_EEPROM_DESCRIPTORS
#define NO_INTERNAL_SERIAL
#define FIXED_CONTROL_ENDPOINT_SIZE 16
#define DEVICE_STATE_AS_GPIOR 0
#define FIXED_NUM_CONFIGURATIONS 1
// #define CONTROL_ONLY_DEVICE
// #define INTERRUPT_CONTROL_ENDPOINT
#define NO_DEVICE_REMOTE_WAKEUP
#define NO_DEVICE_SELF_POWER
/* USB Host Mode Driver Related Tokens: */
// #define HOST_STATE_AS_GPIOR {Insert Value Here}
// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
// #define NO_AUTO_VBUS_MANAGEMENT
// #define INVERTED_VBUS_ENABLE_LINE
#else
#error Unsupported architecture for this LUFA configuration file.
#endif
#endif

View file

@ -0,0 +1,531 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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), NULL);
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t ResponseStatus = STATUS_CMD_FAILED;
CurrentAddress = 0;
/* Perform execution delay, initialize SPI bus */
ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS);
ISPTarget_EnableTargetISP();
ISPTarget_ChangeTargetResetLine(true);
ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS);
/* Continuously attempt to synchronize with the target until either the number of attempts specified
* by the host has exceeded, or the the device sends back the expected response values */
while (Enter_ISP_Params.SynchLoops-- && TimeoutTicksRemaining)
{
uint8_t ResponseBytes[4];
for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
{
ISPProtocol_DelayMS(Enter_ISP_Params.ByteDelay);
ResponseBytes[RByte] = ISPTarget_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;
break;
}
else
{
ISPTarget_ChangeTargetResetLine(false);
ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS);
ISPTarget_ChangeTargetResetLine(true);
ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS);
}
}
Endpoint_Write_8(CMD_ENTER_PROGMODE_ISP);
Endpoint_Write_8(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), NULL);
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
/* Perform pre-exit delay, release the target /RESET, disable the SPI bus and perform the post-exit delay */
ISPProtocol_DelayMS(Leave_ISP_Params.PreDelayMS);
ISPTarget_ChangeTargetResetLine(false);
ISPTarget_DisableTargetISP();
ISPProtocol_DelayMS(Leave_ISP_Params.PostDelayMS);
Endpoint_Write_8(CMD_LEAVE_PROGMODE_ISP);
Endpoint_Write_8(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)), NULL);
Write_Memory_Params.BytesToWrite = SwapEndian_16(Write_Memory_Params.BytesToWrite);
if (Write_Memory_Params.BytesToWrite > sizeof(Write_Memory_Params.ProgData))
{
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_8(V2Command);
Endpoint_Write_8(STATUS_CMD_FAILED);
Endpoint_ClearIN();
return;
}
Endpoint_Read_Stream_LE(&Write_Memory_Params.ProgData, Write_Memory_Params.BytesToWrite, NULL);
// The driver will terminate transfers that are a round multiple of the endpoint bank in size with a ZLP, need
// to catch this and discard it before continuing on with packet processing to prevent communication issues
if (((sizeof(uint8_t) + sizeof(Write_Memory_Params) - sizeof(Write_Memory_Params.ProgData)) +
Write_Memory_Params.BytesToWrite) % AVRISP_DATA_EPSIZE == 0)
{
Endpoint_ClearOUT();
Endpoint_WaitUntilReady();
}
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t ProgrammingStatus = STATUS_CMD_OK;
uint8_t PollValue = (V2Command == CMD_PROGRAM_FLASH_ISP) ? Write_Memory_Params.PollValue1 :
Write_Memory_Params.PollValue2;
uint16_t PollAddress = 0;
uint8_t* NextWriteByte = Write_Memory_Params.ProgData;
uint16_t PageStartAddress = (CurrentAddress & 0xFFFF);
for (uint16_t CurrentByte = 0; CurrentByte < Write_Memory_Params.BytesToWrite; CurrentByte++)
{
uint8_t ByteToWrite = *(NextWriteByte++);
uint8_t ProgrammingMode = Write_Memory_Params.ProgrammingMode;
/* Check to see if we need to send a LOAD EXTENDED ADDRESS command to the target */
if (MustLoadExtendedAddress)
{
ISPTarget_LoadExtendedAddress();
MustLoadExtendedAddress = false;
}
ISPTarget_SendByte(Write_Memory_Params.ProgrammingCommands[0]);
ISPTarget_SendByte(CurrentAddress >> 8);
ISPTarget_SendByte(CurrentAddress & 0xFF);
ISPTarget_SendByte(ByteToWrite);
/* AVR FLASH addressing requires us to modify the write command based on if we are writing a high
* or low byte at the current word address */
if (V2Command == CMD_PROGRAM_FLASH_ISP)
Write_Memory_Params.ProgrammingCommands[0] ^= READ_WRITE_HIGH_BYTE_MASK;
/* Check to see if we have a valid polling address */
if (!(PollAddress) && (ByteToWrite != PollValue))
{
if ((CurrentByte & 0x01) && (V2Command == CMD_PROGRAM_FLASH_ISP))
Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK;
else
Write_Memory_Params.ProgrammingCommands[2] &= ~READ_WRITE_HIGH_BYTE_MASK;
PollAddress = (CurrentAddress & 0xFFFF);
}
/* If in word programming mode, commit the byte to the target's memory */
if (!(ProgrammingMode & PROG_MODE_PAGED_WRITES_MASK))
{
/* If the current polling address is invalid, switch to timed delay write completion mode */
if (!(PollAddress) && !(ProgrammingMode & PROG_MODE_WORD_READYBUSY_MASK))
ProgrammingMode = (ProgrammingMode & ~PROG_MODE_WORD_VALUE_MASK) | PROG_MODE_WORD_TIMEDELAY_MASK;
ProgrammingStatus = ISPTarget_WaitForProgComplete(ProgrammingMode, PollAddress, PollValue,
Write_Memory_Params.DelayMS,
Write_Memory_Params.ProgrammingCommands[2]);
/* Abort the programming loop early if the byte/word programming failed */
if (ProgrammingStatus != STATUS_CMD_OK)
break;
/* Must reset the polling address afterwards, so it is not erroneously used for the next byte */
PollAddress = 0;
}
/* EEPROM just increments the address each byte, flash needs to increment on each word and
* also check to ensure that a LOAD EXTENDED ADDRESS command is issued each time the extended
* address boundary has been crossed during FLASH memory programming */
if ((CurrentByte & 0x01) || (V2Command == CMD_PROGRAM_EEPROM_ISP))
{
CurrentAddress++;
if ((V2Command == CMD_PROGRAM_FLASH_ISP) && !(CurrentAddress & 0xFFFF))
MustLoadExtendedAddress = true;
}
}
/* 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)
{
ISPTarget_SendByte(Write_Memory_Params.ProgrammingCommands[1]);
ISPTarget_SendByte(PageStartAddress >> 8);
ISPTarget_SendByte(PageStartAddress & 0xFF);
ISPTarget_SendByte(0x00);
/* Check if polling is enabled and possible, if not switch to timed delay mode */
if ((Write_Memory_Params.ProgrammingMode & PROG_MODE_PAGED_VALUE_MASK) && !(PollAddress))
{
Write_Memory_Params.ProgrammingMode = (Write_Memory_Params.ProgrammingMode & ~PROG_MODE_PAGED_VALUE_MASK) |
PROG_MODE_PAGED_TIMEDELAY_MASK;
}
ProgrammingStatus = ISPTarget_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue,
Write_Memory_Params.DelayMS,
Write_Memory_Params.ProgrammingCommands[2]);
/* Check to see if the FLASH address has crossed the extended address boundary */
if ((V2Command == CMD_PROGRAM_FLASH_ISP) && !(CurrentAddress & 0xFFFF))
MustLoadExtendedAddress = true;
}
Endpoint_Write_8(V2Command);
Endpoint_Write_8(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), NULL);
Read_Memory_Params.BytesToRead = SwapEndian_16(Read_Memory_Params.BytesToRead);
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_8(V2Command);
Endpoint_Write_8(STATUS_CMD_OK);
/* Read each byte from the device and write them to the packet for the host */
for (uint16_t CurrentByte = 0; CurrentByte < Read_Memory_Params.BytesToRead; CurrentByte++)
{
/* Check to see if we need to send a LOAD EXTENDED ADDRESS command to the target */
if (MustLoadExtendedAddress)
{
ISPTarget_LoadExtendedAddress();
MustLoadExtendedAddress = false;
}
/* Read the next byte from the desired memory space in the device */
ISPTarget_SendByte(Read_Memory_Params.ReadMemoryCommand);
ISPTarget_SendByte(CurrentAddress >> 8);
ISPTarget_SendByte(CurrentAddress & 0xFF);
Endpoint_Write_8(ISPTarget_ReceiveByte());
/* Check if the endpoint bank is currently full, if so send the packet */
if (!(Endpoint_IsReadWriteAllowed()))
{
Endpoint_ClearIN();
Endpoint_WaitUntilReady();
}
/* AVR FLASH addressing requires us to modify the read command based on if we are reading a high
* or low byte at the current word address */
if (V2Command == CMD_READ_FLASH_ISP)
Read_Memory_Params.ReadMemoryCommand ^= READ_WRITE_HIGH_BYTE_MASK;
/* EEPROM just increments the address each byte, flash needs to increment on each word and
* also check to ensure that a LOAD EXTENDED ADDRESS command is issued each time the extended
* address boundary has been crossed */
if ((CurrentByte & 0x01) || (V2Command == CMD_READ_EEPROM_ISP))
{
CurrentAddress++;
if ((V2Command != CMD_READ_EEPROM_ISP) && !(CurrentAddress & 0xFFFF))
MustLoadExtendedAddress = true;
}
}
Endpoint_Write_8(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), NULL);
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t ResponseStatus = STATUS_CMD_OK;
/* Send the chip erase commands as given by the host to the device */
for (uint8_t SByte = 0; SByte < sizeof(Erase_Chip_Params.EraseCommandBytes); SByte++)
ISPTarget_SendByte(Erase_Chip_Params.EraseCommandBytes[SByte]);
/* Use appropriate command completion check as given by the host (delay or busy polling) */
if (!(Erase_Chip_Params.PollMethod))
ISPProtocol_DelayMS(Erase_Chip_Params.EraseDelayMS);
else
ResponseStatus = ISPTarget_WaitWhileTargetBusy();
Endpoint_Write_8(CMD_CHIP_ERASE_ISP);
Endpoint_Write_8(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), NULL);
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t ResponseBytes[4];
/* Send the Fuse or Lock byte read commands as given by the host to the device, store response */
for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
ResponseBytes[RByte] = ISPTarget_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]);
Endpoint_Write_8(V2Command);
Endpoint_Write_8(STATUS_CMD_OK);
Endpoint_Write_8(ResponseBytes[Read_FuseLockSigOSCCAL_Params.RetByte - 1]);
Endpoint_Write_8(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), NULL);
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
/* Send the Fuse or Lock byte program commands as given by the host to the device */
for (uint8_t SByte = 0; SByte < sizeof(Write_FuseLockSig_Params.WriteCommandBytes); SByte++)
ISPTarget_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]);
Endpoint_Write_8(V2Command);
Endpoint_Write_8(STATUS_CMD_OK);
Endpoint_Write_8(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)), NULL);
Endpoint_Read_Stream_LE(&SPI_Multi_Params.TxData, SPI_Multi_Params.TxBytes, NULL);
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_8(CMD_SPI_MULTI);
Endpoint_Write_8(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)
ISPTarget_SendByte(SPI_Multi_Params.TxData[CurrTxPos]);
else
ISPTarget_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_8(ISPTarget_TransferByte(SPI_Multi_Params.TxData[CurrTxPos++]));
else
Endpoint_Write_8(ISPTarget_ReceiveByte());
/* Check to see if we have filled the endpoint bank and need to send the packet */
if (!(Endpoint_IsReadWriteAllowed()))
{
Endpoint_ClearIN();
Endpoint_WaitUntilReady();
}
CurrRxPos++;
}
Endpoint_Write_8(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();
}
}
/** Blocking delay for a given number of milliseconds. This provides a simple wrapper around
* the avr-libc provided delay function, so that the delay function can be called with a
* constant value (to prevent run-time floating point operations being required).
*
* \param[in] DelayMS Number of milliseconds to delay for
*/
void ISPProtocol_DelayMS(uint8_t DelayMS)
{
while (DelayMS-- && TimeoutTicksRemaining)
Delay_MS(1);
}
#endif

View file

@ -0,0 +1,81 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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"
#include "Config/AppConfig.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)
/* 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);
void ISPProtocol_DelayMS(uint8_t DelayMS);
#endif

View file

@ -0,0 +1,370 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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__)
/** List of hardware SPI prescaler masks for possible AVRStudio ISP programming speeds.
*
* \hideinitializer
*/
static const uint8_t SPIMaskFromSCKDuration[] PROGMEM =
{
#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
};
/** Lookup table to convert the slower ISP speeds into a compare value for the software SPI driver.
*
* \hideinitializer
*/
static const uint16_t TimerCompareFromSCKDuration[] PROGMEM =
{
TIMER_COMP(96386), TIMER_COMP(89888), TIMER_COMP(84211), TIMER_COMP(79208), TIMER_COMP(74767),
TIMER_COMP(70797), TIMER_COMP(67227), TIMER_COMP(64000), TIMER_COMP(61069), TIMER_COMP(58395),
TIMER_COMP(55945), TIMER_COMP(51613), TIMER_COMP(49690), TIMER_COMP(47905), TIMER_COMP(46243),
TIMER_COMP(43244), TIMER_COMP(41885), TIMER_COMP(39409), TIMER_COMP(38278), TIMER_COMP(36200),
TIMER_COMP(34335), TIMER_COMP(32654), TIMER_COMP(31129), TIMER_COMP(29740), TIMER_COMP(28470),
TIMER_COMP(27304), TIMER_COMP(25724), TIMER_COMP(24768), TIMER_COMP(23461), TIMER_COMP(22285),
TIMER_COMP(21221), TIMER_COMP(20254), TIMER_COMP(19371), TIMER_COMP(18562), TIMER_COMP(17583),
TIMER_COMP(16914), TIMER_COMP(16097), TIMER_COMP(15356), TIMER_COMP(14520), TIMER_COMP(13914),
TIMER_COMP(13224), TIMER_COMP(12599), TIMER_COMP(12031), TIMER_COMP(11511), TIMER_COMP(10944),
TIMER_COMP(10431), TIMER_COMP(9963), TIMER_COMP(9468), TIMER_COMP(9081), TIMER_COMP(8612),
TIMER_COMP(8239), TIMER_COMP(7851), TIMER_COMP(7498), TIMER_COMP(7137), TIMER_COMP(6809),
TIMER_COMP(6478), TIMER_COMP(6178), TIMER_COMP(5879), TIMER_COMP(5607), TIMER_COMP(5359),
TIMER_COMP(5093), TIMER_COMP(4870), TIMER_COMP(4633), TIMER_COMP(4418), TIMER_COMP(4209),
TIMER_COMP(4019), TIMER_COMP(3823), TIMER_COMP(3645), TIMER_COMP(3474), TIMER_COMP(3310),
TIMER_COMP(3161), TIMER_COMP(3011), TIMER_COMP(2869), TIMER_COMP(2734), TIMER_COMP(2611),
TIMER_COMP(2484), TIMER_COMP(2369), TIMER_COMP(2257), TIMER_COMP(2152), TIMER_COMP(2052),
TIMER_COMP(1956), TIMER_COMP(1866), TIMER_COMP(1779), TIMER_COMP(1695), TIMER_COMP(1615),
TIMER_COMP(1539), TIMER_COMP(1468), TIMER_COMP(1398), TIMER_COMP(1333), TIMER_COMP(1271),
TIMER_COMP(1212), TIMER_COMP(1155), TIMER_COMP(1101), TIMER_COMP(1049), TIMER_COMP(1000),
TIMER_COMP(953), TIMER_COMP(909), TIMER_COMP(866), TIMER_COMP(826), TIMER_COMP(787),
TIMER_COMP(750), TIMER_COMP(715), TIMER_COMP(682), TIMER_COMP(650), TIMER_COMP(619),
TIMER_COMP(590), TIMER_COMP(563), TIMER_COMP(536), TIMER_COMP(511), TIMER_COMP(487),
TIMER_COMP(465), TIMER_COMP(443), TIMER_COMP(422), TIMER_COMP(402), TIMER_COMP(384),
TIMER_COMP(366), TIMER_COMP(349), TIMER_COMP(332), TIMER_COMP(317), TIMER_COMP(302),
TIMER_COMP(288), TIMER_COMP(274), TIMER_COMP(261), TIMER_COMP(249), TIMER_COMP(238),
TIMER_COMP(226), TIMER_COMP(216), TIMER_COMP(206), TIMER_COMP(196), TIMER_COMP(187),
TIMER_COMP(178), TIMER_COMP(170), TIMER_COMP(162), TIMER_COMP(154), TIMER_COMP(147),
TIMER_COMP(140), TIMER_COMP(134), TIMER_COMP(128), TIMER_COMP(122), TIMER_COMP(116),
TIMER_COMP(111), TIMER_COMP(105), TIMER_COMP(100), TIMER_COMP(95.4), TIMER_COMP(90.9),
TIMER_COMP(86.6), TIMER_COMP(82.6), TIMER_COMP(78.7), TIMER_COMP(75.0), TIMER_COMP(71.5),
TIMER_COMP(68.2), TIMER_COMP(65.0), TIMER_COMP(61.9), TIMER_COMP(59.0), TIMER_COMP(56.3),
TIMER_COMP(53.6), TIMER_COMP(51.1)
};
/** Currently selected SPI driver, either hardware (for fast ISP speeds) or software (for slower ISP speeds). */
bool HardwareSPIMode = true;
/** Software SPI data register for sending and receiving */
static volatile uint8_t SoftSPI_Data;
/** Number of bits left to transfer in the software SPI driver */
static volatile uint8_t SoftSPI_BitsRemaining;
/** ISR to handle software SPI transmission and reception */
ISR(TIMER1_COMPA_vect, ISR_BLOCK)
{
/* Check if rising edge (output next bit) or falling edge (read in next bit) */
if (!(PINB & (1 << 1)))
{
if (SoftSPI_Data & (1 << 7))
PORTB |= (1 << 2);
else
PORTB &= ~(1 << 2);
}
else
{
SoftSPI_Data <<= 1;
if (!(--SoftSPI_BitsRemaining))
{
TCCR1B = 0;
TIFR1 = (1 << OCF1A);
}
if (PINB & (1 << 3))
SoftSPI_Data |= (1 << 0);
}
/* Fast toggle of PORTB.1 via the PIN register (see datasheet) */
PINB |= (1 << 1);
}
/** Initializes the appropriate SPI driver (hardware or software, depending on the selected ISP speed) ready for
* communication with the attached target.
*/
void ISPTarget_EnableTargetISP(void)
{
uint8_t SCKDuration = V2Params_GetParameterValue(PARAM_SCK_DURATION);
if (SCKDuration < sizeof(SPIMaskFromSCKDuration))
{
HardwareSPIMode = true;
SPI_Init(pgm_read_byte(&SPIMaskFromSCKDuration[SCKDuration]) | SPI_ORDER_MSB_FIRST |
SPI_SCK_LEAD_RISING | SPI_SAMPLE_LEADING | SPI_MODE_MASTER);
}
else
{
HardwareSPIMode = false;
DDRB |= ((1 << 1) | (1 << 2));
PORTB |= ((1 << 0) | (1 << 3));
ISPTarget_ConfigureSoftwareSPI(SCKDuration);
}
}
/** Shuts down the current selected SPI driver (hardware or software, depending on the selected ISP speed) so that no
* further communications can occur until the driver is re-initialized.
*/
void ISPTarget_DisableTargetISP(void)
{
if (HardwareSPIMode)
{
SPI_Disable();
}
else
{
DDRB &= ~((1 << 1) | (1 << 2));
PORTB &= ~((1 << 0) | (1 << 3));
/* Must re-enable rescue clock once software ISP has exited, as the timer for the rescue clock is
* re-purposed for software SPI */
ISPTarget_ConfigureRescueClock();
}
}
/** Configures the AVR to produce a 4MHz rescue clock out of the OCR1A pin of the AVR, so
* that it can be fed into the XTAL1 pin of an AVR whose fuses have been mis-configured for
* an external clock rather than a crystal. When used, the ISP speed must be 125KHz for this
* functionality to work correctly.
*/
void ISPTarget_ConfigureRescueClock(void)
{
#if defined(XCK_RESCUE_CLOCK_ENABLE)
/* Configure XCK as an output for the specified AVR model */
DDRD |= (1 << 5);
/* Start USART to generate a 4MHz clock on the XCK pin */
UBRR1 = ((F_CPU / 2 / ISP_RESCUE_CLOCK_SPEED) - 1);
UCSR1B = (1 << TXEN1);
UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);
#else
/* Configure OCR1A as an output for the specified AVR model */
#if defined(USB_SERIES_2_AVR)
DDRC |= (1 << 6);
#else
DDRB |= (1 << 5);
#endif
/* Start Timer 1 to generate a 4MHz clock on the OCR1A pin */
TIMSK1 = 0;
TCNT1 = 0;
OCR1A = ((F_CPU / 2 / ISP_RESCUE_CLOCK_SPEED) - 1);
TCCR1A = (1 << COM1A0);
TCCR1B = ((1 << WGM12) | (1 << CS10));
#endif
}
/** Configures the AVR's timer ready to produce software SPI for the slower ISP speeds that
* cannot be obtained when using the AVR's hardware SPI module.
*
* \param[in] SCKDuration Duration of the desired software ISP SCK clock
*/
void ISPTarget_ConfigureSoftwareSPI(const uint8_t SCKDuration)
{
/* Configure Timer 1 for software SPI using the specified SCK duration */
TIMSK1 = (1 << OCIE1A);
TCNT1 = 0;
OCR1A = pgm_read_word(&TimerCompareFromSCKDuration[SCKDuration - sizeof(SPIMaskFromSCKDuration)]);
TCCR1A = 0;
TCCR1B = 0;
}
/** Sends and receives a single byte of data to and from the attached target via software SPI.
*
* \param[in] Byte Byte of data to send to the attached target
*
* \return Received byte of data from the attached target
*/
uint8_t ISPTarget_TransferSoftSPIByte(const uint8_t Byte)
{
SoftSPI_Data = Byte;
SoftSPI_BitsRemaining = 8;
/* Set initial MOSI pin state according to the byte to be transferred */
if (SoftSPI_Data & (1 << 7))
PORTB |= (1 << 2);
else
PORTB &= ~(1 << 2);
TCNT1 = 0;
TCCR1B = ((1 << WGM12) | (1 << CS11));
while (SoftSPI_BitsRemaining && TimeoutTicksRemaining);
TCCR1B = 0;
return SoftSPI_Data;
}
/** 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, \c false otherwise
*/
void ISPTarget_ChangeTargetResetLine(const bool ResetTarget)
{
if (ResetTarget)
{
AUX_LINE_DDR |= AUX_LINE_MASK;
if (!(V2Params_GetParameterValue(PARAM_RESET_POLARITY)))
AUX_LINE_PORT |= AUX_LINE_MASK;
else
AUX_LINE_PORT &= ~AUX_LINE_MASK;
}
else
{
AUX_LINE_DDR &= ~AUX_LINE_MASK;
AUX_LINE_PORT &= ~AUX_LINE_MASK;
}
}
/** Waits until the target has completed the last operation, by continuously polling the device's
* BUSY flag until it is cleared, or until the command 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
{
ISPTarget_SendByte(0xF0);
ISPTarget_SendByte(0x00);
ISPTarget_SendByte(0x00);
}
while ((ISPTarget_ReceiveByte() & 0x01) && TimeoutTicksRemaining);
return (TimeoutTicksRemaining > 0) ? STATUS_CMD_OK : STATUS_RDY_BSY_TOUT;
}
/** 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)
{
ISPTarget_SendByte(LOAD_EXTENDED_ADDRESS_CMD);
ISPTarget_SendByte(0x00);
ISPTarget_SendByte(CurrentAddress >> 16);
ISPTarget_SendByte(0x00);
}
/** 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 \c 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
{
ISPTarget_SendByte(ReadMemCommand);
ISPTarget_SendByte(PollAddress >> 8);
ISPTarget_SendByte(PollAddress & 0xFF);
}
while ((ISPTarget_TransferByte(0x00) == PollValue) && TimeoutTicksRemaining);
if (!(TimeoutTicksRemaining))
ProgrammingStatus = STATUS_CMD_TOUT;
break;
case PROG_MODE_WORD_READYBUSY_MASK:
case PROG_MODE_PAGED_READYBUSY_MASK:
ProgrammingStatus = ISPTarget_WaitWhileTargetBusy();
break;
}
/* Program complete - reset timeout */
TimeoutTicksRemaining = COMMAND_TIMEOUT_TICKS;
return ProgrammingStatus;
}
#endif

View file

@ -0,0 +1,147 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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 <avr/pgmspace.h>
#include <util/delay.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/Peripheral/SPI.h>
#include "../V2Protocol.h"
#include "ISPProtocol.h"
#include "Config/AppConfig.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: */
/** Low level device command to issue an extended FLASH address, for devices with over 128KB of FLASH. */
#define LOAD_EXTENDED_ADDRESS_CMD 0x4D
/** Macro to convert an ISP frequency to a number of timer clock cycles for the software SPI driver. */
#define TIMER_COMP(freq) (((F_CPU / 8) / 2 / freq) - 1)
/** ISP rescue clock speed in Hz, for clocking targets with incorrectly set fuses. */
#define ISP_RESCUE_CLOCK_SPEED 4000000
/* External Variables: */
extern bool HardwareSPIMode;
/* Function Prototypes: */
void ISPTarget_EnableTargetISP(void);
void ISPTarget_DisableTargetISP(void);
void ISPTarget_ConfigureRescueClock(void);
void ISPTarget_ConfigureSoftwareSPI(const uint8_t SCKDuration);
uint8_t ISPTarget_TransferSoftSPIByte(const uint8_t Byte);
void ISPTarget_ChangeTargetResetLine(const bool ResetTarget);
uint8_t ISPTarget_WaitWhileTargetBusy(void);
void ISPTarget_LoadExtendedAddress(void);
uint8_t ISPTarget_WaitForProgComplete(const uint8_t ProgrammingMode,
const uint16_t PollAddress,
const uint8_t PollValue,
const uint8_t DelayMS,
const uint8_t ReadMemCommand);
/* Inline Functions: */
/** Sends a byte of ISP data to the attached target, using the appropriate SPI hardware or
* software routines depending on the selected ISP speed.
*
* \param[in] Byte Byte of data to send to the attached target
*/
static inline void ISPTarget_SendByte(const uint8_t Byte)
{
if (HardwareSPIMode)
SPI_SendByte(Byte);
else
ISPTarget_TransferSoftSPIByte(Byte);
}
/** Receives a byte of ISP data from the attached target, using the appropriate
* SPI hardware or software routines depending on the selected ISP speed.
*
* \return Received byte of data from the attached target
*/
static inline uint8_t ISPTarget_ReceiveByte(void)
{
uint8_t ReceivedByte;
if (HardwareSPIMode)
ReceivedByte = SPI_ReceiveByte();
else
ReceivedByte = ISPTarget_TransferSoftSPIByte(0x00);
#if defined(INVERTED_ISP_MISO)
return ~ReceivedByte;
#else
return ReceivedByte;
#endif
}
/** Sends and receives a byte of ISP data to and from the attached target, using the
* appropriate SPI hardware or software routines depending on the selected ISP speed.
*
* \param[in] Byte Byte of data to send to the attached target
*
* \return Received byte of data from the attached target
*/
static inline uint8_t ISPTarget_TransferByte(const uint8_t Byte)
{
uint8_t ReceivedByte;
if (HardwareSPIMode)
ReceivedByte = SPI_TransferByte(Byte);
else
ReceivedByte = ISPTarget_TransferSoftSPIByte(Byte);
#if defined(INVERTED_ISP_MISO)
return ~ReceivedByte;
#else
return ReceivedByte;
#endif
}
#endif

View file

@ -0,0 +1,267 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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 extended FLASH address */
bool MustLoadExtendedAddress;
/** ISR to manage timeouts whilst processing a V2Protocol command */
ISR(TIMER0_COMPA_vect, ISR_NOBLOCK)
{
if (TimeoutTicksRemaining)
TimeoutTicksRemaining--;
else
TCCR0B = 0;
}
/** Initializes the hardware and software associated with the V2 protocol command handling. */
void V2Protocol_Init(void)
{
#if defined(ADC) && !defined(NO_VTARGET_DETECT)
/* 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_REF_MASK | ADC_RIGHT_ADJUSTED | VTARGET_ADC_CHANNEL_MASK);
#endif
/* Timeout timer initialization (~10ms period) */
OCR0A = (((F_CPU / 1024) / 100) - 1);
TCCR0A = (1 << WGM01);
TIMSK0 = (1 << OCIE0A);
V2Params_LoadNonVolatileParamValues();
#if defined(ENABLE_ISP_PROTOCOL)
ISPTarget_ConfigureRescueClock();
#endif
}
/** 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_8();
/* Reset timeout counter duration and start the timer */
TimeoutTicksRemaining = COMMAND_TIMEOUT_TICKS;
TCCR0B = ((1 << CS02) | (1 << CS00));
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;
}
/* Disable the timeout management timer */
TCCR0B = 0;
Endpoint_WaitUntilReady();
Endpoint_SelectEndpoint(AVRISP_DATA_OUT_EPADDR);
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_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_8(V2Command);
Endpoint_Write_8(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_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_8(CMD_SIGN_ON);
Endpoint_Write_8(STATUS_CMD_OK);
Endpoint_Write_8(sizeof(PROGRAMMER_ID) - 1);
Endpoint_Write_Stream_LE(PROGRAMMER_ID, (sizeof(PROGRAMMER_ID) - 1), NULL);
Endpoint_ClearIN();
}
/** Handler for the CMD_RESET_PROTECTION command, implemented as a dummy ACK function as
* no target short-circuit protection is currently implemented.
*/
static void V2Protocol_ResetProtection(void)
{
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_8(CMD_RESET_PROTECTION);
Endpoint_Write_8(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_8();
uint8_t ParamValue;
if (V2Command == CMD_SET_PARAMETER)
ParamValue = Endpoint_Read_8();
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_8(V2Command);
uint8_t ParamPrivs = V2Params_GetParameterPrivileges(ParamID);
if ((V2Command == CMD_SET_PARAMETER) && (ParamPrivs & PARAM_PRIV_WRITE))
{
Endpoint_Write_8(STATUS_CMD_OK);
V2Params_SetParameterValue(ParamID, ParamValue);
}
else if ((V2Command == CMD_GET_PARAMETER) && (ParamPrivs & PARAM_PRIV_READ))
{
Endpoint_Write_8(STATUS_CMD_OK);
Endpoint_Write_8(V2Params_GetParameterValue(ParamID));
}
else
{
Endpoint_Write_8(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), NULL);
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
if (CurrentAddress & (1UL << 31))
MustLoadExtendedAddress = true;
Endpoint_Write_8(CMD_LOAD_ADDRESS);
Endpoint_Write_8(STATUS_CMD_OK);
Endpoint_ClearIN();
}

View file

@ -0,0 +1,105 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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 <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <LUFA/Drivers/USB/USB.h>
#include "../AVRISPDescriptors.h"
#include "V2ProtocolConstants.h"
#include "V2ProtocolParams.h"
#include "ISP/ISPProtocol.h"
#include "XPROG/XPROGProtocol.h"
#include "Config/AppConfig.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
#if defined(USB_SERIES_4_AVR) && ((VTARGET_ADC_CHANNEL == 2) || (VTARGET_ADC_CHANNEL == 3)) && !defined(NO_VTARGET_DETECT)
#error The U4 AVR chips do not contain ADC channels 2 or 3. Please change VTARGET_ADC_CHANNEL or define NO_VTARGET_DETECT in the makefile.
#endif
#if defined(VTARGET_USE_INTERNAL_REF)
#undef VTARGET_REF_VOLTS
#define VTARGET_REF_VOLTS 2.56
#define VTARGET_REF_MASK ADC_REFERENCE_INT2560MV
#else
#define VTARGET_REF_MASK ADC_REFERENCE_AVCC
#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 (in 10ms ticks). */
#define COMMAND_TIMEOUT_TICKS 100
/** Command timeout ticks remaining counter, GPIOR for speed. */
#define TimeoutTicksRemaining GPIOR1
/** MUX mask for the VTARGET ADC channel number. */
#define VTARGET_ADC_CHANNEL_MASK ADC_GET_CHANNEL_MASK(VTARGET_ADC_CHANNEL)
/* External Variables: */
extern uint32_t CurrentAddress;
extern bool MustLoadExtendedAddress;
/* Function Prototypes: */
void V2Protocol_Init(void);
void V2Protocol_ProcessCommand(void);
#if defined(INCLUDE_FROM_V2PROTOCOL_C)
static void V2Protocol_UnknownCommand(const uint8_t V2Command);
static void V2Protocol_SignOn(void);
static void V2Protocol_GetSetParam(const uint8_t V2Command);
static void V2Protocol_ResetProtection(void);
static void V2Protocol_LoadAddress(void);
#endif
#endif

View file

@ -0,0 +1,90 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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_CMD_ILLEGAL_PARAM 0xCA
#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,207 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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 */
static uint8_t EEMEM EEPROM_Reset_Polarity = 0x01;
/* Non-Volatile Parameter Values for EEPROM storage */
static uint8_t EEMEM EEPROM_SCK_Duration = 0x06;
/* Volatile Parameter Values for RAM storage */
static ParameterItem_t ParameterTable[] =
{
{ .ParamID = PARAM_BUILD_NUMBER_LOW,
.ParamPrivileges = PARAM_PRIV_READ,
.ParamValue = 0 },
{ .ParamID = PARAM_BUILD_NUMBER_HIGH,
.ParamPrivileges = PARAM_PRIV_READ,
.ParamValue = 0 },
{ .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 = FIRMWARE_VERSION_MINOR },
{ .ParamID = PARAM_VTARGET,
.ParamPrivileges = PARAM_PRIV_READ,
.ParamValue = (uint8_t)(3.3 * 10) },
{ .ParamID = PARAM_SCK_DURATION,
.ParamPrivileges = PARAM_PRIV_READ | PARAM_PRIV_WRITE,
.ParamValue = 6 },
{ .ParamID = PARAM_RESET_POLARITY,
.ParamPrivileges = PARAM_PRIV_READ | PARAM_PRIV_WRITE,
.ParamValue = 0x01 },
{ .ParamID = PARAM_STATUS_TGT_CONN,
.ParamPrivileges = PARAM_PRIV_READ,
.ParamValue = STATUS_ISP_READY },
{ .ParamID = PARAM_DISCHARGEDELAY,
.ParamPrivileges = PARAM_PRIV_READ | PARAM_PRIV_WRITE,
.ParamValue = 0x00 },
};
/** Loads saved non-volatile parameter values from the EEPROM into the parameter table, as needed. */
void V2Params_LoadNonVolatileParamValues(void)
{
/* Read parameter values that are stored in non-volatile EEPROM */
uint8_t ResetPolarity = eeprom_read_byte(&EEPROM_Reset_Polarity);
uint8_t SCKDuration = eeprom_read_byte(&EEPROM_SCK_Duration);
/* Update current parameter table if the EEPROM contents was not blank */
if (ResetPolarity != 0xFF)
V2Params_GetParamFromTable(PARAM_RESET_POLARITY)->ParamValue = ResetPolarity;
/* Update current parameter table if the EEPROM contents was not blank */
if (SCKDuration != 0xFF)
V2Params_GetParamFromTable(PARAM_SCK_DURATION)->ParamValue = SCKDuration;
}
/** 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) && !defined(NO_VTARGET_DETECT))
/* Update VTARGET parameter with the latest ADC conversion of VTARGET on supported AVR models */
V2Params_GetParamFromTable(PARAM_VTARGET)->ParamValue = (((uint16_t)(VTARGET_REF_VOLTS * 10 * VTARGET_SCALE_FACTOR) * 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 \c PARAM_PRIV_* masks
*/
uint8_t V2Params_GetParameterPrivileges(const uint8_t ParamID)
{
ParameterItem_t* const ParamInfo = V2Params_GetParamFromTable(ParamID);
if (ParamInfo == NULL)
return 0;
return ParamInfo->ParamPrivileges;
}
/** Retrieves the current value for a given parameter in the parameter table.
*
* \note This function does not first check for read privileges - if the value is being sent to the host via a
* GET PARAM command, \ref V2Params_GetParameterPrivileges() should be called first to ensure that the
* parameter is host-readable.
*
* \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* const ParamInfo = V2Params_GetParamFromTable(ParamID);
if (ParamInfo == NULL)
return 0;
return ParamInfo->ParamValue;
}
/** Sets the value for a given parameter in the parameter table.
*
* \note This function does not first check for write privileges - if the value is being sourced from the host
* via a SET PARAM command, \ref V2Params_GetParameterPrivileges() should be called first to ensure that the
* parameter is host-writable.
*
* \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* const 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_update_byte(&EEPROM_Reset_Polarity, Value);
/* The target SCK line period is a non-volatile parameter, save to EEPROM when changed */
if (ParamID == PARAM_SCK_DURATION)
eeprom_update_byte(&EEPROM_SCK_Duration, 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* const 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 < TABLE_PARAM_COUNT; TableIndex++)
{
if (ParamID == CurrTableItem->ParamID)
return CurrTableItem;
CurrTableItem++;
}
return NULL;
}

View file

@ -0,0 +1,91 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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>
#if defined(ADC)
#include <LUFA/Drivers/Peripheral/ADC.h>
#endif
#include "V2Protocol.h"
#include "V2ProtocolConstants.h"
#include "ISP/ISPTarget.h"
#include "Config/AppConfig.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)
/** Total number of parameters in the parameter table */
#define TABLE_PARAM_COUNT (sizeof(ParameterTable) / sizeof(ParameterTable[0]))
#if (!defined(FIRMWARE_VERSION_MINOR) || defined(__DOXYGEN__))
/** Minor firmware version, reported to the host on request; must match the version
* the host is expecting, or it (may) reject further communications with the programmer. */
#define FIRMWARE_VERSION_MINOR 0x17
#endif
/* 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* const V2Params_GetParamFromTable(const uint8_t ParamID);
#endif
#endif

View file

@ -0,0 +1,274 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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__)
/** Sends the given pointer address to the target's TPI pointer register */
static void TINYNVM_SendPointerAddress(const uint16_t AbsoluteAddress)
{
/* Send the given 16-bit address to the target, LSB first */
XPROGTarget_SendByte(TPI_CMD_SSTPR | 0);
XPROGTarget_SendByte(AbsoluteAddress & 0xFF);
XPROGTarget_SendByte(TPI_CMD_SSTPR | 1);
XPROGTarget_SendByte(AbsoluteAddress >> 8);
}
/** Sends a SIN command to the target with the specified I/O address, ready for the data byte to be written.
*
* \param[in] Address 6-bit I/O address to write to in the target's I/O memory space
*/
static void TINYNVM_SendReadNVMRegister(const uint8_t Address)
{
/* The TPI command for reading from the I/O space uses strange addressing, where the I/O address's upper
* two bits of the 6-bit address are shifted left once - use function to reduce code size */
XPROGTarget_SendByte(TPI_CMD_SIN(Address));
}
/** Sends a SOUT command to the target with the specified I/O address, ready for the data byte to be read.
*
* \param[in] Address 6-bit I/O address to read from in the target's I/O memory space
*/
static void TINYNVM_SendWriteNVMRegister(const uint8_t Address)
{
/* The TPI command for reading from the I/O space uses strange addressing, where the I/O address's upper
* two bits of the 6-bit address are shifted left once - use function to reduce code size */
XPROGTarget_SendByte(TPI_CMD_SOUT(Address));
}
/** Busy-waits while the NVM controller is busy performing a NVM operation, such as a FLASH page read.
*
* \return Boolean \c true if the NVM controller became ready within the timeout period, \c false otherwise
*/
bool TINYNVM_WaitWhileNVMBusBusy(void)
{
/* Poll the STATUS register to check to see if NVM access has been enabled */
for (;;)
{
/* Send the SLDCS command to read the TPI STATUS register to see the NVM bus is active */
XPROGTarget_SendByte(TPI_CMD_SLDCS(TPI_REG_STATUS));
uint8_t StatusRegister = XPROGTarget_ReceiveByte();
/* We might have timed out waiting for the status register read response, check here */
if (!(TimeoutTicksRemaining))
return false;
/* Check the status register read response to see if the NVM bus is enabled */
if (StatusRegister & TPI_STATUS_NVM)
return true;
}
}
/** Waits while the target's NVM controller is busy performing an operation, exiting if the
* timeout period expires.
*
* \return Boolean \c true if the NVM controller became ready within the timeout period, \c false otherwise
*/
bool TINYNVM_WaitWhileNVMControllerBusy(void)
{
/* Poll the STATUS register to check to see if NVM access has been enabled */
for (;;)
{
/* Send the SIN command to read the TPI STATUS register to see the NVM bus is busy */
TINYNVM_SendReadNVMRegister(XPROG_Param_NVMCSRRegAddr);
uint8_t StatusRegister = XPROGTarget_ReceiveByte();
/* We might have timed out waiting for the status register read response, check here */
if (!(TimeoutTicksRemaining))
return false;
/* Check to see if the BUSY flag is still set */
if (!(StatusRegister & (1 << 7)))
return true;
}
}
/** Enables the physical TPI interface on the target and enables access to the internal NVM controller.
*
* \return Boolean \c true if the TPI interface was enabled successfully, \c false otherwise
*/
bool TINYNVM_EnableTPI(void)
{
/* Enable TPI programming mode with the attached target */
XPROGTarget_EnableTargetTPI();
/* Lower direction change guard time to 32 USART bits */
XPROGTarget_SendByte(TPI_CMD_SSTCS(TPI_REG_CTRL));
XPROGTarget_SendByte(0x02);
/* 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 */
return TINYNVM_WaitWhileNVMBusBusy();
}
/** Removes access to the target's NVM controller and physically disables the target's physical TPI interface. */
void TINYNVM_DisableTPI(void)
{
TINYNVM_WaitWhileNVMBusBusy();
do
{
/* Clear the NVMEN bit in the TPI STATUS register to disable TPI mode */
XPROGTarget_SendByte(TPI_CMD_SSTCS(TPI_REG_STATUS));
XPROGTarget_SendByte(0x00);
/* Read back the STATUS register, check to see if it took effect */
XPROGTarget_SendByte(TPI_CMD_SLDCS(TPI_REG_STATUS));
} while (XPROGTarget_ReceiveByte() != 0x00);
XPROGTarget_DisableTargetTPI();
}
/** 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 Length of the data to read from the device
*
* \return Boolean \c true if the command sequence complete successfully
*/
bool TINYNVM_ReadMemory(const uint16_t ReadAddress,
uint8_t* ReadBuffer,
uint16_t ReadSize)
{
/* Wait until the NVM controller is no longer busy */
if (!(TINYNVM_WaitWhileNVMControllerBusy()))
return false;
/* Set the NVM control register to the NO OP command for memory reading */
TINYNVM_SendWriteNVMRegister(XPROG_Param_NVMCMDRegAddr);
XPROGTarget_SendByte(TINY_NVM_CMD_NOOP);
/* Send the address of the location to read from */
TINYNVM_SendPointerAddress(ReadAddress);
while (ReadSize-- && TimeoutTicksRemaining)
{
/* Read the byte of data from the target */
XPROGTarget_SendByte(TPI_CMD_SLD(TPI_POINTER_INDIRECT_PI));
*(ReadBuffer++) = XPROGTarget_ReceiveByte();
}
return (TimeoutTicksRemaining > 0);
}
/** Writes word addressed memory to the target's memory spaces.
*
* \param[in] WriteAddress Start address to write to within the target's address space
* \param[in] WriteBuffer Buffer to source data from
* \param[in] WriteLength Total number of bytes to write to the device (must be an integer multiple of 2)
*
* \return Boolean \c true if the command sequence complete successfully
*/
bool TINYNVM_WriteMemory(const uint16_t WriteAddress,
uint8_t* WriteBuffer,
uint16_t WriteLength)
{
/* Wait until the NVM controller is no longer busy */
if (!(TINYNVM_WaitWhileNVMControllerBusy()))
return false;
/* Must have an integer number of words to write - if extra byte, word-align via a dummy high byte */
if (WriteLength & 0x01)
WriteBuffer[WriteLength++] = 0xFF;
/* Set the NVM control register to the WORD WRITE command for memory writing */
TINYNVM_SendWriteNVMRegister(XPROG_Param_NVMCMDRegAddr);
XPROGTarget_SendByte(TINY_NVM_CMD_WORDWRITE);
/* Send the address of the location to write to */
TINYNVM_SendPointerAddress(WriteAddress);
while (WriteLength)
{
/* Wait until the NVM controller is no longer busy */
if (!(TINYNVM_WaitWhileNVMControllerBusy()))
return false;
/* Write the low byte of data to the target */
XPROGTarget_SendByte(TPI_CMD_SST(TPI_POINTER_INDIRECT_PI));
XPROGTarget_SendByte(*(WriteBuffer++));
/* Write the high byte of data to the target */
XPROGTarget_SendByte(TPI_CMD_SST(TPI_POINTER_INDIRECT_PI));
XPROGTarget_SendByte(*(WriteBuffer++));
/* Need to decrement the write length twice, since we wrote a whole two-byte word */
WriteLength -= 2;
}
return true;
}
/** Erases the target's memory space.
*
* \param[in] EraseCommand NVM erase command to send to the device
* \param[in] Address Address inside the memory space to erase
*
* \return Boolean \c true if the command sequence complete successfully
*/
bool TINYNVM_EraseMemory(const uint8_t EraseCommand,
const uint16_t Address)
{
/* Wait until the NVM controller is no longer busy */
if (!(TINYNVM_WaitWhileNVMControllerBusy()))
return false;
/* Set the NVM control register to the target memory erase command */
TINYNVM_SendWriteNVMRegister(XPROG_Param_NVMCMDRegAddr);
XPROGTarget_SendByte(EraseCommand);
/* Write to a high byte location within the target address space to start the erase process */
TINYNVM_SendPointerAddress(Address | 0x0001);
XPROGTarget_SendByte(TPI_CMD_SST(TPI_POINTER_INDIRECT));
XPROGTarget_SendByte(0x00);
/* Wait until the NVM controller is no longer busy */
if (!(TINYNVM_WaitWhileNVMControllerBusy()))
return false;
return true;
}
#endif

View file

@ -0,0 +1,86 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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"
#include "Config/AppConfig.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_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_WaitWhileNVMControllerBusy(void);
bool TINYNVM_EnableTPI(void);
void TINYNVM_DisableTPI(void);
bool TINYNVM_ReadMemory(const uint16_t ReadAddress,
uint8_t* ReadBuffer,
uint16_t ReadLength);
bool TINYNVM_WriteMemory(const uint16_t WriteAddress,
uint8_t* WriteBuffer,
uint16_t WriteLength);
bool TINYNVM_EraseMemory(const uint8_t EraseCommand,
const uint16_t Address);
#if (defined(INCLUDE_FROM_TINYNVM_C) && defined(ENABLE_XPROG_PROTOCOL))
static void TINYNVM_SendReadNVMRegister(const uint8_t Address);
static void TINYNVM_SendWriteNVMRegister(const uint8_t Address);
static void TINYNVM_SendPointerAddress(const uint16_t AbsoluteAddress);
#endif
#endif

View file

@ -0,0 +1,468 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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 32-bit absolute address to the target.
*
* \param[in] AbsoluteAddress Absolute address to send to the target
*/
static void XMEGANVM_SendAddress(const uint32_t AbsoluteAddress)
{
/* Send the given 32-bit address to the target, LSB first */
XPROGTarget_SendByte(AbsoluteAddress & 0xFF);
XPROGTarget_SendByte(AbsoluteAddress >> 8);
XPROGTarget_SendByte(AbsoluteAddress >> 16);
XPROGTarget_SendByte(AbsoluteAddress >> 24);
}
/** Sends the given NVM register address to the target.
*
* \param[in] Register NVM register whose absolute address is to be sent
*/
static 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);
}
/** Busy-waits while the NVM controller is busy performing a NVM operation, such as a FLASH page read or CRC
* calculation.
*
* \return Boolean \c true if the NVM controller became ready within the timeout period, \c false otherwise
*/
bool XMEGANVM_WaitWhileNVMBusBusy(void)
{
/* Poll the STATUS register to check to see if NVM access has been enabled */
for (;;)
{
/* Send the LDCS command to read the PDI STATUS register to see the NVM bus is active */
XPROGTarget_SendByte(PDI_CMD_LDCS(PDI_REG_STATUS));
uint8_t StatusRegister = XPROGTarget_ReceiveByte();
/* We might have timed out waiting for the status register read response, check here */
if (!(TimeoutTicksRemaining))
return false;
/* Check the status register read response to see if the NVM bus is enabled */
if (StatusRegister & PDI_STATUS_NVM)
return true;
}
}
/** Waits while the target's NVM controller is busy performing an operation, exiting if the
* timeout period expires.
*
* \return Boolean \c true if the NVM controller became ready within the timeout period, \c false otherwise
*/
bool XMEGANVM_WaitWhileNVMControllerBusy(void)
{
/* Preload the pointer register with the NVM STATUS register address to check the BUSY flag */
XPROGTarget_SendByte(PDI_CMD_ST(PDI_POINTER_DIRECT, PDI_DATASIZE_4BYTES));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_STATUS);
/* Poll the NVM STATUS register while the NVM controller is busy */
for (;;)
{
/* Fetch the current status value via the pointer register (without auto-increment afterwards) */
XPROGTarget_SendByte(PDI_CMD_LD(PDI_POINTER_INDIRECT, PDI_DATASIZE_1BYTE));
uint8_t StatusRegister = XPROGTarget_ReceiveByte();
/* We might have timed out waiting for the status register read response, check here */
if (!(TimeoutTicksRemaining))
return false;
/* Check to see if the BUSY flag is still set */
if (!(StatusRegister & (1 << 7)))
return true;
}
}
/** Enables the physical PDI interface on the target and enables access to the internal NVM controller.
*
* \return Boolean \c true if the PDI interface was enabled successfully, \c false otherwise
*/
bool XMEGANVM_EnablePDI(void)
{
/* 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_REG_RESET));
XPROGTarget_SendByte(PDI_RESET_KEY);
/* Lower direction change guard time to 32 USART bits */
XPROGTarget_SendByte(PDI_CMD_STCS(PDI_REG_CTRL));
XPROGTarget_SendByte(0x02);
/* 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 */
return XMEGANVM_WaitWhileNVMBusBusy();
}
/** Removes access to the target's NVM controller and physically disables the target's physical PDI interface. */
void XMEGANVM_DisablePDI(void)
{
XMEGANVM_WaitWhileNVMBusBusy();
/* Clear the RESET key in the RESET PDI register to allow the XMEGA to run - must perform this until the
* change takes effect, as in some cases it takes multiple writes (silicon bug?).
*/
do
{
/* Clear reset register */
XPROGTarget_SendByte(PDI_CMD_STCS(PDI_REG_RESET));
XPROGTarget_SendByte(0x00);
/* Read back the reset register, check to see if it took effect */
XPROGTarget_SendByte(PDI_CMD_LDCS(PDI_REG_RESET));
} while (XPROGTarget_ReceiveByte() != 0x00);
XPROGTarget_DisableTargetPDI();
}
/** 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 \c true if the command sequence complete successfully
*/
bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand,
uint32_t* const CRCDest)
{
*CRCDest = 0;
/* 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_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
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_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX);
/* 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;
/* Load the PDI pointer register with the DAT0 register start address */
XPROGTarget_SendByte(PDI_CMD_ST(PDI_POINTER_DIRECT, PDI_DATASIZE_4BYTES));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT0);
/* Send the REPEAT command to grab the CRC bytes */
XPROGTarget_SendByte(PDI_CMD_REPEAT(PDI_DATASIZE_1BYTE));
XPROGTarget_SendByte(XMEGA_CRC_LENGTH_BYTES - 1);
/* Read in the CRC bytes from the target */
XPROGTarget_SendByte(PDI_CMD_LD(PDI_POINTER_INDIRECT_PI, PDI_DATASIZE_1BYTE));
for (uint8_t i = 0; i < XMEGA_CRC_LENGTH_BYTES; i++)
((uint8_t*)CRCDest)[i] = XPROGTarget_ReceiveByte();
return (TimeoutTicksRemaining > 0);
}
/** 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 \c 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_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
XPROGTarget_SendByte(XMEGA_NVM_CMD_READNVM);
if (ReadSize > 1)
{
/* Load the PDI pointer register with the start address we want to read from */
XPROGTarget_SendByte(PDI_CMD_ST(PDI_POINTER_DIRECT, PDI_DATASIZE_4BYTES));
XMEGANVM_SendAddress(ReadAddress);
/* Send the REPEAT command with the specified number of bytes to read */
XPROGTarget_SendByte(PDI_CMD_REPEAT(PDI_DATASIZE_1BYTE));
XPROGTarget_SendByte(ReadSize - 1);
/* Send a LD command with indirect access and post-increment to read out the bytes */
XPROGTarget_SendByte(PDI_CMD_LD(PDI_POINTER_INDIRECT_PI, PDI_DATASIZE_1BYTE));
while (ReadSize-- && TimeoutTicksRemaining)
*(ReadBuffer++) = XPROGTarget_ReceiveByte();
}
else
{
/* Send a LDS command with the read address to read out the requested byte */
XPROGTarget_SendByte(PDI_CMD_LDS(PDI_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
XMEGANVM_SendAddress(ReadAddress);
*(ReadBuffer++) = XPROGTarget_ReceiveByte();
}
return (TimeoutTicksRemaining > 0);
}
/** 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 Address to write to within the target's address space
* \param[in] Byte Byte to write to the target
*
* \return Boolean \c true if the command sequence complete successfully
*/
bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand,
const uint32_t WriteAddress,
const uint8_t Byte)
{
/* 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_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
XPROGTarget_SendByte(WriteCommand);
/* Send new memory byte to the memory of the target */
XPROGTarget_SendByte(PDI_CMD_STS(PDI_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
XMEGANVM_SendAddress(WriteAddress);
XPROGTarget_SendByte(Byte);
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 \c 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 & XPROG_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_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
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_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX);
}
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_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
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, PDI_DATASIZE_4BYTES));
XMEGANVM_SendAddress(WriteAddress);
/* Send the REPEAT command with the specified number of bytes to write */
XPROGTarget_SendByte(PDI_CMD_REPEAT(PDI_DATASIZE_1BYTE));
XPROGTarget_SendByte(WriteSize - 1);
/* Send a ST command with indirect access and post-increment to write the bytes */
XPROGTarget_SendByte(PDI_CMD_ST(PDI_POINTER_INDIRECT_PI, PDI_DATASIZE_1BYTE));
while (WriteSize--)
XPROGTarget_SendByte(*(WriteBuffer++));
}
if (PageMode & XPROG_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_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
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_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
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 \c 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;
/* EEPROM and Chip erasures are triggered differently to FLASH section erasures */
if (EraseCommand == XMEGA_NVM_CMD_CHIPERASE)
{
/* Send the memory erase command to the target */
XPROGTarget_SendByte(PDI_CMD_STS(PDI_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
XPROGTarget_SendByte(EraseCommand);
/* Set CMDEX bit in NVM CTRLA register to start the erase sequence */
XPROGTarget_SendByte(PDI_CMD_STS(PDI_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX);
}
else if (EraseCommand == XMEGA_NVM_CMD_ERASEEEPROM)
{
/* Send the EEPROM page buffer erase command to the target */
XPROGTarget_SendByte(PDI_CMD_STS(PDI_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
XPROGTarget_SendByte(XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF);
/* Set CMDEX bit in NVM CTRLA register to start the buffer erase */
XPROGTarget_SendByte(PDI_CMD_STS(PDI_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX);
/* Wait until the NVM controller is no longer busy */
if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
return false;
/* Send the EEPROM memory buffer write command to the target */
XPROGTarget_SendByte(PDI_CMD_STS(PDI_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
XPROGTarget_SendByte(XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF);
/* Load the PDI pointer register with the EEPROM page start address */
XPROGTarget_SendByte(PDI_CMD_ST(PDI_POINTER_DIRECT, PDI_DATASIZE_4BYTES));
XMEGANVM_SendAddress(Address);
/* Send the REPEAT command with the specified number of bytes to write */
XPROGTarget_SendByte(PDI_CMD_REPEAT(PDI_DATASIZE_1BYTE));
XPROGTarget_SendByte(XPROG_Param_EEPageSize - 1);
/* Send a ST command with indirect access and post-increment to tag each byte in the EEPROM page buffer */
XPROGTarget_SendByte(PDI_CMD_ST(PDI_POINTER_INDIRECT_PI, PDI_DATASIZE_1BYTE));
for (uint8_t PageByte = 0; PageByte < XPROG_Param_EEPageSize; PageByte++)
XPROGTarget_SendByte(0x00);
/* Send the memory erase command to the target */
XPROGTarget_SendByte(PDI_CMD_STS(PDI_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
XPROGTarget_SendByte(EraseCommand);
/* Set CMDEX bit in NVM CTRLA register to start the EEPROM erase sequence */
XPROGTarget_SendByte(PDI_CMD_STS(PDI_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX);
}
else
{
/* Send the memory erase command to the target */
XPROGTarget_SendByte(PDI_CMD_STS(PDI_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
XPROGTarget_SendByte(EraseCommand);
/* Other erase modes just need us to address a byte within the target memory space */
XPROGTarget_SendByte(PDI_CMD_STS(PDI_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
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,140 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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"
#include "Config/AppConfig.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_CRC_LENGTH_BYTES 3
#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_BIT_CTRLA_CMDEX (1 << 0)
#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: */
bool XMEGANVM_WaitWhileNVMBusBusy(void);
bool XMEGANVM_WaitWhileNVMControllerBusy(void);
bool XMEGANVM_EnablePDI(void);
void XMEGANVM_DisablePDI(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 Byte);
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);
#if defined(INCLUDE_FROM_XMEGANVM_C)
static void XMEGANVM_SendNVMRegAddress(const uint8_t Register);
static void XMEGANVM_SendAddress(const uint32_t AbsoluteAddress);
#endif
#endif

View file

@ -0,0 +1,480 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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 for PDI programming */
uint32_t XPROG_Param_NVMBase = 0x010001C0;
/** Size in bytes of the target's EEPROM page */
uint16_t XPROG_Param_EEPageSize = 32;
/** Address of the TPI device's NVMCMD register for TPI programming */
uint8_t XPROG_Param_NVMCMDRegAddr = 0x33;
/** Address of the TPI device's NVMCSR register for TPI programming */
uint8_t XPROG_Param_NVMCSRRegAddr = 0x32;
/** Currently selected XPROG programming protocol */
uint8_t XPROG_SelectedProtocol = XPROG_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), NULL);
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
XPROG_SelectedProtocol = SetMode_XPROG_Params.Protocol;
Endpoint_Write_8(CMD_XPROG_SETMODE);
Endpoint_Write_8((SetMode_XPROG_Params.Protocol != XPROG_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_8();
switch (XPROGCommand)
{
case XPROG_CMD_ENTER_PROGMODE:
XPROGProtocol_EnterXPROGMode();
break;
case XPROG_CMD_LEAVE_PROGMODE:
XPROGProtocol_LeaveXPROGMode();
break;
case XPROG_CMD_ERASE:
XPROGProtocol_Erase();
break;
case XPROG_CMD_WRITE_MEM:
XPROGProtocol_WriteMemory();
break;
case XPROG_CMD_READ_MEM:
XPROGProtocol_ReadMemory();
break;
case XPROG_CMD_CRC:
XPROGProtocol_ReadCRC();
break;
case XPROG_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_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
bool NVMBusEnabled = false;
if (XPROG_SelectedProtocol == XPROG_PROTOCOL_PDI)
NVMBusEnabled = XMEGANVM_EnablePDI();
else if (XPROG_SelectedProtocol == XPROG_PROTOCOL_TPI)
NVMBusEnabled = TINYNVM_EnableTPI();
Endpoint_Write_8(CMD_XPROG);
Endpoint_Write_8(XPROG_CMD_ENTER_PROGMODE);
Endpoint_Write_8(NVMBusEnabled ? XPROG_ERR_OK : XPROG_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_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
if (XPROG_SelectedProtocol == XPROG_PROTOCOL_PDI)
XMEGANVM_DisablePDI();
else
TINYNVM_DisableTPI();
#if defined(XCK_RESCUE_CLOCK_ENABLE) && defined(ENABLE_ISP_PROTOCOL)
/* If the XCK rescue clock option is enabled, we need to restart it once the
* XPROG mode has been exited, since the XPROG protocol stops it after use. */
ISPTarget_ConfigureRescueClock();
#endif
Endpoint_Write_8(CMD_XPROG);
Endpoint_Write_8(XPROG_CMD_LEAVE_PROGMODE);
Endpoint_Write_8(XPROG_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 = XPROG_ERR_OK;
struct
{
uint8_t MemoryType;
uint32_t Address;
} Erase_XPROG_Params;
Endpoint_Read_Stream_LE(&Erase_XPROG_Params, sizeof(Erase_XPROG_Params), NULL);
Erase_XPROG_Params.Address = SwapEndian_32(Erase_XPROG_Params.Address);
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t EraseCommand;
if (XPROG_SelectedProtocol == XPROG_PROTOCOL_PDI)
{
/* Determine which NVM command to send to the device depending on the memory to erase */
switch (Erase_XPROG_Params.MemoryType)
{
case XPROG_ERASE_CHIP:
EraseCommand = XMEGA_NVM_CMD_CHIPERASE;
break;
case XPROG_ERASE_APP:
EraseCommand = XMEGA_NVM_CMD_ERASEAPPSEC;
break;
case XPROG_ERASE_BOOT:
EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSEC;
break;
case XPROG_ERASE_EEPROM:
EraseCommand = XMEGA_NVM_CMD_ERASEEEPROM;
break;
case XPROG_ERASE_APP_PAGE:
EraseCommand = XMEGA_NVM_CMD_ERASEAPPSECPAGE;
break;
case XPROG_ERASE_BOOT_PAGE:
EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSECPAGE;
break;
case XPROG_ERASE_EEPROM_PAGE:
EraseCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGE;
break;
case XPROG_ERASE_USERSIG:
EraseCommand = XMEGA_NVM_CMD_ERASEUSERSIG;
break;
default:
EraseCommand = XMEGA_NVM_CMD_NOOP;
break;
}
/* Erase the target memory, indicate timeout if occurred */
if (!(XMEGANVM_EraseMemory(EraseCommand, Erase_XPROG_Params.Address)))
ReturnStatus = XPROG_ERR_TIMEOUT;
}
else
{
if (Erase_XPROG_Params.MemoryType == XPROG_ERASE_CHIP)
EraseCommand = TINY_NVM_CMD_CHIPERASE;
else
EraseCommand = TINY_NVM_CMD_SECTIONERASE;
/* Erase the target memory, indicate timeout if occurred */
if (!(TINYNVM_EraseMemory(EraseCommand, Erase_XPROG_Params.Address)))
ReturnStatus = XPROG_ERR_TIMEOUT;
}
Endpoint_Write_8(CMD_XPROG);
Endpoint_Write_8(XPROG_CMD_ERASE);
Endpoint_Write_8(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 = XPROG_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), NULL);
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, NULL);
// The driver will terminate transfers that are a round multiple of the endpoint bank in size with a ZLP, need
// to catch this and discard it before continuing on with packet processing to prevent communication issues
if (((sizeof(uint8_t) + sizeof(WriteMemory_XPROG_Params) - sizeof(WriteMemory_XPROG_Params.ProgData)) +
WriteMemory_XPROG_Params.Length) % AVRISP_DATA_EPSIZE == 0)
{
Endpoint_ClearOUT();
Endpoint_WaitUntilReady();
}
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
if (XPROG_SelectedProtocol == XPROG_PROTOCOL_PDI)
{
/* 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;
switch (WriteMemory_XPROG_Params.MemoryType)
{
case XPROG_MEM_TYPE_APPL:
WriteCommand = XMEGA_NVM_CMD_WRITEAPPSECPAGE;
break;
case XPROG_MEM_TYPE_BOOT:
WriteCommand = XMEGA_NVM_CMD_WRITEBOOTSECPAGE;
break;
case XPROG_MEM_TYPE_EEPROM:
WriteCommand = XMEGA_NVM_CMD_ERASEWRITEEEPROMPAGE;
WriteBuffCommand = XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF;
EraseBuffCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF;
break;
case XPROG_MEM_TYPE_USERSIG:
WriteCommand = XMEGA_NVM_CMD_WRITEUSERSIG;
break;
case XPROG_MEM_TYPE_FUSE:
WriteCommand = XMEGA_NVM_CMD_WRITEFUSE;
PagedMemory = false;
break;
case XPROG_MEM_TYPE_LOCKBITS:
WriteCommand = XMEGA_NVM_CMD_WRITELOCK;
PagedMemory = false;
break;
}
/* 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[0]))))
{
ReturnStatus = XPROG_ERR_TIMEOUT;
}
}
else
{
/* Send write command to the TPI device, indicate timeout if occurred */
if (!(TINYNVM_WriteMemory(WriteMemory_XPROG_Params.Address, WriteMemory_XPROG_Params.ProgData,
WriteMemory_XPROG_Params.Length)))
{
ReturnStatus = XPROG_ERR_TIMEOUT;
}
}
Endpoint_Write_8(CMD_XPROG);
Endpoint_Write_8(XPROG_CMD_WRITE_MEM);
Endpoint_Write_8(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 = XPROG_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), NULL);
ReadMemory_XPROG_Params.Address = SwapEndian_32(ReadMemory_XPROG_Params.Address);
ReadMemory_XPROG_Params.Length = SwapEndian_16(ReadMemory_XPROG_Params.Length);
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t ReadBuffer[256];
if (XPROG_SelectedProtocol == XPROG_PROTOCOL_PDI)
{
/* Read the PDI target's memory, indicate timeout if occurred */
if (!(XMEGANVM_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length)))
ReturnStatus = XPROG_ERR_TIMEOUT;
}
else
{
/* Read the TPI target's memory, indicate timeout if occurred */
if (!(TINYNVM_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length)))
ReturnStatus = XPROG_ERR_TIMEOUT;
}
Endpoint_Write_8(CMD_XPROG);
Endpoint_Write_8(XPROG_CMD_READ_MEM);
Endpoint_Write_8(ReturnStatus);
if (ReturnStatus == XPROG_ERR_OK)
Endpoint_Write_Stream_LE(ReadBuffer, ReadMemory_XPROG_Params.Length, NULL);
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 = XPROG_ERR_OK;
struct
{
uint8_t CRCType;
} ReadCRC_XPROG_Params;
Endpoint_Read_Stream_LE(&ReadCRC_XPROG_Params, sizeof(ReadCRC_XPROG_Params), NULL);
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint32_t MemoryCRC;
if (XPROG_SelectedProtocol == XPROG_PROTOCOL_PDI)
{
uint8_t CRCCommand;
/* Determine which NVM command to send to the device depending on the memory to CRC */
switch (ReadCRC_XPROG_Params.CRCType)
{
case XPROG_CRC_APP:
CRCCommand = XMEGA_NVM_CMD_APPCRC;
break;
case XPROG_CRC_BOOT:
CRCCommand = XMEGA_NVM_CMD_BOOTCRC;
break;
default:
CRCCommand = XMEGA_NVM_CMD_FLASHCRC;
break;
}
/* Perform and retrieve the memory CRC, indicate timeout if occurred */
if (!(XMEGANVM_GetMemoryCRC(CRCCommand, &MemoryCRC)))
ReturnStatus = XPROG_ERR_TIMEOUT;
}
else
{
/* TPI does not support memory CRC */
ReturnStatus = XPROG_ERR_FAILED;
}
Endpoint_Write_8(CMD_XPROG);
Endpoint_Write_8(XPROG_CMD_CRC);
Endpoint_Write_8(ReturnStatus);
if (ReturnStatus == XPROG_ERR_OK)
{
Endpoint_Write_8(MemoryCRC >> 16);
Endpoint_Write_16_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 = XPROG_ERR_OK;
uint8_t XPROGParam = Endpoint_Read_8();
/* Determine which parameter is being set, store the new parameter value */
switch (XPROGParam)
{
case XPROG_PARAM_NVMBASE:
XPROG_Param_NVMBase = Endpoint_Read_32_BE();
break;
case XPROG_PARAM_EEPPAGESIZE:
XPROG_Param_EEPageSize = Endpoint_Read_16_BE();
break;
case XPROG_PARAM_NVMCMD_REG:
XPROG_Param_NVMCMDRegAddr = Endpoint_Read_8();
break;
case XPROG_PARAM_NVMCSR_REG:
XPROG_Param_NVMCSRRegAddr = Endpoint_Read_8();
break;
case XPROG_PARAM_UNKNOWN_1:
/* TODO: Undocumented parameter added in AVRStudio 5.1, purpose unknown. Must ACK and discard or
the communication with AVRStudio 5.1 will fail.
*/
Endpoint_Discard_16();
break;
default:
ReturnStatus = XPROG_ERR_FAILED;
break;
}
Endpoint_ClearOUT();
Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_Write_8(CMD_XPROG);
Endpoint_Write_8(XPROG_CMD_SET_PARAM);
Endpoint_Write_8(ReturnStatus);
Endpoint_ClearIN();
}
#endif

View file

@ -0,0 +1,136 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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 "XMEGANVM.h"
#include "TINYNVM.h"
#include "Config/AppConfig.h"
/* Preprocessor Checks: */
#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
/* On the XPLAIN board, we only need PDI programming
for the ATXMEGA128A1 - disable ISP to prevent hardware
damage and force-enable XPROG.
*/
#undef ENABLE_ISP_PROTOCOL
#if !defined(ENABLE_XPROG_PROTOCOL)
#define ENABLE_XPROG_PROTOCOL
#endif
#endif
/* Macros: */
#define XPROG_CMD_ENTER_PROGMODE 0x01
#define XPROG_CMD_LEAVE_PROGMODE 0x02
#define XPROG_CMD_ERASE 0x03
#define XPROG_CMD_WRITE_MEM 0x04
#define XPROG_CMD_READ_MEM 0x05
#define XPROG_CMD_CRC 0x06
#define XPROG_CMD_SET_PARAM 0x07
#define XPROG_MEM_TYPE_APPL 1
#define XPROG_MEM_TYPE_BOOT 2
#define XPROG_MEM_TYPE_EEPROM 3
#define XPROG_MEM_TYPE_FUSE 4
#define XPROG_MEM_TYPE_LOCKBITS 5
#define XPROG_MEM_TYPE_USERSIG 6
#define XPROG_MEM_TYPE_FACTORY_CALIBRATION 7
#define XPROG_ERASE_CHIP 1
#define XPROG_ERASE_APP 2
#define XPROG_ERASE_BOOT 3
#define XPROG_ERASE_EEPROM 4
#define XPROG_ERASE_APP_PAGE 5
#define XPROG_ERASE_BOOT_PAGE 6
#define XPROG_ERASE_EEPROM_PAGE 7
#define XPROG_ERASE_USERSIG 8
#define XPROG_MEM_WRITE_ERASE 0
#define XPROG_MEM_WRITE_WRITE 1
#define XPROG_CRC_APP 1
#define XPROG_CRC_BOOT 2
#define XPROG_CRC_FLASH 3
#define XPROG_ERR_OK 0
#define XPROG_ERR_FAILED 1
#define XPROG_ERR_COLLISION 2
#define XPROG_ERR_TIMEOUT 3
#define XPROG_PARAM_NVMBASE 0x01
#define XPROG_PARAM_EEPPAGESIZE 0x02
#define XPROG_PARAM_NVMCMD_REG 0x03
#define XPROG_PARAM_NVMCSR_REG 0x04
#define XPROG_PARAM_UNKNOWN_1 0x05
#define XPROG_PROTOCOL_PDI 0x00
#define XPROG_PROTOCOL_JTAG 0x01
#define XPROG_PROTOCOL_TPI 0x02
#define XPROG_PAGEMODE_WRITE (1 << 1)
#define XPROG_PAGEMODE_ERASE (1 << 0)
/* External Variables: */
extern uint32_t XPROG_Param_NVMBase;
extern uint16_t XPROG_Param_EEPageSize;
extern uint8_t XPROG_Param_NVMCSRRegAddr;
extern uint8_t XPROG_Param_NVMCMDRegAddr;
/* Function Prototypes: */
void XPROGProtocol_SetMode(void);
void XPROGProtocol_Command(void);
#if (defined(INCLUDE_FROM_XPROGPROTOCOL_C) && defined(ENABLE_XPROG_PROTOCOL))
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,209 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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. */
bool IsSending;
/** Enables the target's PDI interface, holding the target in reset until PDI mode is exited. */
void XPROGTarget_EnableTargetPDI(void)
{
IsSending = false;
/* 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);
_delay_us(100);
/* Set up the synchronous USART for XMEGA communications - 8 data bits, even parity, 2 stop bits */
UBRR1 = ((F_CPU / 2 / XPROG_HARDWARE_SPEED) - 1);
UCSR1B = (1 << TXEN1);
UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);
/* Send two IDLEs of 12 bits each to enable PDI interface (need at least 16 idle bits) */
XPROGTarget_SendIdle();
XPROGTarget_SendIdle();
}
/** Enables the target's TPI interface, holding the target in reset until TPI mode is exited. */
void XPROGTarget_EnableTargetTPI(void)
{
IsSending = false;
/* Set /RESET line low for at least 400ns to enable TPI functionality */
AUX_LINE_DDR |= AUX_LINE_MASK;
AUX_LINE_PORT &= ~AUX_LINE_MASK;
_delay_us(100);
/* Set Tx and XCK as outputs, Rx as input */
DDRD |= (1 << 5) | (1 << 3);
DDRD &= ~(1 << 2);
/* Set up the synchronous USART for TPI communications - 8 data bits, even parity, 2 stop bits */
UBRR1 = ((F_CPU / 2 / XPROG_HARDWARE_SPEED) - 1);
UCSR1B = (1 << TXEN1);
UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);
/* Send two IDLEs of 12 bits each to enable TPI interface (need at least 16 idle bits) */
XPROGTarget_SendIdle();
XPROGTarget_SendIdle();
}
/** Disables the target's PDI interface, exits programming mode and starts the target's application. */
void XPROGTarget_DisableTargetPDI(void)
{
/* Switch to Rx mode to ensure that all pending transmissions are complete */
if (IsSending)
XPROGTarget_SetRxMode();
/* Turn off receiver and transmitter of the USART, clear settings */
UCSR1A = ((1 << TXC1) | (1 << RXC1));
UCSR1B = 0;
UCSR1C = 0;
/* Tristate all pins */
DDRD &= ~((1 << 5) | (1 << 3));
PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2));
}
/** Disables the target's TPI interface, exits programming mode and starts the target's application. */
void XPROGTarget_DisableTargetTPI(void)
{
/* Switch to Rx mode to ensure that all pending transmissions are complete */
if (IsSending)
XPROGTarget_SetRxMode();
/* Turn off receiver and transmitter of the USART, clear settings */
UCSR1A |= (1 << TXC1) | (1 << RXC1);
UCSR1B = 0;
UCSR1C = 0;
/* Set all USART lines as inputs, tristate */
DDRD &= ~((1 << 5) | (1 << 3));
PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2));
/* Tristate target /RESET line */
AUX_LINE_DDR &= ~AUX_LINE_MASK;
AUX_LINE_PORT &= ~AUX_LINE_MASK;
}
/** Sends a byte via the USART.
*
* \param[in] Byte Byte to send through the USART
*/
void XPROGTarget_SendByte(const uint8_t Byte)
{
/* Switch to Tx mode if currently in Rx mode */
if (!(IsSending))
XPROGTarget_SetTxMode();
/* Wait until there is space in the hardware Tx buffer before writing */
while (!(UCSR1A & (1 << UDRE1)));
UCSR1A |= (1 << TXC1);
UDR1 = Byte;
}
/** Receives a byte via the hardware USART, blocking until data is received or timeout expired.
*
* \return Received byte from the USART
*/
uint8_t XPROGTarget_ReceiveByte(void)
{
/* Switch to Rx mode if currently in Tx mode */
if (IsSending)
XPROGTarget_SetRxMode();
/* Wait until a byte has been received before reading */
while (!(UCSR1A & (1 << RXC1)) && TimeoutTicksRemaining);
return UDR1;
}
/** Sends an IDLE via the USART to the attached target, consisting of a full frame of idle bits. */
void XPROGTarget_SendIdle(void)
{
/* Switch to Tx mode if currently in Rx mode */
if (!(IsSending))
XPROGTarget_SetTxMode();
/* Need to do nothing for a full frame to send an IDLE */
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)));
while (PIND & (1 << 5));
}
}
static void XPROGTarget_SetTxMode(void)
{
/* Wait for a full cycle of the clock */
while (PIND & (1 << 5));
while (!(PIND & (1 << 5)));
while (PIND & (1 << 5));
PORTD |= (1 << 3);
DDRD |= (1 << 3);
UCSR1B &= ~(1 << RXEN1);
UCSR1B |= (1 << TXEN1);
IsSending = true;
}
static void XPROGTarget_SetRxMode(void)
{
while (!(UCSR1A & (1 << TXC1)));
UCSR1A |= (1 << TXC1);
UCSR1B &= ~(1 << TXEN1);
UCSR1B |= (1 << RXEN1);
DDRD &= ~(1 << 3);
PORTD &= ~(1 << 3);
IsSending = false;
}
#endif

View file

@ -0,0 +1,136 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, 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 disclaims 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 XPROGTarget.c.
*/
#ifndef _XPROG_TARGET_
#define _XPROG_TARGET_
/* Includes: */
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include <LUFA/Common/Common.h>
#include "../V2Protocol.h"
#include "XPROGProtocol.h"
#include "Config/AppConfig.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
/** Serial carrier TPI/PDI speed in Hz, when hardware TPI/PDI mode is used. */
#define XPROG_HARDWARE_SPEED 2000000
/** Total number of bits in a single USART frame. */
#define BITS_IN_USART_FRAME 12
/** \name PDI Related Constants
* @{
*/
#define PDI_CMD_LDS(AddressSize, DataSize) (0x00 | ( AddressSize << 2) | DataSize)
#define PDI_CMD_LD(PointerAccess, DataSize) (0x20 | (PointerAccess << 2) | DataSize)
#define PDI_CMD_STS(AddressSize, DataSize) (0x40 | ( AddressSize << 2) | DataSize)
#define PDI_CMD_ST(PointerAccess, DataSize) (0x60 | (PointerAccess << 2) | DataSize)
#define PDI_CMD_LDCS(PDIReg) (0x80 | PDIReg)
#define PDI_CMD_REPEAT(DataSize) (0xA0 | DataSize)
#define PDI_CMD_STCS(PDIReg) (0xC0 | PDIReg)
#define PDI_CMD_KEY 0xE0
#define PDI_REG_STATUS 0
#define PDI_REG_RESET 1
#define PDI_REG_CTRL 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_DATASIZE_1BYTE 0
#define PDI_DATASIZE_2BYTES 1
#define PDI_DATASIZE_3BYTES 2
#define PDI_DATASIZE_4BYTES 3
#define PDI_POINTER_INDIRECT 0
#define PDI_POINTER_INDIRECT_PI 1
#define PDI_POINTER_DIRECT 2
/** @} */
/** \name TPI Related Constants
* @{
*/
#define TPI_CMD_SLD(PointerAccess) (0x20 | PointerAccess)
#define TPI_CMD_SST(PointerAccess) (0x60 | PointerAccess)
#define TPI_CMD_SSTPR 0x68
#define TPI_CMD_SIN(Address) (0x10 | ((Address & 0x30) << 1) | (Address & 0x0F))
#define TPI_CMD_SOUT(Address) (0x90 | ((Address & 0x30) << 1) | (Address & 0x0F))
#define TPI_CMD_SLDCS(TPIReg) (0x80 | TPIReg)
#define TPI_CMD_SSTCS(TPIReg) (0xC0 | TPIReg)
#define TPI_CMD_SKEY 0xE0
#define TPI_REG_STATUS 0x00
#define TPI_REG_CTRL 0x02
#define TPI_REG_ID 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 4
/** @} */
/* 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_SendIdle(void);
bool XPROGTarget_WaitWhileNVMBusBusy(void);
#if (defined(INCLUDE_FROM_XPROGTARGET_C) && defined(ENABLE_XPROG_PROTOCOL))
static void XPROGTarget_SetTxMode(void);
static void XPROGTarget_SetRxMode(void);
#endif
#endif

View file

@ -0,0 +1,90 @@
<asf xmlversion="1.0">
<project caption="AVRISP-MKII Clone Programmer" id="lufa.projects.avrispmkii_clone.avr8">
<require idref="lufa.projects.avrispmkii_clone"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="at90usb1287"/>
<config name="lufa.drivers.board.name" value="usbkey"/>
<build type="define" name="F_CPU" value="8000000UL"/>
<build type="define" name="F_USB" value="8000000UL"/>
</project>
<!-- Required by the XPLAIN Bridge project as well, so split into a meta module -->
<module type="meta" id="lufa.projects.avrispmkii_clone.src" caption="AVRISP-MKII Clone Programmer">
<info type="gui-flag" value="hidden"/>
<device-support-alias value="lufa_avr8"/>
<device-support-alias value="lufa_xmega"/>
<device-support-alias value="lufa_uc3"/>
<info type="gui-flag" value="move-to-root"/>
<build type="include-path" value="."/>
<build type="c-source" value="AVRISPDescriptors.c"/>
<build type="header-file" value="AVRISPDescriptors.h"/>
<build type="include-path" value="Lib"/>
<build type="header-file" value="Lib/V2ProtocolConstants.h"/>
<build type="c-source" value="Lib/V2Protocol.c"/>
<build type="header-file" value="Lib/V2Protocol.h"/>
<build type="c-source" value="Lib/V2ProtocolParams.c"/>
<build type="header-file" value="Lib/V2ProtocolParams.h"/>
<build type="c-source" value="Lib/ISP/ISPProtocol.c"/>
<build type="header-file" value="Lib/ISP/ISPProtocol.h"/>
<build type="c-source" value="Lib/ISP/ISPTarget.c"/>
<build type="header-file" value="Lib/ISP/ISPTarget.h"/>
<build type="c-source" value="Lib/XPROG/XPROGTarget.c"/>
<build type="header-file" value="Lib/XPROG/XPROGTarget.h"/>
<build type="c-source" value="Lib/XPROG/XPROGProtocol.c"/>
<build type="header-file" value="Lib/XPROG/XPROGProtocol.h"/>
<build type="c-source" value="Lib/XPROG/XMEGANVM.c"/>
<build type="header-file" value="Lib/XPROG/XMEGANVM.h"/>
<build type="c-source" value="Lib/XPROG/TINYNVM.c"/>
<build type="header-file" value="Lib/XPROG/TINYNVM.h"/>
<require idref="lufa.drivers.peripheral.adc"/>
<require idref="lufa.drivers.peripheral.spi"/>
</module>
<module type="application" id="lufa.projects.avrispmkii_clone" caption="AVRISP-MKII Clone Programmer">
<info type="description" value="summary">
Clone firmware of the Atmel AVRISP-MKII programmer.
</info>
<info type="gui-flag" value="move-to-root"/>
<info type="keyword" value="Technology">
<keyword value="Low Level APIs"/>
<keyword value="USB Device"/>
</info>
<device-support-alias value="lufa_avr8"/>
<device-support-alias value="lufa_xmega"/>
<device-support-alias value="lufa_uc3"/>
<build type="distribute" subtype="user-file" value="doxyfile"/>
<build type="distribute" subtype="user-file" value="AVRISP-MKII.txt"/>
<build type="c-source" value="AVRISP-MKII.c"/>
<build type="header-file" value="AVRISP-MKII.h"/>
<require idref="lufa.projects.avrispmkii_clone.src"/>
<build type="module-config" subtype="path" value="Config"/>
<build type="module-config" subtype="required-header-file" value="AppConfig.h"/>
<build type="header-file" value="Config/AppConfig.h"/>
<build type="header-file" value="Config/LUFAConfig.h"/>
<require idref="lufa.common"/>
<require idref="lufa.platform"/>
<require idref="lufa.drivers.usb"/>
<require idref="lufa.drivers.peripheral.adc"/>
<require idref="lufa.drivers.peripheral.spi"/>
<require idref="lufa.drivers.board"/>
<require idref="lufa.drivers.board.leds"/>
</module>
</asf>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,39 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2014.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# --------------------------------------
# LUFA Project Makefile.
# --------------------------------------
# Run "make help" for target help.
MCU = at90usb1287
ARCH = AVR8
BOARD = USBKEY
F_CPU = 8000000
F_USB = $(F_CPU)
OPTIMIZATION = s
TARGET = AVRISP-MKII
SRC = $(TARGET).c AVRISPDescriptors.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_SRC_USB)
LUFA_PATH = ../../LUFA
CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/
LD_FLAGS =
# Default target
all:
# Include LUFA build script makefiles
include $(LUFA_PATH)/Build/lufa_core.mk
include $(LUFA_PATH)/Build/lufa_sources.mk
include $(LUFA_PATH)/Build/lufa_build.mk
include $(LUFA_PATH)/Build/lufa_cppcheck.mk
include $(LUFA_PATH)/Build/lufa_doxygen.mk
include $(LUFA_PATH)/Build/lufa_dfu.mk
include $(LUFA_PATH)/Build/lufa_hid.mk
include $(LUFA_PATH)/Build/lufa_avrdude.mk
include $(LUFA_PATH)/Build/lufa_atprogram.mk