Example #1
0
/** 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 \c 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:
			do
			{
				ISPTarget_SendByte(ReadMemCommand);
				ISPTarget_SendByte(PollAddress >> 8);
				ISPTarget_SendByte(PollAddress & 0xFF);
			}
			while ((ISPTarget_TransferByte(0x00) == PollValue) && TimeoutTicksRemaining);

			if (!(TimeoutTicksRemaining))
			  ProgrammingStatus = STATUS_CMD_TOUT;

			break;
		case PROG_MODE_WORD_READYBUSY_MASK:
		case PROG_MODE_PAGED_READYBUSY_MASK:
			ProgrammingStatus = ISPTarget_WaitWhileTargetBusy();
			break;
	}

	/* Program complete - reset timeout */
	wdt_reset();

	return ProgrammingStatus;
}
/** 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), NULL);

	Endpoint_ClearOUT();
	Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);

	uint8_t ResponseStatus = STATUS_CMD_FAILED;

	CurrentAddress = 0;

	/* Perform execution delay, initialize SPI bus */
	ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS);
	ISPTarget_EnableTargetISP();

	ISPTarget_ChangeTargetResetLine(true);
	ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS);

	/* 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-- && TimeoutTicksRemaining)
	{
		uint8_t ResponseBytes[4];

		for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
		{
			ISPProtocol_DelayMS(Enter_ISP_Params.ByteDelay);
			ResponseBytes[RByte] = ISPTarget_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;
			break;
		}
		else
		{
			ISPTarget_ChangeTargetResetLine(false);
			ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS);
			ISPTarget_ChangeTargetResetLine(true);
			ISPProtocol_DelayMS(Enter_ISP_Params.PinStabDelayMS);
		}
	}

	Endpoint_Write_8(CMD_ENTER_PROGMODE_ISP);
	Endpoint_Write_8(ResponseStatus);
	Endpoint_ClearIN();
}
Example #3
0
/** 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), NO_STREAM_CALLBACK);

	Endpoint_ClearOUT();
	Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM);
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);

	uint8_t ResponseStatus = STATUS_CMD_FAILED;
	
	CurrentAddress = 0;
	
	/* Set up the synchronous USART to generate the .5MHz recovery clock on XCK pin */
	UBRR1  = (F_CPU / 500000UL);
	UCSR1B = (1 << TXEN1);
	UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);
	DDRD  |= (1 << 5);

	/* Perform execution delay, initialize SPI bus */
	ISPProtocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS); 
	ISPTarget_Init();

	/* 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) && TimeoutTicksRemaining)
	{
		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] = ISPTarget_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();
}