PYNQ UART controller (ii) the use of polling and interrupt library functions in two ways

The basic flow

1UART initialization

By XUartPs_LookupConfig function, find UART base address ------------>

By XUartPs_CfgInitialize function, initialize UART configuration ------------>

Here Insert Picture Description

2. Mode Configuration

void XUartPs_SetOperMode(XUartPs *InstancePtr, u8 OperationMode)

Spontaneous self-closing with a local loopback
Here Insert Picture Description
Here Insert Picture Description

3. Format reload configuration

Use XUartPs_SetDataFormat function sets the UART data format, including baud rate, data bits, stop bits, and parity. Calling this function should be to ensure that there is no UART transmit and receive data.
cfg in default "8 bit data, 1 stop bit, no parity",
may be used alone XUartPs_SetBaudRate function to set the baud rate.

s32 XUartPs_SetBaudRate(XUartPs *InstancePtr, u32 BaudRate)

XUartPs_SetDataFormat

s32 XUartPs_SetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr)
typedef struct {
		u32 BaudRate;	/**< In bps, ie 1200 */
		u32 DataBits;	/**< Number of data bits */
		u32 Parity;		/**< Parity */
		u8 StopBits;	/**< Number of stop bits */
} XUartPsFormat;
 

4. Data transmission

u32 XUartPs_Send(XUartPs *InstancePtr, u8 *BufferPtr, u32 NumBytes)

The second argument is a pointer pointing to the data buffer to be transmitted; third parameter is the number of bytes sent; return value identifies the number of bytes actually transmitted.

5. Data received

u32 XUartPs_Recv(XUartPs *InstancePtr, u8 *BufferPtr, u32 NumBytes)

The second parameter pointer to the received data to be stored in the buffer; NumBytes third byte count "to" received; return the number of bytes actually received.

The third entry is the use and the return value, to achieve a function of receiving a certain number of data,

Polling Mode 2

initialization

void Uart_init()
{
	XUartPs_Config *Config;
	Config = XUartPs_LookupConfig(UART_DEVICE_ID);
	XUartPs_CfgInitialize(&Uart_PS, Config, Config->BaseAddress);
	}

LOCAL_LOOP send and receive

int Uart_send_receive_LOCAL(XUartPs* Uart_Ps, u8 *SendBuffer, u8 *RecvBuffer, int length)
{
	//自收自发
	XUartPs_SetOperMode(Uart_Ps,XUARTPS_OPER_MODE_LOCAL_LOOP);
	u16 SentCount=0;
	u16 RecvCount=0;
	SentCount=XUartPs_Send(Uart_Ps,SendBuffer,length);
	if (SentCount != length)
		return XST_FAILURE;
	//发送等待
	while(XUartPs_IsSending(Uart_Ps));
	//接收
	while(RecvCount < length) {
		RecvCount += XUartPs_Recv(Uart_Ps, &RecvBuffer[RecvCount],
				(length - RecvCount));
	}
	XUartPs_SetOperMode(Uart_Ps,XUARTPS_OPER_MODE_NORMAL);

	for (u16 Index = 0; Index < length; Index++) {
		if (SendBuffer[Index] != RecvBuffer[Index]) {
			xil_printf("UART Polled Mode failed!\r\n");
			return XST_FAILURE;
		}
	}
	xil_printf("UART Polled Mode succeeded!\r\n");

	return XST_SUCCESS;
}

main.c

#include "sleep.h"

#include "xparameters.h"
#include "xuartps.h"
#include "xil_printf.h"

 
#define UART_DEVICE_ID              XPAR_XUARTPS_0_DEVICE_ID
#define TEST_BUFFER_SIZE 32
XUartPs Uart_PS;		/* Instance of the UART Device */

/*
 * The following buffers are used in this example to send and receive data
 * with the UART.
 */
static u8 SendBuffer[TEST_BUFFER_SIZE];	/* Buffer for Transmitting Data */
static u8 RecvBuffer[TEST_BUFFER_SIZE];	/* Buffer for Receiving Data */



int main(void)
{


	Uart_init();


	while(1)
	{
		sleep(3);
		for (u16 Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
			SendBuffer[Index] = '0' + Index;
			RecvBuffer[Index] = 0;
		}
		Uart_send_receive_LOCAL(&Uart_PS,SendBuffer,RecvBuffer,TEST_BUFFER_SIZE);
	}
	return XST_SUCCESS;
}

Here Insert Picture Description

Normal to send and receive

int Uart_send_receive_Normal(XUartPs* Uart_Ps,  u8 *RecvBuffer, int length)
{
	//正常模式
	XUartPs_SetOperMode(Uart_Ps,XUARTPS_OPER_MODE_NORMAL);
	u16 RecvCount=0;
	u16 SentCount=0;
	//发送等待
	while(XUartPs_IsSending(Uart_Ps));
	//接收
	while(RecvCount < length) {
		RecvCount += XUartPs_Recv(Uart_Ps, &RecvBuffer[RecvCount],
				(length - RecvCount));
	}
	SentCount = XUartPs_Send(Uart_Ps, RecvBuffer, length);
	if (SentCount != length) {
		xil_printf("UART Polled Mode failed!\r\n");
		return XST_FAILURE;
	}
	xil_printf("UART Polled Mode succeeded!\r\n");
	return XST_SUCCESS;
}

main.c

int main(void)
{
	Uart_init();

	while(1)
	{
		sleep(0.1);

		Uart_send_receive_Normal(&Uart_PS,RecvBuffer,TEST_BUFFER_SIZE);
	}
	return XST_SUCCESS;
}

buffer length 10

Only after we send enough data 10, pending the UART will end.

If the data we send a one-time more than 10, the excess data will remain in RxFIFO until the next poll was only read.

Here Insert Picture Description

This article describes the UART polling mode. Unless it is particularly simple application, generally do not use the polling mode. If you want to use the polling mode, the program must have a good architecture or implementation mechanism, to avoid the program indefinitely tie.

3 interrupt mode

uart0 59 #
uart0 82 #

By Xil_ExceptionInit function, to avoid compatibility problems with the previous version have ------------>

By XScuGic_LookupConfig function, find common interrupt controller base address ------------>

By XScuGic_CfgInitialize function initializes the general interrupt controller ------------>

By Xil_ExceptionRegisterHandler function, enable exception interrupt handler ------------>

By XScuGic_Connect function, binding UART interrupt handler ------------>

By XScuGic_Enable function, in general interrupt controller enabled in UART interrupt ------------>

By XUartPs_SetInterruptMask function, set the UART interrupt trigger ------------>

By Xil_ExceptionEnableMask function, enabling the interrupt.

1. Trigger

Use trigger XUartPs_SetInterruptMask function sets the serial port interrupt. The second parameter is set RxFIFO trigger an interrupt.
Here Insert Picture Description

XUartPs_SetInterruptMask(Uart_Ps, XUARTPS_IXR_RXOVR);

Here Insert Picture Description

2.RxFIFO trigger level setting

Use XUartPs_SetFifoThreshold function to set the trigger level of the UART initialization in RxFIFO. RxFIFO number of bytes exceeds this value, a reception data interruption is generated. When not set to default 8. The
void XUartPs_SetFifoThreshold (XUartPs * InstancePtr, U8 TriggerLevel)

Second parameter value should be 1 to 64, because the maximum RxFIFO only store 64 bytes.

3. The interrupt handler

include define

#include "xparameters.h"
#include "xplatform_info.h"
#include "xuartps.h"
#include "xil_exception.h"
#include "xil_printf.h"
#include "xscugic.h"
#include "sleep.h"
#define UART_DEVICE_ID		XPAR_XUARTPS_0_DEVICE_ID
#define INTC_DEVICE_ID		XPAR_SCUGIC_SINGLE_DEVICE_ID
#define UART_INT_IRQ_ID		XPAR_XUARTPS_1_INTR

#define TEST_BUFFER_SIZE	16
XUartPs Uart_PS	;		/* Instance of the UART Device */
XScuGic InterruptController;	/* Instance of the Interrupt Controller */

static u8 RecvBuffer[TEST_BUFFER_SIZE];	/* Buffer for Receiving Data */

volatile int TotalReceivedCount;
volatile int TotalSentCount;

u8 *RecvBufferPtr;

uart init

void Uart_init()
{
	XUartPs_Config *Config;
	Config = XUartPs_LookupConfig(UART_DEVICE_ID);
	XUartPs_CfgInitialize(&Uart_PS, Config, Config->BaseAddress);
	}

interrupt init connect and enable

void inter_init_connect()
{
	XScuGic_Config *IntcConfig; /* Config for interrupt controller */

	/* Initialize the interrupt controller driver */
	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);

	XScuGic_CfgInitialize(&InterruptController, IntcConfig,
						IntcConfig->CpuBaseAddress);
	XScuGic_Disable(&InterruptController,59);
	XScuGic_SetPriorityTriggerType(&InterruptController,59,16,1);//
	//connect and enable
	XScuGic_Connect(&InterruptController, 59U,
				  (Xil_ExceptionHandler) Handler,
				  &Uart_PS);
	XScuGic_Enable(&InterruptController, 59U);
	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
				(Xil_ExceptionHandler) XScuGic_InterruptHandler,
				(void *)&InterruptController);
	Xil_ExceptionEnable();

}

uart handler

void Handler(void *CallBackRef)
{
	u32 ReceivedCount = 0 ;
	u32 IsrStatus;
	XUartPs *UartInstancePtr = (XUartPs *) CallBackRef ;
	IsrStatus = XUartPs_ReadReg(UartInstancePtr->Config.BaseAddress,
				   XUARTPS_IMR_OFFSET);

	IsrStatus &= XUartPs_ReadReg(UartInstancePtr->Config.BaseAddress,
				   XUARTPS_ISR_OFFSET);//中断类型
	if (IsrStatus & (u32)XUARTPS_IXR_RXOVR)   /* 检查RxFIFO是否触发 */
	{
		ReceivedCount = XUartPs_Recv(UartInstancePtr, RecvBuffer, (TEST_BUFFER_SIZE-TotalReceivedCount)) ;
		TotalReceivedCount += ReceivedCount ;

		RecvBufferPtr += ReceivedCount ;
		/* 清除中断标志 */
		XUartPs_WriteReg(UartInstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET, XUARTPS_IXR_RXOVR) ;
	}
	xil_printf("UART inter\r\n");
	if (TotalReceivedCount >= TEST_BUFFER_SIZE) {

			xil_printf("%s", RecvBuffer);
		xil_printf("\r\nI have received %d bytes.\r\n", TotalReceivedCount);
		RecvBufferPtr = RecvBuffer;
		TotalReceivedCount = 0;
	}
}

main

int main(void)
{
	u32 IntrMask;
	Uart_init();
	XUartPs_SetOperMode(&Uart_PS, XUARTPS_OPER_MODE_NORMAL);

	inter_init_connect();

	XUartPs_SetHandler(&Uart_PS, (XUartPs_Handler)Handler, &Uart_PS);
	IntrMask =XUARTPS_IXR_RXOVR;
	XUartPs_SetFifoThreshold(&Uart_PS,8);  //设置RxFIFO的中断触发等级
	XUartPs_SetInterruptMask(&Uart_PS, IntrMask);
	XScuGic_Enable(&InterruptController, 59);
	while(1)
	{
		sleep(1);
		xil_printf("UART 1s in main\r\n");
	}
	return 0;
}

Here Insert Picture Description

Published 452 original articles · won praise 271 · views 730 000 +

Guess you like

Origin blog.csdn.net/qq_35608277/article/details/105266327