예제 #1
0
//////////////////////////// PrintData ////////////////////////////////
int PrintData( ){
	u32 data;
	int dram_addr;

	//Read all data from DRAM
//	int dram_base = 0xa000000;
//	int dram_cieling = 0xa00ffff; //read out data from all integration channels

	// Read only Adj Average data from DRAM
	int dram_base = 0xa000000;
	int dram_cieling = 0xA004000; //read out just adjacent average (0xA004000 - 0xa000000 = 16384)

	Xil_DCacheInvalidateRange(0x00000000, 65536);

	for (dram_addr = dram_base; dram_addr <= dram_cieling; dram_addr+=4){
		if (!sw) { sw = XGpioPs_ReadPin(&Gpio, SW_BREAK_GPIO); } //read pin
		data = Xil_In32(dram_addr);
		xil_printf("%d\r\n",data);
		XUartPs_Recv(&Uart_PS, &RecvBuffer, 32);
		if ( RecvBuffer[0] == 'q' ) { sw = 1;  }
		if(sw) { return sw; }
	}

	return sw;
}
예제 #2
0
//function to receive from UART port
void uart_receive(float* in,int RecvCount){
	u8 buff[RecvCount];
	int counter = 0;
	while(counter < RecvCount){
		while (!XUartPs_IsReceiveData(Config->BaseAddress));
			;//waiting for input
		XUartPs_Recv(&uart,&buff[counter],1);
		counter++;
	}
	in =(float*) buff;
}
예제 #3
0
//////////////////////////// ReadCommandPoll////////////////////////////////
// Function used to clear the read buffer
// Read In new command, expecting a <return>
// Returns buffer size read
int ReadCommandPoll() {
	u32 rbuff = 0;			// read buffer size returned
	int i = 0; 				// index
	XUartPs_SetOptions(&Uart_PS,XUARTPS_OPTION_RESET_RX);	// Clear UART Read Buffer
	for (i=0; i<32; i++ ) { RecvBuffer[i] = '_'; }			// Clear RecvBuffer Variable
	while (!(RecvBuffer[rbuff-1] == '\n' || RecvBuffer[rbuff-1] == '\r' || RecvBuffer[rbuff-1] == 'd')) {
		rbuff += XUartPs_Recv(&Uart_PS, &RecvBuffer[rbuff],(32 - rbuff));
		sleep(0.1);			// Built in Latency ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 0.1 s
	}
	return rbuff;

}
예제 #4
0
파일: helloworld.c 프로젝트: jharrod/uart
/**
*
* This function is the handler which performs processing to handle data events
* from the device.  It is called from an interrupt context. so the amount of
* processing should be minimal.
*
* This handler provides an example of how to handle data for the device and
* is application specific.
*
* @param	CallBackRef contains a callback reference from the driver,
*		in this case it is the instance pointer for the XUartPs driver.
* @param	Event contains the specific kind of event that has occurred.
* @param	EventData contains the number of bytes sent or received for sent
*		and receive events.
*
* @return	None.
*
* @note		None.
*
***************************************************************************/
void Handler(void *CallBackRef, u32 Event, unsigned int EventData)
{
	/* All of the data has been sent */
	if (Event == XUARTPS_EVENT_SENT_DATA) {
		TotalSentCount = EventData;
	}

	/* All of the data has been received */
	if (Event == XUARTPS_EVENT_RECV_DATA) {
		TotalReceivedCount = EventData;
		if (EventData > 0){
			XUartPs_Recv(&uart, ch, TEST_BUFFER_SIZE);
			//ch[0] = (char) XUartPs_RecvByte(XPAR_PS7_UART_1_BASEADDR); //doesn't work
			send = 1;
		}
	}

	/*
	 * Data was received, but not the expected number of bytes, a
	 * timeout just indicates the data stopped for 8 character times
	 */
	if (Event == XUARTPS_EVENT_RECV_TOUT) {
		TotalReceivedCount = EventData;
	}

	/*
	 * Data was received with an error, keep the data but determine
	 * what kind of errors occurred
	 */
	if (Event == XUARTPS_EVENT_RECV_ERROR) {
		TotalReceivedCount = EventData;
		TotalErrorCount++;
	}

	/*
	 * Data was received with an parity or frame or break error, keep the data
	 * but determine what kind of errors occurred. Specific to Zynq Ultrascale+
	 * MP.
	 */
	if (Event == XUARTPS_EVENT_PARE_FRAME_BRKE) {
		TotalReceivedCount = EventData;
		TotalErrorCount++;
	}

	/*
	 * Data was received with an overrun error, keep the data but determine
	 * what kind of errors occurred. Specific to Zynq Ultrascale+ MP.
	 */
	if (Event == XUARTPS_EVENT_RECV_ORERR) {
		TotalReceivedCount = EventData;
		TotalErrorCount++;
	}
}
예제 #5
0
//////////////////////////// DAQ ////////////////////////////////
int DAQ(){
	int buffsize; 	//BRAM buffer size
	int dram_addr;	// DRAM Address

	XUartPs_SetOptions(&Uart_PS,XUARTPS_OPTION_RESET_RX);

	Xil_Out32 (XPAR_AXI_DMA_0_BASEADDR + 0x48, 0xa000000); 		// DMA Transfer Step 1
	Xil_Out32 (XPAR_AXI_DMA_0_BASEADDR + 0x58 , 65536);			// DMA Transfer Step 2
	sleep(1);						// Built in Latency ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 s
	ClearBuffers();												// Clear Buffers.
	// Capture garbage in DRAM
	for (dram_addr = 0xa000000; dram_addr <= 0xA004000; dram_addr+=4){Xil_In32(dram_addr);}

	while(1){
		buffsize = Xil_In32 (XPAR_AXI_GPIO_11_BASEADDR);
		if (!sw) { sw = XGpioPs_ReadPin(&Gpio, SW_BREAK_GPIO); } //read pin
		XUartPs_Recv(&Uart_PS, &RecvBuffer, 32);
		if ( RecvBuffer[0] == 'q' ) { sw = 1; }
		if(sw) { return sw;	}

		if(buffsize >= 4095){
			//Xil_Out32 (XPAR_AXI_GPIO_18_BASEADDR, 0); // Disable Capture Module in FPGA
			Xil_Out32 (XPAR_AXI_GPIO_15_BASEADDR, 1);
			//sleep(10);  // Built in Latency ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 10 s
			Xil_Out32 (XPAR_AXI_DMA_0_BASEADDR + 0x48, 0xa000000);
			Xil_Out32 (XPAR_AXI_DMA_0_BASEADDR + 0x58 , 65536);
			sleep(1); 			// Built in Latency ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 s
			Xil_Out32 (XPAR_AXI_GPIO_15_BASEADDR, 0);
			//Xil_Out32(XPAR_AXI_GPIO_18_BASEADDR, 1);
			ClearBuffers();
			PrintData();
		}
	}

	return sw;
}
/**
*
* This function does a minimal test on the UartPS device and driver as a
* design example. The purpose of this function is to illustrate
* how to use the XUartPs driver.
*
* This function sends data and expects to receive the same data through the
* device using the local loopback mode.
*
* This function uses interrupt mode of the device.
*
* @param	IntcInstPtr is a pointer to the instance of the Scu Gic driver.
* @param	UartInstPtr is a pointer to the instance of the UART driver
*		which is going to be connected to the interrupt controller.
* @param	DeviceId is the device Id of the UART device and is typically
*		XPAR_<UARTPS_instance>_DEVICE_ID value from xparameters.h.
* @param	UartIntrId is the interrupt Id and is typically
*		XPAR_<UARTPS_instance>_INTR value from xparameters.h.
*
* @return	XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note
*
* This function contains an infinite loop such that if interrupts are not
* working it may never return.
*
**************************************************************************/
int UartPsIntrExample(XScuGic *IntcInstPtr, XUartPs *UartInstPtr,
                      u16 DeviceId, u16 UartIntrId)
{
    int Status;
    XUartPs_Config *Config;
    int Index;
    u32 IntrMask;
    int BadByteCount = 0;

    /*
     * Initialize the UART driver so that it's ready to use
     * Look up the configuration in the config table, then initialize it.
     */
    Config = XUartPs_LookupConfig(DeviceId);
    if (NULL == Config) {
        return XST_FAILURE;
    }

    Status = XUartPs_CfgInitialize(UartInstPtr, Config, Config->BaseAddress);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    /*
     * Check hardware build
     */
    Status = XUartPs_SelfTest(UartInstPtr);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    /*
     * Connect the UART to the interrupt subsystem such that interrupts
     * can occur. This function is application specific.
     */
    Status = SetupInterruptSystem(IntcInstPtr, UartInstPtr, UartIntrId);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    /*
     * Setup the handlers for the UART that will be called from the
     * interrupt context when data has been sent and received, specify
     * a pointer to the UART driver instance as the callback reference
     * so the handlers are able to access the instance data
     */
    XUartPs_SetHandler(UartInstPtr, (XUartPs_Handler)Handler, UartInstPtr);

    /*
     * Enable the interrupt of the UART so interrupts will occur, setup
     * a local loopback so data that is sent will be received.
     */
    IntrMask =
        XUARTPS_IXR_TOUT | XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING |
        XUARTPS_IXR_OVER | XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXFULL |
        XUARTPS_IXR_RXOVR;
    XUartPs_SetInterruptMask(UartInstPtr, IntrMask);

    XUartPs_SetOperMode(UartInstPtr, XUARTPS_OPER_MODE_LOCAL_LOOP);

    /*
     * Set the receiver timeout. If it is not set, and the last few bytes
     * of data do not trigger the over-water or full interrupt, the bytes
     * will not be received. By default it is disabled.
     *
     * The setting of 8 will timeout after 8 x 4 = 32 character times.
     * Increase the time out value if baud rate is high, decrease it if
     * baud rate is low.
     */
    XUartPs_SetRecvTimeout(UartInstPtr, 8);


    /*
     * Initialize the send buffer bytes with a pattern and the
     * the receive buffer bytes to zero to allow the receive data to be
     * verified
     */
    for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {

        SendBuffer[Index] = (Index % 26) + 'A';

        RecvBuffer[Index] = 0;
    }

    /*
     * Start receiving data before sending it since there is a loopback,
     * ignoring the number of bytes received as the return value since we
     * know it will be zero
     */
    XUartPs_Recv(UartInstPtr, RecvBuffer, TEST_BUFFER_SIZE);

    /*
     * Send the buffer using the UART and ignore the number of bytes sent
     * as the return value since we are using it in interrupt mode.
     */
    XUartPs_Send(UartInstPtr, SendBuffer, TEST_BUFFER_SIZE);

    /*
     * Wait for the entire buffer to be received, letting the interrupt
     * processing work in the background, this function may get locked
     * up in this loop if the interrupts are not working correctly.
     */
    while (1) {
        if ((TotalSentCount == TEST_BUFFER_SIZE) &&
                (TotalReceivedCount == TEST_BUFFER_SIZE)) {
            break;
        }
    }

    /*
     * Verify the entire receive buffer was successfully received
     */
    for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
        if (RecvBuffer[Index] != SendBuffer[Index]) {
            BadByteCount++;
        }
    }



    /*
     * Set the UART in Normal Mode
     */
    XUartPs_SetOperMode(UartInstPtr, XUARTPS_OPER_MODE_NORMAL);


    /*
     * If any bytes were not correct, return an error
     */
    if (BadByteCount != 0) {
        return XST_FAILURE;
    }

    return XST_SUCCESS;
}
예제 #7
0
void Handler(void *CallBackRef, u32 Event, unsigned int EventData)
{
	/*
	 * All of the data has been sent
	 */
	if (Event == XUARTPS_EVENT_SENT_DATA);

	/*
	 * All of the data has been received
	 */
	if (Event == XUARTPS_EVENT_RECV_DATA) {
		XUartPs_Recv(&Uart_Ps, uartBuffer, UART_BUFFER_SIZE);
		//XUartPs_Send(&Uart_Ps, RecvBuffer, TEST_BUFFER_SIZE);
		if(uartBuffer[2] == 0x41){//Up Arrow: 1B 5B 41
			if(contrast != 8)
				contrast++;
		}
		if(uartBuffer[2] == 0x42){//Down Arrow: 1B 5B 42
			if(contrast != 0)
				contrast--;
		}
		if(uartBuffer[2] == 0x43){//Right Arrow: 1B 5B 43
			roadPosition++;
		}
		if(uartBuffer[2] == 0x44){//Left Arrow: 1B 5B 44
			roadPosition--;
		}
		setContrast();


	}

	/*
	 * Data was received, but not the expected number of bytes, a
	 * timeout just indicates the data stopped for 8 character times
	 */
	if (Event == XUARTPS_EVENT_RECV_TOUT){
		XUartPs_Recv(&Uart_Ps, uartBuffer, UART_BUFFER_SIZE);
		//Letter characters received are ascii
		//w and s used to increase and shrink the size of the road
		XUartPs_Send(&Uart_Ps, uartBuffer, 1);
		switch(uartBuffer[0]){
		case 0x77://w: 0x77
			roadSizeRight++;
			break;
		case 0x73://s: 0x73
			roadSizeRight--;
			break;
		case 0x71://q: 0x71
			roadSizeLeft++;
			break;
		case 0x61://a: 0x61
			roadSizeLeft--;
			break;
		case 0x63://c: 0x63
			calibrate = !calibrate;
			break;
		case 0x74://t: 0x74
			if( blanking_position < 15)
				blanking_position++;
			setThreshold();
			break;
		case 0x67://g: 0x67
			if(blanking_position > 0)
				blanking_position--;
			setThreshold();
			break;
		case 0x31://1: 0x31
			cross_row = 0;
			break;
		case 0x32://2: 0x32
			start_blink = 1;
			break;
		case 0x33://3: 0x33
			schl_xing_row = 0;
			break;
		case 0x72://r: 0x72
			start_recording = 1;
			break;
		case 0x70://p 0x70
			playback_idx = 0;
			break;
		case 0x65://e 0x65
			if(frameRateSelect < 3)
				frameRateSelect++;
			framerate = FRAME_RATE_VALS[frameRateSelect];
			printf("Framerate: %f", framerate);
			break;
		case 0x64://d
			if(frameRateSelect > 0)
				frameRateSelect--;
			framerate = FRAME_RATE_VALS[frameRateSelect];
			printf("Framerate: %f", framerate);
			break;
		case 0x79://y
			road_vert_pos--;
			break;
		case 0x68://h
			road_vert_pos++;
			break;
		}
	}


	/*
	 * Data was received with an error, keep the data but determine
	 * what kind of errors occurred
	 */
	if (Event == XUARTPS_EVENT_RECV_ERROR);
}
예제 #8
0
/**
*
* This function does a minimal test on the XUartPs device in polled mode.
*
* This function sends data and expects to receive the data thru the UART
* using the local loopback mode.
*
*
* @param	DeviceId is the unique device id from hardware build.
*
* @return	XST_SUCCESS if successful, XST_FAILURE if unsuccessful
*
* @note
* This function polls the UART, it may hang if the hardware is not
* working correctly.
*
****************************************************************************/
int UartPsPolledExample(u16 DeviceId)
{
	int Status;
	XUartPs_Config *Config;
	unsigned int SentCount;
	unsigned int ReceivedCount;
	u16 Index;
	u32 LoopCount = 0;

	/*
	 * Initialize the UART driver so that it's ready to use.
	 * Look up the configuration in the config table, then initialize it.
	 */
	Config = XUartPs_LookupConfig(DeviceId);
	if (NULL == Config) {
		return XST_FAILURE;
	}

	Status = XUartPs_CfgInitialize(&Uart_PS, Config, Config->BaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Check hardware build.
	 */
	Status = XUartPs_SelfTest(&Uart_PS);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Use local loopback mode.
	 */
	XUartPs_SetOperMode(&Uart_PS, XUARTPS_OPER_MODE_LOCAL_LOOP);

	/*
	 * Initialize the send buffer bytes with a pattern and zero out
	 * the receive buffer.
	 */
	for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
		SendBuffer[Index] = '0' + Index;
		RecvBuffer[Index] = 0;
	}

	/*
	 * Block sending the buffer.
	 */
	SentCount = XUartPs_Send(&Uart_PS, SendBuffer, TEST_BUFFER_SIZE);
	if (SentCount != TEST_BUFFER_SIZE) {
		return XST_FAILURE;
	}

	/*
	 * Wait while the UART is sending the data so that we are guaranteed
	 * to get the data the 1st time we call receive, otherwise this function
	 * may enter receive before the data has arrived
	 */
	while (XUartPs_IsSending(&Uart_PS)) {
		LoopCount++;
	}

	/*
	 * Block receiving the buffer.
	 */
	ReceivedCount = 0;
	while (ReceivedCount < TEST_BUFFER_SIZE) {
		ReceivedCount +=
			XUartPs_Recv(&Uart_PS, &RecvBuffer[ReceivedCount],
				      (TEST_BUFFER_SIZE - ReceivedCount));
	}

	/*
	 * Check the receive buffer against the send buffer and verify the
	 * data was correctly received
	 */
	for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
		if (SendBuffer[Index] != RecvBuffer[Index]) {
			return XST_FAILURE;
		}
	}

	/*
	 * Restore to normal mode.
	 */
	XUartPs_SetOperMode(&Uart_PS, XUARTPS_OPER_MODE_NORMAL);

	return XST_SUCCESS;
}
예제 #9
0
int main()
{
	int sentCount;
	int aliveLed = 0;
	int numBytes;
	int currentGain;
	unsigned char id, prevId;
	int sw, i1;
    int success;
    int pa, prevPa;
	static int testBlinkCount;
	int txCount = 0, txTryCount = 0, txSuccess;
	unsigned char numUartRead, curValue;
	unsigned char rxBuf[256], txBuf[256];

    init_platform();

    if(SetupPeripherals() != XST_SUCCESS)
    	return -1;

	if ( Chilipepper_Initialize() != 0 )
		return -1;

	// by default we are in receive
	Chilipepper_SetPA( 1 );
	Chilipepper_SetTxRxSw( 1 ); // 0- transmit, 1-receive

	// enable the Chilipepper LED to indicate we are operational
	Chilipepper_SetLed( 1 );


	xil_printf("\r\n\r\nWelcome to Toyon's Chilipepper QPSK demo. This demo was written in MATLAB using Mathworks HDL Coder.\r\n\r\n");
	//Chilipepper_SetRxGain( 20 );
	prevPa = 0;
	prevId = 0;
	//Chilipepper_Reset();
    while (1)
    {
		currentGain = Chilipepper_ControlAgc();
    	WriteLedGain( currentGain );
    	pa = XGpio_DiscreteRead(&gpio_sw_tx_pa, 1);
    	if (pa != prevPa)
    		Chilipepper_SetTxGain( pa );
    	prevPa = pa;
        sw = XGpio_DiscreteRead(&gpio_sw_test, 1);
    	switch (sw)
    	{
    	case 0: // normal operation
    		// during normal operation adjust the AGC

        	// main priority is to parse OTA packets
    		numBytes = Chilipepper_ReadPacket( rxBuf, &id );

    		if (numBytes > 0)
    			XGpio_DiscreteWrite(&gpio_blinky, 1, 1);

    		// if ID is zero then this is an ACK - should never see this here
    		// if ID is not zero we need to send a packet back with the payload being the ID

    		// Here we've received the same packet as last time. This means the sender must not
    		// have gotten the ACK we sent. So, let's just send the ACK again, but don't write to UART.
    		if (id != 0 && numBytes > 0 && id == prevId)
			{
				// received the same packet again so transmitter must not have gotten ACK
				Chilipepper_WriteAckPacket( txBuf, id );
    			XGpio_DiscreteWrite(&gpio_blinky, 1, 0);
			}
    		// This is a normal receive situation. We get a packet, write it to UART, and send ACK
    		else if ( id != 0 && numBytes > 0)
    		{
                // first thing we need to do if ID is not zero is send back ACK with payload
                // being id
                Chilipepper_WriteAckPacket( txBuf, id );

    			sentCount = 0;
    			while (sentCount < numBytes)
    			{
    				curValue = rxBuf[sentCount+4];
    				sentCount += XUartPs_Send(&uartPs, &curValue, 1);
    			}

    			prevId = id;
    			XGpio_DiscreteWrite(&gpio_blinky, 1, 0);
    		}

			// now that we've gotten the radio stuff out of the way, let's parse things coming over the UART
    		do
    		{
    			numUartRead = XUartPs_Recv(&uartPs, &txBuf[txCount+4], 1);
				if (numUartRead == 1)
					txCount++;
    		} while(numUartRead == 1);

			// only attempt to send something if we have something to send
			if (txCount > 0)
			{
    			XGpio_DiscreteWrite(&gpio_blinky, 1, 1);
				if (txCount >= 10 || txTryCount > 100000)
				{
					txSuccess = Chilipepper_WritePacketWithAck( txBuf, txCount, rxBuf );
					if (txSuccess == 1)
					{
		    			XGpio_DiscreteWrite(&gpio_blinky, 1, 0);
					}
	    			txCount = 0;
	    			txTryCount = 0;
				}
			}
			txTryCount++;
	    	// flip the LED1 so the user knows the processor is alive
			testBlinkCount += 1;
	    	if (testBlinkCount > 100000)
	    	{
	    		if (aliveLed == 0)
	    			aliveLed = 1;
	    		else
	    			aliveLed = 0;
	    		testBlinkCount = 1;
	    		XGpio_DiscreteWrite(&gpio_blinky, 2, aliveLed);
	    	}
    		break;
    	case 1: // continuously send out packets
    		// do it once and then stall for a bit
    		for (i1=0; i1<5000; i1++)
    		{
    			if (i1 == 0)
    			{
    				XGpio_DiscreteWrite(&gpio_blinky, 1, 1);
    				Chilipepper_WriteTestPacket( 1 );
    				XGpio_DiscreteWrite(&gpio_blinky, 1, 0);
    			}
    		}
        	// flip the LED1 so the user knows the processor is alive
    		testBlinkCount += 1;
        	if (testBlinkCount > 2000)
        	{
        		if (aliveLed == 0)
        			aliveLed = 1;
        		else
        			aliveLed = 0;
        		testBlinkCount = 1;
        		XGpio_DiscreteWrite(&gpio_blinky, 2, aliveLed);
        	}
    		break;
    	case 2: // initiate packet transmission with a button press
        	// flip the LED1 so the user knows the processor is alive
    		testBlinkCount += 1;
        	if (testBlinkCount > 200000)
        	{
        		if (aliveLed == 0)
        			aliveLed = 1;
        		else
        			aliveLed = 0;
        		testBlinkCount = 1;
        		XGpio_DiscreteWrite(&gpio_blinky, 2, aliveLed);
        	}

        	if (DebouncButton() == 0)
    			break;

			XGpio_DiscreteWrite(&gpio_blinky, 1, 1);
        	success = Chilipepper_WriteTestPacketWithAck( rxBuf );
        	if (success == 1)
				XGpio_DiscreteWrite(&gpio_blinky, 1, 0);
        	else
        	{
        		Chilipepper_Reset();
        	}
    		break;
    	default:
    		break;
    	}

    }
    cleanup_platform();

    return 0;
}
예제 #10
0
/**
*
* This function runs a self-test on the driver and hardware device. This self
* test performs a local loopback and verifies data can be sent and received.
*
* The time for this test is proportional to the baud rate that has been set
* prior to calling this function.
*
* The mode and control registers are restored before return.
*
* @param	InstancePtr is a pointer to the XUartPs instance
*
* @return
*		 - XST_SUCCESS if the test was successful
*		- XST_UART_TEST_FAIL if the test failed looping back the data
*
* @note
*
* This function can hang if the hardware is not functioning properly.
*
******************************************************************************/
s32 XUartPs_SelfTest(XUartPs *InstancePtr)
{
	s32 Status = XST_SUCCESS;
	u32 IntrRegister;
	u32 ModeRegister;
	u8 Index;
	u32 ReceiveDataResult;

	/*
	 * Assert validates the input arguments
	 */
	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	/*
	 * Disable all interrupts in the interrupt disable register
	 */
	IntrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
				   XUARTPS_IMR_OFFSET);
	XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET,
		XUARTPS_IXR_MASK);

	/*
	 * Setup for local loopback
	 */
	ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
				   XUARTPS_MR_OFFSET);
	XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET,
			   ((ModeRegister & (u32)(~XUARTPS_MR_CHMODE_MASK)) |
				(u32)XUARTPS_MR_CHMODE_L_LOOP));

	/*
	 * Send a number of bytes and receive them, one at a time.
	 */
	for (Index = 0U; Index < XUARTPS_TOTAL_BYTES; Index++) {
		/*
		 * Send out the byte and if it was not sent then the failure
		 * will be caught in the comparison at the end
		 */
		(void)XUartPs_Send(InstancePtr, &TestString[Index], 1U);

		/*
		 * Wait until the byte is received. This can hang if the HW
		 * is broken. Watch for the FIFO empty flag to be false.
		 */
		ReceiveDataResult = Xil_In32((InstancePtr->Config.BaseAddress) + XUARTPS_SR_OFFSET) &
				XUARTPS_SR_RXEMPTY;
		while (ReceiveDataResult == XUARTPS_SR_RXEMPTY ) {
			ReceiveDataResult = Xil_In32((InstancePtr->Config.BaseAddress) + XUARTPS_SR_OFFSET) &
					XUARTPS_SR_RXEMPTY;
		}

		/*
		 * Receive the byte
		 */
		(void)XUartPs_Recv(InstancePtr, &ReturnString[Index], 1U);
	}

	/*
	 * Compare the bytes received to the bytes sent to verify the exact data
	 * was received
	 */
	for (Index = 0U; Index < XUARTPS_TOTAL_BYTES; Index++) {
		if (TestString[Index] != ReturnString[Index]) {
			Status = XST_UART_TEST_FAIL;
		}
	}

	/*
	 * Restore the registers which were altered to put into polling and
	 * loopback modes so that this test is not destructive
	 */
	XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET,
			   IntrRegister);
	XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET,
			   ModeRegister);

	return Status;
}