Commit 2f6c0960 authored by Dean Camera's avatar Dean Camera
Browse files

Complete initial working revision of PDI programming in the AVRISP project...

Complete initial working revision of PDI programming in the AVRISP project (XMEGAs can now be programmed by the firmware).
parent 79efd8c7
......@@ -18,18 +18,20 @@
* The following is a list of known AVR USB development boards, which recommend using LUFA for the USB stack. Some of these
* are open design, and all are available for purchase as completed development boards suitable for project development.
*
* - Micropendous, an open design/source set of AVR USB development boards: http://micropendous.org/
* - Benito #7, a no-frills USB board: http://www.dorkbotpdx.org/wiki/benito
* - Bumble-B, yet another AT90USB162 development board: http://fletchtronics.net/bumble-b
* - Micropendous, an open design/source set of AVR USB development boards: http://micropendous.org/
* - Nanduino, a do-it-yourself AT90USB162 board: http://www.makestuff.eu/wordpress/?page_id=569
* - Teensy and Teensy++, two other AVR USB development boards: http://www.pjrc.com/teensy/index.html
* - USB10 AKA "The Ferret", a AT90USB162 development board: http://www.soc-machines.com
* - USBFoo, an AT90USB162 based development board: http://shop.kernelconcepts.de/product_info.php?products_id=102
* - Teensy and Teensy++, two other AVR USB development boards: http://www.pjrc.com/teensy/index.html
*
* \section Sec_LUFAProjects Projects Using LUFA (Hobbyist)
*
* The following are known hobbyist projects using LUFA. Most are open source, and show off interesting ways that the LUFA library
* can be incorporated into many different applications.
*
* - Arcade Controller: http://fletchtronics.net/arcade-controller-made-petunia
* - Bicycle POV: http://www.code.google.com/p/bicycleledpov/
* - CAMTRIG, a remote Camera Trigger device: http://code.astraw.com/projects/motmot/camtrig
* - "Fingerlicking Wingdinger" (WARNING: Bad Language if no Javascript), a MIDI controller - http://noisybox.net/electronics/wingdinger/
......
......@@ -96,7 +96,7 @@ bool NVMTarget_WaitWhileNVMControllerBusy(void)
* \param[in] CRCCommand NVM CRC command to issue to the target
* \param[out] CRCDest CRC Destination when read from the target
*
* \return Boolean true if the command sequence complete sucessfully
* \return Boolean true if the command sequence complete successfully
*/
bool NVMTarget_GetMemoryCRC(uint8_t CRCCommand, uint32_t* CRCDest)
{
......@@ -148,7 +148,7 @@ bool NVMTarget_GetMemoryCRC(uint8_t CRCCommand, uint32_t* CRCDest)
* \param[out] ReadBuffer Buffer to store read data into
* \param[in] ReadSize Number of bytes to read
*
* \return Boolean true if the command sequence complete sucessfully
* \return Boolean true if the command sequence complete successfully
*/
bool NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize)
{
......@@ -156,7 +156,7 @@ bool NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t Re
if (!(NVMTarget_WaitWhileNVMControllerBusy()))
return false;
/* Send the READNVM command to the NVM controller for reading of an aribtrary location */
/* Send the READNVM command to the NVM controller for reading of an arbitrary location */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
PDITarget_SendByte(NVM_CMD_READNVM);
......@@ -166,9 +166,8 @@ bool NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t Re
NVMTarget_SendAddress(ReadAddress);
/* Send the REPEAT command with the specified number of bytes to read */
PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_2BYTES);
PDITarget_SendByte(ReadSize & 0xFF);
PDITarget_SendByte(ReadSize >> 8);
PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE);
PDITarget_SendByte(ReadSize - 1);
/* Send a LD command with indirect access and postincrement to read out the bytes */
PDITarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
......@@ -185,26 +184,23 @@ bool NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t Re
* \param[in] WriteBuffer Buffer to source data from
* \param[in] WriteSize Number of bytes to write
*
* \return Boolean true if the command sequence complete sucessfully
* \return Boolean true if the command sequence complete successfully
*/
bool NVMTarget_WriteByteMemory(uint8_t WriteCommand, uint32_t WriteAddress, uint8_t* WriteBuffer, uint16_t WriteSize)
bool NVMTarget_WriteByteMemory(uint8_t WriteCommand, uint32_t WriteAddress, uint8_t* WriteBuffer)
{
for (uint16_t i = 0; i < WriteSize; i++)
{
/* Wait until the NVM controller is no longer busy */
if (!(NVMTarget_WaitWhileNVMControllerBusy()))
return false;
/* Wait until the NVM controller is no longer busy */
if (!(NVMTarget_WaitWhileNVMControllerBusy()))
return false;
/* Send the memory write command to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
PDITarget_SendByte(WriteCommand);
/* Send the memory write command to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
PDITarget_SendByte(WriteCommand);
/* Send each new memory byte to the memory to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
NVMTarget_SendAddress(WriteAddress++);
PDITarget_SendByte(*(WriteBuffer++));
}
/* Send new memory byte to the memory to the target */
PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
NVMTarget_SendAddress(WriteAddress++);
PDITarget_SendByte(*(WriteBuffer++));
return true;
}
......@@ -219,7 +215,7 @@ bool NVMTarget_WriteByteMemory(uint8_t WriteCommand, uint32_t WriteAddress, uint
* \param[in] WriteBuffer Buffer to source data from
* \param[in] WriteSize Number of bytes to write
*
* \return Boolean true if the command sequence complete sucessfully
* \return Boolean true if the command sequence complete successfully
*/
bool NVMTarget_WritePageMemory(uint8_t WriteBuffCommand, uint8_t EraseBuffCommand, uint8_t WritePageCommand,
uint8_t PageMode, uint32_t WriteAddress, uint8_t* WriteBuffer, uint16_t WriteSize)
......@@ -257,22 +253,13 @@ bool NVMTarget_WritePageMemory(uint8_t WriteBuffCommand, uint8_t EraseBuffComman
NVMTarget_SendAddress(WriteAddress);
/* Send the REPEAT command with the specified number of bytes to write */
PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_2BYTES);
PDITarget_SendByte(WriteSize & 0xFF);
PDITarget_SendByte(WriteSize >> 8);
PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE);
PDITarget_SendByte(WriteSize - 1);
/* Send a ST command with indirect access and postincrement to write the bytes */
PDITarget_SendByte(PDI_CMD_ST | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
for (uint16_t i = 0; i < WriteSize; i++)
PDITarget_SendByte(*(WriteBuffer++));
// TEMP
PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
NVMTarget_SendNVMRegAddress(NVM_REG_STATUS);
GPIOR0 = PDITarget_ReceiveByte();
if (!(GPIOR0 & (1 << 0)))
JTAG_DEBUG_POINT();
// END TEMP
}
if (PageMode & XPRG_PAGEMODE_WRITE)
......@@ -300,7 +287,7 @@ bool NVMTarget_WritePageMemory(uint8_t WriteBuffCommand, uint8_t EraseBuffComman
* \param[in] EraseCommand NVM erase command to send to the device
* \param[in] Address Address inside the memory space to erase
*
* \return Boolean true if the command sequence complete sucessfully
* \return Boolean true if the command sequence complete successfully
*/
bool NVMTarget_EraseMemory(uint8_t EraseCommand, uint32_t Address)
{
......@@ -313,7 +300,7 @@ bool NVMTarget_EraseMemory(uint8_t EraseCommand, uint32_t Address)
NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
PDITarget_SendByte(EraseCommand);
/* Chip erase is handled seperately, since it's procedure is different to other erase types */
/* Chip erase is handled separately, since it's procedure is different to other erase types */
if (EraseCommand == NVM_CMD_CHIPERASE)
{
/* Set CMDEX bit in NVM CTRLA register to start the chip erase */
......
......@@ -77,7 +77,7 @@
#define NVM_CMD_LOADFLASHPAGEBUFF 0x23
#define NVM_CMD_ERASEFLASHPAGEBUFF 0x26
#define NVM_CMD_ERASEFLASHPAGE 0x2B
#define NVM_CMD_FLASHPAGEWRITE 0x2E
#define NVM_CMD_WRITEFLASHPAGE 0x2E
#define NVM_CMD_ERASEWRITEFLASH 0x2F
#define NVM_CMD_FLASHCRC 0x78
#define NVM_CMD_ERASEAPPSEC 0x20
......@@ -111,8 +111,7 @@
bool NVMTarget_WaitWhileNVMControllerBusy(void);
bool NVMTarget_GetMemoryCRC(uint8_t CRCCommand, uint32_t* CRCDest);
bool NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize);
bool NVMTarget_WriteByteMemory(uint8_t WriteCommand, uint32_t WriteAddress, uint8_t* WriteBuffer,
uint16_t WriteSize);
bool NVMTarget_WriteByteMemory(uint8_t WriteCommand, uint32_t WriteAddress, uint8_t* WriteBuffer);
bool NVMTarget_WritePageMemory(uint8_t WriteBuffCommand, uint8_t EraseBuffCommand, uint8_t WritePageCommand,
uint8_t PageMode, uint32_t WriteAddress, uint8_t* WriteBuffer, uint16_t WriteSize);
bool NVMTarget_EraseMemory(uint8_t EraseCommand, uint32_t Address);
......
......@@ -37,8 +37,6 @@
#include "PDIProtocol.h"
#if defined(ENABLE_PDI_PROTOCOL) || defined(__DOXYGEN__)
#warning PDI Programming Protocol support is incomplete and not currently suitable for general use.
/** Base absolute address for the target's NVM controller */
uint32_t XPROG_Param_NVMBase;
......@@ -164,6 +162,7 @@ static void PDIProtocol_Erase(void)
uint8_t EraseCommand = NVM_CMD_NOOP;
/* Determine which NVM command to send to the device depending on the memory to erase */
if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_CHIP)
EraseCommand = NVM_CMD_CHIPERASE;
else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_APP)
......@@ -181,6 +180,7 @@ static void PDIProtocol_Erase(void)
else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_USERSIG)
EraseCommand = NVM_CMD_ERASEUSERSIG;
/* Erase the target memory, indicate timeout if ocurred */
if (!(NVMTarget_EraseMemory(EraseCommand, Erase_XPROG_Params.Address)))
ReturnStatus = XPRG_ERR_TIMEOUT;
......@@ -213,65 +213,51 @@ static void PDIProtocol_WriteMemory(void)
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t WriteCommand = NVM_CMD_NOOP;
uint8_t WriteBuffCommand = NVM_CMD_NOOP;
uint8_t EraseBuffCommand = NVM_CMD_NOOP;
bool PagedMemory = false;
/* Assume FLASH page programming by default, as it is the common case */
uint8_t WriteCommand = NVM_CMD_WRITEFLASHPAGE;
uint8_t WriteBuffCommand = NVM_CMD_LOADFLASHPAGEBUFF;
uint8_t EraseBuffCommand = NVM_CMD_ERASEFLASHPAGEBUFF;
bool PagedMemory = true;
if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_APPL)
{
WriteCommand = NVM_CMD_ERASEWRITEFLASH;
WriteBuffCommand = NVM_CMD_LOADFLASHPAGEBUFF;
EraseBuffCommand = NVM_CMD_ERASEFLASHPAGEBUFF;
PagedMemory = true;
WriteCommand = NVM_CMD_WRITEAPPSECPAGE;
}
else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_BOOT)
{
WriteCommand = NVM_CMD_ERASEWRITEFLASH;
WriteBuffCommand = NVM_CMD_LOADFLASHPAGEBUFF;
EraseBuffCommand = NVM_CMD_ERASEFLASHPAGEBUFF;
PagedMemory = true;
WriteCommand = NVM_CMD_WRITEBOOTSECPAGE;
}
else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_EEPROM)
{
WriteCommand = NVM_CMD_ERASEWRITEEEPROMPAGE;
WriteCommand = NVM_CMD_WRITEEEPROMPAGE;
WriteBuffCommand = NVM_CMD_LOADEEPROMPAGEBUFF;
EraseBuffCommand = NVM_CMD_ERASEEEPROMPAGEBUFF;
PagedMemory = true;
}
else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_USERSIG)
{
/* User signature is paged, but needs us to manually indicate the mode bits since the host doesn't set them */
WriteMemory_XPROG_Params.PageMode = (XPRG_PAGEMODE_ERASE | XPRG_PAGEMODE_WRITE);
WriteCommand = NVM_CMD_WRITEUSERSIG;
WriteBuffCommand = NVM_CMD_LOADFLASHPAGEBUFF;
EraseBuffCommand = NVM_CMD_ERASEFLASHPAGEBUFF;
PagedMemory = true;
}
else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_FUSE)
{
WriteCommand = NVM_CMD_WRITEFUSE;
WriteCommand = NVM_CMD_WRITEFUSE;
PagedMemory = false;
}
else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_LOCKBITS)
{
WriteCommand = NVM_CMD_WRITELOCK;
WriteCommand = NVM_CMD_WRITELOCK;
PagedMemory = false;
}
if (PagedMemory)
{
if (!(NVMTarget_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand,
WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address,
WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length)))
{
ReturnStatus = XPRG_ERR_TIMEOUT;
}
}
else
/* Send the appropriate memory write commands to the device, indicate timeout if occurred */
if ((PagedMemory && !NVMTarget_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand,
WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address,
WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length)) ||
(!PagedMemory && !NVMTarget_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address,
WriteMemory_XPROG_Params.ProgData)))
{
if (!(NVMTarget_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address, WriteMemory_XPROG_Params.ProgData,
WriteMemory_XPROG_Params.Length)))
{
ReturnStatus = XPRG_ERR_TIMEOUT;
}
ReturnStatus = XPRG_ERR_TIMEOUT;
}
Endpoint_Write_Byte(CMD_XPROG);
......@@ -301,8 +287,9 @@ static void PDIProtocol_ReadMemory(void)
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
uint8_t ReadBuffer[ReadMemory_XPROG_Params.Length];
uint8_t ReadBuffer[256];
/* Read the target's memory, indicate timeout if occurred */
if (!(NVMTarget_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length)))
ReturnStatus = XPRG_ERR_TIMEOUT;
......@@ -335,6 +322,7 @@ static void PDIProtocol_ReadCRC(void)
uint8_t CRCCommand = NVM_CMD_NOOP;
uint32_t MemoryCRC;
/* Determine which NVM command to send to the device depending on the memory to CRC */
if (ReadCRC_XPROG_Params.CRCType == XPRG_CRC_APP)
CRCCommand = NVM_CMD_APPCRC;
else if (ReadCRC_XPROG_Params.CRCType == XPRG_CRC_BOOT)
......@@ -342,6 +330,7 @@ static void PDIProtocol_ReadCRC(void)
else
CRCCommand = NVM_CMD_FLASHCRC;
/* Perform and retrieve the memory CRC, indicate timeout if occurred */
if (!(NVMTarget_GetMemoryCRC(CRCCommand, &MemoryCRC)))
ReturnStatus = XPRG_ERR_TIMEOUT;
......@@ -367,6 +356,7 @@ static void PDIProtocol_SetParam(void)
uint8_t XPROGParam = Endpoint_Read_Byte();
/* Determine which parameter is being set, store the new parameter value */
if (XPROGParam == XPRG_PARAM_NVMBASE)
XPROG_Param_NVMBase = Endpoint_Read_DWord_BE();
else if (XPROGParam == XPRG_PARAM_EEPPAGESIZE)
......
......@@ -98,8 +98,8 @@
#define XPRG_PROTOCOL_PDI 0x00
#define XPRG_PROTOCOL_JTAG 0x01
#define XPRG_PAGEMODE_WRITE (1 << 0)
#define XPRG_PAGEMODE_ERASE (1 << 1)
#define XPRG_PAGEMODE_WRITE (1 << 1)
#define XPRG_PAGEMODE_ERASE (1 << 0)
/* External Variables: */
extern uint32_t XPROG_Param_NVMBase;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment