From 31d7194252cdde340fa874c258e257312cb3ba8f Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Wed, 23 Dec 2009 14:45:47 +0000 Subject: Make seperate ISP, PDI and TPI folders in the AVRISP project Lib subdirectory to hold each protocol's files. --- Projects/AVRISP/Lib/ISP/ISPProtocol.c | 474 ++++++++++++++++++++++++++++++++++ Projects/AVRISP/Lib/ISP/ISPProtocol.h | 97 +++++++ Projects/AVRISP/Lib/ISP/ISPTarget.c | 202 +++++++++++++++ Projects/AVRISP/Lib/ISP/ISPTarget.h | 76 ++++++ Projects/AVRISP/Lib/ISPProtocol.c | 474 ---------------------------------- Projects/AVRISP/Lib/ISPProtocol.h | 97 ------- Projects/AVRISP/Lib/ISPTarget.c | 202 --------------- Projects/AVRISP/Lib/ISPTarget.h | 76 ------ Projects/AVRISP/Lib/PDI/PDIProtocol.c | 376 +++++++++++++++++++++++++++ Projects/AVRISP/Lib/PDI/PDIProtocol.h | 122 +++++++++ Projects/AVRISP/Lib/PDI/PDITarget.c | 335 ++++++++++++++++++++++++ Projects/AVRISP/Lib/PDI/PDITarget.h | 112 ++++++++ Projects/AVRISP/Lib/PDI/XMEGANVM.c | 332 ++++++++++++++++++++++++ Projects/AVRISP/Lib/PDI/XMEGANVM.h | 121 +++++++++ Projects/AVRISP/Lib/PDIProtocol.c | 376 --------------------------- Projects/AVRISP/Lib/PDIProtocol.h | 122 --------- Projects/AVRISP/Lib/PDITarget.c | 335 ------------------------ Projects/AVRISP/Lib/PDITarget.h | 112 -------- Projects/AVRISP/Lib/TINYNVM.c | 43 --- Projects/AVRISP/Lib/TINYNVM.h | 62 ----- Projects/AVRISP/Lib/TPI/TINYNVM.c | 43 +++ Projects/AVRISP/Lib/TPI/TINYNVM.h | 62 +++++ Projects/AVRISP/Lib/TPI/TPIProtocol.c | 44 ++++ Projects/AVRISP/Lib/TPI/TPIProtocol.h | 58 +++++ Projects/AVRISP/Lib/TPI/TPITarget.c | 338 ++++++++++++++++++++++++ Projects/AVRISP/Lib/TPI/TPITarget.h | 101 ++++++++ Projects/AVRISP/Lib/TPIProtocol.c | 44 ---- Projects/AVRISP/Lib/TPIProtocol.h | 58 ----- Projects/AVRISP/Lib/TPITarget.c | 338 ------------------------ Projects/AVRISP/Lib/TPITarget.h | 101 -------- Projects/AVRISP/Lib/XMEGANVM.c | 332 ------------------------ Projects/AVRISP/Lib/XMEGANVM.h | 121 --------- 32 files changed, 2893 insertions(+), 2893 deletions(-) create mode 100644 Projects/AVRISP/Lib/ISP/ISPProtocol.c create mode 100644 Projects/AVRISP/Lib/ISP/ISPProtocol.h create mode 100644 Projects/AVRISP/Lib/ISP/ISPTarget.c create mode 100644 Projects/AVRISP/Lib/ISP/ISPTarget.h delete mode 100644 Projects/AVRISP/Lib/ISPProtocol.c delete mode 100644 Projects/AVRISP/Lib/ISPProtocol.h delete mode 100644 Projects/AVRISP/Lib/ISPTarget.c delete mode 100644 Projects/AVRISP/Lib/ISPTarget.h create mode 100644 Projects/AVRISP/Lib/PDI/PDIProtocol.c create mode 100644 Projects/AVRISP/Lib/PDI/PDIProtocol.h create mode 100644 Projects/AVRISP/Lib/PDI/PDITarget.c create mode 100644 Projects/AVRISP/Lib/PDI/PDITarget.h create mode 100644 Projects/AVRISP/Lib/PDI/XMEGANVM.c create mode 100644 Projects/AVRISP/Lib/PDI/XMEGANVM.h delete mode 100644 Projects/AVRISP/Lib/PDIProtocol.c delete mode 100644 Projects/AVRISP/Lib/PDIProtocol.h delete mode 100644 Projects/AVRISP/Lib/PDITarget.c delete mode 100644 Projects/AVRISP/Lib/PDITarget.h delete mode 100644 Projects/AVRISP/Lib/TINYNVM.c delete mode 100644 Projects/AVRISP/Lib/TINYNVM.h create mode 100644 Projects/AVRISP/Lib/TPI/TINYNVM.c create mode 100644 Projects/AVRISP/Lib/TPI/TINYNVM.h create mode 100644 Projects/AVRISP/Lib/TPI/TPIProtocol.c create mode 100644 Projects/AVRISP/Lib/TPI/TPIProtocol.h create mode 100644 Projects/AVRISP/Lib/TPI/TPITarget.c create mode 100644 Projects/AVRISP/Lib/TPI/TPITarget.h delete mode 100644 Projects/AVRISP/Lib/TPIProtocol.c delete mode 100644 Projects/AVRISP/Lib/TPIProtocol.h delete mode 100644 Projects/AVRISP/Lib/TPITarget.c delete mode 100644 Projects/AVRISP/Lib/TPITarget.h delete mode 100644 Projects/AVRISP/Lib/XMEGANVM.c delete mode 100644 Projects/AVRISP/Lib/XMEGANVM.h diff --git a/Projects/AVRISP/Lib/ISP/ISPProtocol.c b/Projects/AVRISP/Lib/ISP/ISPProtocol.c new file mode 100644 index 000000000..e769cee8a --- /dev/null +++ b/Projects/AVRISP/Lib/ISP/ISPProtocol.c @@ -0,0 +1,474 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * ISP Protocol handler, to process V2 Protocol wrapped ISP commands used in Atmel programmer devices. + */ + +#include "ISPProtocol.h" + +#if defined(ENABLE_ISP_PROTOCOL) || defined(__DOXYGEN__) + +/** Handler for the CMD_ENTER_PROGMODE_ISP command, which attempts to enter programming mode on + * the attached device, returning success or failure back to the host. + */ +void ISPProtocol_EnterISPMode(void) +{ + struct + { + uint8_t TimeoutMS; + uint8_t PinStabDelayMS; + uint8_t ExecutionDelayMS; + uint8_t SynchLoops; + uint8_t ByteDelay; + uint8_t PollValue; + uint8_t PollIndex; + uint8_t EnterProgBytes[4]; + } Enter_ISP_Params; + + Endpoint_Read_Stream_LE(&Enter_ISP_Params, sizeof(Enter_ISP_Params)); + + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + uint8_t ResponseStatus = STATUS_CMD_FAILED; + + CurrentAddress = 0; + + ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS); + SPI_Init(ISPTarget_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING | SPI_SAMPLE_LEADING | SPI_MODE_MASTER); + + while (Enter_ISP_Params.SynchLoops-- && (ResponseStatus == STATUS_CMD_FAILED)) + { + uint8_t ResponseBytes[4]; + + ISPTarget_ChangeTargetResetLine(true); + ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS); + + for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++) + { + ISPProtocol_DelayMS(Enter_ISP_Params.ByteDelay); + ResponseBytes[RByte] = SPI_TransferByte(Enter_ISP_Params.EnterProgBytes[RByte]); + } + + /* Check if polling disabled, or if the polled value matches the expected value */ + if (!(Enter_ISP_Params.PollIndex) || (ResponseBytes[Enter_ISP_Params.PollIndex - 1] == Enter_ISP_Params.PollValue)) + { + ResponseStatus = STATUS_CMD_OK; + } + else + { + ISPTarget_ChangeTargetResetLine(false); + ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS); + } + } + + Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP); + Endpoint_Write_Byte(ResponseStatus); + Endpoint_ClearIN(); +} + +/** Handler for the CMD_LEAVE_ISP command, which releases the target from programming mode. */ +void ISPProtocol_LeaveISPMode(void) +{ + struct + { + uint8_t PreDelayMS; + uint8_t PostDelayMS; + } Leave_ISP_Params; + + Endpoint_Read_Stream_LE(&Leave_ISP_Params, sizeof(Leave_ISP_Params)); + + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + ISPProtocol_DelayMS(Leave_ISP_Params.PreDelayMS); + ISPTarget_ChangeTargetResetLine(false); + SPI_ShutDown(); + ISPProtocol_DelayMS(Leave_ISP_Params.PostDelayMS); + + Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP); + Endpoint_Write_Byte(STATUS_CMD_OK); + Endpoint_ClearIN(); +} + +/** Handler for the CMD_PROGRAM_FLASH_ISP and CMD_PROGRAM_EEPROM_ISP commands, writing out bytes, + * words or pages of data to the attached device. + * + * \param[in] V2Command Issued V2 Protocol command byte from the host + */ +void ISPProtocol_ProgramMemory(uint8_t V2Command) +{ + struct + { + uint16_t BytesToWrite; + uint8_t ProgrammingMode; + uint8_t DelayMS; + uint8_t ProgrammingCommands[3]; + uint8_t PollValue1; + uint8_t PollValue2; + uint8_t ProgData[256]; // Note, the Jungo driver has a very short ACK timeout period, need to buffer the + } Write_Memory_Params; // whole page and ACK the packet as fast as possible to prevent it from aborting + + Endpoint_Read_Stream_LE(&Write_Memory_Params, (sizeof(Write_Memory_Params) - + sizeof(Write_Memory_Params.ProgData))); + + + Write_Memory_Params.BytesToWrite = SwapEndian_16(Write_Memory_Params.BytesToWrite); + + if (Write_Memory_Params.BytesToWrite > sizeof(Write_Memory_Params.ProgData)) + { + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + Endpoint_Write_Byte(V2Command); + Endpoint_Write_Byte(STATUS_CMD_FAILED); + Endpoint_ClearIN(); + return; + } + + Endpoint_Read_Stream_LE(&Write_Memory_Params.ProgData, Write_Memory_Params.BytesToWrite); + + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + uint8_t ProgrammingStatus = STATUS_CMD_OK; + uint16_t PollAddress = 0; + uint8_t PollValue = (V2Command == CMD_PROGRAM_FLASH_ISP) ? Write_Memory_Params.PollValue1 : + Write_Memory_Params.PollValue2; + uint8_t* NextWriteByte = Write_Memory_Params.ProgData; + + if (MustSetAddress) + { + if (CurrentAddress & (1UL << 31)) + ISPTarget_LoadExtendedAddress(); + + MustSetAddress = false; + } + + if (Write_Memory_Params.ProgrammingMode & PROG_MODE_PAGED_WRITES_MASK) + { + uint16_t StartAddress = (CurrentAddress & 0xFFFF); + + /* Paged mode memory programming */ + for (uint16_t CurrentByte = 0; CurrentByte < Write_Memory_Params.BytesToWrite; CurrentByte++) + { + bool IsOddByte = (CurrentByte & 0x01); + uint8_t ByteToWrite = *(NextWriteByte++); + + if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP)) + Write_Memory_Params.ProgrammingCommands[0] |= READ_WRITE_HIGH_BYTE_MASK; + else + Write_Memory_Params.ProgrammingCommands[0] &= ~READ_WRITE_HIGH_BYTE_MASK; + + SPI_SendByte(Write_Memory_Params.ProgrammingCommands[0]); + SPI_SendByte(CurrentAddress >> 8); + SPI_SendByte(CurrentAddress & 0xFF); + SPI_SendByte(ByteToWrite); + + if (!(PollAddress) && (ByteToWrite != PollValue)) + { + if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP)) + Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK; + + PollAddress = (CurrentAddress & 0xFFFF); + } + + if (IsOddByte || (V2Command == CMD_PROGRAM_EEPROM_ISP)) + CurrentAddress++; + } + + /* If the current page must be committed, send the PROGRAM PAGE command to the target */ + if (Write_Memory_Params.ProgrammingMode & PROG_MODE_COMMIT_PAGE_MASK) + { + SPI_SendByte(Write_Memory_Params.ProgrammingCommands[1]); + SPI_SendByte(StartAddress >> 8); + SPI_SendByte(StartAddress & 0xFF); + SPI_SendByte(0x00); + + /* Check if polling is possible, if not switch to timed delay mode */ + if (!(PollAddress)) + { + Write_Memory_Params.ProgrammingMode &= ~PROG_MODE_PAGED_VALUE_MASK; + Write_Memory_Params.ProgrammingMode |= PROG_MODE_PAGED_TIMEDELAY_MASK; + } + + ProgrammingStatus = ISPTarget_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue, + Write_Memory_Params.DelayMS, Write_Memory_Params.ProgrammingCommands[2]); + } + } + else + { + /* Word/byte mode memory programming */ + for (uint16_t CurrentByte = 0; CurrentByte < Write_Memory_Params.BytesToWrite; CurrentByte++) + { + bool IsOddByte = (CurrentByte & 0x01); + uint8_t ByteToWrite = *(NextWriteByte++); + + if (IsOddByte && (V2Command == CMD_READ_FLASH_ISP)) + Write_Memory_Params.ProgrammingCommands[0] |= READ_WRITE_HIGH_BYTE_MASK; + else + Write_Memory_Params.ProgrammingCommands[0] &= ~READ_WRITE_HIGH_BYTE_MASK; + + SPI_SendByte(Write_Memory_Params.ProgrammingCommands[0]); + SPI_SendByte(CurrentAddress >> 8); + SPI_SendByte(CurrentAddress & 0xFF); + SPI_SendByte(ByteToWrite); + + if (ByteToWrite != PollValue) + { + if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP)) + Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK; + + PollAddress = (CurrentAddress & 0xFFFF); + } + + if (IsOddByte || (V2Command == CMD_PROGRAM_EEPROM_ISP)) + CurrentAddress++; + + ProgrammingStatus = ISPTarget_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue, + Write_Memory_Params.DelayMS, Write_Memory_Params.ProgrammingCommands[2]); + + if (ProgrammingStatus != STATUS_CMD_OK) + break; + } + } + + Endpoint_Write_Byte(V2Command); + Endpoint_Write_Byte(ProgrammingStatus); + Endpoint_ClearIN(); +} + +/** Handler for the CMD_READ_FLASH_ISP and CMD_READ_EEPROM_ISP commands, reading in bytes, + * words or pages of data from the attached device. + * + * \param[in] V2Command Issued V2 Protocol command byte from the host + */ +void ISPProtocol_ReadMemory(uint8_t V2Command) +{ + struct + { + uint16_t BytesToRead; + uint8_t ReadMemoryCommand; + } Read_Memory_Params; + + Endpoint_Read_Stream_LE(&Read_Memory_Params, sizeof(Read_Memory_Params)); + Read_Memory_Params.BytesToRead = SwapEndian_16(Read_Memory_Params.BytesToRead); + + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + Endpoint_Write_Byte(V2Command); + Endpoint_Write_Byte(STATUS_CMD_OK); + + if (MustSetAddress) + { + if (CurrentAddress & (1UL << 31)) + ISPTarget_LoadExtendedAddress(); + + MustSetAddress = false; + } + + for (uint16_t CurrentByte = 0; CurrentByte < Read_Memory_Params.BytesToRead; CurrentByte++) + { + bool IsOddByte = (CurrentByte & 0x01); + + if (IsOddByte && (V2Command == CMD_READ_FLASH_ISP)) + Read_Memory_Params.ReadMemoryCommand |= READ_WRITE_HIGH_BYTE_MASK; + else + Read_Memory_Params.ReadMemoryCommand &= ~READ_WRITE_HIGH_BYTE_MASK; + + SPI_SendByte(Read_Memory_Params.ReadMemoryCommand); + SPI_SendByte(CurrentAddress >> 8); + SPI_SendByte(CurrentAddress & 0xFF); + Endpoint_Write_Byte(SPI_ReceiveByte()); + + /* Check if the endpoint bank is currently full */ + if (!(Endpoint_IsReadWriteAllowed())) + { + Endpoint_ClearIN(); + Endpoint_WaitUntilReady(); + } + + if ((IsOddByte && (V2Command == CMD_READ_FLASH_ISP)) || (V2Command == CMD_READ_EEPROM_ISP)) + CurrentAddress++; + } + + Endpoint_Write_Byte(STATUS_CMD_OK); + + bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed()); + Endpoint_ClearIN(); + + /* Ensure last packet is a short packet to terminate the transfer */ + if (IsEndpointFull) + { + Endpoint_WaitUntilReady(); + Endpoint_ClearIN(); + Endpoint_WaitUntilReady(); + } +} + +/** Handler for the CMD_CHI_ERASE_ISP command, clearing the target's FLASH memory. */ +void ISPProtocol_ChipErase(void) +{ + struct + { + uint8_t EraseDelayMS; + uint8_t PollMethod; + uint8_t EraseCommandBytes[4]; + } Erase_Chip_Params; + + Endpoint_Read_Stream_LE(&Erase_Chip_Params, sizeof(Erase_Chip_Params)); + + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + uint8_t ResponseStatus = STATUS_CMD_OK; + + for (uint8_t SByte = 0; SByte < sizeof(Erase_Chip_Params.EraseCommandBytes); SByte++) + SPI_SendByte(Erase_Chip_Params.EraseCommandBytes[SByte]); + + if (!(Erase_Chip_Params.PollMethod)) + ISPProtocol_DelayMS(Erase_Chip_Params.EraseDelayMS); + else + ResponseStatus = ISPTarget_WaitWhileTargetBusy(); + + Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP); + Endpoint_Write_Byte(ResponseStatus); + Endpoint_ClearIN(); +} + +/** Handler for the CMD_READ_FUSE_ISP, CMD_READ_LOCK_ISP, CMD_READ_SIGNATURE_ISP and CMD_READ_OSCCAL commands, + * reading the requested configuration byte from the device. + * + * \param[in] V2Command Issued V2 Protocol command byte from the host + */ +void ISPProtocol_ReadFuseLockSigOSCCAL(uint8_t V2Command) +{ + struct + { + uint8_t RetByte; + uint8_t ReadCommandBytes[4]; + } Read_FuseLockSigOSCCAL_Params; + + Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params, sizeof(Read_FuseLockSigOSCCAL_Params)); + + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + uint8_t ResponseBytes[4]; + + for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++) + ResponseBytes[RByte] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]); + + Endpoint_Write_Byte(V2Command); + Endpoint_Write_Byte(STATUS_CMD_OK); + Endpoint_Write_Byte(ResponseBytes[Read_FuseLockSigOSCCAL_Params.RetByte - 1]); + Endpoint_Write_Byte(STATUS_CMD_OK); + Endpoint_ClearIN(); +} + +/** Handler for the CMD_WRITE_FUSE_ISP and CMD_WRITE_LOCK_ISP commands, writing the requested configuration + * byte to the device. + * + * \param[in] V2Command Issued V2 Protocol command byte from the host + */ +void ISPProtocol_WriteFuseLock(uint8_t V2Command) +{ + struct + { + uint8_t WriteCommandBytes[4]; + } Write_FuseLockSig_Params; + + Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params, sizeof(Write_FuseLockSig_Params)); + + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + for (uint8_t SByte = 0; SByte < sizeof(Write_FuseLockSig_Params.WriteCommandBytes); SByte++) + SPI_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]); + + Endpoint_Write_Byte(V2Command); + Endpoint_Write_Byte(STATUS_CMD_OK); + Endpoint_Write_Byte(STATUS_CMD_OK); + Endpoint_ClearIN(); +} + +/** Handler for the CMD_SPI_MULTI command, writing and reading arbitrary SPI data to and from the attached device. */ +void ISPProtocol_SPIMulti(void) +{ + struct + { + uint8_t TxBytes; + uint8_t RxBytes; + uint8_t RxStartAddr; + uint8_t TxData[255]; + } SPI_Multi_Params; + + Endpoint_Read_Stream_LE(&SPI_Multi_Params, sizeof(SPI_Multi_Params) - sizeof(SPI_Multi_Params.TxData)); + Endpoint_Read_Stream_LE(&SPI_Multi_Params.TxData, SPI_Multi_Params.TxBytes); + + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + Endpoint_Write_Byte(CMD_SPI_MULTI); + Endpoint_Write_Byte(STATUS_CMD_OK); + + uint8_t CurrTxPos = 0; + uint8_t CurrRxPos = 0; + + /* Write out bytes to transmit until the start of the bytes to receive is met */ + while (CurrTxPos < SPI_Multi_Params.RxStartAddr) + { + if (CurrTxPos < SPI_Multi_Params.TxBytes) + SPI_SendByte(SPI_Multi_Params.TxData[CurrTxPos]); + else + SPI_SendByte(0); + + CurrTxPos++; + } + + /* Transmit remaining bytes with padding as needed, read in response bytes */ + while (CurrRxPos < SPI_Multi_Params.RxBytes) + { + if (CurrTxPos < SPI_Multi_Params.TxBytes) + Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params.TxData[CurrTxPos++])); + else + Endpoint_Write_Byte(SPI_ReceiveByte()); + + CurrRxPos++; + } + + Endpoint_Write_Byte(STATUS_CMD_OK); + Endpoint_ClearIN(); +} + +#endif \ No newline at end of file diff --git a/Projects/AVRISP/Lib/ISP/ISPProtocol.h b/Projects/AVRISP/Lib/ISP/ISPProtocol.h new file mode 100644 index 000000000..85a669a4e --- /dev/null +++ b/Projects/AVRISP/Lib/ISP/ISPProtocol.h @@ -0,0 +1,97 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for ISPProtocol.c. + */ + +#ifndef _ISP_PROTOCOL_ +#define _ISP_PROTOCOL_ + + /* Includes: */ + #include + + #include "V2Protocol.h" + + /* Preprocessor Checks: */ + #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) + #undef ENABLE_ISP_PROTOCOL + #undef ENABLE_TPI_PROTOCOL + + #if !defined(ENABLE_PDI_PROTOCOL) + #define ENABLE_PDI_PROTOCOL + #endif + #endif + + /* Macros: */ + /** Mask for the reading or writing of the high byte in a FLASH word when issuing a low-level programming command */ + #define READ_WRITE_HIGH_BYTE_MASK (1 << 3) + + #define PROG_MODE_PAGED_WRITES_MASK (1 << 0) + #define PROG_MODE_WORD_TIMEDELAY_MASK (1 << 1) + #define PROG_MODE_WORD_VALUE_MASK (1 << 2) + #define PROG_MODE_WORD_READYBUSY_MASK (1 << 3) + #define PROG_MODE_PAGED_TIMEDELAY_MASK (1 << 4) + #define PROG_MODE_PAGED_VALUE_MASK (1 << 5) + #define PROG_MODE_PAGED_READYBUSY_MASK (1 << 6) + #define PROG_MODE_COMMIT_PAGE_MASK (1 << 7) + + /* Inline Functions: */ + /** Blocking delay for a given number of milliseconds, via a hardware timer. + * + * \param[in] DelayMS Number of milliseconds to delay for + */ + static inline void ISPProtocol_DelayMS(uint8_t DelayMS) + { + TCNT0 = 0; + TIFR0 = (1 << OCF1A); + + while (DelayMS) + { + if (TIFR0 & (1 << OCF1A)) + { + TIFR0 = (1 << OCF1A); + DelayMS--; + } + } + } + + /* Function Prototypes: */ + void ISPProtocol_EnterISPMode(void); + void ISPProtocol_LeaveISPMode(void); + void ISPProtocol_ProgramMemory(const uint8_t V2Command); + void ISPProtocol_ReadMemory(const uint8_t V2Command); + void ISPProtocol_ChipErase(void); + void ISPProtocol_ReadFuseLockSigOSCCAL(const uint8_t V2Command); + void ISPProtocol_WriteFuseLock(const uint8_t V2Command); + void ISPProtocol_SPIMulti(void); + +#endif diff --git a/Projects/AVRISP/Lib/ISP/ISPTarget.c b/Projects/AVRISP/Lib/ISP/ISPTarget.c new file mode 100644 index 000000000..e99e3e53c --- /dev/null +++ b/Projects/AVRISP/Lib/ISP/ISPTarget.c @@ -0,0 +1,202 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Target-related functions for the ISP Protocol decoder. + */ + +#include "ISPTarget.h" + +#if defined(ENABLE_ISP_PROTOCOL) || defined(__DOXYGEN__) + +/** Converts the given AVR Studio SCK duration parameter (set by a SET PARAM command from the host) to the nearest + * possible SPI clock prescaler mask for passing to the SPI_Init() routine. + * + * \return Nearest SPI prescaler mask for the given SCK frequency + */ +uint8_t ISPTarget_GetSPIPrescalerMask(void) +{ + static const uint8_t SPIMaskFromSCKDuration[] = + { + #if (F_CPU == 8000000) + SPI_SPEED_FCPU_DIV_2, // AVRStudio = 8MHz SPI, Actual = 4MHz SPI + SPI_SPEED_FCPU_DIV_2, // AVRStudio = 4MHz SPI, Actual = 4MHz SPI + SPI_SPEED_FCPU_DIV_4, // AVRStudio = 2MHz SPI, Actual = 2MHz SPI + SPI_SPEED_FCPU_DIV_8, // AVRStudio = 1MHz SPI, Actual = 1MHz SPI + SPI_SPEED_FCPU_DIV_16, // AVRStudio = 500KHz SPI, Actual = 500KHz SPI + SPI_SPEED_FCPU_DIV_32, // AVRStudio = 250KHz SPI, Actual = 250KHz SPI + SPI_SPEED_FCPU_DIV_64 // AVRStudio = 125KHz SPI, Actual = 125KHz SPI + #elif (F_CPU == 16000000) + SPI_SPEED_FCPU_DIV_2, // AVRStudio = 8MHz SPI, Actual = 8MHz SPI + SPI_SPEED_FCPU_DIV_4, // AVRStudio = 4MHz SPI, Actual = 4MHz SPI + SPI_SPEED_FCPU_DIV_8, // AVRStudio = 2MHz SPI, Actual = 2MHz SPI + SPI_SPEED_FCPU_DIV_16, // AVRStudio = 1MHz SPI, Actual = 1MHz SPI + SPI_SPEED_FCPU_DIV_32, // AVRStudio = 500KHz SPI, Actual = 500KHz SPI + SPI_SPEED_FCPU_DIV_64, // AVRStudio = 250KHz SPI, Actual = 250KHz SPI + SPI_SPEED_FCPU_DIV_128 // AVRStudio = 125KHz SPI, Actual = 125KHz SPI + #else + #error No SPI prescaler masks for chosen F_CPU speed. + #endif + }; + + uint8_t SCKDuration = V2Params_GetParameterValue(PARAM_SCK_DURATION); + + if (SCKDuration >= sizeof(SPIMaskFromSCKDuration)) + SCKDuration = (sizeof(SPIMaskFromSCKDuration) - 1); + + return SPIMaskFromSCKDuration[SCKDuration]; +} + +/** Asserts or deasserts the target's reset line, using the correct polarity as set by the host using a SET PARAM command. + * When not asserted, the line is tristated so as not to interfere with normal device operation. + * + * \param[in] ResetTarget Boolean true when the target should be held in reset, false otherwise + */ +void ISPTarget_ChangeTargetResetLine(const bool ResetTarget) +{ + if (ResetTarget) + { + RESET_LINE_DDR |= RESET_LINE_MASK; + + if (!(V2Params_GetParameterValue(PARAM_RESET_POLARITY))) + RESET_LINE_PORT |= RESET_LINE_MASK; + } + else + { + RESET_LINE_DDR &= ~RESET_LINE_MASK; + RESET_LINE_PORT &= ~RESET_LINE_MASK; + } +} + +/** Waits until the last issued target memory programming command has completed, via the check mode given and using + * the given parameters. + * + * \param[in] ProgrammingMode Programming mode used and completion check to use, a mask of PROG_MODE_* constants + * \param[in] PollAddress Memory address to poll for completion if polling check mode used + * \param[in] PollValue Poll value to check against if polling check mode used + * \param[in] DelayMS Milliseconds to delay before returning if delay check mode used + * \param[in] ReadMemCommand Device low-level READ MEMORY command to send if value check mode used + * + * \return V2 Protocol status \ref STATUS_CMD_OK if the no timeout occurred, \ref STATUS_RDY_BSY_TOUT or + * \ref STATUS_CMD_TOUT otherwise + */ +uint8_t ISPTarget_WaitForProgComplete(const uint8_t ProgrammingMode, const uint16_t PollAddress, const uint8_t PollValue, + const uint8_t DelayMS, const uint8_t ReadMemCommand) +{ + uint8_t ProgrammingStatus = STATUS_CMD_OK; + + /* Determine method of Programming Complete check */ + switch (ProgrammingMode & ~(PROG_MODE_PAGED_WRITES_MASK | PROG_MODE_COMMIT_PAGE_MASK)) + { + case PROG_MODE_WORD_TIMEDELAY_MASK: + case PROG_MODE_PAGED_TIMEDELAY_MASK: + ISPProtocol_DelayMS(DelayMS); + break; + case PROG_MODE_WORD_VALUE_MASK: + case PROG_MODE_PAGED_VALUE_MASK: + TCNT0 = 0; + TIFR0 = (1 << OCF1A); + + uint8_t TimeoutMS = TARGET_BUSY_TIMEOUT_MS; + + do + { + SPI_SendByte(ReadMemCommand); + SPI_SendByte(PollAddress >> 8); + SPI_SendByte(PollAddress & 0xFF); + + if (TIFR0 & (1 << OCF1A)) + { + TIFR0 = (1 << OCF1A); + TimeoutMS--; + } + } + while ((SPI_TransferByte(0x00) != PollValue) && TimeoutMS); + + if (!(TimeoutMS)) + ProgrammingStatus = STATUS_CMD_TOUT; + + break; + case PROG_MODE_WORD_READYBUSY_MASK: + case PROG_MODE_PAGED_READYBUSY_MASK: + ProgrammingStatus = ISPTarget_WaitWhileTargetBusy(); + break; + } + + return ProgrammingStatus; +} + +/** Waits until the target has completed the last operation, by continuously polling the device's + * BUSY flag until it is cleared, or until the \ref TARGET_BUSY_TIMEOUT_MS timeout period has expired. + * + * \return V2 Protocol status \ref STATUS_CMD_OK if the no timeout occurred, \ref STATUS_RDY_BSY_TOUT otherwise + */ +uint8_t ISPTarget_WaitWhileTargetBusy(void) +{ + TCNT0 = 0; + TIFR0 = (1 << OCF1A); + + uint8_t TimeoutMS = TARGET_BUSY_TIMEOUT_MS; + + do + { + SPI_SendByte(0xF0); + SPI_SendByte(0x00); + + SPI_SendByte(0x00); + + if (TIFR0 & (1 << OCF1A)) + { + TIFR0 = (1 << OCF1A); + TimeoutMS--; + } + } + while ((SPI_ReceiveByte() & 0x01) && TimeoutMS); + + if (!(TimeoutMS)) + return STATUS_RDY_BSY_TOUT; + else + return STATUS_CMD_OK; +} + +/** Sends a low-level LOAD EXTENDED ADDRESS command to the target, for addressing of memory beyond the + * 64KB boundary. This sends the command with the correct address as indicated by the current address + * pointer variable set by the host when a SET ADDRESS command is issued. + */ +void ISPTarget_LoadExtendedAddress(void) +{ + SPI_SendByte(0x4D); + SPI_SendByte(0x00); + SPI_SendByte((CurrentAddress & 0x00FF0000) >> 16); + SPI_SendByte(0x00); +} + +#endif diff --git a/Projects/AVRISP/Lib/ISP/ISPTarget.h b/Projects/AVRISP/Lib/ISP/ISPTarget.h new file mode 100644 index 000000000..62d8bbb4b --- /dev/null +++ b/Projects/AVRISP/Lib/ISP/ISPTarget.h @@ -0,0 +1,76 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for ISPTarget.c. + */ + +#ifndef _ISP_TARGET_ +#define _ISP_TARGET_ + + /* Includes: */ + #include + #include + + #include + #include + + #include "../Descriptors.h" + #include "V2ProtocolConstants.h" + #include "V2ProtocolParams.h" + + /* Preprocessor Checks: */ + #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) + #undef ENABLE_ISP_PROTOCOL + #undef ENABLE_TPI_PROTOCOL + + #if !defined(ENABLE_PDI_PROTOCOL) + #define ENABLE_PDI_PROTOCOL + #endif + #endif + + /* Macros: */ + /** Total number of allowable ISP programming speeds supported by the device */ + #define TOTAL_ISP_PROGRAMMING_SPEEDS 7 + + /** Timeout in milliseconds of target busy-wait loops waiting for a command to complete */ + #define TARGET_BUSY_TIMEOUT_MS 100 + + /* Function Prototypes: */ + uint8_t ISPTarget_GetSPIPrescalerMask(void); + void ISPTarget_ChangeTargetResetLine(const bool ResetTarget); + uint8_t ISPTarget_WaitForProgComplete(const uint8_t ProgrammingMode, const uint16_t PollAddress, + const uint8_t PollValue, const uint8_t DelayMS, + const uint8_t ReadMemCommand); + uint8_t ISPTarget_WaitWhileTargetBusy(void); + void ISPTarget_LoadExtendedAddress(void); + +#endif diff --git a/Projects/AVRISP/Lib/ISPProtocol.c b/Projects/AVRISP/Lib/ISPProtocol.c deleted file mode 100644 index e769cee8a..000000000 --- a/Projects/AVRISP/Lib/ISPProtocol.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * ISP Protocol handler, to process V2 Protocol wrapped ISP commands used in Atmel programmer devices. - */ - -#include "ISPProtocol.h" - -#if defined(ENABLE_ISP_PROTOCOL) || defined(__DOXYGEN__) - -/** Handler for the CMD_ENTER_PROGMODE_ISP command, which attempts to enter programming mode on - * the attached device, returning success or failure back to the host. - */ -void ISPProtocol_EnterISPMode(void) -{ - struct - { - uint8_t TimeoutMS; - uint8_t PinStabDelayMS; - uint8_t ExecutionDelayMS; - uint8_t SynchLoops; - uint8_t ByteDelay; - uint8_t PollValue; - uint8_t PollIndex; - uint8_t EnterProgBytes[4]; - } Enter_ISP_Params; - - Endpoint_Read_Stream_LE(&Enter_ISP_Params, sizeof(Enter_ISP_Params)); - - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - uint8_t ResponseStatus = STATUS_CMD_FAILED; - - CurrentAddress = 0; - - ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS); - SPI_Init(ISPTarget_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING | SPI_SAMPLE_LEADING | SPI_MODE_MASTER); - - while (Enter_ISP_Params.SynchLoops-- && (ResponseStatus == STATUS_CMD_FAILED)) - { - uint8_t ResponseBytes[4]; - - ISPTarget_ChangeTargetResetLine(true); - ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS); - - for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++) - { - ISPProtocol_DelayMS(Enter_ISP_Params.ByteDelay); - ResponseBytes[RByte] = SPI_TransferByte(Enter_ISP_Params.EnterProgBytes[RByte]); - } - - /* Check if polling disabled, or if the polled value matches the expected value */ - if (!(Enter_ISP_Params.PollIndex) || (ResponseBytes[Enter_ISP_Params.PollIndex - 1] == Enter_ISP_Params.PollValue)) - { - ResponseStatus = STATUS_CMD_OK; - } - else - { - ISPTarget_ChangeTargetResetLine(false); - ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS); - } - } - - Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP); - Endpoint_Write_Byte(ResponseStatus); - Endpoint_ClearIN(); -} - -/** Handler for the CMD_LEAVE_ISP command, which releases the target from programming mode. */ -void ISPProtocol_LeaveISPMode(void) -{ - struct - { - uint8_t PreDelayMS; - uint8_t PostDelayMS; - } Leave_ISP_Params; - - Endpoint_Read_Stream_LE(&Leave_ISP_Params, sizeof(Leave_ISP_Params)); - - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - ISPProtocol_DelayMS(Leave_ISP_Params.PreDelayMS); - ISPTarget_ChangeTargetResetLine(false); - SPI_ShutDown(); - ISPProtocol_DelayMS(Leave_ISP_Params.PostDelayMS); - - Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP); - Endpoint_Write_Byte(STATUS_CMD_OK); - Endpoint_ClearIN(); -} - -/** Handler for the CMD_PROGRAM_FLASH_ISP and CMD_PROGRAM_EEPROM_ISP commands, writing out bytes, - * words or pages of data to the attached device. - * - * \param[in] V2Command Issued V2 Protocol command byte from the host - */ -void ISPProtocol_ProgramMemory(uint8_t V2Command) -{ - struct - { - uint16_t BytesToWrite; - uint8_t ProgrammingMode; - uint8_t DelayMS; - uint8_t ProgrammingCommands[3]; - uint8_t PollValue1; - uint8_t PollValue2; - uint8_t ProgData[256]; // Note, the Jungo driver has a very short ACK timeout period, need to buffer the - } Write_Memory_Params; // whole page and ACK the packet as fast as possible to prevent it from aborting - - Endpoint_Read_Stream_LE(&Write_Memory_Params, (sizeof(Write_Memory_Params) - - sizeof(Write_Memory_Params.ProgData))); - - - Write_Memory_Params.BytesToWrite = SwapEndian_16(Write_Memory_Params.BytesToWrite); - - if (Write_Memory_Params.BytesToWrite > sizeof(Write_Memory_Params.ProgData)) - { - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - Endpoint_Write_Byte(V2Command); - Endpoint_Write_Byte(STATUS_CMD_FAILED); - Endpoint_ClearIN(); - return; - } - - Endpoint_Read_Stream_LE(&Write_Memory_Params.ProgData, Write_Memory_Params.BytesToWrite); - - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - uint8_t ProgrammingStatus = STATUS_CMD_OK; - uint16_t PollAddress = 0; - uint8_t PollValue = (V2Command == CMD_PROGRAM_FLASH_ISP) ? Write_Memory_Params.PollValue1 : - Write_Memory_Params.PollValue2; - uint8_t* NextWriteByte = Write_Memory_Params.ProgData; - - if (MustSetAddress) - { - if (CurrentAddress & (1UL << 31)) - ISPTarget_LoadExtendedAddress(); - - MustSetAddress = false; - } - - if (Write_Memory_Params.ProgrammingMode & PROG_MODE_PAGED_WRITES_MASK) - { - uint16_t StartAddress = (CurrentAddress & 0xFFFF); - - /* Paged mode memory programming */ - for (uint16_t CurrentByte = 0; CurrentByte < Write_Memory_Params.BytesToWrite; CurrentByte++) - { - bool IsOddByte = (CurrentByte & 0x01); - uint8_t ByteToWrite = *(NextWriteByte++); - - if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP)) - Write_Memory_Params.ProgrammingCommands[0] |= READ_WRITE_HIGH_BYTE_MASK; - else - Write_Memory_Params.ProgrammingCommands[0] &= ~READ_WRITE_HIGH_BYTE_MASK; - - SPI_SendByte(Write_Memory_Params.ProgrammingCommands[0]); - SPI_SendByte(CurrentAddress >> 8); - SPI_SendByte(CurrentAddress & 0xFF); - SPI_SendByte(ByteToWrite); - - if (!(PollAddress) && (ByteToWrite != PollValue)) - { - if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP)) - Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK; - - PollAddress = (CurrentAddress & 0xFFFF); - } - - if (IsOddByte || (V2Command == CMD_PROGRAM_EEPROM_ISP)) - CurrentAddress++; - } - - /* If the current page must be committed, send the PROGRAM PAGE command to the target */ - if (Write_Memory_Params.ProgrammingMode & PROG_MODE_COMMIT_PAGE_MASK) - { - SPI_SendByte(Write_Memory_Params.ProgrammingCommands[1]); - SPI_SendByte(StartAddress >> 8); - SPI_SendByte(StartAddress & 0xFF); - SPI_SendByte(0x00); - - /* Check if polling is possible, if not switch to timed delay mode */ - if (!(PollAddress)) - { - Write_Memory_Params.ProgrammingMode &= ~PROG_MODE_PAGED_VALUE_MASK; - Write_Memory_Params.ProgrammingMode |= PROG_MODE_PAGED_TIMEDELAY_MASK; - } - - ProgrammingStatus = ISPTarget_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue, - Write_Memory_Params.DelayMS, Write_Memory_Params.ProgrammingCommands[2]); - } - } - else - { - /* Word/byte mode memory programming */ - for (uint16_t CurrentByte = 0; CurrentByte < Write_Memory_Params.BytesToWrite; CurrentByte++) - { - bool IsOddByte = (CurrentByte & 0x01); - uint8_t ByteToWrite = *(NextWriteByte++); - - if (IsOddByte && (V2Command == CMD_READ_FLASH_ISP)) - Write_Memory_Params.ProgrammingCommands[0] |= READ_WRITE_HIGH_BYTE_MASK; - else - Write_Memory_Params.ProgrammingCommands[0] &= ~READ_WRITE_HIGH_BYTE_MASK; - - SPI_SendByte(Write_Memory_Params.ProgrammingCommands[0]); - SPI_SendByte(CurrentAddress >> 8); - SPI_SendByte(CurrentAddress & 0xFF); - SPI_SendByte(ByteToWrite); - - if (ByteToWrite != PollValue) - { - if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP)) - Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK; - - PollAddress = (CurrentAddress & 0xFFFF); - } - - if (IsOddByte || (V2Command == CMD_PROGRAM_EEPROM_ISP)) - CurrentAddress++; - - ProgrammingStatus = ISPTarget_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue, - Write_Memory_Params.DelayMS, Write_Memory_Params.ProgrammingCommands[2]); - - if (ProgrammingStatus != STATUS_CMD_OK) - break; - } - } - - Endpoint_Write_Byte(V2Command); - Endpoint_Write_Byte(ProgrammingStatus); - Endpoint_ClearIN(); -} - -/** Handler for the CMD_READ_FLASH_ISP and CMD_READ_EEPROM_ISP commands, reading in bytes, - * words or pages of data from the attached device. - * - * \param[in] V2Command Issued V2 Protocol command byte from the host - */ -void ISPProtocol_ReadMemory(uint8_t V2Command) -{ - struct - { - uint16_t BytesToRead; - uint8_t ReadMemoryCommand; - } Read_Memory_Params; - - Endpoint_Read_Stream_LE(&Read_Memory_Params, sizeof(Read_Memory_Params)); - Read_Memory_Params.BytesToRead = SwapEndian_16(Read_Memory_Params.BytesToRead); - - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - Endpoint_Write_Byte(V2Command); - Endpoint_Write_Byte(STATUS_CMD_OK); - - if (MustSetAddress) - { - if (CurrentAddress & (1UL << 31)) - ISPTarget_LoadExtendedAddress(); - - MustSetAddress = false; - } - - for (uint16_t CurrentByte = 0; CurrentByte < Read_Memory_Params.BytesToRead; CurrentByte++) - { - bool IsOddByte = (CurrentByte & 0x01); - - if (IsOddByte && (V2Command == CMD_READ_FLASH_ISP)) - Read_Memory_Params.ReadMemoryCommand |= READ_WRITE_HIGH_BYTE_MASK; - else - Read_Memory_Params.ReadMemoryCommand &= ~READ_WRITE_HIGH_BYTE_MASK; - - SPI_SendByte(Read_Memory_Params.ReadMemoryCommand); - SPI_SendByte(CurrentAddress >> 8); - SPI_SendByte(CurrentAddress & 0xFF); - Endpoint_Write_Byte(SPI_ReceiveByte()); - - /* Check if the endpoint bank is currently full */ - if (!(Endpoint_IsReadWriteAllowed())) - { - Endpoint_ClearIN(); - Endpoint_WaitUntilReady(); - } - - if ((IsOddByte && (V2Command == CMD_READ_FLASH_ISP)) || (V2Command == CMD_READ_EEPROM_ISP)) - CurrentAddress++; - } - - Endpoint_Write_Byte(STATUS_CMD_OK); - - bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed()); - Endpoint_ClearIN(); - - /* Ensure last packet is a short packet to terminate the transfer */ - if (IsEndpointFull) - { - Endpoint_WaitUntilReady(); - Endpoint_ClearIN(); - Endpoint_WaitUntilReady(); - } -} - -/** Handler for the CMD_CHI_ERASE_ISP command, clearing the target's FLASH memory. */ -void ISPProtocol_ChipErase(void) -{ - struct - { - uint8_t EraseDelayMS; - uint8_t PollMethod; - uint8_t EraseCommandBytes[4]; - } Erase_Chip_Params; - - Endpoint_Read_Stream_LE(&Erase_Chip_Params, sizeof(Erase_Chip_Params)); - - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - uint8_t ResponseStatus = STATUS_CMD_OK; - - for (uint8_t SByte = 0; SByte < sizeof(Erase_Chip_Params.EraseCommandBytes); SByte++) - SPI_SendByte(Erase_Chip_Params.EraseCommandBytes[SByte]); - - if (!(Erase_Chip_Params.PollMethod)) - ISPProtocol_DelayMS(Erase_Chip_Params.EraseDelayMS); - else - ResponseStatus = ISPTarget_WaitWhileTargetBusy(); - - Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP); - Endpoint_Write_Byte(ResponseStatus); - Endpoint_ClearIN(); -} - -/** Handler for the CMD_READ_FUSE_ISP, CMD_READ_LOCK_ISP, CMD_READ_SIGNATURE_ISP and CMD_READ_OSCCAL commands, - * reading the requested configuration byte from the device. - * - * \param[in] V2Command Issued V2 Protocol command byte from the host - */ -void ISPProtocol_ReadFuseLockSigOSCCAL(uint8_t V2Command) -{ - struct - { - uint8_t RetByte; - uint8_t ReadCommandBytes[4]; - } Read_FuseLockSigOSCCAL_Params; - - Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params, sizeof(Read_FuseLockSigOSCCAL_Params)); - - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - uint8_t ResponseBytes[4]; - - for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++) - ResponseBytes[RByte] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]); - - Endpoint_Write_Byte(V2Command); - Endpoint_Write_Byte(STATUS_CMD_OK); - Endpoint_Write_Byte(ResponseBytes[Read_FuseLockSigOSCCAL_Params.RetByte - 1]); - Endpoint_Write_Byte(STATUS_CMD_OK); - Endpoint_ClearIN(); -} - -/** Handler for the CMD_WRITE_FUSE_ISP and CMD_WRITE_LOCK_ISP commands, writing the requested configuration - * byte to the device. - * - * \param[in] V2Command Issued V2 Protocol command byte from the host - */ -void ISPProtocol_WriteFuseLock(uint8_t V2Command) -{ - struct - { - uint8_t WriteCommandBytes[4]; - } Write_FuseLockSig_Params; - - Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params, sizeof(Write_FuseLockSig_Params)); - - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - for (uint8_t SByte = 0; SByte < sizeof(Write_FuseLockSig_Params.WriteCommandBytes); SByte++) - SPI_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]); - - Endpoint_Write_Byte(V2Command); - Endpoint_Write_Byte(STATUS_CMD_OK); - Endpoint_Write_Byte(STATUS_CMD_OK); - Endpoint_ClearIN(); -} - -/** Handler for the CMD_SPI_MULTI command, writing and reading arbitrary SPI data to and from the attached device. */ -void ISPProtocol_SPIMulti(void) -{ - struct - { - uint8_t TxBytes; - uint8_t RxBytes; - uint8_t RxStartAddr; - uint8_t TxData[255]; - } SPI_Multi_Params; - - Endpoint_Read_Stream_LE(&SPI_Multi_Params, sizeof(SPI_Multi_Params) - sizeof(SPI_Multi_Params.TxData)); - Endpoint_Read_Stream_LE(&SPI_Multi_Params.TxData, SPI_Multi_Params.TxBytes); - - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - Endpoint_Write_Byte(CMD_SPI_MULTI); - Endpoint_Write_Byte(STATUS_CMD_OK); - - uint8_t CurrTxPos = 0; - uint8_t CurrRxPos = 0; - - /* Write out bytes to transmit until the start of the bytes to receive is met */ - while (CurrTxPos < SPI_Multi_Params.RxStartAddr) - { - if (CurrTxPos < SPI_Multi_Params.TxBytes) - SPI_SendByte(SPI_Multi_Params.TxData[CurrTxPos]); - else - SPI_SendByte(0); - - CurrTxPos++; - } - - /* Transmit remaining bytes with padding as needed, read in response bytes */ - while (CurrRxPos < SPI_Multi_Params.RxBytes) - { - if (CurrTxPos < SPI_Multi_Params.TxBytes) - Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params.TxData[CurrTxPos++])); - else - Endpoint_Write_Byte(SPI_ReceiveByte()); - - CurrRxPos++; - } - - Endpoint_Write_Byte(STATUS_CMD_OK); - Endpoint_ClearIN(); -} - -#endif \ No newline at end of file diff --git a/Projects/AVRISP/Lib/ISPProtocol.h b/Projects/AVRISP/Lib/ISPProtocol.h deleted file mode 100644 index 85a669a4e..000000000 --- a/Projects/AVRISP/Lib/ISPProtocol.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Header file for ISPProtocol.c. - */ - -#ifndef _ISP_PROTOCOL_ -#define _ISP_PROTOCOL_ - - /* Includes: */ - #include - - #include "V2Protocol.h" - - /* Preprocessor Checks: */ - #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) - #undef ENABLE_ISP_PROTOCOL - #undef ENABLE_TPI_PROTOCOL - - #if !defined(ENABLE_PDI_PROTOCOL) - #define ENABLE_PDI_PROTOCOL - #endif - #endif - - /* Macros: */ - /** Mask for the reading or writing of the high byte in a FLASH word when issuing a low-level programming command */ - #define READ_WRITE_HIGH_BYTE_MASK (1 << 3) - - #define PROG_MODE_PAGED_WRITES_MASK (1 << 0) - #define PROG_MODE_WORD_TIMEDELAY_MASK (1 << 1) - #define PROG_MODE_WORD_VALUE_MASK (1 << 2) - #define PROG_MODE_WORD_READYBUSY_MASK (1 << 3) - #define PROG_MODE_PAGED_TIMEDELAY_MASK (1 << 4) - #define PROG_MODE_PAGED_VALUE_MASK (1 << 5) - #define PROG_MODE_PAGED_READYBUSY_MASK (1 << 6) - #define PROG_MODE_COMMIT_PAGE_MASK (1 << 7) - - /* Inline Functions: */ - /** Blocking delay for a given number of milliseconds, via a hardware timer. - * - * \param[in] DelayMS Number of milliseconds to delay for - */ - static inline void ISPProtocol_DelayMS(uint8_t DelayMS) - { - TCNT0 = 0; - TIFR0 = (1 << OCF1A); - - while (DelayMS) - { - if (TIFR0 & (1 << OCF1A)) - { - TIFR0 = (1 << OCF1A); - DelayMS--; - } - } - } - - /* Function Prototypes: */ - void ISPProtocol_EnterISPMode(void); - void ISPProtocol_LeaveISPMode(void); - void ISPProtocol_ProgramMemory(const uint8_t V2Command); - void ISPProtocol_ReadMemory(const uint8_t V2Command); - void ISPProtocol_ChipErase(void); - void ISPProtocol_ReadFuseLockSigOSCCAL(const uint8_t V2Command); - void ISPProtocol_WriteFuseLock(const uint8_t V2Command); - void ISPProtocol_SPIMulti(void); - -#endif diff --git a/Projects/AVRISP/Lib/ISPTarget.c b/Projects/AVRISP/Lib/ISPTarget.c deleted file mode 100644 index e99e3e53c..000000000 --- a/Projects/AVRISP/Lib/ISPTarget.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Target-related functions for the ISP Protocol decoder. - */ - -#include "ISPTarget.h" - -#if defined(ENABLE_ISP_PROTOCOL) || defined(__DOXYGEN__) - -/** Converts the given AVR Studio SCK duration parameter (set by a SET PARAM command from the host) to the nearest - * possible SPI clock prescaler mask for passing to the SPI_Init() routine. - * - * \return Nearest SPI prescaler mask for the given SCK frequency - */ -uint8_t ISPTarget_GetSPIPrescalerMask(void) -{ - static const uint8_t SPIMaskFromSCKDuration[] = - { - #if (F_CPU == 8000000) - SPI_SPEED_FCPU_DIV_2, // AVRStudio = 8MHz SPI, Actual = 4MHz SPI - SPI_SPEED_FCPU_DIV_2, // AVRStudio = 4MHz SPI, Actual = 4MHz SPI - SPI_SPEED_FCPU_DIV_4, // AVRStudio = 2MHz SPI, Actual = 2MHz SPI - SPI_SPEED_FCPU_DIV_8, // AVRStudio = 1MHz SPI, Actual = 1MHz SPI - SPI_SPEED_FCPU_DIV_16, // AVRStudio = 500KHz SPI, Actual = 500KHz SPI - SPI_SPEED_FCPU_DIV_32, // AVRStudio = 250KHz SPI, Actual = 250KHz SPI - SPI_SPEED_FCPU_DIV_64 // AVRStudio = 125KHz SPI, Actual = 125KHz SPI - #elif (F_CPU == 16000000) - SPI_SPEED_FCPU_DIV_2, // AVRStudio = 8MHz SPI, Actual = 8MHz SPI - SPI_SPEED_FCPU_DIV_4, // AVRStudio = 4MHz SPI, Actual = 4MHz SPI - SPI_SPEED_FCPU_DIV_8, // AVRStudio = 2MHz SPI, Actual = 2MHz SPI - SPI_SPEED_FCPU_DIV_16, // AVRStudio = 1MHz SPI, Actual = 1MHz SPI - SPI_SPEED_FCPU_DIV_32, // AVRStudio = 500KHz SPI, Actual = 500KHz SPI - SPI_SPEED_FCPU_DIV_64, // AVRStudio = 250KHz SPI, Actual = 250KHz SPI - SPI_SPEED_FCPU_DIV_128 // AVRStudio = 125KHz SPI, Actual = 125KHz SPI - #else - #error No SPI prescaler masks for chosen F_CPU speed. - #endif - }; - - uint8_t SCKDuration = V2Params_GetParameterValue(PARAM_SCK_DURATION); - - if (SCKDuration >= sizeof(SPIMaskFromSCKDuration)) - SCKDuration = (sizeof(SPIMaskFromSCKDuration) - 1); - - return SPIMaskFromSCKDuration[SCKDuration]; -} - -/** Asserts or deasserts the target's reset line, using the correct polarity as set by the host using a SET PARAM command. - * When not asserted, the line is tristated so as not to interfere with normal device operation. - * - * \param[in] ResetTarget Boolean true when the target should be held in reset, false otherwise - */ -void ISPTarget_ChangeTargetResetLine(const bool ResetTarget) -{ - if (ResetTarget) - { - RESET_LINE_DDR |= RESET_LINE_MASK; - - if (!(V2Params_GetParameterValue(PARAM_RESET_POLARITY))) - RESET_LINE_PORT |= RESET_LINE_MASK; - } - else - { - RESET_LINE_DDR &= ~RESET_LINE_MASK; - RESET_LINE_PORT &= ~RESET_LINE_MASK; - } -} - -/** Waits until the last issued target memory programming command has completed, via the check mode given and using - * the given parameters. - * - * \param[in] ProgrammingMode Programming mode used and completion check to use, a mask of PROG_MODE_* constants - * \param[in] PollAddress Memory address to poll for completion if polling check mode used - * \param[in] PollValue Poll value to check against if polling check mode used - * \param[in] DelayMS Milliseconds to delay before returning if delay check mode used - * \param[in] ReadMemCommand Device low-level READ MEMORY command to send if value check mode used - * - * \return V2 Protocol status \ref STATUS_CMD_OK if the no timeout occurred, \ref STATUS_RDY_BSY_TOUT or - * \ref STATUS_CMD_TOUT otherwise - */ -uint8_t ISPTarget_WaitForProgComplete(const uint8_t ProgrammingMode, const uint16_t PollAddress, const uint8_t PollValue, - const uint8_t DelayMS, const uint8_t ReadMemCommand) -{ - uint8_t ProgrammingStatus = STATUS_CMD_OK; - - /* Determine method of Programming Complete check */ - switch (ProgrammingMode & ~(PROG_MODE_PAGED_WRITES_MASK | PROG_MODE_COMMIT_PAGE_MASK)) - { - case PROG_MODE_WORD_TIMEDELAY_MASK: - case PROG_MODE_PAGED_TIMEDELAY_MASK: - ISPProtocol_DelayMS(DelayMS); - break; - case PROG_MODE_WORD_VALUE_MASK: - case PROG_MODE_PAGED_VALUE_MASK: - TCNT0 = 0; - TIFR0 = (1 << OCF1A); - - uint8_t TimeoutMS = TARGET_BUSY_TIMEOUT_MS; - - do - { - SPI_SendByte(ReadMemCommand); - SPI_SendByte(PollAddress >> 8); - SPI_SendByte(PollAddress & 0xFF); - - if (TIFR0 & (1 << OCF1A)) - { - TIFR0 = (1 << OCF1A); - TimeoutMS--; - } - } - while ((SPI_TransferByte(0x00) != PollValue) && TimeoutMS); - - if (!(TimeoutMS)) - ProgrammingStatus = STATUS_CMD_TOUT; - - break; - case PROG_MODE_WORD_READYBUSY_MASK: - case PROG_MODE_PAGED_READYBUSY_MASK: - ProgrammingStatus = ISPTarget_WaitWhileTargetBusy(); - break; - } - - return ProgrammingStatus; -} - -/** Waits until the target has completed the last operation, by continuously polling the device's - * BUSY flag until it is cleared, or until the \ref TARGET_BUSY_TIMEOUT_MS timeout period has expired. - * - * \return V2 Protocol status \ref STATUS_CMD_OK if the no timeout occurred, \ref STATUS_RDY_BSY_TOUT otherwise - */ -uint8_t ISPTarget_WaitWhileTargetBusy(void) -{ - TCNT0 = 0; - TIFR0 = (1 << OCF1A); - - uint8_t TimeoutMS = TARGET_BUSY_TIMEOUT_MS; - - do - { - SPI_SendByte(0xF0); - SPI_SendByte(0x00); - - SPI_SendByte(0x00); - - if (TIFR0 & (1 << OCF1A)) - { - TIFR0 = (1 << OCF1A); - TimeoutMS--; - } - } - while ((SPI_ReceiveByte() & 0x01) && TimeoutMS); - - if (!(TimeoutMS)) - return STATUS_RDY_BSY_TOUT; - else - return STATUS_CMD_OK; -} - -/** Sends a low-level LOAD EXTENDED ADDRESS command to the target, for addressing of memory beyond the - * 64KB boundary. This sends the command with the correct address as indicated by the current address - * pointer variable set by the host when a SET ADDRESS command is issued. - */ -void ISPTarget_LoadExtendedAddress(void) -{ - SPI_SendByte(0x4D); - SPI_SendByte(0x00); - SPI_SendByte((CurrentAddress & 0x00FF0000) >> 16); - SPI_SendByte(0x00); -} - -#endif diff --git a/Projects/AVRISP/Lib/ISPTarget.h b/Projects/AVRISP/Lib/ISPTarget.h deleted file mode 100644 index 62d8bbb4b..000000000 --- a/Projects/AVRISP/Lib/ISPTarget.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Header file for ISPTarget.c. - */ - -#ifndef _ISP_TARGET_ -#define _ISP_TARGET_ - - /* Includes: */ - #include - #include - - #include - #include - - #include "../Descriptors.h" - #include "V2ProtocolConstants.h" - #include "V2ProtocolParams.h" - - /* Preprocessor Checks: */ - #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) - #undef ENABLE_ISP_PROTOCOL - #undef ENABLE_TPI_PROTOCOL - - #if !defined(ENABLE_PDI_PROTOCOL) - #define ENABLE_PDI_PROTOCOL - #endif - #endif - - /* Macros: */ - /** Total number of allowable ISP programming speeds supported by the device */ - #define TOTAL_ISP_PROGRAMMING_SPEEDS 7 - - /** Timeout in milliseconds of target busy-wait loops waiting for a command to complete */ - #define TARGET_BUSY_TIMEOUT_MS 100 - - /* Function Prototypes: */ - uint8_t ISPTarget_GetSPIPrescalerMask(void); - void ISPTarget_ChangeTargetResetLine(const bool ResetTarget); - uint8_t ISPTarget_WaitForProgComplete(const uint8_t ProgrammingMode, const uint16_t PollAddress, - const uint8_t PollValue, const uint8_t DelayMS, - const uint8_t ReadMemCommand); - uint8_t ISPTarget_WaitWhileTargetBusy(void); - void ISPTarget_LoadExtendedAddress(void); - -#endif diff --git a/Projects/AVRISP/Lib/PDI/PDIProtocol.c b/Projects/AVRISP/Lib/PDI/PDIProtocol.c new file mode 100644 index 000000000..16ac209df --- /dev/null +++ b/Projects/AVRISP/Lib/PDI/PDIProtocol.c @@ -0,0 +1,376 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * PDI Protocol handler, to process V2 Protocol wrapped PDI commands used in Atmel programmer devices. + */ + +#define INCLUDE_FROM_PDIPROTOCOL_C +#include "PDIProtocol.h" + +#if defined(ENABLE_PDI_PROTOCOL) || defined(__DOXYGEN__) +/** Base absolute address for the target's NVM controller */ +uint32_t XPROG_Param_NVMBase = 0x010001C0; + +/** Size in bytes of the target's EEPROM page */ +uint32_t XPROG_Param_EEPageSize; + +/** Handler for the CMD_XPROG_SETMODE command, which sets the programmer-to-target protocol used for PDI + * XMEGA programming (either PDI or JTAG). Only PDI programming is supported. + */ +void PDIProtocol_XPROG_SetMode(void) +{ + struct + { + uint8_t Protocol; + } SetMode_XPROG_Params; + + Endpoint_Read_Stream_LE(&SetMode_XPROG_Params, sizeof(SetMode_XPROG_Params)); + + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + Endpoint_Write_Byte(CMD_XPROG_SETMODE); + Endpoint_Write_Byte((SetMode_XPROG_Params.Protocol == XPRG_PROTOCOL_PDI) ? STATUS_CMD_OK : STATUS_CMD_FAILED); + Endpoint_ClearIN(); +} + +/** Handler for the CMD_XPROG command, which wraps up XPROG commands in a V2 wrapper which need to be + * removed and processed so that the underlying XPROG command can be handled. + */ +void PDIProtocol_XPROG_Command(void) +{ + uint8_t XPROGCommand = Endpoint_Read_Byte(); + + switch (XPROGCommand) + { + case XPRG_CMD_ENTER_PROGMODE: + PDIProtocol_EnterXPROGMode(); + break; + case XPRG_CMD_LEAVE_PROGMODE: + PDIProtocol_LeaveXPROGMode(); + break; + case XPRG_CMD_ERASE: + PDIProtocol_Erase(); + break; + case XPRG_CMD_WRITE_MEM: + PDIProtocol_WriteMemory(); + break; + case XPRG_CMD_READ_MEM: + PDIProtocol_ReadMemory(); + break; + case XPRG_CMD_CRC: + PDIProtocol_ReadCRC(); + break; + case XPRG_CMD_SET_PARAM: + PDIProtocol_SetParam(); + break; + } +} + +/** Handler for the XPROG ENTER_PROGMODE command to establish a PDI connection with the attached device. */ +static void PDIProtocol_EnterXPROGMode(void) +{ + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + /* Enable PDI programming mode with the attached target */ + PDITarget_EnableTargetPDI(); + + /* Store the RESET key into the RESET PDI register to keep the XMEGA in reset */ + PDITarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG); + PDITarget_SendByte(PDI_RESET_KEY); + + /* Enable access to the XPROG NVM bus by sending the documented NVM access key to the device */ + PDITarget_SendByte(PDI_CMD_KEY); + for (uint8_t i = sizeof(PDI_NVMENABLE_KEY); i > 0; i--) + PDITarget_SendByte(PDI_NVMENABLE_KEY[i - 1]); + + /* Wait until the NVM bus becomes active */ + bool NVMBusEnabled = PDITarget_WaitWhileNVMBusBusy(); + + Endpoint_Write_Byte(CMD_XPROG); + Endpoint_Write_Byte(XPRG_CMD_ENTER_PROGMODE); + Endpoint_Write_Byte(NVMBusEnabled ? XPRG_ERR_OK : XPRG_ERR_FAILED); + Endpoint_ClearIN(); +} + +/** Handler for the XPROG LEAVE_PROGMODE command to terminate the PDI programming connection with + * the attached device. + */ +static void PDIProtocol_LeaveXPROGMode(void) +{ + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + /* Clear the RESET key in the RESET PDI register to allow the XMEGA to run */ + PDITarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG); + PDITarget_SendByte(0x00); + + PDITarget_DisableTargetPDI(); + + Endpoint_Write_Byte(CMD_XPROG); + Endpoint_Write_Byte(XPRG_CMD_LEAVE_PROGMODE); + Endpoint_Write_Byte(XPRG_ERR_OK); + Endpoint_ClearIN(); +} + +/** Handler for the XPRG ERASE command to erase a specific memory address space in the attached device. */ +static void PDIProtocol_Erase(void) +{ + uint8_t ReturnStatus = XPRG_ERR_OK; + + struct + { + uint8_t MemoryType; + uint32_t Address; + } Erase_XPROG_Params; + + Endpoint_Read_Stream_LE(&Erase_XPROG_Params, sizeof(Erase_XPROG_Params)); + Erase_XPROG_Params.Address = SwapEndian_32(Erase_XPROG_Params.Address); + + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + uint8_t EraseCommand = XMEGA_NVM_CMD_NOOP; + + /* Determine which NVM command to send to the device depending on the memory to erase */ + if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_CHIP) + EraseCommand = XMEGA_NVM_CMD_CHIPERASE; + else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_APP) + EraseCommand = XMEGA_NVM_CMD_ERASEAPPSEC; + else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_BOOT) + EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSEC; + else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_EEPROM) + EraseCommand = XMEGA_NVM_CMD_ERASEEEPROM; + else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_APP_PAGE) + EraseCommand = XMEGA_NVM_CMD_ERASEAPPSECPAGE; + else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_BOOT_PAGE) + EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSECPAGE; + else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_EEPROM_PAGE) + EraseCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGE; + else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_USERSIG) + EraseCommand = XMEGA_NVM_CMD_ERASEUSERSIG; + + /* Erase the target memory, indicate timeout if ocurred */ + if (!(XMEGANVM_EraseMemory(EraseCommand, Erase_XPROG_Params.Address))) + ReturnStatus = XPRG_ERR_TIMEOUT; + + Endpoint_Write_Byte(CMD_XPROG); + Endpoint_Write_Byte(XPRG_CMD_ERASE); + Endpoint_Write_Byte(ReturnStatus); + Endpoint_ClearIN(); +} + +/** Handler for the XPROG WRITE_MEMORY command to write to a specific memory space within the attached device. */ +static void PDIProtocol_WriteMemory(void) +{ + uint8_t ReturnStatus = XPRG_ERR_OK; + + struct + { + uint8_t MemoryType; + uint8_t PageMode; + uint32_t Address; + uint16_t Length; + uint8_t ProgData[256]; + } WriteMemory_XPROG_Params; + + Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params, (sizeof(WriteMemory_XPROG_Params) - + sizeof(WriteMemory_XPROG_Params).ProgData)); + WriteMemory_XPROG_Params.Address = SwapEndian_32(WriteMemory_XPROG_Params.Address); + WriteMemory_XPROG_Params.Length = SwapEndian_16(WriteMemory_XPROG_Params.Length); + Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length); + + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + /* Assume FLASH page programming by default, as it is the common case */ + uint8_t WriteCommand = XMEGA_NVM_CMD_WRITEFLASHPAGE; + uint8_t WriteBuffCommand = XMEGA_NVM_CMD_LOADFLASHPAGEBUFF; + uint8_t EraseBuffCommand = XMEGA_NVM_CMD_ERASEFLASHPAGEBUFF; + bool PagedMemory = true; + + if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_APPL) + { + WriteCommand = XMEGA_NVM_CMD_WRITEAPPSECPAGE; + } + else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_BOOT) + { + WriteCommand = XMEGA_NVM_CMD_WRITEBOOTSECPAGE; + } + else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_EEPROM) + { + WriteCommand = XMEGA_NVM_CMD_WRITEEEPROMPAGE; + WriteBuffCommand = XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF; + EraseBuffCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF; + } + else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_USERSIG) + { + /* User signature is paged, but needs us to manually indicate the mode bits since the host doesn't set them */ + WriteMemory_XPROG_Params.PageMode = (XPRG_PAGEMODE_ERASE | XPRG_PAGEMODE_WRITE); + WriteCommand = XMEGA_NVM_CMD_WRITEUSERSIG; + } + else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_FUSE) + { + WriteCommand = XMEGA_NVM_CMD_WRITEFUSE; + PagedMemory = false; + } + else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_LOCKBITS) + { + WriteCommand = XMEGA_NVM_CMD_WRITELOCK; + PagedMemory = false; + } + + /* Send the appropriate memory write commands to the device, indicate timeout if occurred */ + if ((PagedMemory && !XMEGANVM_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand, + WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address, + WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length)) || + (!PagedMemory && !XMEGANVM_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address, + WriteMemory_XPROG_Params.ProgData))) + { + ReturnStatus = XPRG_ERR_TIMEOUT; + } + + Endpoint_Write_Byte(CMD_XPROG); + Endpoint_Write_Byte(XPRG_CMD_WRITE_MEM); + Endpoint_Write_Byte(ReturnStatus); + Endpoint_ClearIN(); +} + +/** Handler for the XPROG READ_MEMORY command to read data from a specific address space within the + * attached device. + */ +static void PDIProtocol_ReadMemory(void) +{ + uint8_t ReturnStatus = XPRG_ERR_OK; + + struct + { + uint8_t MemoryType; + uint32_t Address; + uint16_t Length; + } ReadMemory_XPROG_Params; + + Endpoint_Read_Stream_LE(&ReadMemory_XPROG_Params, sizeof(ReadMemory_XPROG_Params)); + ReadMemory_XPROG_Params.Address = SwapEndian_32(ReadMemory_XPROG_Params.Address); + ReadMemory_XPROG_Params.Length = SwapEndian_16(ReadMemory_XPROG_Params.Length); + + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + uint8_t ReadBuffer[256]; + + /* Read the target's memory, indicate timeout if occurred */ + if (!(XMEGANVM_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length))) + ReturnStatus = XPRG_ERR_TIMEOUT; + + Endpoint_Write_Byte(CMD_XPROG); + Endpoint_Write_Byte(XPRG_CMD_READ_MEM); + Endpoint_Write_Byte(ReturnStatus); + + if (ReturnStatus == XPRG_ERR_OK) + Endpoint_Write_Stream_LE(ReadBuffer, ReadMemory_XPROG_Params.Length); + + Endpoint_ClearIN(); +} + +/** Handler for the XPROG CRC command to read a specific memory space's CRC value for comparison between the + * attached device's memory and a data set on the host. + */ +static void PDIProtocol_ReadCRC(void) +{ + uint8_t ReturnStatus = XPRG_ERR_OK; + + struct + { + uint8_t CRCType; + } ReadCRC_XPROG_Params; + + Endpoint_Read_Stream_LE(&ReadCRC_XPROG_Params, sizeof(ReadCRC_XPROG_Params)); + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + uint8_t CRCCommand = XMEGA_NVM_CMD_NOOP; + uint32_t MemoryCRC; + + /* Determine which NVM command to send to the device depending on the memory to CRC */ + if (ReadCRC_XPROG_Params.CRCType == XPRG_CRC_APP) + CRCCommand = XMEGA_NVM_CMD_APPCRC; + else if (ReadCRC_XPROG_Params.CRCType == XPRG_CRC_BOOT) + CRCCommand = XMEGA_NVM_CMD_BOOTCRC; + else + CRCCommand = XMEGA_NVM_CMD_FLASHCRC; + + /* Perform and retrieve the memory CRC, indicate timeout if occurred */ + if (!(XMEGANVM_GetMemoryCRC(CRCCommand, &MemoryCRC))) + ReturnStatus = XPRG_ERR_TIMEOUT; + + Endpoint_Write_Byte(CMD_XPROG); + Endpoint_Write_Byte(XPRG_CMD_CRC); + Endpoint_Write_Byte(ReturnStatus); + + if (ReturnStatus == XPRG_ERR_OK) + { + Endpoint_Write_Byte(MemoryCRC >> 16); + Endpoint_Write_Word_LE(MemoryCRC & 0xFFFF); + } + + Endpoint_ClearIN(); +} + +/** Handler for the XPROG SET_PARAM command to set a PDI parameter for use when communicating with the + * attached device. + */ +static void PDIProtocol_SetParam(void) +{ + uint8_t ReturnStatus = XPRG_ERR_OK; + + uint8_t XPROGParam = Endpoint_Read_Byte(); + + /* Determine which parameter is being set, store the new parameter value */ + if (XPROGParam == XPRG_PARAM_NVMBASE) + XPROG_Param_NVMBase = Endpoint_Read_DWord_BE(); + else if (XPROGParam == XPRG_PARAM_EEPPAGESIZE) + XPROG_Param_EEPageSize = Endpoint_Read_Word_BE(); + else + ReturnStatus = XPRG_ERR_FAILED; + + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + Endpoint_Write_Byte(CMD_XPROG); + Endpoint_Write_Byte(XPRG_CMD_SET_PARAM); + Endpoint_Write_Byte(ReturnStatus); + Endpoint_ClearIN(); +} + +#endif diff --git a/Projects/AVRISP/Lib/PDI/PDIProtocol.h b/Projects/AVRISP/Lib/PDI/PDIProtocol.h new file mode 100644 index 000000000..c1fbef466 --- /dev/null +++ b/Projects/AVRISP/Lib/PDI/PDIProtocol.h @@ -0,0 +1,122 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for PDIProtocol.c. + */ + +#ifndef _PDI_PROTOCOL_ +#define _PDI_PROTOCOL_ + + /* Includes: */ + #include + #include + #include + + #include "V2Protocol.h" + #include "PDITarget.h" + #include "XMEGANVM.h" + + /* Preprocessor Checks: */ + #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) + #undef ENABLE_ISP_PROTOCOL + #undef ENABLE_TPI_PROTOCOL + + #if !defined(ENABLE_PDI_PROTOCOL) + #define ENABLE_PDI_PROTOCOL + #endif + #endif + + /* Macros: */ + #define XPRG_CMD_ENTER_PROGMODE 0x01 + #define XPRG_CMD_LEAVE_PROGMODE 0x02 + #define XPRG_CMD_ERASE 0x03 + #define XPRG_CMD_WRITE_MEM 0x04 + #define XPRG_CMD_READ_MEM 0x05 + #define XPRG_CMD_CRC 0x06 + #define XPRG_CMD_SET_PARAM 0x07 + + #define XPRG_MEM_TYPE_APPL 1 + #define XPRG_MEM_TYPE_BOOT 2 + #define XPRG_MEM_TYPE_EEPROM 3 + #define XPRG_MEM_TYPE_FUSE 4 + #define XPRG_MEM_TYPE_LOCKBITS 5 + #define XPRG_MEM_TYPE_USERSIG 6 + #define XPRG_MEM_TYPE_FACTORY_CALIBRATION 7 + + #define XPRG_ERASE_CHIP 1 + #define XPRG_ERASE_APP 2 + #define XPRG_ERASE_BOOT 3 + #define XPRG_ERASE_EEPROM 4 + #define XPRG_ERASE_APP_PAGE 5 + #define XPRG_ERASE_BOOT_PAGE 6 + #define XPRG_ERASE_EEPROM_PAGE 7 + #define XPRG_ERASE_USERSIG 8 + + #define XPRG_MEM_WRITE_ERASE 0 + #define XPRG_MEM_WRITE_WRITE 1 + + #define XPRG_CRC_APP 1 + #define XPRG_CRC_BOOT 2 + #define XPRG_CRC_FLASH 3 + + #define XPRG_ERR_OK 0 + #define XPRG_ERR_FAILED 1 + #define XPRG_ERR_COLLISION 2 + #define XPRG_ERR_TIMEOUT 3 + + #define XPRG_PARAM_NVMBASE 0x01 + #define XPRG_PARAM_EEPPAGESIZE 0x02 + + #define XPRG_PROTOCOL_PDI 0x00 + #define XPRG_PROTOCOL_JTAG 0x01 + + #define XPRG_PAGEMODE_WRITE (1 << 1) + #define XPRG_PAGEMODE_ERASE (1 << 0) + + /* External Variables: */ + extern uint32_t XPROG_Param_NVMBase; + + /* Function Prototypes: */ + void PDIProtocol_XPROG_SetMode(void); + void PDIProtocol_XPROG_Command(void); + + #if defined(INCLUDE_FROM_PDIPROTOCOL_C) + static void PDIProtocol_EnterXPROGMode(void); + static void PDIProtocol_LeaveXPROGMode(void); + static void PDIProtocol_SetParam(void); + static void PDIProtocol_Erase(void); + static void PDIProtocol_WriteMemory(void); + static void PDIProtocol_ReadMemory(void); + static void PDIProtocol_ReadCRC(void); + #endif + +#endif diff --git a/Projects/AVRISP/Lib/PDI/PDITarget.c b/Projects/AVRISP/Lib/PDI/PDITarget.c new file mode 100644 index 000000000..2c6ffd9a6 --- /dev/null +++ b/Projects/AVRISP/Lib/PDI/PDITarget.c @@ -0,0 +1,335 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Target-related functions for the PDI Protocol decoder. + */ + +#define INCLUDE_FROM_PDITARGET_C +#include "PDITarget.h" + +#if defined(ENABLE_PDI_PROTOCOL) || defined(__DOXYGEN__) + +/** Flag to indicate if the USART is currently in Tx or Rx mode. */ +volatile bool IsSending; + +#if !defined(PDI_VIA_HARDWARE_USART) +/** Software USART raw frame bits for transmission/reception. */ +volatile uint16_t SoftUSART_Data; + +/** Bits remaining to be sent or received via the software USART - set as a GPIOR for speed. */ +#define SoftUSART_BitCount GPIOR2 + + +/** ISR to manage the software USART when bit-banged USART mode is selected. */ +ISR(TIMER1_COMPA_vect, ISR_BLOCK) +{ + /* Toggle CLOCK pin in a single cycle (see AVR datasheet) */ + BITBANG_PDICLOCK_PIN |= BITBANG_PDICLOCK_MASK; + + /* If not sending or receiving, just exit */ + if (!(SoftUSART_BitCount)) + return; + + /* Check to see if we are at a rising or falling edge of the clock */ + if (BITBANG_PDICLOCK_PORT & BITBANG_PDICLOCK_MASK) + { + /* If at rising clock edge and we are in send mode, abort */ + if (IsSending) + return; + + /* Wait for the start bit when receiving */ + if ((SoftUSART_BitCount == BITS_IN_PDI_FRAME) && (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK)) + return; + + /* Shift in the bit one less than the frame size in position, so that the start bit will eventually + * be discarded leaving the data to be byte-aligned for quick access */ + if (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK) + SoftUSART_Data |= (1 << (BITS_IN_PDI_FRAME - 1)); + + SoftUSART_Data >>= 1; + SoftUSART_BitCount--; + } + else + { + /* If at falling clock edge and we are in receive mode, abort */ + if (!IsSending) + return; + + /* Set the data line to the next bit value */ + if (SoftUSART_Data & 0x01) + BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK; + else + BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK; + + SoftUSART_Data >>= 1; + SoftUSART_BitCount--; + } +} +#endif + +/** Enables the target's PDI interface, holding the target in reset until PDI mode is exited. */ +void PDITarget_EnableTargetPDI(void) +{ +#if defined(PDI_VIA_HARDWARE_USART) + /* Set Tx and XCK as outputs, Rx as input */ + DDRD |= (1 << 5) | (1 << 3); + DDRD &= ~(1 << 2); + + /* Set DATA line high for at least 90ns to disable /RESET functionality */ + PORTD |= (1 << 3); + asm volatile ("NOP"::); + asm volatile ("NOP"::); + + /* Set up the synchronous USART for XMEGA communications - + 8 data bits, even parity, 2 stop bits */ + UBRR1 = (F_CPU / 1000000UL); + UCSR1B = (1 << TXEN1); + UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1); + + /* Send two BREAKs of 12 bits each to enable PDI interface (need at least 16 idle bits) */ + PDITarget_SendBreak(); + PDITarget_SendBreak(); +#else + /* Set DATA and CLOCK lines to outputs */ + BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK; + BITBANG_PDICLOCK_DDR |= BITBANG_PDICLOCK_MASK; + + /* Set DATA line high for at least 90ns to disable /RESET functionality */ + BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK; + asm volatile ("NOP"::); + asm volatile ("NOP"::); + + /* Fire timer compare ISR every 100 cycles to manage the software USART */ + OCR1A = 80; + TCCR1B = (1 << WGM12) | (1 << CS10); + TIMSK1 = (1 << OCIE1A); + + /* Send two BREAKs of 12 bits each to enable TPI interface (need at least 16 idle bits) */ + PDITarget_SendBreak(); + PDITarget_SendBreak(); +#endif +} + +/** Disables the target's PDI interface, exits programming mode and starts the target's application. */ +void PDITarget_DisableTargetPDI(void) +{ +#if defined(PDI_VIA_HARDWARE_USART) + /* Turn off receiver and transmitter of the USART, clear settings */ + UCSR1A |= (1 << TXC1) | (1 << RXC1); + UCSR1B = 0; + UCSR1C = 0; + + /* Set all USART lines as input, tristate */ + DDRD &= ~((1 << 5) | (1 << 3)); + PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2)); +#else + /* Set DATA and CLOCK lines to inputs */ + BITBANG_PDIDATA_DDR &= ~BITBANG_PDIDATA_MASK; + BITBANG_PDICLOCK_DDR &= ~BITBANG_PDICLOCK_MASK; + + /* Tristate DATA and CLOCK lines */ + BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK; + BITBANG_PDICLOCK_PORT &= ~BITBANG_PDICLOCK_MASK; +#endif +} + +/** Sends a byte via the USART. + * + * \param[in] Byte Byte to send through the USART + */ +void PDITarget_SendByte(const uint8_t Byte) +{ +#if defined(PDI_VIA_HARDWARE_USART) + /* Switch to Tx mode if currently in Rx mode */ + if (!(IsSending)) + { + PORTD |= (1 << 3); + DDRD |= (1 << 3); + + UCSR1B |= (1 << TXEN1); + UCSR1B &= ~(1 << RXEN1); + + IsSending = true; + } + + /* Wait until there is space in the hardware Tx buffer before writing */ + while (!(UCSR1A & (1 << UDRE1))); + UCSR1A |= (1 << TXC1); + UDR1 = Byte; +#else + /* Switch to Tx mode if currently in Rx mode */ + if (!(IsSending)) + { + BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK; + BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK; + + IsSending = true; + } + + /* Calculate the new USART frame data here while while we wait for a previous byte (if any) to finish sending */ + uint16_t NewUSARTData = ((1 << 11) | (1 << 10) | (0 << 9) | ((uint16_t)Byte << 1) | (0 << 0)); + + /* Compute Even parity - while a bit is still set, chop off lowest bit and toggle parity bit */ + uint8_t ParityData = Byte; + while (ParityData) + { + NewUSARTData ^= (1 << 9); + ParityData &= (ParityData - 1); + } + + /* Wait until transmitter is idle before writing new data */ + while (SoftUSART_BitCount); + + /* Data shifted out LSB first, START DATA PARITY STOP STOP */ + SoftUSART_Data = NewUSARTData; + SoftUSART_BitCount = BITS_IN_PDI_FRAME; +#endif +} + +/** Receives a byte via the software USART, blocking until data is received. + * + * \return Received byte from the USART + */ +uint8_t PDITarget_ReceiveByte(void) +{ +#if defined(PDI_VIA_HARDWARE_USART) + /* Switch to Rx mode if currently in Tx mode */ + if (IsSending) + { + while (!(UCSR1A & (1 << TXC1))); + UCSR1A |= (1 << TXC1); + + UCSR1B &= ~(1 << TXEN1); + UCSR1B |= (1 << RXEN1); + + DDRD &= ~(1 << 3); + PORTD &= ~(1 << 3); + + IsSending = false; + } + + /* Wait until a byte has been received before reading */ + while (!(UCSR1A & (1 << RXC1))); + return UDR1; +#else + /* Switch to Rx mode if currently in Tx mode */ + if (IsSending) + { + while (SoftUSART_BitCount); + + BITBANG_PDIDATA_DDR &= ~BITBANG_PDIDATA_MASK; + BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK; + + IsSending = false; + } + + /* Wait until a byte has been received before reading */ + SoftUSART_BitCount = BITS_IN_PDI_FRAME; + while (SoftUSART_BitCount); + + /* Throw away the parity and stop bits to leave only the data (start bit is already discarded) */ + return (uint8_t)SoftUSART_Data; +#endif +} + +/** Sends a BREAK via the USART to the attached target, consisting of a full frame of idle bits. */ +void PDITarget_SendBreak(void) +{ +#if defined(PDI_VIA_HARDWARE_USART) + /* Switch to Tx mode if currently in Rx mode */ + if (!(IsSending)) + { + PORTD |= (1 << 3); + DDRD |= (1 << 3); + + UCSR1B &= ~(1 << RXEN1); + UCSR1B |= (1 << TXEN1); + + IsSending = true; + } + + /* Need to do nothing for a full frame to send a BREAK */ + for (uint8_t i = 0; i < BITS_IN_PDI_FRAME; i++) + { + /* Wait for a full cycle of the clock */ + while (PIND & (1 << 5)); + while (!(PIND & (1 << 5))); + } +#else + /* Switch to Tx mode if currently in Rx mode */ + if (!(IsSending)) + { + BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK; + BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK; + + IsSending = true; + } + + while (SoftUSART_BitCount); + + /* Need to do nothing for a full frame to send a BREAK */ + SoftUSART_Data = 0x0FFF; + SoftUSART_BitCount = BITS_IN_PDI_FRAME; +#endif +} + +/** Busy-waits while the NVM controller is busy performing a NVM operation, such as a FLASH page read or CRC + * calculation. + * + * \return Boolean true if the NVM controller became ready within the timeout period, false otherwise + */ +bool PDITarget_WaitWhileNVMBusBusy(void) +{ + TCNT0 = 0; + TIFR0 = (1 << OCF1A); + + uint8_t TimeoutMS = PDI_NVM_TIMEOUT_MS; + + /* Poll the STATUS register to check to see if NVM access has been enabled */ + while (TimeoutMS) + { + /* Send the LDCS command to read the PDI STATUS register to see the NVM bus is active */ + PDITarget_SendByte(PDI_CMD_LDCS | PDI_STATUS_REG); + if (PDITarget_ReceiveByte() & PDI_STATUS_NVM) + return true; + + if (TIFR0 & (1 << OCF1A)) + { + TIFR0 = (1 << OCF1A); + TimeoutMS--; + } + } + + return false; +} + +#endif diff --git a/Projects/AVRISP/Lib/PDI/PDITarget.h b/Projects/AVRISP/Lib/PDI/PDITarget.h new file mode 100644 index 000000000..cf7780c17 --- /dev/null +++ b/Projects/AVRISP/Lib/PDI/PDITarget.h @@ -0,0 +1,112 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for PDITarget.c. + */ + +#ifndef _PDI_TARGET_ +#define _PDI_TARGET_ + + /* Includes: */ + #include + #include + #include + + #include + + /* Preprocessor Checks: */ + #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) + #undef ENABLE_ISP_PROTOCOL + #undef ENABLE_TPI_PROTOCOL + + #if !defined(ENABLE_PDI_PROTOCOL) + #define ENABLE_PDI_PROTOCOL + #endif + #endif + + /* Defines: */ + #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) + #define PDI_VIA_HARDWARE_USART + #else + #define BITBANG_PDIDATA_PORT PORTB + #define BITBANG_PDIDATA_DDR DDRB + #define BITBANG_PDIDATA_PIN PINB + #define BITBANG_PDIDATA_MASK (1 << 3) + + #define BITBANG_PDICLOCK_PORT RESET_LINE_PORT + #define BITBANG_PDICLOCK_DDR RESET_LINE_DDR + #define BITBANG_PDICLOCK_PIN RESET_LINE_PIN + #define BITBANG_PDICLOCK_MASK RESET_LINE_MASK + #endif + + /** Total number of bits in a single USART frame */ + #define BITS_IN_PDI_FRAME 12 + + /** Timeout in milliseconds of a PDI busy-wait command */ + #define PDI_NVM_TIMEOUT_MS 100 + + #define PDI_CMD_LDS 0x00 + #define PDI_CMD_LD 0x20 + #define PDI_CMD_STS 0x40 + #define PDI_CMD_ST 0x60 + #define PDI_CMD_LDCS 0x80 + #define PDI_CMD_REPEAT 0xA0 + #define PDI_CMD_STCS 0xC0 + #define PDI_CMD_KEY 0xE0 + + #define PDI_STATUS_REG 0 + #define PDI_RESET_REG 1 + #define PDI_CTRL_REG 2 + + #define PDI_STATUS_NVM (1 << 1) + #define PDI_RESET_KEY 0x59 + + #define PDI_NVMENABLE_KEY (uint8_t[]){0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF} + + #define PDI_DATSIZE_1BYTE 0 + #define PDI_DATSIZE_2BYTES 1 + #define PDI_DATSIZE_3BYTES 2 + #define PDI_DATSIZE_4BYTES 3 + + #define PDI_POINTER_INDIRECT 0 + #define PDI_POINTER_INDIRECT_PI 1 + #define PDI_POINTER_DIRECT 2 + + /* Function Prototypes: */ + void PDITarget_EnableTargetPDI(void); + void PDITarget_DisableTargetPDI(void); + void PDITarget_SendByte(const uint8_t Byte); + uint8_t PDITarget_ReceiveByte(void); + void PDITarget_SendBreak(void); + bool PDITarget_WaitWhileNVMBusBusy(void); + +#endif diff --git a/Projects/AVRISP/Lib/PDI/XMEGANVM.c b/Projects/AVRISP/Lib/PDI/XMEGANVM.c new file mode 100644 index 000000000..ed8719c4e --- /dev/null +++ b/Projects/AVRISP/Lib/PDI/XMEGANVM.c @@ -0,0 +1,332 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Target-related functions for the XMEGA target's NVM module. + */ + +#define INCLUDE_FROM_XMEGA_NVM_C +#include "XMEGANVM.h" + +#if defined(ENABLE_PDI_PROTOCOL) || defined(__DOXYGEN__) + +/** Sends the given NVM register address to the target. + * + * \param[in] Register NVM register whose absolute address is to be sent + */ +void XMEGANVM_SendNVMRegAddress(const uint8_t Register) +{ + /* Determine the absolute register address from the NVM base memory address and the NVM register address */ + uint32_t Address = XPROG_Param_NVMBase | Register; + + /* Send the calculated 32-bit address to the target, LSB first */ + XMEGANVM_SendAddress(Address); +} + +/** Sends the given 32-bit absolute address to the target. + * + * \param[in] AbsoluteAddress Absolute address to send to the target + */ +void XMEGANVM_SendAddress(const uint32_t AbsoluteAddress) +{ + /* Send the given 32-bit address to the target, LSB first */ + PDITarget_SendByte(AbsoluteAddress & 0xFF); + PDITarget_SendByte(AbsoluteAddress >> 8); + PDITarget_SendByte(AbsoluteAddress >> 16); + PDITarget_SendByte(AbsoluteAddress >> 24); +} + +/** Waits while the target's NVM controller is busy performing an operation, exiting if the + * timeout period expires. + * + * \return Boolean true if the NVM controller became ready within the timeout period, false otherwise + */ +bool XMEGANVM_WaitWhileNVMControllerBusy(void) +{ + TCNT0 = 0; + TIFR0 = (1 << OCF1A); + + uint8_t TimeoutMS = XMEGA_NVM_BUSY_TIMEOUT_MS; + + /* Poll the NVM STATUS register while the NVM controller is busy */ + while (TimeoutMS) + { + /* Send a LDS command to read the NVM STATUS register to check the BUSY flag */ + PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_STATUS); + + /* Check to see if the BUSY flag is still set */ + if (!(PDITarget_ReceiveByte() & (1 << 7))) + return true; + + if (TIFR0 & (1 << OCF1A)) + { + TIFR0 = (1 << OCF1A); + TimeoutMS--; + } + } + + return false; +} + +/** Retrieves the CRC value of the given memory space. + * + * \param[in] CRCCommand NVM CRC command to issue to the target + * \param[out] CRCDest CRC Destination when read from the target + * + * \return Boolean true if the command sequence complete successfully + */ +bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest) +{ + /* Wait until the NVM controller is no longer busy */ + if (!(XMEGANVM_WaitWhileNVMControllerBusy())) + return false; + + /* Set the NVM command to the correct CRC read command */ + PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD); + PDITarget_SendByte(CRCCommand); + + /* Set CMDEX bit in NVM CTRLA register to start the CRC generation */ + PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA); + PDITarget_SendByte(1 << 0); + + /* Wait until the NVM bus is ready again */ + if (!(PDITarget_WaitWhileNVMBusBusy())) + return false; + + /* Wait until the NVM controller is no longer busy */ + if (!(XMEGANVM_WaitWhileNVMControllerBusy())) + return false; + + *CRCDest = 0; + + /* Read the first generated CRC byte value */ + PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT0); + *CRCDest = PDITarget_ReceiveByte(); + + /* Read the second generated CRC byte value */ + PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT1); + *CRCDest |= ((uint16_t)PDITarget_ReceiveByte() << 8); + + /* Read the third generated CRC byte value */ + PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT2); + *CRCDest |= ((uint32_t)PDITarget_ReceiveByte() << 16); + + return true; +} + +/** Reads memory from the target's memory spaces. + * + * \param[in] ReadAddress Start address to read from within the target's address space + * \param[out] ReadBuffer Buffer to store read data into + * \param[in] ReadSize Number of bytes to read + * + * \return Boolean true if the command sequence complete successfully + */ +bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const uint16_t ReadSize) +{ + /* Wait until the NVM controller is no longer busy */ + if (!(XMEGANVM_WaitWhileNVMControllerBusy())) + return false; + + /* Send the READNVM command to the NVM controller for reading of an arbitrary location */ + PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD); + PDITarget_SendByte(XMEGA_NVM_CMD_READNVM); + + /* Load the PDI pointer register with the start address we want to read from */ + PDITarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES); + XMEGANVM_SendAddress(ReadAddress); + + /* Send the REPEAT command with the specified number of bytes to read */ + PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE); + PDITarget_SendByte(ReadSize - 1); + + /* Send a LD command with indirect access and postincrement to read out the bytes */ + PDITarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE); + for (uint16_t i = 0; i < ReadSize; i++) + *(ReadBuffer++) = PDITarget_ReceiveByte(); + + return true; +} + +/** Writes byte addressed memory to the target's memory spaces. + * + * \param[in] WriteCommand Command to send to the device to write each memory byte + * \param[in] WriteAddress Start address to write to within the target's address space + * \param[in] WriteBuffer Buffer to source data from + * + * \return Boolean true if the command sequence complete successfully + */ +bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer) +{ + /* Wait until the NVM controller is no longer busy */ + if (!(XMEGANVM_WaitWhileNVMControllerBusy())) + return false; + + /* Send the memory write command to the target */ + PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD); + PDITarget_SendByte(WriteCommand); + + /* Send new memory byte to the memory to the target */ + PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendAddress(WriteAddress); + PDITarget_SendByte(*(WriteBuffer++)); + + return true; +} + +/** Writes page addressed memory to the target's memory spaces. + * + * \param[in] WriteBuffCommand Command to send to the device to write a byte to the memory page buffer + * \param[in] EraseBuffCommand Command to send to the device to erase the memory page buffer + * \param[in] WritePageCommand Command to send to the device to write the page buffer to the destination memory + * \param[in] PageMode Bitfield indicating what operations need to be executed on the specified page + * \param[in] WriteAddress Start address to write the page data to within the target's address space + * \param[in] WriteBuffer Buffer to source data from + * \param[in] WriteSize Number of bytes to write + * + * \return Boolean true if the command sequence complete successfully + */ +bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t EraseBuffCommand, + const uint8_t WritePageCommand, const uint8_t PageMode, const uint32_t WriteAddress, + const uint8_t* WriteBuffer, const uint16_t WriteSize) +{ + if (PageMode & XPRG_PAGEMODE_ERASE) + { + /* Wait until the NVM controller is no longer busy */ + if (!(XMEGANVM_WaitWhileNVMControllerBusy())) + return false; + + /* Send the memory buffer erase command to the target */ + PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD); + PDITarget_SendByte(EraseBuffCommand); + + /* Set CMDEX bit in NVM CTRLA register to start the buffer erase */ + PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA); + PDITarget_SendByte(1 << 0); + } + + if (WriteSize) + { + /* Wait until the NVM controller is no longer busy */ + if (!(XMEGANVM_WaitWhileNVMControllerBusy())) + return false; + + /* Send the memory buffer write command to the target */ + PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD); + PDITarget_SendByte(WriteBuffCommand); + + /* Load the PDI pointer register with the start address we want to write to */ + PDITarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES); + XMEGANVM_SendAddress(WriteAddress); + + /* Send the REPEAT command with the specified number of bytes to write */ + PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE); + PDITarget_SendByte(WriteSize - 1); + + /* Send a ST command with indirect access and postincrement to write the bytes */ + PDITarget_SendByte(PDI_CMD_ST | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE); + for (uint16_t i = 0; i < WriteSize; i++) + PDITarget_SendByte(*(WriteBuffer++)); + } + + if (PageMode & XPRG_PAGEMODE_WRITE) + { + /* Wait until the NVM controller is no longer busy */ + if (!(XMEGANVM_WaitWhileNVMControllerBusy())) + return false; + + /* Send the memory write command to the target */ + PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD); + PDITarget_SendByte(WritePageCommand); + + /* Send the address of the first page location to write the memory page */ + PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendAddress(WriteAddress); + PDITarget_SendByte(0x00); + } + + return true; +} + +/** Erases a specific memory space of the target. + * + * \param[in] EraseCommand NVM erase command to send to the device + * \param[in] Address Address inside the memory space to erase + * + * \return Boolean true if the command sequence complete successfully + */ +bool XMEGANVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address) +{ + /* Wait until the NVM controller is no longer busy */ + if (!(XMEGANVM_WaitWhileNVMControllerBusy())) + return false; + + /* Send the memory erase command to the target */ + PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD); + PDITarget_SendByte(EraseCommand); + + /* Chip erase is handled separately, since it's procedure is different to other erase types */ + if (EraseCommand == XMEGA_NVM_CMD_CHIPERASE) + { + /* Set CMDEX bit in NVM CTRLA register to start the chip erase */ + PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA); + PDITarget_SendByte(1 << 0); + } + else + { + /* Other erase modes just need us to address a byte within the target memory space */ + PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); + XMEGANVM_SendAddress(Address); + PDITarget_SendByte(0x00); + } + + /* Wait until the NVM bus is ready again */ + if (!(PDITarget_WaitWhileNVMBusBusy())) + return false; + + return true; +} + +#endif diff --git a/Projects/AVRISP/Lib/PDI/XMEGANVM.h b/Projects/AVRISP/Lib/PDI/XMEGANVM.h new file mode 100644 index 000000000..c31c7e8f1 --- /dev/null +++ b/Projects/AVRISP/Lib/PDI/XMEGANVM.h @@ -0,0 +1,121 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for XMEGANVM.c. + */ + +#ifndef _XMEGA_NVM__ +#define _XMEGA_NVM_ + + /* Includes: */ + #include + #include + #include + + #include + + #include "PDIProtocol.h" + #include "PDITarget.h" + + /* Preprocessor Checks: */ + #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) + #undef ENABLE_ISP_PROTOCOL + #undef ENABLE_TPI_PROTOCOL + + #if !defined(ENABLE_PDI_PROTOCOL) + #define ENABLE_PDI_PROTOCOL + #endif + #endif + + /* Defines: */ + #define XMEGA_NVM_BUSY_TIMEOUT_MS 200 + + #define XMEGA_NVM_REG_ADDR0 0x00 + #define XMEGA_NVM_REG_ADDR1 0x01 + #define XMEGA_NVM_REG_ADDR2 0x02 + #define XMEGA_NVM_REG_DAT0 0x04 + #define XMEGA_NVM_REG_DAT1 0x05 + #define XMEGA_NVM_REG_DAT2 0x06 + #define XMEGA_NVM_REG_CMD 0x0A + #define XMEGA_NVM_REG_CTRLA 0x0B + #define XMEGA_NVM_REG_CTRLB 0x0C + #define XMEGA_NVM_REG_INTCTRL 0x0D + #define XMEGA_NVM_REG_STATUS 0x0F + #define XMEGA_NVM_REG_LOCKBITS 0x10 + + #define XMEGA_NVM_CMD_NOOP 0x00 + #define XMEGA_NVM_CMD_CHIPERASE 0x40 + #define XMEGA_NVM_CMD_READNVM 0x43 + #define XMEGA_NVM_CMD_LOADFLASHPAGEBUFF 0x23 + #define XMEGA_NVM_CMD_ERASEFLASHPAGEBUFF 0x26 + #define XMEGA_NVM_CMD_ERASEFLASHPAGE 0x2B + #define XMEGA_NVM_CMD_WRITEFLASHPAGE 0x2E + #define XMEGA_NVM_CMD_ERASEWRITEFLASH 0x2F + #define XMEGA_NVM_CMD_FLASHCRC 0x78 + #define XMEGA_NVM_CMD_ERASEAPPSEC 0x20 + #define XMEGA_NVM_CMD_ERASEAPPSECPAGE 0x22 + #define XMEGA_NVM_CMD_WRITEAPPSECPAGE 0x24 + #define XMEGA_NVM_CMD_ERASEWRITEAPPSECPAGE 0x25 + #define XMEGA_NVM_CMD_APPCRC 0x38 + #define XMEGA_NVM_CMD_ERASEBOOTSEC 0x68 + #define XMEGA_NVM_CMD_ERASEBOOTSECPAGE 0x2A + #define XMEGA_NVM_CMD_WRITEBOOTSECPAGE 0x2C + #define XMEGA_NVM_CMD_ERASEWRITEBOOTSECPAGE 0x2D + #define XMEGA_NVM_CMD_BOOTCRC 0x39 + #define XMEGA_NVM_CMD_READUSERSIG 0x03 + #define XMEGA_NVM_CMD_ERASEUSERSIG 0x18 + #define XMEGA_NVM_CMD_WRITEUSERSIG 0x1A + #define XMEGA_NVM_CMD_READCALIBRATION 0x02 + #define XMEGA_NVM_CMD_READFUSE 0x07 + #define XMEGA_NVM_CMD_WRITEFUSE 0x4C + #define XMEGA_NVM_CMD_WRITELOCK 0x08 + #define XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF 0x33 + #define XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF 0x36 + #define XMEGA_NVM_CMD_ERASEEEPROM 0x30 + #define XMEGA_NVM_CMD_ERASEEEPROMPAGE 0x32 + #define XMEGA_NVM_CMD_WRITEEEPROMPAGE 0x34 + #define XMEGA_NVM_CMD_ERASEWRITEEEPROMPAGE 0x35 + #define XMEGA_NVM_CMD_READEEPROM 0x06 + + /* Function Prototypes: */ + void XMEGANVM_SendNVMRegAddress(const uint8_t Register); + void XMEGANVM_SendAddress(const uint32_t AbsoluteAddress); + bool XMEGANVM_WaitWhileNVMControllerBusy(void); + bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest); + bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const uint16_t ReadSize); + bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer); + bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t EraseBuffCommand, + const uint8_t WritePageCommand, const uint8_t PageMode, const uint32_t WriteAddress, + const uint8_t* WriteBuffer, const uint16_t WriteSize); + bool XMEGANVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address); + +#endif diff --git a/Projects/AVRISP/Lib/PDIProtocol.c b/Projects/AVRISP/Lib/PDIProtocol.c deleted file mode 100644 index 16ac209df..000000000 --- a/Projects/AVRISP/Lib/PDIProtocol.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * PDI Protocol handler, to process V2 Protocol wrapped PDI commands used in Atmel programmer devices. - */ - -#define INCLUDE_FROM_PDIPROTOCOL_C -#include "PDIProtocol.h" - -#if defined(ENABLE_PDI_PROTOCOL) || defined(__DOXYGEN__) -/** Base absolute address for the target's NVM controller */ -uint32_t XPROG_Param_NVMBase = 0x010001C0; - -/** Size in bytes of the target's EEPROM page */ -uint32_t XPROG_Param_EEPageSize; - -/** Handler for the CMD_XPROG_SETMODE command, which sets the programmer-to-target protocol used for PDI - * XMEGA programming (either PDI or JTAG). Only PDI programming is supported. - */ -void PDIProtocol_XPROG_SetMode(void) -{ - struct - { - uint8_t Protocol; - } SetMode_XPROG_Params; - - Endpoint_Read_Stream_LE(&SetMode_XPROG_Params, sizeof(SetMode_XPROG_Params)); - - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - Endpoint_Write_Byte(CMD_XPROG_SETMODE); - Endpoint_Write_Byte((SetMode_XPROG_Params.Protocol == XPRG_PROTOCOL_PDI) ? STATUS_CMD_OK : STATUS_CMD_FAILED); - Endpoint_ClearIN(); -} - -/** Handler for the CMD_XPROG command, which wraps up XPROG commands in a V2 wrapper which need to be - * removed and processed so that the underlying XPROG command can be handled. - */ -void PDIProtocol_XPROG_Command(void) -{ - uint8_t XPROGCommand = Endpoint_Read_Byte(); - - switch (XPROGCommand) - { - case XPRG_CMD_ENTER_PROGMODE: - PDIProtocol_EnterXPROGMode(); - break; - case XPRG_CMD_LEAVE_PROGMODE: - PDIProtocol_LeaveXPROGMode(); - break; - case XPRG_CMD_ERASE: - PDIProtocol_Erase(); - break; - case XPRG_CMD_WRITE_MEM: - PDIProtocol_WriteMemory(); - break; - case XPRG_CMD_READ_MEM: - PDIProtocol_ReadMemory(); - break; - case XPRG_CMD_CRC: - PDIProtocol_ReadCRC(); - break; - case XPRG_CMD_SET_PARAM: - PDIProtocol_SetParam(); - break; - } -} - -/** Handler for the XPROG ENTER_PROGMODE command to establish a PDI connection with the attached device. */ -static void PDIProtocol_EnterXPROGMode(void) -{ - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - /* Enable PDI programming mode with the attached target */ - PDITarget_EnableTargetPDI(); - - /* Store the RESET key into the RESET PDI register to keep the XMEGA in reset */ - PDITarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG); - PDITarget_SendByte(PDI_RESET_KEY); - - /* Enable access to the XPROG NVM bus by sending the documented NVM access key to the device */ - PDITarget_SendByte(PDI_CMD_KEY); - for (uint8_t i = sizeof(PDI_NVMENABLE_KEY); i > 0; i--) - PDITarget_SendByte(PDI_NVMENABLE_KEY[i - 1]); - - /* Wait until the NVM bus becomes active */ - bool NVMBusEnabled = PDITarget_WaitWhileNVMBusBusy(); - - Endpoint_Write_Byte(CMD_XPROG); - Endpoint_Write_Byte(XPRG_CMD_ENTER_PROGMODE); - Endpoint_Write_Byte(NVMBusEnabled ? XPRG_ERR_OK : XPRG_ERR_FAILED); - Endpoint_ClearIN(); -} - -/** Handler for the XPROG LEAVE_PROGMODE command to terminate the PDI programming connection with - * the attached device. - */ -static void PDIProtocol_LeaveXPROGMode(void) -{ - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - /* Clear the RESET key in the RESET PDI register to allow the XMEGA to run */ - PDITarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG); - PDITarget_SendByte(0x00); - - PDITarget_DisableTargetPDI(); - - Endpoint_Write_Byte(CMD_XPROG); - Endpoint_Write_Byte(XPRG_CMD_LEAVE_PROGMODE); - Endpoint_Write_Byte(XPRG_ERR_OK); - Endpoint_ClearIN(); -} - -/** Handler for the XPRG ERASE command to erase a specific memory address space in the attached device. */ -static void PDIProtocol_Erase(void) -{ - uint8_t ReturnStatus = XPRG_ERR_OK; - - struct - { - uint8_t MemoryType; - uint32_t Address; - } Erase_XPROG_Params; - - Endpoint_Read_Stream_LE(&Erase_XPROG_Params, sizeof(Erase_XPROG_Params)); - Erase_XPROG_Params.Address = SwapEndian_32(Erase_XPROG_Params.Address); - - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - uint8_t EraseCommand = XMEGA_NVM_CMD_NOOP; - - /* Determine which NVM command to send to the device depending on the memory to erase */ - if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_CHIP) - EraseCommand = XMEGA_NVM_CMD_CHIPERASE; - else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_APP) - EraseCommand = XMEGA_NVM_CMD_ERASEAPPSEC; - else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_BOOT) - EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSEC; - else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_EEPROM) - EraseCommand = XMEGA_NVM_CMD_ERASEEEPROM; - else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_APP_PAGE) - EraseCommand = XMEGA_NVM_CMD_ERASEAPPSECPAGE; - else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_BOOT_PAGE) - EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSECPAGE; - else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_EEPROM_PAGE) - EraseCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGE; - else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_USERSIG) - EraseCommand = XMEGA_NVM_CMD_ERASEUSERSIG; - - /* Erase the target memory, indicate timeout if ocurred */ - if (!(XMEGANVM_EraseMemory(EraseCommand, Erase_XPROG_Params.Address))) - ReturnStatus = XPRG_ERR_TIMEOUT; - - Endpoint_Write_Byte(CMD_XPROG); - Endpoint_Write_Byte(XPRG_CMD_ERASE); - Endpoint_Write_Byte(ReturnStatus); - Endpoint_ClearIN(); -} - -/** Handler for the XPROG WRITE_MEMORY command to write to a specific memory space within the attached device. */ -static void PDIProtocol_WriteMemory(void) -{ - uint8_t ReturnStatus = XPRG_ERR_OK; - - struct - { - uint8_t MemoryType; - uint8_t PageMode; - uint32_t Address; - uint16_t Length; - uint8_t ProgData[256]; - } WriteMemory_XPROG_Params; - - Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params, (sizeof(WriteMemory_XPROG_Params) - - sizeof(WriteMemory_XPROG_Params).ProgData)); - WriteMemory_XPROG_Params.Address = SwapEndian_32(WriteMemory_XPROG_Params.Address); - WriteMemory_XPROG_Params.Length = SwapEndian_16(WriteMemory_XPROG_Params.Length); - Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length); - - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - /* Assume FLASH page programming by default, as it is the common case */ - uint8_t WriteCommand = XMEGA_NVM_CMD_WRITEFLASHPAGE; - uint8_t WriteBuffCommand = XMEGA_NVM_CMD_LOADFLASHPAGEBUFF; - uint8_t EraseBuffCommand = XMEGA_NVM_CMD_ERASEFLASHPAGEBUFF; - bool PagedMemory = true; - - if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_APPL) - { - WriteCommand = XMEGA_NVM_CMD_WRITEAPPSECPAGE; - } - else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_BOOT) - { - WriteCommand = XMEGA_NVM_CMD_WRITEBOOTSECPAGE; - } - else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_EEPROM) - { - WriteCommand = XMEGA_NVM_CMD_WRITEEEPROMPAGE; - WriteBuffCommand = XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF; - EraseBuffCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF; - } - else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_USERSIG) - { - /* User signature is paged, but needs us to manually indicate the mode bits since the host doesn't set them */ - WriteMemory_XPROG_Params.PageMode = (XPRG_PAGEMODE_ERASE | XPRG_PAGEMODE_WRITE); - WriteCommand = XMEGA_NVM_CMD_WRITEUSERSIG; - } - else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_FUSE) - { - WriteCommand = XMEGA_NVM_CMD_WRITEFUSE; - PagedMemory = false; - } - else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_LOCKBITS) - { - WriteCommand = XMEGA_NVM_CMD_WRITELOCK; - PagedMemory = false; - } - - /* Send the appropriate memory write commands to the device, indicate timeout if occurred */ - if ((PagedMemory && !XMEGANVM_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand, - WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address, - WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length)) || - (!PagedMemory && !XMEGANVM_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address, - WriteMemory_XPROG_Params.ProgData))) - { - ReturnStatus = XPRG_ERR_TIMEOUT; - } - - Endpoint_Write_Byte(CMD_XPROG); - Endpoint_Write_Byte(XPRG_CMD_WRITE_MEM); - Endpoint_Write_Byte(ReturnStatus); - Endpoint_ClearIN(); -} - -/** Handler for the XPROG READ_MEMORY command to read data from a specific address space within the - * attached device. - */ -static void PDIProtocol_ReadMemory(void) -{ - uint8_t ReturnStatus = XPRG_ERR_OK; - - struct - { - uint8_t MemoryType; - uint32_t Address; - uint16_t Length; - } ReadMemory_XPROG_Params; - - Endpoint_Read_Stream_LE(&ReadMemory_XPROG_Params, sizeof(ReadMemory_XPROG_Params)); - ReadMemory_XPROG_Params.Address = SwapEndian_32(ReadMemory_XPROG_Params.Address); - ReadMemory_XPROG_Params.Length = SwapEndian_16(ReadMemory_XPROG_Params.Length); - - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - uint8_t ReadBuffer[256]; - - /* Read the target's memory, indicate timeout if occurred */ - if (!(XMEGANVM_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length))) - ReturnStatus = XPRG_ERR_TIMEOUT; - - Endpoint_Write_Byte(CMD_XPROG); - Endpoint_Write_Byte(XPRG_CMD_READ_MEM); - Endpoint_Write_Byte(ReturnStatus); - - if (ReturnStatus == XPRG_ERR_OK) - Endpoint_Write_Stream_LE(ReadBuffer, ReadMemory_XPROG_Params.Length); - - Endpoint_ClearIN(); -} - -/** Handler for the XPROG CRC command to read a specific memory space's CRC value for comparison between the - * attached device's memory and a data set on the host. - */ -static void PDIProtocol_ReadCRC(void) -{ - uint8_t ReturnStatus = XPRG_ERR_OK; - - struct - { - uint8_t CRCType; - } ReadCRC_XPROG_Params; - - Endpoint_Read_Stream_LE(&ReadCRC_XPROG_Params, sizeof(ReadCRC_XPROG_Params)); - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - uint8_t CRCCommand = XMEGA_NVM_CMD_NOOP; - uint32_t MemoryCRC; - - /* Determine which NVM command to send to the device depending on the memory to CRC */ - if (ReadCRC_XPROG_Params.CRCType == XPRG_CRC_APP) - CRCCommand = XMEGA_NVM_CMD_APPCRC; - else if (ReadCRC_XPROG_Params.CRCType == XPRG_CRC_BOOT) - CRCCommand = XMEGA_NVM_CMD_BOOTCRC; - else - CRCCommand = XMEGA_NVM_CMD_FLASHCRC; - - /* Perform and retrieve the memory CRC, indicate timeout if occurred */ - if (!(XMEGANVM_GetMemoryCRC(CRCCommand, &MemoryCRC))) - ReturnStatus = XPRG_ERR_TIMEOUT; - - Endpoint_Write_Byte(CMD_XPROG); - Endpoint_Write_Byte(XPRG_CMD_CRC); - Endpoint_Write_Byte(ReturnStatus); - - if (ReturnStatus == XPRG_ERR_OK) - { - Endpoint_Write_Byte(MemoryCRC >> 16); - Endpoint_Write_Word_LE(MemoryCRC & 0xFFFF); - } - - Endpoint_ClearIN(); -} - -/** Handler for the XPROG SET_PARAM command to set a PDI parameter for use when communicating with the - * attached device. - */ -static void PDIProtocol_SetParam(void) -{ - uint8_t ReturnStatus = XPRG_ERR_OK; - - uint8_t XPROGParam = Endpoint_Read_Byte(); - - /* Determine which parameter is being set, store the new parameter value */ - if (XPROGParam == XPRG_PARAM_NVMBASE) - XPROG_Param_NVMBase = Endpoint_Read_DWord_BE(); - else if (XPROGParam == XPRG_PARAM_EEPPAGESIZE) - XPROG_Param_EEPageSize = Endpoint_Read_Word_BE(); - else - ReturnStatus = XPRG_ERR_FAILED; - - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - Endpoint_Write_Byte(CMD_XPROG); - Endpoint_Write_Byte(XPRG_CMD_SET_PARAM); - Endpoint_Write_Byte(ReturnStatus); - Endpoint_ClearIN(); -} - -#endif diff --git a/Projects/AVRISP/Lib/PDIProtocol.h b/Projects/AVRISP/Lib/PDIProtocol.h deleted file mode 100644 index c1fbef466..000000000 --- a/Projects/AVRISP/Lib/PDIProtocol.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Header file for PDIProtocol.c. - */ - -#ifndef _PDI_PROTOCOL_ -#define _PDI_PROTOCOL_ - - /* Includes: */ - #include - #include - #include - - #include "V2Protocol.h" - #include "PDITarget.h" - #include "XMEGANVM.h" - - /* Preprocessor Checks: */ - #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) - #undef ENABLE_ISP_PROTOCOL - #undef ENABLE_TPI_PROTOCOL - - #if !defined(ENABLE_PDI_PROTOCOL) - #define ENABLE_PDI_PROTOCOL - #endif - #endif - - /* Macros: */ - #define XPRG_CMD_ENTER_PROGMODE 0x01 - #define XPRG_CMD_LEAVE_PROGMODE 0x02 - #define XPRG_CMD_ERASE 0x03 - #define XPRG_CMD_WRITE_MEM 0x04 - #define XPRG_CMD_READ_MEM 0x05 - #define XPRG_CMD_CRC 0x06 - #define XPRG_CMD_SET_PARAM 0x07 - - #define XPRG_MEM_TYPE_APPL 1 - #define XPRG_MEM_TYPE_BOOT 2 - #define XPRG_MEM_TYPE_EEPROM 3 - #define XPRG_MEM_TYPE_FUSE 4 - #define XPRG_MEM_TYPE_LOCKBITS 5 - #define XPRG_MEM_TYPE_USERSIG 6 - #define XPRG_MEM_TYPE_FACTORY_CALIBRATION 7 - - #define XPRG_ERASE_CHIP 1 - #define XPRG_ERASE_APP 2 - #define XPRG_ERASE_BOOT 3 - #define XPRG_ERASE_EEPROM 4 - #define XPRG_ERASE_APP_PAGE 5 - #define XPRG_ERASE_BOOT_PAGE 6 - #define XPRG_ERASE_EEPROM_PAGE 7 - #define XPRG_ERASE_USERSIG 8 - - #define XPRG_MEM_WRITE_ERASE 0 - #define XPRG_MEM_WRITE_WRITE 1 - - #define XPRG_CRC_APP 1 - #define XPRG_CRC_BOOT 2 - #define XPRG_CRC_FLASH 3 - - #define XPRG_ERR_OK 0 - #define XPRG_ERR_FAILED 1 - #define XPRG_ERR_COLLISION 2 - #define XPRG_ERR_TIMEOUT 3 - - #define XPRG_PARAM_NVMBASE 0x01 - #define XPRG_PARAM_EEPPAGESIZE 0x02 - - #define XPRG_PROTOCOL_PDI 0x00 - #define XPRG_PROTOCOL_JTAG 0x01 - - #define XPRG_PAGEMODE_WRITE (1 << 1) - #define XPRG_PAGEMODE_ERASE (1 << 0) - - /* External Variables: */ - extern uint32_t XPROG_Param_NVMBase; - - /* Function Prototypes: */ - void PDIProtocol_XPROG_SetMode(void); - void PDIProtocol_XPROG_Command(void); - - #if defined(INCLUDE_FROM_PDIPROTOCOL_C) - static void PDIProtocol_EnterXPROGMode(void); - static void PDIProtocol_LeaveXPROGMode(void); - static void PDIProtocol_SetParam(void); - static void PDIProtocol_Erase(void); - static void PDIProtocol_WriteMemory(void); - static void PDIProtocol_ReadMemory(void); - static void PDIProtocol_ReadCRC(void); - #endif - -#endif diff --git a/Projects/AVRISP/Lib/PDITarget.c b/Projects/AVRISP/Lib/PDITarget.c deleted file mode 100644 index 2c6ffd9a6..000000000 --- a/Projects/AVRISP/Lib/PDITarget.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Target-related functions for the PDI Protocol decoder. - */ - -#define INCLUDE_FROM_PDITARGET_C -#include "PDITarget.h" - -#if defined(ENABLE_PDI_PROTOCOL) || defined(__DOXYGEN__) - -/** Flag to indicate if the USART is currently in Tx or Rx mode. */ -volatile bool IsSending; - -#if !defined(PDI_VIA_HARDWARE_USART) -/** Software USART raw frame bits for transmission/reception. */ -volatile uint16_t SoftUSART_Data; - -/** Bits remaining to be sent or received via the software USART - set as a GPIOR for speed. */ -#define SoftUSART_BitCount GPIOR2 - - -/** ISR to manage the software USART when bit-banged USART mode is selected. */ -ISR(TIMER1_COMPA_vect, ISR_BLOCK) -{ - /* Toggle CLOCK pin in a single cycle (see AVR datasheet) */ - BITBANG_PDICLOCK_PIN |= BITBANG_PDICLOCK_MASK; - - /* If not sending or receiving, just exit */ - if (!(SoftUSART_BitCount)) - return; - - /* Check to see if we are at a rising or falling edge of the clock */ - if (BITBANG_PDICLOCK_PORT & BITBANG_PDICLOCK_MASK) - { - /* If at rising clock edge and we are in send mode, abort */ - if (IsSending) - return; - - /* Wait for the start bit when receiving */ - if ((SoftUSART_BitCount == BITS_IN_PDI_FRAME) && (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK)) - return; - - /* Shift in the bit one less than the frame size in position, so that the start bit will eventually - * be discarded leaving the data to be byte-aligned for quick access */ - if (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK) - SoftUSART_Data |= (1 << (BITS_IN_PDI_FRAME - 1)); - - SoftUSART_Data >>= 1; - SoftUSART_BitCount--; - } - else - { - /* If at falling clock edge and we are in receive mode, abort */ - if (!IsSending) - return; - - /* Set the data line to the next bit value */ - if (SoftUSART_Data & 0x01) - BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK; - else - BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK; - - SoftUSART_Data >>= 1; - SoftUSART_BitCount--; - } -} -#endif - -/** Enables the target's PDI interface, holding the target in reset until PDI mode is exited. */ -void PDITarget_EnableTargetPDI(void) -{ -#if defined(PDI_VIA_HARDWARE_USART) - /* Set Tx and XCK as outputs, Rx as input */ - DDRD |= (1 << 5) | (1 << 3); - DDRD &= ~(1 << 2); - - /* Set DATA line high for at least 90ns to disable /RESET functionality */ - PORTD |= (1 << 3); - asm volatile ("NOP"::); - asm volatile ("NOP"::); - - /* Set up the synchronous USART for XMEGA communications - - 8 data bits, even parity, 2 stop bits */ - UBRR1 = (F_CPU / 1000000UL); - UCSR1B = (1 << TXEN1); - UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1); - - /* Send two BREAKs of 12 bits each to enable PDI interface (need at least 16 idle bits) */ - PDITarget_SendBreak(); - PDITarget_SendBreak(); -#else - /* Set DATA and CLOCK lines to outputs */ - BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK; - BITBANG_PDICLOCK_DDR |= BITBANG_PDICLOCK_MASK; - - /* Set DATA line high for at least 90ns to disable /RESET functionality */ - BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK; - asm volatile ("NOP"::); - asm volatile ("NOP"::); - - /* Fire timer compare ISR every 100 cycles to manage the software USART */ - OCR1A = 80; - TCCR1B = (1 << WGM12) | (1 << CS10); - TIMSK1 = (1 << OCIE1A); - - /* Send two BREAKs of 12 bits each to enable TPI interface (need at least 16 idle bits) */ - PDITarget_SendBreak(); - PDITarget_SendBreak(); -#endif -} - -/** Disables the target's PDI interface, exits programming mode and starts the target's application. */ -void PDITarget_DisableTargetPDI(void) -{ -#if defined(PDI_VIA_HARDWARE_USART) - /* Turn off receiver and transmitter of the USART, clear settings */ - UCSR1A |= (1 << TXC1) | (1 << RXC1); - UCSR1B = 0; - UCSR1C = 0; - - /* Set all USART lines as input, tristate */ - DDRD &= ~((1 << 5) | (1 << 3)); - PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2)); -#else - /* Set DATA and CLOCK lines to inputs */ - BITBANG_PDIDATA_DDR &= ~BITBANG_PDIDATA_MASK; - BITBANG_PDICLOCK_DDR &= ~BITBANG_PDICLOCK_MASK; - - /* Tristate DATA and CLOCK lines */ - BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK; - BITBANG_PDICLOCK_PORT &= ~BITBANG_PDICLOCK_MASK; -#endif -} - -/** Sends a byte via the USART. - * - * \param[in] Byte Byte to send through the USART - */ -void PDITarget_SendByte(const uint8_t Byte) -{ -#if defined(PDI_VIA_HARDWARE_USART) - /* Switch to Tx mode if currently in Rx mode */ - if (!(IsSending)) - { - PORTD |= (1 << 3); - DDRD |= (1 << 3); - - UCSR1B |= (1 << TXEN1); - UCSR1B &= ~(1 << RXEN1); - - IsSending = true; - } - - /* Wait until there is space in the hardware Tx buffer before writing */ - while (!(UCSR1A & (1 << UDRE1))); - UCSR1A |= (1 << TXC1); - UDR1 = Byte; -#else - /* Switch to Tx mode if currently in Rx mode */ - if (!(IsSending)) - { - BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK; - BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK; - - IsSending = true; - } - - /* Calculate the new USART frame data here while while we wait for a previous byte (if any) to finish sending */ - uint16_t NewUSARTData = ((1 << 11) | (1 << 10) | (0 << 9) | ((uint16_t)Byte << 1) | (0 << 0)); - - /* Compute Even parity - while a bit is still set, chop off lowest bit and toggle parity bit */ - uint8_t ParityData = Byte; - while (ParityData) - { - NewUSARTData ^= (1 << 9); - ParityData &= (ParityData - 1); - } - - /* Wait until transmitter is idle before writing new data */ - while (SoftUSART_BitCount); - - /* Data shifted out LSB first, START DATA PARITY STOP STOP */ - SoftUSART_Data = NewUSARTData; - SoftUSART_BitCount = BITS_IN_PDI_FRAME; -#endif -} - -/** Receives a byte via the software USART, blocking until data is received. - * - * \return Received byte from the USART - */ -uint8_t PDITarget_ReceiveByte(void) -{ -#if defined(PDI_VIA_HARDWARE_USART) - /* Switch to Rx mode if currently in Tx mode */ - if (IsSending) - { - while (!(UCSR1A & (1 << TXC1))); - UCSR1A |= (1 << TXC1); - - UCSR1B &= ~(1 << TXEN1); - UCSR1B |= (1 << RXEN1); - - DDRD &= ~(1 << 3); - PORTD &= ~(1 << 3); - - IsSending = false; - } - - /* Wait until a byte has been received before reading */ - while (!(UCSR1A & (1 << RXC1))); - return UDR1; -#else - /* Switch to Rx mode if currently in Tx mode */ - if (IsSending) - { - while (SoftUSART_BitCount); - - BITBANG_PDIDATA_DDR &= ~BITBANG_PDIDATA_MASK; - BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK; - - IsSending = false; - } - - /* Wait until a byte has been received before reading */ - SoftUSART_BitCount = BITS_IN_PDI_FRAME; - while (SoftUSART_BitCount); - - /* Throw away the parity and stop bits to leave only the data (start bit is already discarded) */ - return (uint8_t)SoftUSART_Data; -#endif -} - -/** Sends a BREAK via the USART to the attached target, consisting of a full frame of idle bits. */ -void PDITarget_SendBreak(void) -{ -#if defined(PDI_VIA_HARDWARE_USART) - /* Switch to Tx mode if currently in Rx mode */ - if (!(IsSending)) - { - PORTD |= (1 << 3); - DDRD |= (1 << 3); - - UCSR1B &= ~(1 << RXEN1); - UCSR1B |= (1 << TXEN1); - - IsSending = true; - } - - /* Need to do nothing for a full frame to send a BREAK */ - for (uint8_t i = 0; i < BITS_IN_PDI_FRAME; i++) - { - /* Wait for a full cycle of the clock */ - while (PIND & (1 << 5)); - while (!(PIND & (1 << 5))); - } -#else - /* Switch to Tx mode if currently in Rx mode */ - if (!(IsSending)) - { - BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK; - BITBANG_PDIDATA_DDR |= BITBANG_PDIDATA_MASK; - - IsSending = true; - } - - while (SoftUSART_BitCount); - - /* Need to do nothing for a full frame to send a BREAK */ - SoftUSART_Data = 0x0FFF; - SoftUSART_BitCount = BITS_IN_PDI_FRAME; -#endif -} - -/** Busy-waits while the NVM controller is busy performing a NVM operation, such as a FLASH page read or CRC - * calculation. - * - * \return Boolean true if the NVM controller became ready within the timeout period, false otherwise - */ -bool PDITarget_WaitWhileNVMBusBusy(void) -{ - TCNT0 = 0; - TIFR0 = (1 << OCF1A); - - uint8_t TimeoutMS = PDI_NVM_TIMEOUT_MS; - - /* Poll the STATUS register to check to see if NVM access has been enabled */ - while (TimeoutMS) - { - /* Send the LDCS command to read the PDI STATUS register to see the NVM bus is active */ - PDITarget_SendByte(PDI_CMD_LDCS | PDI_STATUS_REG); - if (PDITarget_ReceiveByte() & PDI_STATUS_NVM) - return true; - - if (TIFR0 & (1 << OCF1A)) - { - TIFR0 = (1 << OCF1A); - TimeoutMS--; - } - } - - return false; -} - -#endif diff --git a/Projects/AVRISP/Lib/PDITarget.h b/Projects/AVRISP/Lib/PDITarget.h deleted file mode 100644 index cf7780c17..000000000 --- a/Projects/AVRISP/Lib/PDITarget.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Header file for PDITarget.c. - */ - -#ifndef _PDI_TARGET_ -#define _PDI_TARGET_ - - /* Includes: */ - #include - #include - #include - - #include - - /* Preprocessor Checks: */ - #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) - #undef ENABLE_ISP_PROTOCOL - #undef ENABLE_TPI_PROTOCOL - - #if !defined(ENABLE_PDI_PROTOCOL) - #define ENABLE_PDI_PROTOCOL - #endif - #endif - - /* Defines: */ - #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) - #define PDI_VIA_HARDWARE_USART - #else - #define BITBANG_PDIDATA_PORT PORTB - #define BITBANG_PDIDATA_DDR DDRB - #define BITBANG_PDIDATA_PIN PINB - #define BITBANG_PDIDATA_MASK (1 << 3) - - #define BITBANG_PDICLOCK_PORT RESET_LINE_PORT - #define BITBANG_PDICLOCK_DDR RESET_LINE_DDR - #define BITBANG_PDICLOCK_PIN RESET_LINE_PIN - #define BITBANG_PDICLOCK_MASK RESET_LINE_MASK - #endif - - /** Total number of bits in a single USART frame */ - #define BITS_IN_PDI_FRAME 12 - - /** Timeout in milliseconds of a PDI busy-wait command */ - #define PDI_NVM_TIMEOUT_MS 100 - - #define PDI_CMD_LDS 0x00 - #define PDI_CMD_LD 0x20 - #define PDI_CMD_STS 0x40 - #define PDI_CMD_ST 0x60 - #define PDI_CMD_LDCS 0x80 - #define PDI_CMD_REPEAT 0xA0 - #define PDI_CMD_STCS 0xC0 - #define PDI_CMD_KEY 0xE0 - - #define PDI_STATUS_REG 0 - #define PDI_RESET_REG 1 - #define PDI_CTRL_REG 2 - - #define PDI_STATUS_NVM (1 << 1) - #define PDI_RESET_KEY 0x59 - - #define PDI_NVMENABLE_KEY (uint8_t[]){0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF} - - #define PDI_DATSIZE_1BYTE 0 - #define PDI_DATSIZE_2BYTES 1 - #define PDI_DATSIZE_3BYTES 2 - #define PDI_DATSIZE_4BYTES 3 - - #define PDI_POINTER_INDIRECT 0 - #define PDI_POINTER_INDIRECT_PI 1 - #define PDI_POINTER_DIRECT 2 - - /* Function Prototypes: */ - void PDITarget_EnableTargetPDI(void); - void PDITarget_DisableTargetPDI(void); - void PDITarget_SendByte(const uint8_t Byte); - uint8_t PDITarget_ReceiveByte(void); - void PDITarget_SendBreak(void); - bool PDITarget_WaitWhileNVMBusBusy(void); - -#endif diff --git a/Projects/AVRISP/Lib/TINYNVM.c b/Projects/AVRISP/Lib/TINYNVM.c deleted file mode 100644 index 206ea39f2..000000000 --- a/Projects/AVRISP/Lib/TINYNVM.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Target-related functions for the TINY target's NVM module. - */ - -#define INCLUDE_FROM_TINYNVM_C -#include "TINYNVM.h" - -#if defined(ENABLE_TPI_PROTOCOL) || defined(__DOXYGEN__) - -// TODO - -#endif diff --git a/Projects/AVRISP/Lib/TINYNVM.h b/Projects/AVRISP/Lib/TINYNVM.h deleted file mode 100644 index eca3c98b8..000000000 --- a/Projects/AVRISP/Lib/TINYNVM.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Header file for TINYNVM.c. - */ - -#ifndef _TINY_NVM_ -#define _TINY_NVM_ - - /* Includes: */ - #include - #include - #include - - #include - - #include "TPIProtocol.h" - #include "TPITarget.h" - - /* Preprocessor Checks: */ - #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) - #undef ENABLE_ISP_PROTOCOL - #undef ENABLE_TPI_PROTOCOL - - #if !defined(ENABLE_PDI_PROTOCOL) - #define ENABLE_PDI_PROTOCOL - #endif - #endif - - /* Defines: */ - #define TINY_NVM_BUSY_TIMEOUT_MS 100 - -#endif diff --git a/Projects/AVRISP/Lib/TPI/TINYNVM.c b/Projects/AVRISP/Lib/TPI/TINYNVM.c new file mode 100644 index 000000000..206ea39f2 --- /dev/null +++ b/Projects/AVRISP/Lib/TPI/TINYNVM.c @@ -0,0 +1,43 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Target-related functions for the TINY target's NVM module. + */ + +#define INCLUDE_FROM_TINYNVM_C +#include "TINYNVM.h" + +#if defined(ENABLE_TPI_PROTOCOL) || defined(__DOXYGEN__) + +// TODO + +#endif diff --git a/Projects/AVRISP/Lib/TPI/TINYNVM.h b/Projects/AVRISP/Lib/TPI/TINYNVM.h new file mode 100644 index 000000000..eca3c98b8 --- /dev/null +++ b/Projects/AVRISP/Lib/TPI/TINYNVM.h @@ -0,0 +1,62 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for TINYNVM.c. + */ + +#ifndef _TINY_NVM_ +#define _TINY_NVM_ + + /* Includes: */ + #include + #include + #include + + #include + + #include "TPIProtocol.h" + #include "TPITarget.h" + + /* Preprocessor Checks: */ + #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) + #undef ENABLE_ISP_PROTOCOL + #undef ENABLE_TPI_PROTOCOL + + #if !defined(ENABLE_PDI_PROTOCOL) + #define ENABLE_PDI_PROTOCOL + #endif + #endif + + /* Defines: */ + #define TINY_NVM_BUSY_TIMEOUT_MS 100 + +#endif diff --git a/Projects/AVRISP/Lib/TPI/TPIProtocol.c b/Projects/AVRISP/Lib/TPI/TPIProtocol.c new file mode 100644 index 000000000..a95e94b60 --- /dev/null +++ b/Projects/AVRISP/Lib/TPI/TPIProtocol.c @@ -0,0 +1,44 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * TPI Protocol handler, to process V2 Protocol wrapped TPI commands used in Atmel programmer devices. + */ + +#define INCLUDE_FROM_TPIPROTOCOL_C +#include "TPIProtocol.h" + +#if defined(ENABLE_TPI_PROTOCOL) || defined(__DOXYGEN__) +#warning TPI Programming Protocol is currently incomplete and is not suitable for general use. + +// TODO + +#endif diff --git a/Projects/AVRISP/Lib/TPI/TPIProtocol.h b/Projects/AVRISP/Lib/TPI/TPIProtocol.h new file mode 100644 index 000000000..2b6849c1e --- /dev/null +++ b/Projects/AVRISP/Lib/TPI/TPIProtocol.h @@ -0,0 +1,58 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for TPIProtocol.c. + */ + +#ifndef _TPI_PROTOCOL_ +#define _TPI_PROTOCOL_ + + /* Includes: */ + #include + #include + #include + + #include "V2Protocol.h" + #include "TPITarget.h" + #include "TINYNVM.h" + + /* Preprocessor Checks: */ + #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) + #undef ENABLE_ISP_PROTOCOL + #undef ENABLE_TPI_PROTOCOL + + #if !defined(ENABLE_PDI_PROTOCOL) + #define ENABLE_PDI_PROTOCOL + #endif + #endif + +#endif diff --git a/Projects/AVRISP/Lib/TPI/TPITarget.c b/Projects/AVRISP/Lib/TPI/TPITarget.c new file mode 100644 index 000000000..464d40305 --- /dev/null +++ b/Projects/AVRISP/Lib/TPI/TPITarget.c @@ -0,0 +1,338 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Target-related functions for the TPI Protocol decoder. + */ + +#define INCLUDE_FROM_TPITARGET_C +#include "TPITarget.h" + +#if defined(ENABLE_TPI_PROTOCOL) || defined(__DOXYGEN__) + +/** Flag to indicate if the USART is currently in Tx or Rx mode. */ +volatile bool IsSending; + +#if !defined(TPI_VIA_HARDWARE_USART) +/** Software USART raw frame bits for transmission/reception. */ +volatile uint16_t SoftUSART_Data; + +/** Bits remaining to be sent or received via the software USART - set as a GPIOR for speed. */ +#define SoftUSART_BitCount GPIOR2 + + +/** ISR to manage the software USART when bit-banged USART mode is selected. */ +ISR(TIMER1_CAPT_vect, ISR_BLOCK) +{ + /* Toggle CLOCK pin in a single cycle (see AVR datasheet) */ + BITBANG_TPICLOCK_PIN |= BITBANG_TPICLOCK_MASK; + + /* If not sending or receiving, just exit */ + if (!(SoftUSART_BitCount)) + return; + + /* Check to see if we are at a rising or falling edge of the clock */ + if (BITBANG_TPICLOCK_PORT & BITBANG_TPICLOCK_MASK) + { + /* If at rising clock edge and we are in send mode, abort */ + if (IsSending) + return; + + /* Wait for the start bit when receiving */ + if ((SoftUSART_BitCount == BITS_IN_TPI_FRAME) && (BITBANG_TPIDATA_PIN & BITBANG_TPIDATA_MASK)) + return; + + /* Shift in the bit one less than the frame size in position, so that the start bit will eventually + * be discarded leaving the data to be byte-aligned for quick access */ + if (BITBANG_TPIDATA_PIN & BITBANG_TPIDATA_MASK) + SoftUSART_Data |= (1 << (BITS_IN_TPI_FRAME - 1)); + + SoftUSART_Data >>= 1; + SoftUSART_BitCount--; + } + else + { + /* If at falling clock edge and we are in receive mode, abort */ + if (!IsSending) + return; + + /* Set the data line to the next bit value */ + if (SoftUSART_Data & 0x01) + BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK; + else + BITBANG_TPIDATA_PORT &= ~BITBANG_TPIDATA_MASK; + + SoftUSART_Data >>= 1; + SoftUSART_BitCount--; + } +} +#endif + +/** Enables the target's TPI interface, holding the target in reset until TPI mode is exited. */ +void TPITarget_EnableTargetTPI(void) +{ + /* Set /RESET line low for at least 90ns to enable TPI functionality */ + RESET_LINE_DDR |= RESET_LINE_MASK; + RESET_LINE_PORT &= ~RESET_LINE_MASK; + asm volatile ("NOP"::); + asm volatile ("NOP"::); + +#if defined(TPI_VIA_HARDWARE_USART) + /* Set Tx and XCK as outputs, Rx as input */ + DDRD |= (1 << 5) | (1 << 3); + DDRD &= ~(1 << 2); + + /* Set up the synchronous USART for XMEGA communications - + 8 data bits, even parity, 2 stop bits */ + UBRR1 = (F_CPU / 1000000UL); + UCSR1B = (1 << TXEN1); + UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1); + + /* Send two BREAKs of 12 bits each to enable TPI interface (need at least 16 idle bits) */ + TPITarget_SendBreak(); + TPITarget_SendBreak(); +#else + /* Set DATA and CLOCK lines to outputs */ + BITBANG_TPIDATA_DDR |= BITBANG_TPIDATA_MASK; + BITBANG_TPICLOCK_DDR |= BITBANG_TPICLOCK_MASK; + + /* Set DATA line high for idle state */ + BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK; + + /* Fire timer capture ISR every 100 cycles to manage the software USART */ + OCR1A = 80; + TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10); + TIMSK1 = (1 << ICIE1); + + /* Send two BREAKs of 12 bits each to enable TPI interface (need at least 16 idle bits) */ + TPITarget_SendBreak(); + TPITarget_SendBreak(); +#endif +} + +/** Disables the target's TPI interface, exits programming mode and starts the target's application. */ +void TPITarget_DisableTargetTPI(void) +{ +#if defined(TPI_VIA_HARDWARE_USART) + /* Turn off receiver and transmitter of the USART, clear settings */ + UCSR1A |= (1 << TXC1) | (1 << RXC1); + UCSR1B = 0; + UCSR1C = 0; + + /* Set all USART lines as input, tristate */ + DDRD &= ~((1 << 5) | (1 << 3)); + PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2)); +#else + /* Set DATA and CLOCK lines to inputs */ + BITBANG_TPIDATA_DDR &= ~BITBANG_TPIDATA_MASK; + BITBANG_TPICLOCK_DDR &= ~BITBANG_TPICLOCK_MASK; + + /* Tristate DATA and CLOCK lines */ + BITBANG_TPIDATA_PORT &= ~BITBANG_TPIDATA_MASK; + BITBANG_TPICLOCK_PORT &= ~BITBANG_TPICLOCK_MASK; +#endif + + /* Tristate target /RESET line */ + RESET_LINE_DDR &= ~RESET_LINE_MASK; + RESET_LINE_PORT &= ~RESET_LINE_MASK; +} + +/** Sends a byte via the USART. + * + * \param[in] Byte Byte to send through the USART + */ +void TPITarget_SendByte(const uint8_t Byte) +{ +#if defined(TPI_VIA_HARDWARE_USART) + /* Switch to Tx mode if currently in Rx mode */ + if (!(IsSending)) + { + PORTD |= (1 << 3); + DDRD |= (1 << 3); + + UCSR1B |= (1 << TXEN1); + UCSR1B &= ~(1 << RXEN1); + + IsSending = true; + } + + /* Wait until there is space in the hardware Tx buffer before writing */ + while (!(UCSR1A & (1 << UDRE1))); + UCSR1A |= (1 << TXC1); + UDR1 = Byte; +#else + /* Switch to Tx mode if currently in Rx mode */ + if (!(IsSending)) + { + BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK; + BITBANG_TPIDATA_DDR |= BITBANG_TPIDATA_MASK; + + IsSending = true; + } + + /* Calculate the new USART frame data here while while we wait for a previous byte (if any) to finish sending */ + uint16_t NewUSARTData = ((1 << 11) | (1 << 10) | (0 << 9) | ((uint16_t)Byte << 1) | (0 << 0)); + + /* Compute Even parity - while a bit is still set, chop off lowest bit and toggle parity bit */ + uint8_t ParityData = Byte; + while (ParityData) + { + NewUSARTData ^= (1 << 9); + ParityData &= (ParityData - 1); + } + + /* Wait until transmitter is idle before writing new data */ + while (SoftUSART_BitCount); + + /* Data shifted out LSB first, START DATA PARITY STOP STOP */ + SoftUSART_Data = NewUSARTData; + SoftUSART_BitCount = BITS_IN_TPI_FRAME; +#endif +} + +/** Receives a byte via the software USART, blocking until data is received. + * + * \return Received byte from the USART + */ +uint8_t TPITarget_ReceiveByte(void) +{ +#if defined(TPI_VIA_HARDWARE_USART) + /* Switch to Rx mode if currently in Tx mode */ + if (IsSending) + { + while (!(UCSR1A & (1 << TXC1))); + UCSR1A |= (1 << TXC1); + + UCSR1B &= ~(1 << TXEN1); + UCSR1B |= (1 << RXEN1); + + DDRD &= ~(1 << 3); + PORTD &= ~(1 << 3); + + IsSending = false; + } + + /* Wait until a byte has been received before reading */ + while (!(UCSR1A & (1 << RXC1))); + return UDR1; +#else + /* Switch to Rx mode if currently in Tx mode */ + if (IsSending) + { + while (SoftUSART_BitCount); + + BITBANG_TPIDATA_DDR &= ~BITBANG_TPIDATA_MASK; + BITBANG_TPIDATA_PORT &= ~BITBANG_TPIDATA_MASK; + + IsSending = false; + } + + /* Wait until a byte has been received before reading */ + SoftUSART_BitCount = BITS_IN_TPI_FRAME; + while (SoftUSART_BitCount); + + /* Throw away the parity and stop bits to leave only the data (start bit is already discarded) */ + return (uint8_t)SoftUSART_Data; +#endif +} + +/** Sends a BREAK via the USART to the attached target, consisting of a full frame of idle bits. */ +void TPITarget_SendBreak(void) +{ +#if defined(TPI_VIA_HARDWARE_USART) + /* Switch to Tx mode if currently in Rx mode */ + if (!(IsSending)) + { + PORTD |= (1 << 3); + DDRD |= (1 << 3); + + UCSR1B &= ~(1 << RXEN1); + UCSR1B |= (1 << TXEN1); + + IsSending = true; + } + + /* Need to do nothing for a full frame to send a BREAK */ + for (uint8_t i = 0; i < BITS_IN_TPI_FRAME; i++) + { + /* Wait for a full cycle of the clock */ + while (PIND & (1 << 5)); + while (!(PIND & (1 << 5))); + } +#else + /* Switch to Tx mode if currently in Rx mode */ + if (!(IsSending)) + { + BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK; + BITBANG_TPIDATA_DDR |= BITBANG_TPIDATA_MASK; + + IsSending = true; + } + + while (SoftUSART_BitCount); + + /* Need to do nothing for a full frame to send a BREAK */ + SoftUSART_Data = 0x0FFF; + SoftUSART_BitCount = BITS_IN_TPI_FRAME; +#endif +} + +/** Busy-waits while the NVM controller is busy performing a NVM operation, such as a FLASH page read or CRC + * calculation. + * + * \return Boolean true if the NVM controller became ready within the timeout period, false otherwise + */ +bool TPITarget_WaitWhileNVMBusBusy(void) +{ + TCNT0 = 0; + TIFR0 = (1 << OCF1A); + + uint8_t TimeoutMS = TPI_NVM_TIMEOUT_MS; + + /* Poll the STATUS register to check to see if NVM access has been enabled */ + while (TimeoutMS) + { + /* Send the LDCS command to read the TPI STATUS register to see the NVM bus is active */ + TPITarget_SendByte(TPI_CMD_SLDCS | TPI_STATUS_REG); + if (TPITarget_ReceiveByte() & TPI_STATUS_NVM) + return true; + + if (TIFR0 & (1 << OCF1A)) + { + TIFR0 = (1 << OCF1A); + TimeoutMS--; + } + } + + return false; +} + +#endif diff --git a/Projects/AVRISP/Lib/TPI/TPITarget.h b/Projects/AVRISP/Lib/TPI/TPITarget.h new file mode 100644 index 000000000..596bdce21 --- /dev/null +++ b/Projects/AVRISP/Lib/TPI/TPITarget.h @@ -0,0 +1,101 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for TPITarget.c. + */ + +#ifndef _TPI_TARGET_ +#define _TPI_TARGET_ + + /* Includes: */ + #include + #include + #include + + #include + + /* Preprocessor Checks: */ + #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) + #undef ENABLE_ISP_PROTOCOL + #undef ENABLE_TPI_PROTOCOL + + #if !defined(ENABLE_PDI_PROTOCOL) + #define ENABLE_PDI_PROTOCOL + #endif + #endif + + /* Defines: */ + #define BITBANG_TPIDATA_PORT PORTB + #define BITBANG_TPIDATA_DDR DDRB + #define BITBANG_TPIDATA_PIN PINB + #define BITBANG_TPIDATA_MASK (1 << 3) + + #define BITBANG_TPICLOCK_PORT PORTB + #define BITBANG_TPICLOCK_DDR DDRB + #define BITBANG_TPICLOCK_PIN PINB + #define BITBANG_TPICLOCK_MASK (1 << 1) + + /** Total number of bits in a single USART frame */ + #define BITS_IN_TPI_FRAME 12 + + /** Timeout in milliseconds of a PDI busy-wait command */ + #define TPI_NVM_TIMEOUT_MS 100 + + #define TPI_CMD_SLD 0x20 + #define TPI_CMD_SST 0x60 + #define TPI_CMD_SSTPR 0x68 + #define TPI_CMD_SIN 0x10 + #define TPI_CMD_SOUT 0x90 + #define TPI_CMD_SLDCS 0x80 + #define TPI_CMD_SSTCS 0xC0 + #define TPI_CMD_SKEY 0xE0 + + #define TPI_STATUS_REG 0x00 + #define TPI_CTRL_REG 0x02 + #define TPI_ID_REG 0x0F + + #define TPI_STATUS_NVM (1 << 1) + + #define TPI_NVMENABLE_KEY (uint8_t[]){0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF} + + #define TPI_POINTER_INDIRECT 0 + #define TPI_POINTER_INDIRECT_PI (1 << 2) + + /* Function Prototypes: */ + void TPITarget_EnableTargetTPI(void); + void TPITarget_DisableTargetTPI(void); + void TPITarget_SendByte(const uint8_t Byte); + uint8_t TPITarget_ReceiveByte(void); + void TPITarget_SendBreak(void); + bool TPITarget_WaitWhileNVMBusBusy(void); + +#endif diff --git a/Projects/AVRISP/Lib/TPIProtocol.c b/Projects/AVRISP/Lib/TPIProtocol.c deleted file mode 100644 index a95e94b60..000000000 --- a/Projects/AVRISP/Lib/TPIProtocol.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * TPI Protocol handler, to process V2 Protocol wrapped TPI commands used in Atmel programmer devices. - */ - -#define INCLUDE_FROM_TPIPROTOCOL_C -#include "TPIProtocol.h" - -#if defined(ENABLE_TPI_PROTOCOL) || defined(__DOXYGEN__) -#warning TPI Programming Protocol is currently incomplete and is not suitable for general use. - -// TODO - -#endif diff --git a/Projects/AVRISP/Lib/TPIProtocol.h b/Projects/AVRISP/Lib/TPIProtocol.h deleted file mode 100644 index 2b6849c1e..000000000 --- a/Projects/AVRISP/Lib/TPIProtocol.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Header file for TPIProtocol.c. - */ - -#ifndef _TPI_PROTOCOL_ -#define _TPI_PROTOCOL_ - - /* Includes: */ - #include - #include - #include - - #include "V2Protocol.h" - #include "TPITarget.h" - #include "TINYNVM.h" - - /* Preprocessor Checks: */ - #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) - #undef ENABLE_ISP_PROTOCOL - #undef ENABLE_TPI_PROTOCOL - - #if !defined(ENABLE_PDI_PROTOCOL) - #define ENABLE_PDI_PROTOCOL - #endif - #endif - -#endif diff --git a/Projects/AVRISP/Lib/TPITarget.c b/Projects/AVRISP/Lib/TPITarget.c deleted file mode 100644 index 464d40305..000000000 --- a/Projects/AVRISP/Lib/TPITarget.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Target-related functions for the TPI Protocol decoder. - */ - -#define INCLUDE_FROM_TPITARGET_C -#include "TPITarget.h" - -#if defined(ENABLE_TPI_PROTOCOL) || defined(__DOXYGEN__) - -/** Flag to indicate if the USART is currently in Tx or Rx mode. */ -volatile bool IsSending; - -#if !defined(TPI_VIA_HARDWARE_USART) -/** Software USART raw frame bits for transmission/reception. */ -volatile uint16_t SoftUSART_Data; - -/** Bits remaining to be sent or received via the software USART - set as a GPIOR for speed. */ -#define SoftUSART_BitCount GPIOR2 - - -/** ISR to manage the software USART when bit-banged USART mode is selected. */ -ISR(TIMER1_CAPT_vect, ISR_BLOCK) -{ - /* Toggle CLOCK pin in a single cycle (see AVR datasheet) */ - BITBANG_TPICLOCK_PIN |= BITBANG_TPICLOCK_MASK; - - /* If not sending or receiving, just exit */ - if (!(SoftUSART_BitCount)) - return; - - /* Check to see if we are at a rising or falling edge of the clock */ - if (BITBANG_TPICLOCK_PORT & BITBANG_TPICLOCK_MASK) - { - /* If at rising clock edge and we are in send mode, abort */ - if (IsSending) - return; - - /* Wait for the start bit when receiving */ - if ((SoftUSART_BitCount == BITS_IN_TPI_FRAME) && (BITBANG_TPIDATA_PIN & BITBANG_TPIDATA_MASK)) - return; - - /* Shift in the bit one less than the frame size in position, so that the start bit will eventually - * be discarded leaving the data to be byte-aligned for quick access */ - if (BITBANG_TPIDATA_PIN & BITBANG_TPIDATA_MASK) - SoftUSART_Data |= (1 << (BITS_IN_TPI_FRAME - 1)); - - SoftUSART_Data >>= 1; - SoftUSART_BitCount--; - } - else - { - /* If at falling clock edge and we are in receive mode, abort */ - if (!IsSending) - return; - - /* Set the data line to the next bit value */ - if (SoftUSART_Data & 0x01) - BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK; - else - BITBANG_TPIDATA_PORT &= ~BITBANG_TPIDATA_MASK; - - SoftUSART_Data >>= 1; - SoftUSART_BitCount--; - } -} -#endif - -/** Enables the target's TPI interface, holding the target in reset until TPI mode is exited. */ -void TPITarget_EnableTargetTPI(void) -{ - /* Set /RESET line low for at least 90ns to enable TPI functionality */ - RESET_LINE_DDR |= RESET_LINE_MASK; - RESET_LINE_PORT &= ~RESET_LINE_MASK; - asm volatile ("NOP"::); - asm volatile ("NOP"::); - -#if defined(TPI_VIA_HARDWARE_USART) - /* Set Tx and XCK as outputs, Rx as input */ - DDRD |= (1 << 5) | (1 << 3); - DDRD &= ~(1 << 2); - - /* Set up the synchronous USART for XMEGA communications - - 8 data bits, even parity, 2 stop bits */ - UBRR1 = (F_CPU / 1000000UL); - UCSR1B = (1 << TXEN1); - UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1); - - /* Send two BREAKs of 12 bits each to enable TPI interface (need at least 16 idle bits) */ - TPITarget_SendBreak(); - TPITarget_SendBreak(); -#else - /* Set DATA and CLOCK lines to outputs */ - BITBANG_TPIDATA_DDR |= BITBANG_TPIDATA_MASK; - BITBANG_TPICLOCK_DDR |= BITBANG_TPICLOCK_MASK; - - /* Set DATA line high for idle state */ - BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK; - - /* Fire timer capture ISR every 100 cycles to manage the software USART */ - OCR1A = 80; - TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10); - TIMSK1 = (1 << ICIE1); - - /* Send two BREAKs of 12 bits each to enable TPI interface (need at least 16 idle bits) */ - TPITarget_SendBreak(); - TPITarget_SendBreak(); -#endif -} - -/** Disables the target's TPI interface, exits programming mode and starts the target's application. */ -void TPITarget_DisableTargetTPI(void) -{ -#if defined(TPI_VIA_HARDWARE_USART) - /* Turn off receiver and transmitter of the USART, clear settings */ - UCSR1A |= (1 << TXC1) | (1 << RXC1); - UCSR1B = 0; - UCSR1C = 0; - - /* Set all USART lines as input, tristate */ - DDRD &= ~((1 << 5) | (1 << 3)); - PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2)); -#else - /* Set DATA and CLOCK lines to inputs */ - BITBANG_TPIDATA_DDR &= ~BITBANG_TPIDATA_MASK; - BITBANG_TPICLOCK_DDR &= ~BITBANG_TPICLOCK_MASK; - - /* Tristate DATA and CLOCK lines */ - BITBANG_TPIDATA_PORT &= ~BITBANG_TPIDATA_MASK; - BITBANG_TPICLOCK_PORT &= ~BITBANG_TPICLOCK_MASK; -#endif - - /* Tristate target /RESET line */ - RESET_LINE_DDR &= ~RESET_LINE_MASK; - RESET_LINE_PORT &= ~RESET_LINE_MASK; -} - -/** Sends a byte via the USART. - * - * \param[in] Byte Byte to send through the USART - */ -void TPITarget_SendByte(const uint8_t Byte) -{ -#if defined(TPI_VIA_HARDWARE_USART) - /* Switch to Tx mode if currently in Rx mode */ - if (!(IsSending)) - { - PORTD |= (1 << 3); - DDRD |= (1 << 3); - - UCSR1B |= (1 << TXEN1); - UCSR1B &= ~(1 << RXEN1); - - IsSending = true; - } - - /* Wait until there is space in the hardware Tx buffer before writing */ - while (!(UCSR1A & (1 << UDRE1))); - UCSR1A |= (1 << TXC1); - UDR1 = Byte; -#else - /* Switch to Tx mode if currently in Rx mode */ - if (!(IsSending)) - { - BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK; - BITBANG_TPIDATA_DDR |= BITBANG_TPIDATA_MASK; - - IsSending = true; - } - - /* Calculate the new USART frame data here while while we wait for a previous byte (if any) to finish sending */ - uint16_t NewUSARTData = ((1 << 11) | (1 << 10) | (0 << 9) | ((uint16_t)Byte << 1) | (0 << 0)); - - /* Compute Even parity - while a bit is still set, chop off lowest bit and toggle parity bit */ - uint8_t ParityData = Byte; - while (ParityData) - { - NewUSARTData ^= (1 << 9); - ParityData &= (ParityData - 1); - } - - /* Wait until transmitter is idle before writing new data */ - while (SoftUSART_BitCount); - - /* Data shifted out LSB first, START DATA PARITY STOP STOP */ - SoftUSART_Data = NewUSARTData; - SoftUSART_BitCount = BITS_IN_TPI_FRAME; -#endif -} - -/** Receives a byte via the software USART, blocking until data is received. - * - * \return Received byte from the USART - */ -uint8_t TPITarget_ReceiveByte(void) -{ -#if defined(TPI_VIA_HARDWARE_USART) - /* Switch to Rx mode if currently in Tx mode */ - if (IsSending) - { - while (!(UCSR1A & (1 << TXC1))); - UCSR1A |= (1 << TXC1); - - UCSR1B &= ~(1 << TXEN1); - UCSR1B |= (1 << RXEN1); - - DDRD &= ~(1 << 3); - PORTD &= ~(1 << 3); - - IsSending = false; - } - - /* Wait until a byte has been received before reading */ - while (!(UCSR1A & (1 << RXC1))); - return UDR1; -#else - /* Switch to Rx mode if currently in Tx mode */ - if (IsSending) - { - while (SoftUSART_BitCount); - - BITBANG_TPIDATA_DDR &= ~BITBANG_TPIDATA_MASK; - BITBANG_TPIDATA_PORT &= ~BITBANG_TPIDATA_MASK; - - IsSending = false; - } - - /* Wait until a byte has been received before reading */ - SoftUSART_BitCount = BITS_IN_TPI_FRAME; - while (SoftUSART_BitCount); - - /* Throw away the parity and stop bits to leave only the data (start bit is already discarded) */ - return (uint8_t)SoftUSART_Data; -#endif -} - -/** Sends a BREAK via the USART to the attached target, consisting of a full frame of idle bits. */ -void TPITarget_SendBreak(void) -{ -#if defined(TPI_VIA_HARDWARE_USART) - /* Switch to Tx mode if currently in Rx mode */ - if (!(IsSending)) - { - PORTD |= (1 << 3); - DDRD |= (1 << 3); - - UCSR1B &= ~(1 << RXEN1); - UCSR1B |= (1 << TXEN1); - - IsSending = true; - } - - /* Need to do nothing for a full frame to send a BREAK */ - for (uint8_t i = 0; i < BITS_IN_TPI_FRAME; i++) - { - /* Wait for a full cycle of the clock */ - while (PIND & (1 << 5)); - while (!(PIND & (1 << 5))); - } -#else - /* Switch to Tx mode if currently in Rx mode */ - if (!(IsSending)) - { - BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK; - BITBANG_TPIDATA_DDR |= BITBANG_TPIDATA_MASK; - - IsSending = true; - } - - while (SoftUSART_BitCount); - - /* Need to do nothing for a full frame to send a BREAK */ - SoftUSART_Data = 0x0FFF; - SoftUSART_BitCount = BITS_IN_TPI_FRAME; -#endif -} - -/** Busy-waits while the NVM controller is busy performing a NVM operation, such as a FLASH page read or CRC - * calculation. - * - * \return Boolean true if the NVM controller became ready within the timeout period, false otherwise - */ -bool TPITarget_WaitWhileNVMBusBusy(void) -{ - TCNT0 = 0; - TIFR0 = (1 << OCF1A); - - uint8_t TimeoutMS = TPI_NVM_TIMEOUT_MS; - - /* Poll the STATUS register to check to see if NVM access has been enabled */ - while (TimeoutMS) - { - /* Send the LDCS command to read the TPI STATUS register to see the NVM bus is active */ - TPITarget_SendByte(TPI_CMD_SLDCS | TPI_STATUS_REG); - if (TPITarget_ReceiveByte() & TPI_STATUS_NVM) - return true; - - if (TIFR0 & (1 << OCF1A)) - { - TIFR0 = (1 << OCF1A); - TimeoutMS--; - } - } - - return false; -} - -#endif diff --git a/Projects/AVRISP/Lib/TPITarget.h b/Projects/AVRISP/Lib/TPITarget.h deleted file mode 100644 index 596bdce21..000000000 --- a/Projects/AVRISP/Lib/TPITarget.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Header file for TPITarget.c. - */ - -#ifndef _TPI_TARGET_ -#define _TPI_TARGET_ - - /* Includes: */ - #include - #include - #include - - #include - - /* Preprocessor Checks: */ - #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) - #undef ENABLE_ISP_PROTOCOL - #undef ENABLE_TPI_PROTOCOL - - #if !defined(ENABLE_PDI_PROTOCOL) - #define ENABLE_PDI_PROTOCOL - #endif - #endif - - /* Defines: */ - #define BITBANG_TPIDATA_PORT PORTB - #define BITBANG_TPIDATA_DDR DDRB - #define BITBANG_TPIDATA_PIN PINB - #define BITBANG_TPIDATA_MASK (1 << 3) - - #define BITBANG_TPICLOCK_PORT PORTB - #define BITBANG_TPICLOCK_DDR DDRB - #define BITBANG_TPICLOCK_PIN PINB - #define BITBANG_TPICLOCK_MASK (1 << 1) - - /** Total number of bits in a single USART frame */ - #define BITS_IN_TPI_FRAME 12 - - /** Timeout in milliseconds of a PDI busy-wait command */ - #define TPI_NVM_TIMEOUT_MS 100 - - #define TPI_CMD_SLD 0x20 - #define TPI_CMD_SST 0x60 - #define TPI_CMD_SSTPR 0x68 - #define TPI_CMD_SIN 0x10 - #define TPI_CMD_SOUT 0x90 - #define TPI_CMD_SLDCS 0x80 - #define TPI_CMD_SSTCS 0xC0 - #define TPI_CMD_SKEY 0xE0 - - #define TPI_STATUS_REG 0x00 - #define TPI_CTRL_REG 0x02 - #define TPI_ID_REG 0x0F - - #define TPI_STATUS_NVM (1 << 1) - - #define TPI_NVMENABLE_KEY (uint8_t[]){0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF} - - #define TPI_POINTER_INDIRECT 0 - #define TPI_POINTER_INDIRECT_PI (1 << 2) - - /* Function Prototypes: */ - void TPITarget_EnableTargetTPI(void); - void TPITarget_DisableTargetTPI(void); - void TPITarget_SendByte(const uint8_t Byte); - uint8_t TPITarget_ReceiveByte(void); - void TPITarget_SendBreak(void); - bool TPITarget_WaitWhileNVMBusBusy(void); - -#endif diff --git a/Projects/AVRISP/Lib/XMEGANVM.c b/Projects/AVRISP/Lib/XMEGANVM.c deleted file mode 100644 index ed8719c4e..000000000 --- a/Projects/AVRISP/Lib/XMEGANVM.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Target-related functions for the XMEGA target's NVM module. - */ - -#define INCLUDE_FROM_XMEGA_NVM_C -#include "XMEGANVM.h" - -#if defined(ENABLE_PDI_PROTOCOL) || defined(__DOXYGEN__) - -/** Sends the given NVM register address to the target. - * - * \param[in] Register NVM register whose absolute address is to be sent - */ -void XMEGANVM_SendNVMRegAddress(const uint8_t Register) -{ - /* Determine the absolute register address from the NVM base memory address and the NVM register address */ - uint32_t Address = XPROG_Param_NVMBase | Register; - - /* Send the calculated 32-bit address to the target, LSB first */ - XMEGANVM_SendAddress(Address); -} - -/** Sends the given 32-bit absolute address to the target. - * - * \param[in] AbsoluteAddress Absolute address to send to the target - */ -void XMEGANVM_SendAddress(const uint32_t AbsoluteAddress) -{ - /* Send the given 32-bit address to the target, LSB first */ - PDITarget_SendByte(AbsoluteAddress & 0xFF); - PDITarget_SendByte(AbsoluteAddress >> 8); - PDITarget_SendByte(AbsoluteAddress >> 16); - PDITarget_SendByte(AbsoluteAddress >> 24); -} - -/** Waits while the target's NVM controller is busy performing an operation, exiting if the - * timeout period expires. - * - * \return Boolean true if the NVM controller became ready within the timeout period, false otherwise - */ -bool XMEGANVM_WaitWhileNVMControllerBusy(void) -{ - TCNT0 = 0; - TIFR0 = (1 << OCF1A); - - uint8_t TimeoutMS = XMEGA_NVM_BUSY_TIMEOUT_MS; - - /* Poll the NVM STATUS register while the NVM controller is busy */ - while (TimeoutMS) - { - /* Send a LDS command to read the NVM STATUS register to check the BUSY flag */ - PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_STATUS); - - /* Check to see if the BUSY flag is still set */ - if (!(PDITarget_ReceiveByte() & (1 << 7))) - return true; - - if (TIFR0 & (1 << OCF1A)) - { - TIFR0 = (1 << OCF1A); - TimeoutMS--; - } - } - - return false; -} - -/** Retrieves the CRC value of the given memory space. - * - * \param[in] CRCCommand NVM CRC command to issue to the target - * \param[out] CRCDest CRC Destination when read from the target - * - * \return Boolean true if the command sequence complete successfully - */ -bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest) -{ - /* Wait until the NVM controller is no longer busy */ - if (!(XMEGANVM_WaitWhileNVMControllerBusy())) - return false; - - /* Set the NVM command to the correct CRC read command */ - PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD); - PDITarget_SendByte(CRCCommand); - - /* Set CMDEX bit in NVM CTRLA register to start the CRC generation */ - PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA); - PDITarget_SendByte(1 << 0); - - /* Wait until the NVM bus is ready again */ - if (!(PDITarget_WaitWhileNVMBusBusy())) - return false; - - /* Wait until the NVM controller is no longer busy */ - if (!(XMEGANVM_WaitWhileNVMControllerBusy())) - return false; - - *CRCDest = 0; - - /* Read the first generated CRC byte value */ - PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT0); - *CRCDest = PDITarget_ReceiveByte(); - - /* Read the second generated CRC byte value */ - PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT1); - *CRCDest |= ((uint16_t)PDITarget_ReceiveByte() << 8); - - /* Read the third generated CRC byte value */ - PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT2); - *CRCDest |= ((uint32_t)PDITarget_ReceiveByte() << 16); - - return true; -} - -/** Reads memory from the target's memory spaces. - * - * \param[in] ReadAddress Start address to read from within the target's address space - * \param[out] ReadBuffer Buffer to store read data into - * \param[in] ReadSize Number of bytes to read - * - * \return Boolean true if the command sequence complete successfully - */ -bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const uint16_t ReadSize) -{ - /* Wait until the NVM controller is no longer busy */ - if (!(XMEGANVM_WaitWhileNVMControllerBusy())) - return false; - - /* Send the READNVM command to the NVM controller for reading of an arbitrary location */ - PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD); - PDITarget_SendByte(XMEGA_NVM_CMD_READNVM); - - /* Load the PDI pointer register with the start address we want to read from */ - PDITarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES); - XMEGANVM_SendAddress(ReadAddress); - - /* Send the REPEAT command with the specified number of bytes to read */ - PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE); - PDITarget_SendByte(ReadSize - 1); - - /* Send a LD command with indirect access and postincrement to read out the bytes */ - PDITarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE); - for (uint16_t i = 0; i < ReadSize; i++) - *(ReadBuffer++) = PDITarget_ReceiveByte(); - - return true; -} - -/** Writes byte addressed memory to the target's memory spaces. - * - * \param[in] WriteCommand Command to send to the device to write each memory byte - * \param[in] WriteAddress Start address to write to within the target's address space - * \param[in] WriteBuffer Buffer to source data from - * - * \return Boolean true if the command sequence complete successfully - */ -bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer) -{ - /* Wait until the NVM controller is no longer busy */ - if (!(XMEGANVM_WaitWhileNVMControllerBusy())) - return false; - - /* Send the memory write command to the target */ - PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD); - PDITarget_SendByte(WriteCommand); - - /* Send new memory byte to the memory to the target */ - PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendAddress(WriteAddress); - PDITarget_SendByte(*(WriteBuffer++)); - - return true; -} - -/** Writes page addressed memory to the target's memory spaces. - * - * \param[in] WriteBuffCommand Command to send to the device to write a byte to the memory page buffer - * \param[in] EraseBuffCommand Command to send to the device to erase the memory page buffer - * \param[in] WritePageCommand Command to send to the device to write the page buffer to the destination memory - * \param[in] PageMode Bitfield indicating what operations need to be executed on the specified page - * \param[in] WriteAddress Start address to write the page data to within the target's address space - * \param[in] WriteBuffer Buffer to source data from - * \param[in] WriteSize Number of bytes to write - * - * \return Boolean true if the command sequence complete successfully - */ -bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t EraseBuffCommand, - const uint8_t WritePageCommand, const uint8_t PageMode, const uint32_t WriteAddress, - const uint8_t* WriteBuffer, const uint16_t WriteSize) -{ - if (PageMode & XPRG_PAGEMODE_ERASE) - { - /* Wait until the NVM controller is no longer busy */ - if (!(XMEGANVM_WaitWhileNVMControllerBusy())) - return false; - - /* Send the memory buffer erase command to the target */ - PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD); - PDITarget_SendByte(EraseBuffCommand); - - /* Set CMDEX bit in NVM CTRLA register to start the buffer erase */ - PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA); - PDITarget_SendByte(1 << 0); - } - - if (WriteSize) - { - /* Wait until the NVM controller is no longer busy */ - if (!(XMEGANVM_WaitWhileNVMControllerBusy())) - return false; - - /* Send the memory buffer write command to the target */ - PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD); - PDITarget_SendByte(WriteBuffCommand); - - /* Load the PDI pointer register with the start address we want to write to */ - PDITarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES); - XMEGANVM_SendAddress(WriteAddress); - - /* Send the REPEAT command with the specified number of bytes to write */ - PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE); - PDITarget_SendByte(WriteSize - 1); - - /* Send a ST command with indirect access and postincrement to write the bytes */ - PDITarget_SendByte(PDI_CMD_ST | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE); - for (uint16_t i = 0; i < WriteSize; i++) - PDITarget_SendByte(*(WriteBuffer++)); - } - - if (PageMode & XPRG_PAGEMODE_WRITE) - { - /* Wait until the NVM controller is no longer busy */ - if (!(XMEGANVM_WaitWhileNVMControllerBusy())) - return false; - - /* Send the memory write command to the target */ - PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD); - PDITarget_SendByte(WritePageCommand); - - /* Send the address of the first page location to write the memory page */ - PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendAddress(WriteAddress); - PDITarget_SendByte(0x00); - } - - return true; -} - -/** Erases a specific memory space of the target. - * - * \param[in] EraseCommand NVM erase command to send to the device - * \param[in] Address Address inside the memory space to erase - * - * \return Boolean true if the command sequence complete successfully - */ -bool XMEGANVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address) -{ - /* Wait until the NVM controller is no longer busy */ - if (!(XMEGANVM_WaitWhileNVMControllerBusy())) - return false; - - /* Send the memory erase command to the target */ - PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD); - PDITarget_SendByte(EraseCommand); - - /* Chip erase is handled separately, since it's procedure is different to other erase types */ - if (EraseCommand == XMEGA_NVM_CMD_CHIPERASE) - { - /* Set CMDEX bit in NVM CTRLA register to start the chip erase */ - PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA); - PDITarget_SendByte(1 << 0); - } - else - { - /* Other erase modes just need us to address a byte within the target memory space */ - PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2)); - XMEGANVM_SendAddress(Address); - PDITarget_SendByte(0x00); - } - - /* Wait until the NVM bus is ready again */ - if (!(PDITarget_WaitWhileNVMBusBusy())) - return false; - - return true; -} - -#endif diff --git a/Projects/AVRISP/Lib/XMEGANVM.h b/Projects/AVRISP/Lib/XMEGANVM.h deleted file mode 100644 index c31c7e8f1..000000000 --- a/Projects/AVRISP/Lib/XMEGANVM.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2009. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Header file for XMEGANVM.c. - */ - -#ifndef _XMEGA_NVM__ -#define _XMEGA_NVM_ - - /* Includes: */ - #include - #include - #include - - #include - - #include "PDIProtocol.h" - #include "PDITarget.h" - - /* Preprocessor Checks: */ - #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) - #undef ENABLE_ISP_PROTOCOL - #undef ENABLE_TPI_PROTOCOL - - #if !defined(ENABLE_PDI_PROTOCOL) - #define ENABLE_PDI_PROTOCOL - #endif - #endif - - /* Defines: */ - #define XMEGA_NVM_BUSY_TIMEOUT_MS 200 - - #define XMEGA_NVM_REG_ADDR0 0x00 - #define XMEGA_NVM_REG_ADDR1 0x01 - #define XMEGA_NVM_REG_ADDR2 0x02 - #define XMEGA_NVM_REG_DAT0 0x04 - #define XMEGA_NVM_REG_DAT1 0x05 - #define XMEGA_NVM_REG_DAT2 0x06 - #define XMEGA_NVM_REG_CMD 0x0A - #define XMEGA_NVM_REG_CTRLA 0x0B - #define XMEGA_NVM_REG_CTRLB 0x0C - #define XMEGA_NVM_REG_INTCTRL 0x0D - #define XMEGA_NVM_REG_STATUS 0x0F - #define XMEGA_NVM_REG_LOCKBITS 0x10 - - #define XMEGA_NVM_CMD_NOOP 0x00 - #define XMEGA_NVM_CMD_CHIPERASE 0x40 - #define XMEGA_NVM_CMD_READNVM 0x43 - #define XMEGA_NVM_CMD_LOADFLASHPAGEBUFF 0x23 - #define XMEGA_NVM_CMD_ERASEFLASHPAGEBUFF 0x26 - #define XMEGA_NVM_CMD_ERASEFLASHPAGE 0x2B - #define XMEGA_NVM_CMD_WRITEFLASHPAGE 0x2E - #define XMEGA_NVM_CMD_ERASEWRITEFLASH 0x2F - #define XMEGA_NVM_CMD_FLASHCRC 0x78 - #define XMEGA_NVM_CMD_ERASEAPPSEC 0x20 - #define XMEGA_NVM_CMD_ERASEAPPSECPAGE 0x22 - #define XMEGA_NVM_CMD_WRITEAPPSECPAGE 0x24 - #define XMEGA_NVM_CMD_ERASEWRITEAPPSECPAGE 0x25 - #define XMEGA_NVM_CMD_APPCRC 0x38 - #define XMEGA_NVM_CMD_ERASEBOOTSEC 0x68 - #define XMEGA_NVM_CMD_ERASEBOOTSECPAGE 0x2A - #define XMEGA_NVM_CMD_WRITEBOOTSECPAGE 0x2C - #define XMEGA_NVM_CMD_ERASEWRITEBOOTSECPAGE 0x2D - #define XMEGA_NVM_CMD_BOOTCRC 0x39 - #define XMEGA_NVM_CMD_READUSERSIG 0x03 - #define XMEGA_NVM_CMD_ERASEUSERSIG 0x18 - #define XMEGA_NVM_CMD_WRITEUSERSIG 0x1A - #define XMEGA_NVM_CMD_READCALIBRATION 0x02 - #define XMEGA_NVM_CMD_READFUSE 0x07 - #define XMEGA_NVM_CMD_WRITEFUSE 0x4C - #define XMEGA_NVM_CMD_WRITELOCK 0x08 - #define XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF 0x33 - #define XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF 0x36 - #define XMEGA_NVM_CMD_ERASEEEPROM 0x30 - #define XMEGA_NVM_CMD_ERASEEEPROMPAGE 0x32 - #define XMEGA_NVM_CMD_WRITEEEPROMPAGE 0x34 - #define XMEGA_NVM_CMD_ERASEWRITEEEPROMPAGE 0x35 - #define XMEGA_NVM_CMD_READEEPROM 0x06 - - /* Function Prototypes: */ - void XMEGANVM_SendNVMRegAddress(const uint8_t Register); - void XMEGANVM_SendAddress(const uint32_t AbsoluteAddress); - bool XMEGANVM_WaitWhileNVMControllerBusy(void); - bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest); - bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const uint16_t ReadSize); - bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer); - bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t EraseBuffCommand, - const uint8_t WritePageCommand, const uint8_t PageMode, const uint32_t WriteAddress, - const uint8_t* WriteBuffer, const uint16_t WriteSize); - bool XMEGANVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address); - -#endif -- cgit v1.2.3