XILINX ZYNQ 7000 UART 笔记

记录一下学习串口的代码

首先看SDK生成的BSP代码包
bsp\ps7_cortexa9_0\libsrc
在这里插入图片描述
这里可以说是XILINX 的外设库函数
先来看串口UART的库函数uartps_v3_7\src
在这里插入图片描述

先看 xuartps_g.c
开头说明这个文件是由HS自动产生的I

* CAUTION: This file is automatically generated by HSI.
* Version: 2018.3
* DO NOT EDIT.

然后定义了UART 设备的基本参数

/*
* The configuration table for devices
*/

XUartPs_Config XUartPs_ConfigTable[XPAR_XUARTPS_NUM_INSTANCES] =
{
	{
		XPAR_PS7_UART_1_DEVICE_ID,
		XPAR_PS7_UART_1_BASEADDR,
		XPAR_PS7_UART_1_UART_CLK_FREQ_HZ,
		XPAR_PS7_UART_1_HAS_MODEM
	}
};

xuartps_hw.c 包含三个API,数据的发送,接收和reset
在这里插入图片描述
xuartps_intr.c 关于中断的操作
在这里插入图片描述
xuartps_options.c 串口模块的设置
在这里插入图片描述

xuartps_selftest.c 串口模块的自测函数
xuartps_sinit.c 串口模块的初始化函数

参考SDK的串口中断代码。

串口模块的初始化,XILINX 官方代码的运作方式是
0.在ps7_init.c中对IO进行设定,指定什么IO口用于UART
1.每个外设都有一个device ID 用于区分多个外设
2.每个外设的基本信息放在Lookuptable中,由SDK在bsp阶段生成。
3.获取外设的基本信息通过查找LookupConfig进行,找到外设的基础地址和基础配置。
4.然后进行外设的定制化配置XUartPs_CfgInitialize
5.外设的设置通过BaseAddress索引到外设的寄存器基地址
6.UartInstPtr是一个软件结构体,用于管理串口外设,把外设对象化

	/*
	 * 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;
	}

在BSP生成阶段形成的外设Table

XUartPs_Config XUartPs_ConfigTable[XPAR_XUARTPS_NUM_INSTANCES] =
{
	{
		XPAR_PS7_UART_1_DEVICE_ID,
		XPAR_PS7_UART_1_BASEADDR,
		XPAR_PS7_UART_1_UART_CLK_FREQ_HZ,
		XPAR_PS7_UART_1_HAS_MODEM
	}
};

串口初始化的详细过程

s32 XUartPs_CfgInitialize(XUartPs *InstancePtr,
				   XUartPs_Config * Config, u32 EffectiveAddr)
{
	s32 Status;
	u32 ModeRegister;
	u32 BaudRate;

	/* Assert validates the input arguments */
	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(Config != NULL);

	/* Setup the driver instance using passed in parameters */
	InstancePtr->Config.BaseAddress = EffectiveAddr;
	InstancePtr->Config.InputClockHz = Config->InputClockHz;
	InstancePtr->Config.ModemPinsConnected = Config->ModemPinsConnected;

	/* Initialize other instance data to default values */
	InstancePtr->Handler = (XUartPs_Handler)XUartPs_StubHandler;

	InstancePtr->SendBuffer.NextBytePtr = NULL;
	InstancePtr->SendBuffer.RemainingBytes = 0U;
	InstancePtr->SendBuffer.RequestedBytes = 0U;

	InstancePtr->ReceiveBuffer.NextBytePtr = NULL;
	InstancePtr->ReceiveBuffer.RemainingBytes = 0U;
	InstancePtr->ReceiveBuffer.RequestedBytes = 0U;

	/* Initialize the platform data */
	InstancePtr->Platform = XGetPlatform_Info();

	InstancePtr->is_rxbs_error = 0U;

	/* Flag that the driver instance is ready to use */
	InstancePtr->IsReady = XIL_COMPONENT_IS_READY;

	/*
	 * Set the default baud rate here, can be changed prior to
	 * starting the device
	 */
	BaudRate = (u32)XUARTPS_DFT_BAUDRATE;
	Status = XUartPs_SetBaudRate(InstancePtr, BaudRate);
	if (Status != (s32)XST_SUCCESS) {
		InstancePtr->IsReady = 0U;
	} else {

		/*
		 * Set up the default data format: 8 bit data, 1 stop bit, no
		 * parity
		 */
		ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
					  XUARTPS_MR_OFFSET);

		/* Mask off what's already there */
		ModeRegister &= (~((u32)XUARTPS_MR_CHARLEN_MASK |
						 (u32)XUARTPS_MR_STOPMODE_MASK |
						 (u32)XUARTPS_MR_PARITY_MASK));

		/* Set the register value to the desired data format */
		ModeRegister |=	((u32)XUARTPS_MR_CHARLEN_8_BIT |
						 (u32)XUARTPS_MR_STOPMODE_1_BIT |
						 (u32)XUARTPS_MR_PARITY_NONE);

		/* Write the mode register out */
		XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET,
				   ModeRegister);

		/* Set the RX FIFO trigger at 8 data bytes. */
		XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
				   XUARTPS_RXWM_OFFSET, 0x08U);

		/* Set the RX timeout to 1, which will be 4 character time */
		XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
				   XUARTPS_RXTOUT_OFFSET, 0x01U);

		/* Disable all interrupts, polled mode is the default */
		XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET,
				   XUARTPS_IXR_MASK);

		Status = XST_SUCCESS;
	}
	return Status;
}

XILINX 对寄存器的管理并没有使用对象化的方法
下面两个函数是写寄存器的读写函数
使用基地址 + 偏移地址的方式

XUartPs_WriteReg
XUartPs_ReadReg

InstancePtr->Config.BaseAddress 为基地址
每个寄存器 有具体的偏移地址

#define XUARTPS_CR_OFFSET		0x0000U  /**< Control Register [8:0] */
#define XUARTPS_MR_OFFSET		0x0004U  /**< Mode Register [9:0] */
#define XUARTPS_IER_OFFSET		0x0008U  /**< Interrupt Enable [12:0] */
#define XUARTPS_IDR_OFFSET		0x000CU  /**< Interrupt Disable [12:0] */
#define XUARTPS_IMR_OFFSET		0x0010U  /**< Interrupt Mask [12:0] */
#define XUARTPS_ISR_OFFSET		0x0014U  /**< Interrupt Status [12:0]*/
#define XUARTPS_BAUDGEN_OFFSET	0x0018U  /**< Baud Rate Generator [15:0] */
#define XUARTPS_RXTOUT_OFFSET	0x001CU  /**< RX Timeout [7:0] */
#define XUARTPS_RXWM_OFFSET		0x0020U  /**< RX FIFO Trigger Level [5:0] */
#define XUARTPS_MODEMCR_OFFSET	0x0024U  /**< Modem Control [5:0] */
#define XUARTPS_MODEMSR_OFFSET	0x0028U  /**< Modem Status [8:0] */
#define XUARTPS_SR_OFFSET		0x002CU  /**< Channel Status [14:0] */
#define XUARTPS_FIFO_OFFSET		0x0030U  /**< FIFO [7:0] */
#define XUARTPS_BAUDDIV_OFFSET	0x0034U  /**< Baud Rate Divider [7:0] */
#define XUARTPS_FLOWDEL_OFFSET	0x0038U  /**< Flow Delay [5:0] */
#define XUARTPS_TXWM_OFFSET		0x0044U  /**< TX FIFO Trigger Level [5:0] */
#define XUARTPS_RXBS_OFFSET		0x0048U  /**< RX FIFO Byte Status [11:0] */

所有的寄存器操作通过专用的读写寄存器API完成。

完成串口外设的配置后,需要对串口的中断进行配置。
中断的管理主要通过SCU GIC进行。

XScuGic_Config *IntcConfig; /* Config for interrupt controller */

	/* Initialize the interrupt controller driver */
	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
	if (NULL == IntcConfig) {
		return XST_FAILURE;
	}

	Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
					IntcConfig->CpuBaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Connect the interrupt controller interrupt handler to the
	 * hardware interrupt handling logic in the processor.
	 */
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
				(Xil_ExceptionHandler) XScuGic_InterruptHandler,
				IntcInstancePtr);

GIC也是PS系统的外设。通过LookupConfig 去寻找其基础地址和基础配置。
其地址和基础配置都是BSP生成阶段自动生成。

接着对GIC进行详细的配置

XScuGic_Config XScuGic_ConfigTable[XPAR_XSCUGIC_NUM_INSTANCES] =
{
	{
		XPAR_PS7_SCUGIC_0_DEVICE_ID,
		XPAR_PS7_SCUGIC_0_BASEADDR,
		XPAR_PS7_SCUGIC_0_DIST_BASEADDR,
		{{0}}		/**< Initialize the HandlerTable to 0 */
	}
};
**s32  XScuGic_CfgInitialize(XScuGic *InstancePtr,
				XScuGic_Config *ConfigPtr,
				u32 EffectiveAddr)
{
	u32 Int_Id;
	u32 Cpu_Id = CpuId + (u32)1;
	(void) EffectiveAddr;

	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(ConfigPtr != NULL);
	/*
     * Detect Zynq-7000 base silicon configuration,Dual or Single CPU.
     * If it is single CPU cnfiguration then invoke assert for CPU ID=1
	 */
#ifdef ARMA9
	if (XPAR_CPU_ID == 0x01) {
		Xil_AssertNonvoid((Xil_In32(XPS_EFUSE_BASEADDR 
			+ EFUSE_STATUS_OFFSET) & EFUSE_STATUS_CPU_MASK) == 0);
	}
#endif

	if (InstancePtr->IsReady != XIL_COMPONENT_IS_READY) {

		InstancePtr->IsReady = 0U;
		InstancePtr->Config = ConfigPtr;


		for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS;
				Int_Id++) {
			/*
			* Initalize the handler to point to a stub to handle an
			* interrupt which has not been connected to a handler
			* Only initialize it if the handler is 0 which means it
			* was not initialized statically by the tools/user. Set
			* the callback reference to this instance so that
			* unhandled interrupts can be tracked.
			*/
			if ((InstancePtr->Config->HandlerTable[Int_Id].Handler
					== (Xil_InterruptHandler)NULL)) {
				InstancePtr->Config->HandlerTable[Int_Id].Handler 
						= (Xil_InterruptHandler)StubHandler;
			}
			InstancePtr->Config->HandlerTable[Int_Id].CallBackRef =
								InstancePtr;
		}
		XScuGic_Stop(InstancePtr);
		DistributorInit(InstancePtr, Cpu_Id);
		CPUInitialize(InstancePtr);

		InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
	}

	return XST_SUCCESS;
}

1.ZYNQ 系统最大的IRQ 数量是95个
2.如果中断服务函数没有被指定,那么默认指定一个标准的中断函数。用意是当发生中断的时候跳转到未被指定的函数中会出现错误和无法跟踪的情况。

for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS;
				Int_Id++) {
			/*
			* Initalize the handler to point to a stub to handle an
			* interrupt which has not been connected to a handler
			* Only initialize it if the handler is 0 which means it
			* was not initialized statically by the tools/user. Set
			* the callback reference to this instance so that
			* unhandled interrupts can be tracked.
			*/
			if ((InstancePtr->Config->HandlerTable[Int_Id].Handler
					== (Xil_InterruptHandler)NULL)) {
				InstancePtr->Config->HandlerTable[Int_Id].Handler 
						= (Xil_InterruptHandler)StubHandler;
			}
			InstancePtr->Config->HandlerTable[Int_Id].CallBackRef =
								InstancePtr;
		}

ARM 9 处理器的中断向量表前面几个

{Xil_ExceptionNullHandler, NULL},
	{Xil_UndefinedExceptionHandler, NULL},
	{Xil_ExceptionNullHandler, NULL},
	{Xil_PrefetchAbortHandler, NULL},
	{Xil_DataAbortHandler, NULL},
	{Xil_ExceptionNullHandler, NULL},
	{Xil_ExceptionNullHandler, NULL},

当发生中断后GIC把对应的中断发给CPU,CPU进入中断服务,首先是进行硬件中断这个不由软件控制。
也就是上表的跳转是硬件产生的。然后执行对应的中断函数

/*
	 * Connect the interrupt controller interrupt handler to the
	 * hardware interrupt handling logic in the processor.
	 */
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
				(Xil_ExceptionHandler) XScuGic_InterruptHandler,
				IntcInstancePtr);

然后在异常处理函数中去寻找是什么外设发生了中断,跳转到对应的函数进行处理

接下来需要把对应的中断服务函数进行注册,也就是把中断服务函数放到中断table 表中

	Status = XScuGic_Connect(IntcInstancePtr, UartIntrId,
				  (Xil_ExceptionHandler) XUartPs_InterruptHandler,
				  (void *) UartInstancePtr);

进入到中断服务函数里面后再去读寄存器判断具体的中断标志位,从而识别是什么地方发生了中断。

void XUartPs_InterruptHandler(XUartPs *InstancePtr)
{
	u32 IsrStatus;

	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	/*
	 * Read the interrupt ID register to determine which
	 * interrupt is active
	 */
	IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
				   XUARTPS_IMR_OFFSET);

	IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
				   XUARTPS_ISR_OFFSET);

	/* Dispatch an appropriate handler. */
	if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY |
			(u32)XUARTPS_IXR_RXFULL)) != (u32)0) {
		/* Received data interrupt */
		ReceiveDataHandler(InstancePtr);
	}

	if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL))
									 != (u32)0) {
		/* Transmit data interrupt */
		SendDataHandler(InstancePtr, IsrStatus);
	}

	/* XUARTPS_IXR_RBRK is applicable only for Zynq Ultrascale+ MP */
	if ((IsrStatus & ((u32)XUARTPS_IXR_OVER | (u32)XUARTPS_IXR_FRAMING |
			(u32)XUARTPS_IXR_PARITY | (u32)XUARTPS_IXR_RBRK)) != (u32)0) {
		/* Received Error Status interrupt */
		ReceiveErrorHandler(InstancePtr, IsrStatus);
	}

	if((IsrStatus & ((u32)XUARTPS_IXR_TOUT)) != (u32)0) {
		/* Received Timeout interrupt */
		ReceiveTimeoutHandler(InstancePtr);
	}

	if((IsrStatus & ((u32)XUARTPS_IXR_DMS)) != (u32)0) {
		/* Modem status interrupt */
		ModemHandler(InstancePtr);
	}

	/* Clear the interrupt status. */
	XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET,
		IsrStatus);


最后UART 代码

#include <xuartps.h>
#include <xstatus.h>
#include "xscugic.h"

#define UART_ID0  XPAR_XUARTPS_0_DEVICE_ID
#define SCU_ID0   XPAR_SCUGIC_SINGLE_DEVICE_ID
#define UART_INT_IRQ_ID		XPAR_XUARTPS_1_INTR
XUartPs UartPs0;
XScuGic InterruptController;
void UserDelay1(u32 t)
{
	u32 i = 0;

	while (--t >2)
	{
		for (i = 0; i < 9999; i++)
		{
			;
		}
		
	}
	
}

void XUartPs_InterruptHandler1(XUartPs *call_back_ref)
{

	XUartPs *uart_instance_ptr = (XUartPs *) call_back_ref;
	u32 rec_data = 0 ;
	u32 isr_status ; //中断状态标志

	//读取中断 ID 寄存器,判断触发的是哪种中断
	isr_status = XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,
	XUARTPS_IMR_OFFSET);
	isr_status &= XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,
	XUARTPS_ISR_OFFSET);

     //判断中断标志位 RxFIFO 是否触发
	if (isr_status & (u32)XUARTPS_IXR_RXOVR){
		rec_data = XUartPs_RecvByte(uart_instance_ptr->Config.BaseAddress);
		//清除中断标志
		XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress,
		XUARTPS_ISR_OFFSET, XUARTPS_IXR_RXOVR) ;
	}
    XUartPs_SendByte(uart_instance_ptr->Config.BaseAddress,rec_data);
}
/**
 * @description:
 * @return {*}
 */
int MyUartTest1(void)
{

    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(UART_ID0);
	if (NULL == Config) {
		return XST_FAILURE;
	}

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

    UserDelay1(300);

	Status = XUartPs_SelfTest(&UartPs0);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

    UserDelay1(300);
	
	xil_printf("My Uart cfg  and self test completed\r\n");

    UserDelay1(300);
    
    XUartPs_SetOperMode(&UartPs0, XUARTPS_OPER_MODE_NORMAL);

    XUartPs_SetBaudRate(&UartPs0,115200);

    XUartPs_SetFifoThreshold(&UartPs0, 1);


    uart_intr_init();
}

 void uart_intr_init(void)
 {
    int status;
	XScuGic_Config *intc_cfg;
    intc_cfg = XScuGic_LookupConfig(SCU_ID0);


	status = XScuGic_CfgInitialize(&InterruptController, intc_cfg,
    intc_cfg->CpuBaseAddress);

	Xil_ExceptionInit();

	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
    (Xil_ExceptionHandler)XScuGic_InterruptHandler,
    (void *)&InterruptController);

	Xil_ExceptionEnable();

	XScuGic_Connect(&InterruptController, UART_INT_IRQ_ID,
    (Xil_ExceptionHandler) &XUartPs_InterruptHandler1,(void *) &UartPs0);

	XUartPs_SetInterruptMask(&UartPs0, XUARTPS_IXR_RXOVR);

	XScuGic_Enable(&InterruptController, UART_INT_IRQ_ID);
 }

超时机制代码


#include <xuartps.h>
#include <xstatus.h>
#include "xscugic.h"

#define UART_ID0  XPAR_XUARTPS_0_DEVICE_ID
#define SCU_ID0   XPAR_SCUGIC_SINGLE_DEVICE_ID
#define UART_INT_IRQ_ID		XPAR_XUARTPS_1_INTR
XUartPs UartPs0;
XScuGic InterruptController;
void UserDelay1(u32 t)
{
	u32 i = 0;

	while (--t >2)
	{
		for (i = 0; i < 9999; i++)
		{
			;
		}
		
	}
	
}

void XUartPs_InterruptHandler1(XUartPs *call_back_ref)
{

	XUartPs *uart_instance_ptr = (XUartPs *) call_back_ref;
	u32 rec_data = 0 ;
	u32 isr_status ; //中断状态标志

	//读取中断 ID 寄存器,判断触发的是哪种中断
	isr_status = XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,
	XUARTPS_IMR_OFFSET);
	isr_status &= XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,
	XUARTPS_ISR_OFFSET);


     //判断中断标志位 RxFIFO 是否触发
	if (isr_status & (u32)XUARTPS_IXR_RXOVR)
	{
		xil_printf("F:");
		while (XUartPs_IsReceiveData(uart_instance_ptr->Config.BaseAddress))
		{
			rec_data = XUartPs_RecvByte(uart_instance_ptr->Config.BaseAddress);
			XUartPs_SendByte(uart_instance_ptr->Config.BaseAddress,rec_data);
		}
		
		//清除中断标志
		XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress,
		XUARTPS_ISR_OFFSET, XUARTPS_IXR_RXOVR) ;
		
	}

	
	if (isr_status & XUARTPS_IXR_TOUT)
	{
	    xil_printf("T:");
		while (XUartPs_IsReceiveData(uart_instance_ptr->Config.BaseAddress))
		{
			rec_data = XUartPs_RecvByte(uart_instance_ptr->Config.BaseAddress);
			XUartPs_SendByte(uart_instance_ptr->Config.BaseAddress,rec_data);
		}
		XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress,
		XUARTPS_ISR_OFFSET, XUARTPS_IXR_TOUT) ;
	}
	
}	
   
/**
 * @description:
 * @return {*}
 */
int MyUartTest1(void)
{

    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(UART_ID0);
	if (NULL == Config) {
		return XST_FAILURE;
	}

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

    UserDelay1(300);

	Status = XUartPs_SelfTest(&UartPs0);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

    UserDelay1(300);
	
	xil_printf("My Uart cfg  and self test completed\r\n");

    UserDelay1(300);
    
    XUartPs_SetOperMode(&UartPs0, XUARTPS_OPER_MODE_NORMAL);

    XUartPs_SetBaudRate(&UartPs0,115200);

    XUartPs_SetFifoThreshold(&UartPs0, 32);

    XUartPs_SetRecvTimeout(&UartPs0,888);
    uart_intr_init();
}

 void uart_intr_init(void)
 {
    int status;
	XScuGic_Config *intc_cfg;
    intc_cfg = XScuGic_LookupConfig(SCU_ID0);


	status = XScuGic_CfgInitialize(&InterruptController, intc_cfg,
    intc_cfg->CpuBaseAddress);

	Xil_ExceptionInit();

	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
    (Xil_ExceptionHandler)XScuGic_InterruptHandler,
    (void *)&InterruptController);

	Xil_ExceptionEnable();

	XScuGic_Connect(&InterruptController, UART_INT_IRQ_ID,
    (Xil_ExceptionHandler) &XUartPs_InterruptHandler1,(void *) &UartPs0);

	XUartPs_SetInterruptMask(&UartPs0, XUARTPS_IXR_RXOVR|XUARTPS_IXR_TOUT);

	XScuGic_Enable(&InterruptController, UART_INT_IRQ_ID);
 }

UATR的API
代码如下比较简单

/****************************************************************************/
/**
*
* This function sends one byte using the device. This function operates in
* polled mode and blocks until the data has been put into the TX FIFO register.
*
* @param	BaseAddress contains the base address of the device.
* @param	Data contains the byte to be sent.
*
* @return	None.
*
* @note		None.
*
*****************************************************************************/
void XUartPs_SendByte(u32 BaseAddress, u8 Data)
{
	/* Wait until there is space in TX FIFO */
	while (XUartPs_IsTransmitFull(BaseAddress)) {
		;
	}

	/* Write the byte into the TX FIFO */
	XUartPs_WriteReg(BaseAddress, XUARTPS_FIFO_OFFSET, (u32)Data);
}

/****************************************************************************/
/**
*
* This function receives a byte from the device. It operates in polled mode
* and blocks until a byte has received.
*
* @param	BaseAddress contains the base address of the device.
*
* @return	The data byte received.
*
* @note		None.
*
*****************************************************************************/
u8 XUartPs_RecvByte(u32 BaseAddress)
{
	u32 RecievedByte;
	/* Wait until there is data */
	while (!XUartPs_IsReceiveData(BaseAddress)) {
		;
	}
	RecievedByte = XUartPs_ReadReg(BaseAddress, XUARTPS_FIFO_OFFSET);
	/* Return the byte received */
	return (u8)RecievedByte;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值