diff options
| author | Dean Camera <dean@fourwalledcubicle.com> | 2009-12-15 05:17:52 +0000 | 
|---|---|---|
| committer | Dean Camera <dean@fourwalledcubicle.com> | 2009-12-15 05:17:52 +0000 | 
| commit | 79efd8c79e723adb3392367ae62356c5c3a835d0 (patch) | |
| tree | 5232f8c3a61e63287008fafae32cf1cf568fed9e /Projects/AVRISP | |
| parent | 8ea051de637f09f0fd2895f5a18ee9f337b9b1f1 (diff) | |
| download | lufa-79efd8c79e723adb3392367ae62356c5c3a835d0.tar.gz lufa-79efd8c79e723adb3392367ae62356c5c3a835d0.tar.bz2 lufa-79efd8c79e723adb3392367ae62356c5c3a835d0.zip  | |
Fix a bug in the Still Image Host Class driver where the returned block status code was being truncated.
Add programming support to the AVRISP project's PDI programming mode; paged memory writes are not currently functional.
Diffstat (limited to 'Projects/AVRISP')
| -rw-r--r-- | Projects/AVRISP/Lib/NVMTarget.c | 122 | ||||
| -rw-r--r-- | Projects/AVRISP/Lib/NVMTarget.h | 6 | ||||
| -rw-r--r-- | Projects/AVRISP/Lib/PDIProtocol.c | 32 | ||||
| -rw-r--r-- | Projects/AVRISP/Lib/PDIProtocol.h | 3 | 
4 files changed, 133 insertions, 30 deletions
diff --git a/Projects/AVRISP/Lib/NVMTarget.c b/Projects/AVRISP/Lib/NVMTarget.c index d84ae6b85..b6922d5e5 100644 --- a/Projects/AVRISP/Lib/NVMTarget.c +++ b/Projects/AVRISP/Lib/NVMTarget.c @@ -161,41 +161,35 @@ bool NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t Re  	NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
  	PDITarget_SendByte(NVM_CMD_READNVM);
 -	/* Send the address of the first location to read from - this also primes the internal address
 -	 * counters so that we can use the REPEAT command later to save on overhead for multiple bytes */
 -	PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
 +	/* 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);
  	NVMTarget_SendAddress(ReadAddress);
 -	*ReadBuffer = PDITarget_ReceiveByte();
 -	/* Check to see if we are reading more than a single byte */
 -	if (ReadSize > 1)
 -	{
 -		/* Send the REPEAT command with the specified number of bytes remaining to read */
 -		PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_2BYTES);
 -		PDITarget_SendByte(ReadSize &  0xFF);
 -		PDITarget_SendByte(ReadSize >> 8);
 +	/* Send the REPEAT command with the specified number of bytes to read */
 +	PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_2BYTES);
 +	PDITarget_SendByte(ReadSize &  0xFF);
 +	PDITarget_SendByte(ReadSize >> 8);
 -		/* Send a LD command with indirect access and postincrement to read out the remaining 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();
 -	}
 +	/* 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 page
 - *  \param[in]  WriteAddress      Start address to write to within the target's address space
 - *  \param[in]  WriteBuffer       Buffer to source data from
 - *  \param[in]  WriteSize         Number of bytes to write
 + *  \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
 + *  \param[in]  WriteSize     Number of bytes to write
   *
   *  \return Boolean true if the command sequence complete sucessfully
   */
  bool NVMTarget_WriteByteMemory(uint8_t WriteCommand, uint32_t WriteAddress, uint8_t* WriteBuffer, uint16_t WriteSize)
  {
 -	for (uint8_t i = 0; i < WriteSize; i++)
 +	for (uint16_t i = 0; i < WriteSize; i++)
  	{
  		/* Wait until the NVM controller is no longer busy */
  		if (!(NVMTarget_WaitWhileNVMControllerBusy()))
 @@ -215,6 +209,92 @@ bool NVMTarget_WriteByteMemory(uint8_t WriteCommand, uint32_t WriteAddress, uint  	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 sucessfully
 + */
 +bool NVMTarget_WritePageMemory(uint8_t WriteBuffCommand, uint8_t EraseBuffCommand, uint8_t WritePageCommand,
 +                               uint8_t PageMode, uint32_t WriteAddress, uint8_t* WriteBuffer, uint16_t WriteSize)
 +{
 +	if (PageMode & XPRG_PAGEMODE_ERASE)
 +	{
 +		/* Wait until the NVM controller is no longer busy */
 +		if (!(NVMTarget_WaitWhileNVMControllerBusy()))
 +		  return false;
 +
 +		/* Send the memory buffer erase command to the target */
 +		PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
 +		NVMTarget_SendNVMRegAddress(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));
 +		NVMTarget_SendNVMRegAddress(NVM_REG_CTRLA);
 +		PDITarget_SendByte(1 << 0);
 +	}
 +
 +	if (WriteSize)
 +	{
 +		/* Wait until the NVM controller is no longer busy */
 +		if (!(NVMTarget_WaitWhileNVMControllerBusy()))
 +		  return false;
 +
 +		/* Send the memory buffer write command to the target */
 +		PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
 +		NVMTarget_SendNVMRegAddress(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);
 +		NVMTarget_SendAddress(WriteAddress);
 +
 +		/* Send the REPEAT command with the specified number of bytes to write */
 +		PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_2BYTES);
 +		PDITarget_SendByte(WriteSize &  0xFF);
 +		PDITarget_SendByte(WriteSize >> 8);
 +			
 +		/* Send a ST command with indirect access and postincrement to write the bytes */
 +		PDITarget_SendByte(PDI_CMD_ST | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
 +		for (uint16_t i = 0; i < WriteSize; i++)
 +		  PDITarget_SendByte(*(WriteBuffer++));
 +
 +		// TEMP
 +		PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
 +		NVMTarget_SendNVMRegAddress(NVM_REG_STATUS);
 +		GPIOR0 = PDITarget_ReceiveByte();
 +		if (!(GPIOR0 & (1 << 0)))
 +		  JTAG_DEBUG_POINT();
 +		// END TEMP
 +	}
 +	
 +	if (PageMode & XPRG_PAGEMODE_WRITE)
 +	{
 +		/* Wait until the NVM controller is no longer busy */
 +		if (!(NVMTarget_WaitWhileNVMControllerBusy()))
 +		  return false;
 +
 +		/* Send the memory write command to the target */
 +		PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
 +		NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
 +		PDITarget_SendByte(WritePageCommand);
 +		
 +		/* Send the address of the first page location to write the memory page */
 +		PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
 +		NVMTarget_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
 diff --git a/Projects/AVRISP/Lib/NVMTarget.h b/Projects/AVRISP/Lib/NVMTarget.h index dea9ff3de..3608fcb35 100644 --- a/Projects/AVRISP/Lib/NVMTarget.h +++ b/Projects/AVRISP/Lib/NVMTarget.h @@ -74,8 +74,8 @@  		#define NVM_CMD_NOOP                   0x00
  		#define NVM_CMD_CHIPERASE              0x40
  		#define NVM_CMD_READNVM                0x43
 -		#define NVM_CMD_LOADFLASHBUFF          0x23
 -		#define NVM_CMD_ERASEFLASHBUFF         0x26
 +		#define NVM_CMD_LOADFLASHPAGEBUFF      0x23
 +		#define NVM_CMD_ERASEFLASHPAGEBUFF     0x26
  		#define NVM_CMD_ERASEFLASHPAGE         0x2B
  		#define NVM_CMD_FLASHPAGEWRITE         0x2E
  		#define NVM_CMD_ERASEWRITEFLASH        0x2F
 @@ -113,6 +113,8 @@  		bool NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize);
  		bool NVMTarget_WriteByteMemory(uint8_t WriteCommand, uint32_t WriteAddress, uint8_t* WriteBuffer,
  		                               uint16_t WriteSize);
 +		bool NVMTarget_WritePageMemory(uint8_t WriteBuffCommand, uint8_t EraseBuffCommand, uint8_t WritePageCommand,
 +		                               uint8_t PageMode, uint32_t WriteAddress, uint8_t* WriteBuffer, uint16_t WriteSize);
  		bool NVMTarget_EraseMemory(uint8_t EraseCommand, uint32_t Address);
  #endif
 diff --git a/Projects/AVRISP/Lib/PDIProtocol.c b/Projects/AVRISP/Lib/PDIProtocol.c index 36aa3b4c5..aa03fc494 100644 --- a/Projects/AVRISP/Lib/PDIProtocol.c +++ b/Projects/AVRISP/Lib/PDIProtocol.c @@ -201,7 +201,7 @@ static void PDIProtocol_WriteMemory(void)  		uint8_t  PageMode;
  		uint32_t Address;
  		uint16_t Length;
 -		uint8_t  ProgData[512];
 +		uint8_t  ProgData[256];
  	} WriteMemory_XPROG_Params;
  	Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params, (sizeof(WriteMemory_XPROG_Params) -
 @@ -215,24 +215,37 @@ static void PDIProtocol_WriteMemory(void)  	uint8_t WriteCommand     = NVM_CMD_NOOP;
 -	uint8_t WritePageCommand = NVM_CMD_NOOP;
 +	uint8_t WriteBuffCommand = NVM_CMD_NOOP;
 +	uint8_t EraseBuffCommand = NVM_CMD_NOOP;
  	bool    PagedMemory      = false;
  	if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_APPL)
  	{
 -		PagedMemory = true;
 +		WriteCommand     = NVM_CMD_ERASEWRITEFLASH;
 +		WriteBuffCommand = NVM_CMD_LOADFLASHPAGEBUFF;
 +		EraseBuffCommand = NVM_CMD_ERASEFLASHPAGEBUFF;
 +		PagedMemory      = true;
  	}
  	else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_BOOT)
  	{
 -		PagedMemory = true;
 +		WriteCommand     = NVM_CMD_ERASEWRITEFLASH;
 +		WriteBuffCommand = NVM_CMD_LOADFLASHPAGEBUFF;
 +		EraseBuffCommand = NVM_CMD_ERASEFLASHPAGEBUFF;
 +		PagedMemory      = true;
  	}
  	else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_EEPROM)
  	{
 -		PagedMemory = true;
 +		WriteCommand     = NVM_CMD_ERASEWRITEEEPROMPAGE;
 +		WriteBuffCommand = NVM_CMD_LOADEEPROMPAGEBUFF;
 +		EraseBuffCommand = NVM_CMD_ERASEEEPROMPAGEBUFF;
 +		PagedMemory      = true;
  	}
  	else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_USERSIG)
  	{
 -		PagedMemory = true;
 +		WriteCommand     = NVM_CMD_WRITEUSERSIG;
 +		WriteBuffCommand = NVM_CMD_LOADFLASHPAGEBUFF;
 +		EraseBuffCommand = NVM_CMD_ERASEFLASHPAGEBUFF;
 +		PagedMemory      = true;
  	}
  	else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_FUSE)
  	{
 @@ -245,7 +258,12 @@ static void PDIProtocol_WriteMemory(void)  	if (PagedMemory)
  	{
 -
 +		if (!(NVMTarget_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand, 
 +		                                WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address,
 +		                                WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length)))
 +		{
 +			ReturnStatus = XPRG_ERR_TIMEOUT;
 +		}
  	}
  	else
  	{
 diff --git a/Projects/AVRISP/Lib/PDIProtocol.h b/Projects/AVRISP/Lib/PDIProtocol.h index 490e14bf5..127f0866e 100644 --- a/Projects/AVRISP/Lib/PDIProtocol.h +++ b/Projects/AVRISP/Lib/PDIProtocol.h @@ -97,6 +97,9 @@  		#define XPRG_PROTOCOL_PDI                   0x00
  		#define XPRG_PROTOCOL_JTAG                  0x01
 +		
 +		#define XPRG_PAGEMODE_WRITE                 (1 << 0)
 +		#define XPRG_PAGEMODE_ERASE                 (1 << 1)
  	/* External Variables: */
  		extern uint32_t XPROG_Param_NVMBase;
  | 
