From 8a55d80e7e1214b8625b413fa0123a8b6ce9c825 Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Mon, 14 Dec 2009 04:39:16 +0000
Subject: [PATCH] Fix NVM commands so that memory reads and CRC generations now
 work correctly using unoptimized PDI commands.

---
 Projects/AVRISP/Lib/NVMTarget.c   | 49 +++++++++++++++----
 Projects/AVRISP/Lib/NVMTarget.h   | 79 +++++++++++++++++++++----------
 Projects/AVRISP/Lib/PDIProtocol.c | 24 +++++-----
 3 files changed, 108 insertions(+), 44 deletions(-)

diff --git a/Projects/AVRISP/Lib/NVMTarget.c b/Projects/AVRISP/Lib/NVMTarget.c
index 104d0a8b0..fee432cfb 100644
--- a/Projects/AVRISP/Lib/NVMTarget.c
+++ b/Projects/AVRISP/Lib/NVMTarget.c
@@ -42,10 +42,18 @@ void NVMTarget_SendNVMRegAddress(uint8_t Register)
 {
 	uint32_t Address = XPROG_Param_NVMBase | Register;
 
-	PDITarget_SendByte(Address >> 24);
-	PDITarget_SendByte(Address >> 26);
-	PDITarget_SendByte(Address >> 8);
 	PDITarget_SendByte(Address &  0xFF);
+	PDITarget_SendByte(Address >> 8);
+	PDITarget_SendByte(Address >> 16);
+	PDITarget_SendByte(Address >> 24);
+}
+
+void NVMTarget_SendAddress(uint32_t AbsoluteAddress)
+{
+	PDITarget_SendByte(AbsoluteAddress &  0xFF);
+	PDITarget_SendByte(AbsoluteAddress >> 8);
+	PDITarget_SendByte(AbsoluteAddress >> 16);
+	PDITarget_SendByte(AbsoluteAddress >> 24);
 }
 
 bool NVMTarget_WaitWhileNVMBusBusy(void)
@@ -68,7 +76,7 @@ void NVMTarget_WaitWhileNVMControllerBusy(void)
 	/* Poll the NVM STATUS register while the NVM controller is busy */
 	for (;;)
 	{
-		PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_1BYTE << 2));
+		PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
 		NVMTarget_SendNVMRegAddress(NVM_REG_STATUS);
 		
 		if (!(PDITarget_ReceiveByte() & (1 << 7)))
@@ -80,13 +88,15 @@ uint32_t NVMTarget_GetMemoryCRC(uint8_t MemoryCommand)
 {
 	uint32_t MemoryCRC;
 
+	NVMTarget_WaitWhileNVMControllerBusy();
+
 	/* Set the NVM command to the correct CRC read command */
-	PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_1BYTE << 2));
+	PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
 	NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
 	PDITarget_SendByte(MemoryCommand);
 
 	/* Set CMDEX bit in NVM CTRLA register to start the CRC generation */
-	PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_1BYTE << 2));
+	PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
 	NVMTarget_SendNVMRegAddress(NVM_REG_CTRLA);
 	PDITarget_SendByte(1 << 0);
 
@@ -94,14 +104,37 @@ uint32_t NVMTarget_GetMemoryCRC(uint8_t MemoryCommand)
 	NVMTarget_WaitWhileNVMBusBusy();
 	NVMTarget_WaitWhileNVMControllerBusy();
 	
-	/* Read the three byte generated CRC value */
-	PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_3BYTES << 2));
+	/* Read the three bytes generated CRC value */
+	PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
 	NVMTarget_SendNVMRegAddress(NVM_REG_DAT0);
 	MemoryCRC  = PDITarget_ReceiveByte();
+
+	PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
+	NVMTarget_SendNVMRegAddress(NVM_REG_DAT1);
 	MemoryCRC |= ((uint16_t)PDITarget_ReceiveByte() << 8);
+
+	PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
+	NVMTarget_SendNVMRegAddress(NVM_REG_DAT2);
 	MemoryCRC |= ((uint32_t)PDITarget_ReceiveByte() << 16);
 	
 	return MemoryCRC;
 }
 
+void NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize)
+{
+	NVMTarget_WaitWhileNVMControllerBusy();
+
+	PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
+	NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
+	PDITarget_SendByte(NVM_CMD_READNVM);
+
+	/* TODO: Optimize via REPEAT and buffer orientated commands */
+	for (uint16_t i = 0; i < ReadSize; i++)
+	{
+		PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
+		NVMTarget_SendAddress(ReadAddress++);
+		*(ReadBuffer++) = PDITarget_ReceiveByte();
+	}
+}
+
 #endif
diff --git a/Projects/AVRISP/Lib/NVMTarget.h b/Projects/AVRISP/Lib/NVMTarget.h
index 5afb4c013..0f2dad504 100644
--- a/Projects/AVRISP/Lib/NVMTarget.h
+++ b/Projects/AVRISP/Lib/NVMTarget.h
@@ -56,35 +56,66 @@
 		#endif
 
 	/* Defines: */
-		#define FLASH_BASE           0x00800000
-		#define EPPROM_BASE          0x008C0000
-		#define FUSE_BASE            0x008F0020
-		#define DATAMEM_BASE         0x01000000
-		#define PROD_SIGNATURE_BASE  0x008E0200
-		#define USER_SIGNATURE_BASE  0x008E0400
+		#define FLASH_BASE                     0x00800000
+		#define EPPROM_BASE                    0x008C0000
+		#define FUSE_BASE                      0x008F0020
+		#define DATAMEM_BASE                   0x01000000
+		#define PROD_SIGNATURE_BASE            0x008E0200
+		#define USER_SIGNATURE_BASE            0x008E0400
 		
-		#define NVM_REG_ADDR0        0x00
-		#define NVM_REG_ADDR1        0x01
-		#define NVM_REG_ADDR2        0x02
-		#define NVM_REG_DAT0         0x04
-		#define NVM_REG_DAT1         0x05
-		#define NVM_REG_DAT2         0x06
-		#define NVM_REG_CMD          0x0A
-		#define NVM_REG_CTRLA        0x0B
-		#define NVM_REG_CTRLB        0x0C
-		#define NVM_REG_INTCTRL      0x0D
-		#define NVM_REG_STATUS       0x0F
-		#define NVM_REG_LOCKBITS     0x10
+		#define NVM_REG_ADDR0                  0x00
+		#define NVM_REG_ADDR1                  0x01
+		#define NVM_REG_ADDR2                  0x02
+		#define NVM_REG_DAT0                   0x04
+		#define NVM_REG_DAT1                   0x05
+		#define NVM_REG_DAT2                   0x06
+		#define NVM_REG_CMD                    0x0A
+		#define NVM_REG_CTRLA                  0x0B
+		#define NVM_REG_CTRLB                  0x0C
+		#define NVM_REG_INTCTRL                0x0D
+		#define NVM_REG_STATUS                 0x0F
+		#define NVM_REG_LOCKBITS               0x10
 		
-		#define NVM_CMD_APPCRC       0x38
-		#define NVM_CMD_BOOTCRC      0x39
-		#define NVM_CMD_FLASHCRC     0x78
-		#define NVM_CMD_READUSERSIG  0x03
-				
+		#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_ERASEFLASHPAGE         0x2B
+		#define NVM_CMD_FLASHPAGEWRITE         0x2E
+		#define NVM_CMD_ERASEWRITEFLASH        0x2F
+		#define NVM_CMD_FLASHCRC               0x78
+		#define NVM_CMD_ERASEAPPSEC            0x20
+		#define NVM_CMD_ERASEAPPSECPAGE        0x22
+		#define NVM_CMD_WRITEAPPSECPAGE        0x24
+		#define NVM_CMD_ERASEWRITEAPPSECPAGE   0x25
+		#define NVM_CMD_APPCRC                 0x38
+		#define NVM_CMD_ERASEBOOTSEC           0x68
+		#define NVM_CMD_ERASEBOOTSECPAGE       0x2A
+		#define NVM_CMD_WRITEBOOTSECPAGE       0x2C
+		#define NVM_CMD_ERASEWRITEBOOTSECPAGE  0x2D
+		#define NVM_CMD_BOOTCRC                0x39
+		#define NVM_CMD_READUSERSIG            0x03
+		#define NVM_CMD_ERASEUSERSIG           0x18
+		#define NVM_CMD_WRITEUSERSIG           0x1A
+		#define NVM_CMD_READCALIBRATION        0x02
+		#define NVM_CMD_READFUSE               0x07
+		#define NVM_CMD_WRITEFUSE              0x4C
+		#define NVM_CMD_WRITELOCK              0x08
+		#define NVM_CMD_LOADEEPROMPAGEBUFF     0x33
+		#define NVM_CMD_ERASEEEPROMPAGEBUFF    0x36
+		#define NVM_CMD_ERASEEEPROM            0x30
+		#define NVM_CMD_ERASEEEPROMPAGE        0x32
+		#define NVM_CMD_WRITEEEPROMPAGE        0x34
+		#define NVM_CMD_ERASEWRITEEEPROMPAGE   0x35
+		#define NVM_CMD_READEEPROM             0x06
+
 	/* Function Prototypes: */
-		void NVMTarget_SendNVMRegAddress(uint8_t Register);
+		void     NVMTarget_SendNVMRegAddress(uint8_t Register);
+		void     NVMTarget_SendAddress(uint32_t AbsoluteAddress);
 		bool     NVMTarget_WaitWhileNVMBusBusy(void);
 		void     NVMTarget_WaitWhileNVMControllerBusy(void);
 		uint32_t NVMTarget_GetMemoryCRC(uint8_t MemoryCommand);
+		void     NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize);
 
 #endif
diff --git a/Projects/AVRISP/Lib/PDIProtocol.c b/Projects/AVRISP/Lib/PDIProtocol.c
index a7b11557c..e3255a0c6 100644
--- a/Projects/AVRISP/Lib/PDIProtocol.c
+++ b/Projects/AVRISP/Lib/PDIProtocol.c
@@ -216,20 +216,17 @@ static void PDIProtocol_ReadMemory(void)
 
 	Endpoint_ClearOUT();
 	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
-	
-	if (ReadMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_USERSIG)
-	{
-		PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_1BYTE << 2));
-		NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
-		PDITarget_SendByte(NVM_CMD_READUSERSIG);
 
-		// TODO
-	}
-	
+	uint8_t ReadBuffer[ReadMemory_XPROG_Params.Length];
+	NVMTarget_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length);
+
 	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();
 }
 
@@ -250,13 +247,16 @@ static void PDIProtocol_ReadCRC(void)
 	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
 	
 	uint32_t MemoryCRC;
+	uint8_t  CRCCommand;
 
 	if (ReadCRC_XPROG_Params.CRCType == XPRG_CRC_APP)
-	  MemoryCRC = NVMTarget_GetMemoryCRC(NVM_CMD_APPCRC);
+	  CRCCommand = NVM_CMD_APPCRC;
 	else if (ReadCRC_XPROG_Params.CRCType == XPRG_CRC_BOOT)
-	  MemoryCRC = NVMTarget_GetMemoryCRC(NVM_CMD_BOOTCRC);
+	  CRCCommand = NVM_CMD_BOOTCRC;
 	else
-	  MemoryCRC = NVMTarget_GetMemoryCRC(NVM_CMD_FLASHCRC);
+	  CRCCommand = NVM_CMD_FLASHCRC;
+	
+	MemoryCRC = NVMTarget_GetMemoryCRC(CRCCommand);
 	
 	Endpoint_Write_Byte(CMD_XPROG);
 	Endpoint_Write_Byte(XPRG_CMD_CRC);
-- 
GitLab