Clean up and add more comments to the AVRISP-MKII project. Make sure the SPI_MULTI command handler supports multiple packet responses. Use slightly smaller/faster repeated indirect-load commands when retrieving the PDI target's memory CRCs.
This commit is contained in:
		
							parent
							
								
									b0ce1eab66
								
							
						
					
					
						commit
						f3d370a777
					
				
					 10 changed files with 87 additions and 47 deletions
				
			
		|  | @ -65,7 +65,9 @@ void ISPProtocol_EnterISPMode(void) | |||
| 
 | ||||
| 	ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS);  | ||||
| 	SPI_Init(ISPTarget_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING | SPI_SAMPLE_LEADING | SPI_MODE_MASTER); | ||||
| 		 | ||||
| 
 | ||||
| 	/* Continuously attempt to synchronize with the target until either the number of attempts specified
 | ||||
| 	 * by the host has exceeded, or the the device sends back the expected response values */ | ||||
| 	while (Enter_ISP_Params.SynchLoops-- && (ResponseStatus == STATUS_CMD_FAILED)) | ||||
| 	{ | ||||
| 		uint8_t ResponseBytes[4]; | ||||
|  | @ -110,6 +112,7 @@ void ISPProtocol_LeaveISPMode(void) | |||
| 	Endpoint_ClearOUT(); | ||||
| 	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); | ||||
| 
 | ||||
| 	/* Perform pre-exit delay, release the target /RESET, disable the SPI bus and perform the post-exit delay */ | ||||
| 	ISPProtocol_DelayMS(Leave_ISP_Params.PreDelayMS); | ||||
| 	ISPTarget_ChangeTargetResetLine(false); | ||||
| 	SPI_ShutDown(); | ||||
|  | @ -166,6 +169,9 @@ void ISPProtocol_ProgramMemory(uint8_t V2Command) | |||
| 	                                                                    Write_Memory_Params.PollValue2; | ||||
| 	uint8_t* NextWriteByte = Write_Memory_Params.ProgData; | ||||
| 
 | ||||
| 	/* Check to see if the host has issued a SET ADDRESS command and we haven't sent a
 | ||||
| 	 * LOAD EXTENDED ADDRESS command (if needed, used when operating beyond the 128KB | ||||
| 	 * FLASH barrier) */ | ||||
| 	if (MustSetAddress) | ||||
| 	{ | ||||
| 		if (CurrentAddress & (1UL << 31)) | ||||
|  | @ -174,6 +180,7 @@ void ISPProtocol_ProgramMemory(uint8_t V2Command) | |||
| 		MustSetAddress = false; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Check the programming mode desired by the host, either Paged or Word memory writes */ | ||||
| 	if (Write_Memory_Params.ProgrammingMode & PROG_MODE_PAGED_WRITES_MASK) | ||||
| 	{ | ||||
| 		uint16_t StartAddress = (CurrentAddress & 0xFFFF); | ||||
|  | @ -184,16 +191,16 @@ void ISPProtocol_ProgramMemory(uint8_t V2Command) | |||
| 			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); | ||||
| 			 | ||||
| 			/* AVR FLASH addressing requires us to modify the write command based on if we are writing a high
 | ||||
| 			 * or low byte at the current word address */ | ||||
| 			Write_Memory_Params.ProgrammingCommands[0] ^= READ_WRITE_HIGH_BYTE_MASK; | ||||
| 
 | ||||
| 			/* Check to see the write completion method, to see if we have a valid polling address */ | ||||
| 			if (!(PollAddress) && (ByteToWrite != PollValue)) | ||||
| 			{ | ||||
| 				if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP)) | ||||
|  | @ -289,6 +296,9 @@ void ISPProtocol_ReadMemory(uint8_t V2Command) | |||
| 	Endpoint_Write_Byte(V2Command); | ||||
| 	Endpoint_Write_Byte(STATUS_CMD_OK); | ||||
| 	 | ||||
| 	/* Check to see if the host has issued a SET ADDRESS command and we haven't sent a
 | ||||
| 	 * LOAD EXTENDED ADDRESS command (if needed, used when operating beyond the 128KB | ||||
| 	 * FLASH barrier) */ | ||||
| 	if (MustSetAddress) | ||||
| 	{ | ||||
| 		if (CurrentAddress & (1UL << 31)) | ||||
|  | @ -297,28 +307,30 @@ void ISPProtocol_ReadMemory(uint8_t V2Command) | |||
| 		MustSetAddress = false; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Read each byte from the device and write them to the packet for the host */ | ||||
| 	for (uint16_t CurrentByte = 0; CurrentByte < Read_Memory_Params.BytesToRead; CurrentByte++) | ||||
| 	{ | ||||
| 		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; | ||||
| 
 | ||||
| 		/* Read the next byte from the desired memory space in the device */ | ||||
| 		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 */ | ||||
| 		/* Check if the endpoint bank is currently full, if so send the packet */ | ||||
| 		if (!(Endpoint_IsReadWriteAllowed())) | ||||
| 		{ | ||||
| 			Endpoint_ClearIN(); | ||||
| 			Endpoint_WaitUntilReady(); | ||||
| 		} | ||||
| 		 | ||||
| 		if ((IsOddByte && (V2Command == CMD_READ_FLASH_ISP)) || (V2Command == CMD_READ_EEPROM_ISP)) | ||||
| 		/* AVR FLASH addressing requires us to modify the read command based on if we are reading a high
 | ||||
| 		 * or low byte at the current word address */ | ||||
| 		if (V2Command == CMD_READ_FLASH_ISP) | ||||
| 		  Read_Memory_Params.ReadMemoryCommand ^= READ_WRITE_HIGH_BYTE_MASK; | ||||
| 
 | ||||
| 		/* Only increment the current address if we have read both bytes in the current word when in FLASH
 | ||||
| 		 * read mode, or for each byte when in EEPROM read mode */		  | ||||
| 		if (((CurrentByte & 0x01) && (V2Command == CMD_READ_FLASH_ISP)) || (V2Command == CMD_READ_EEPROM_ISP)) | ||||
| 		  CurrentAddress++; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -353,9 +365,11 @@ void ISPProtocol_ChipErase(void) | |||
| 	 | ||||
| 	uint8_t ResponseStatus = STATUS_CMD_OK; | ||||
| 	 | ||||
| 	/* Send the chip erase commands as given by the host to the device */ | ||||
| 	for (uint8_t SByte = 0; SByte < sizeof(Erase_Chip_Params.EraseCommandBytes); SByte++) | ||||
| 	  SPI_SendByte(Erase_Chip_Params.EraseCommandBytes[SByte]); | ||||
| 
 | ||||
| 	/* Use appropriate command completion check as given by the host (delay or busy polling) */ | ||||
| 	if (!(Erase_Chip_Params.PollMethod)) | ||||
| 	  ISPProtocol_DelayMS(Erase_Chip_Params.EraseDelayMS); | ||||
| 	else | ||||
|  | @ -385,7 +399,8 @@ void ISPProtocol_ReadFuseLockSigOSCCAL(uint8_t V2Command) | |||
| 	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); | ||||
| 
 | ||||
| 	uint8_t ResponseBytes[4]; | ||||
| 		 | ||||
| 
 | ||||
| 	/* Send the Fuse or Lock byte read commands as given by the host to the device, store response */ | ||||
| 	for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++) | ||||
| 	  ResponseBytes[RByte] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]); | ||||
| 		 | ||||
|  | @ -413,6 +428,7 @@ void ISPProtocol_WriteFuseLock(uint8_t V2Command) | |||
| 	Endpoint_ClearOUT(); | ||||
| 	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); | ||||
| 
 | ||||
| 	/* Send the Fuse or Lock byte program commands as given by the host to the device */ | ||||
| 	for (uint8_t SByte = 0; SByte < sizeof(Write_FuseLockSig_Params.WriteCommandBytes); SByte++) | ||||
| 	  SPI_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]); | ||||
| 		 | ||||
|  | @ -463,12 +479,29 @@ void ISPProtocol_SPIMulti(void) | |||
| 		  Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params.TxData[CurrTxPos++])); | ||||
| 		else | ||||
| 		  Endpoint_Write_Byte(SPI_ReceiveByte()); | ||||
| 		   | ||||
| 		/* Check to see if we have filled the endpoint bank and need to send the packet */ | ||||
| 		if (!(Endpoint_IsReadWriteAllowed())) | ||||
| 		{ | ||||
| 			Endpoint_ClearIN(); | ||||
| 			Endpoint_WaitUntilReady(); | ||||
| 		} | ||||
| 		 | ||||
| 		CurrRxPos++; | ||||
| 	}	 | ||||
| 	 | ||||
| 	Endpoint_Write_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();	 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -58,6 +58,7 @@ void V2Protocol_ProcessCommand(void) | |||
| { | ||||
| 	uint8_t V2Command = Endpoint_Read_Byte(); | ||||
| 	 | ||||
| 	/* Set total command processing timeout value, enable timeout management interrupt */ | ||||
| 	TimeoutMSRemaining = COMMAND_TIMEOUT_MS; | ||||
| 	TIMSK0 |= (1 << OCIE0A); | ||||
| 
 | ||||
|  | @ -121,6 +122,7 @@ void V2Protocol_ProcessCommand(void) | |||
| 			break; | ||||
| 	} | ||||
| 		 | ||||
| 	/* Disable timeout management interrupt once processing has completed */ | ||||
| 	TIMSK0 &= ~(1 << OCIE0A); | ||||
| 
 | ||||
| 	Endpoint_WaitUntilReady(); | ||||
|  | @ -162,8 +164,8 @@ static void V2Protocol_SignOn(void) | |||
| 	Endpoint_ClearIN(); | ||||
| } | ||||
| 
 | ||||
| /** Handler for the CMD_RESET_PROTECTION command, currently implemented as a dummy ACK function
 | ||||
|  *  as no ISP short-circuit protection is currently implemented. | ||||
| /** Handler for the CMD_RESET_PROTECTION command, implemented as a dummy ACK function as
 | ||||
|  *  no target short-circuit protection is currently implemented. | ||||
|  */ | ||||
| static void V2Protocol_ResetProtection(void) | ||||
| { | ||||
|  |  | |||
|  | @ -170,7 +170,7 @@ static ParameterItem_t* V2Params_GetParamFromTable(const uint8_t ParamID) | |||
| 	ParameterItem_t* CurrTableItem = ParameterTable; | ||||
| 
 | ||||
| 	/* Find the parameter in the parameter table if present */ | ||||
| 	for (uint8_t TableIndex = 0; TableIndex < (sizeof(ParameterTable) / sizeof(ParameterTable[0])); TableIndex++) | ||||
| 	for (uint8_t TableIndex = 0; TableIndex < TABLE_PARAM_COUNT; TableIndex++) | ||||
| 	{ | ||||
| 		if (ParamID == CurrTableItem->ParamID) | ||||
| 		  return CurrTableItem; | ||||
|  |  | |||
|  | @ -52,10 +52,13 @@ | |||
| 
 | ||||
| 	/* Macros: */ | ||||
| 		/** Parameter privilege mask to allow the host PC to read the parameter's value */ | ||||
| 		#define PARAM_PRIV_READ   (1 << 0) | ||||
| 		#define PARAM_PRIV_READ     (1 << 0) | ||||
| 
 | ||||
| 		/** Parameter privilege mask to allow the host PC to change the parameter's value */ | ||||
| 		#define PARAM_PRIV_WRITE  (1 << 1) | ||||
| 		#define PARAM_PRIV_WRITE    (1 << 1) | ||||
| 		 | ||||
| 		/** Total number of parameters in the parameter table */ | ||||
| 		#define TABLE_PARAM_COUNT   (sizeof(ParameterTable) / sizeof(ParameterTable[0])) | ||||
| 
 | ||||
| 	/* Type Defines: */ | ||||
| 		/** Type define for a parameter table entry indicating a PC readable or writable device parameter. */ | ||||
|  |  | |||
|  | @ -136,24 +136,18 @@ bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest) | |||
| 	if (!(XMEGANVM_WaitWhileNVMControllerBusy())) | ||||
| 	  return false; | ||||
| 	 | ||||
| 	uint32_t MemoryCRC = 0; | ||||
| 	 | ||||
| 	/* Read the first generated CRC byte value */ | ||||
| 	XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2)); | ||||
| 	/* Load the PDI pointer register with the DAT0 register start address */ | ||||
| 	XPROGTarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES); | ||||
| 	XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT0); | ||||
| 	MemoryCRC  = XPROGTarget_ReceiveByte(); | ||||
| 
 | ||||
| 	/* Read the second generated CRC byte value */ | ||||
| 	XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2)); | ||||
| 	XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT1); | ||||
| 	MemoryCRC |= ((uint16_t)XPROGTarget_ReceiveByte() << 8); | ||||
| 
 | ||||
| 	/* Read the third generated CRC byte value */ | ||||
| 	XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2)); | ||||
| 	XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT2); | ||||
| 	MemoryCRC |= ((uint32_t)XPROGTarget_ReceiveByte() << 16); | ||||
| 	/* Send the REPEAT command to grab the CRC bytes */ | ||||
| 	XPROGTarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE); | ||||
| 	XPROGTarget_SendByte(XMEGA_CRC_LENGTH - 1); | ||||
| 	 | ||||
| 	*CRCDest = MemoryCRC; | ||||
| 	/* Read in the CRC bytes from the target */ | ||||
| 	XPROGTarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE); | ||||
| 	for (uint8_t i = 0; i < XMEGA_CRC_LENGTH; i++) | ||||
| 	  ((uint8_t*)CRCDest)[i] = XPROGTarget_ReceiveByte(); | ||||
| 	 | ||||
| 	return true; | ||||
| } | ||||
|  |  | |||
|  | @ -56,6 +56,8 @@ | |||
| 		#endif | ||||
| 
 | ||||
| 	/* Defines: */ | ||||
| 		#define XMEGA_CRC_LENGTH                     3 | ||||
| 	 | ||||
| 		#define XMEGA_NVM_REG_ADDR0                  0x00 | ||||
| 		#define XMEGA_NVM_REG_ADDR1                  0x01 | ||||
| 		#define XMEGA_NVM_REG_ADDR2                  0x02 | ||||
|  |  | |||
|  | @ -38,7 +38,7 @@ | |||
| 
 | ||||
| #if defined(ENABLE_XPROG_PROTOCOL) || defined(__DOXYGEN__) | ||||
| /** Base absolute address for the target's NVM controller for PDI programming */ | ||||
| uint32_t XPROG_Param_NVMBase    = 0x010001C0; | ||||
| uint32_t XPROG_Param_NVMBase = 0x010001C0; | ||||
| 
 | ||||
| /** Size in bytes of the target's EEPROM page */ | ||||
| uint16_t XPROG_Param_EEPageSize; | ||||
|  | @ -455,10 +455,10 @@ static void XPROGProtocol_SetParam(void) | |||
| 		case XPRG_PARAM_EEPPAGESIZE: | ||||
| 			XPROG_Param_EEPageSize = Endpoint_Read_Word_BE(); | ||||
| 			break; | ||||
| 		case XPRG_PARAM_NVMCMD: | ||||
| 		case XPRG_PARAM_NVMCMD_REG: | ||||
| 			XPROG_Param_NVMCMDRegAddr = Endpoint_Read_Byte(); | ||||
| 			break; | ||||
| 		case XPRG_PARAM_NVMCSR: | ||||
| 		case XPRG_PARAM_NVMCSR_REG: | ||||
| 			XPROG_Param_NVMCSRRegAddr = Endpoint_Read_Byte(); | ||||
| 			break; | ||||
| 		default: | ||||
|  |  | |||
|  | @ -98,12 +98,12 @@ | |||
| 
 | ||||
| 		#define XPRG_PARAM_NVMBASE                  0x01 | ||||
| 		#define XPRG_PARAM_EEPPAGESIZE              0x02 | ||||
| 		#define XPRG_PARAM_NVMCMD                   0x03 | ||||
| 		#define XPRG_PARAM_NVMCSR                   0x04 | ||||
| 		#define XPRG_PARAM_NVMCMD_REG               0x03 /* Undocumented, Reverse-engineered */ | ||||
| 		#define XPRG_PARAM_NVMCSR_REG               0x04 /* Undocumented, Reverse-engineered */ | ||||
| 		 | ||||
| 		#define XPRG_PROTOCOL_PDI                   0x00 | ||||
| 		#define XPRG_PROTOCOL_JTAG                  0x01 | ||||
| 		#define XPRG_PROTOCOL_TPI                   0x02 | ||||
| 		#define XPRG_PROTOCOL_TPI                   0x02 /* Undocumented, Reverse-engineered */ | ||||
| 		 | ||||
| 		#define XPRG_PAGEMODE_WRITE                 (1 << 1) | ||||
| 		#define XPRG_PAGEMODE_ERASE                 (1 << 0) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dean Camera
						Dean Camera