ZYNQ 串口持续触发 TX FIFO EMPTY中断 XUARTPS_IXR_TXEMPTY

文章目录

    • 1.ZYNQ 串口持续触发 TX FIFO EMPTY中断(XUARTPS_IXR_TXEMPTY)
      • 问题描述:
      • 产生原因:
      • 解决办法:

1.ZYNQ 串口持续触发 TX FIFO EMPTY中断(XUARTPS_IXR_TXEMPTY)

问题描述:

​ ZYNQ 7020 串口工作为中断触发模式。使用XUartPs_Send()函数发送完成数据之后,会产生一个 TX FIFO EMPTY中断(尽管串口初始化中断时并没有使能XUARTPS_IXR_TXEMPTY中断),同时会调用串口中断处理函数,如果没有清除处中断标志位,除非关闭中断XScuGic_Disable()否则会持续调用中断处理函数,影响程序正常运行。

产生原因:

​ 调用XUartPs_Send()函数时,会先关闭TX EMPTY和TX FULL中断

	/*
	 * Disable the UART transmit interrupts to allow this call to stop a
	 * previous operation that may be interrupt driven.
	 */
	XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET,
					  (XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TXFULL));

     BytesSent = XUartPs_SendBuffer(InstancePtr);

​ 然后调用XUartPs_SendBuffer()函数,在该函数中,如果开启了接收中断,则会开启TX EMPTY的中断。

/*
	 * If interrupts are enabled as indicated by the receive interrupt, then
	 * enable the TX FIFO empty interrupt, so further action can be taken
	 * for this sending.
	 */
	ImrRegister =
		XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
				  XUARTPS_IMR_OFFSET);
	if (((ImrRegister & XUARTPS_IXR_RXFULL) != (u32)0) ||
		((ImrRegister & XUARTPS_IXR_RXEMPTY) != (u32)0)||
		((ImrRegister & XUARTPS_IXR_RXOVR) != (u32)0)) {

		XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
					   XUARTPS_IER_OFFSET,
					   ImrRegister | (u32)XUARTPS_IXR_TXEMPTY);//使能TX EMPTY中断
	}

解决办法:

(1)在中断处理函数中对发送FIFO中断进行判断,如果触发该中断,则清除中断标志。

(2)使用XUartPs_SendByte()按字节发送数据。

串口发送代码:

void Ublox_Cfg(u8 type)
{
     
	switch(type)
	{
     
		case Hot:
		{
     
			unsigned char uart_send[] ={
     0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x68};
			XUartPs_Send(&Uart_Ps, uart_send, 12);
			break;
		}
		default:
			break;
	}
}

中断处理函数代码:

void uart_handler(void *call_back_ref)
{
     
	XUartPs *uart_instance_ptr = (XUartPs *) call_back_ref;
	u32 IsrStatus;
	u32 rx_realnumber;
	//读取中断 ID 寄存器,判断触发的是哪种中断
	IsrStatus = XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,
	XUARTPS_IMR_OFFSET);
	IsrStatus &= XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,
	XUARTPS_ISR_OFFSET);
	if((IsrStatus & (u32)XUARTPS_IXR_TXEMPTY))
	{
     
		XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress, XUARTPS_ISR_OFFSET, XUARTPS_IXR_TXEMPTY) ;//clear TX FIFO中断
	}
	if((IsrStatus & (u32)XUARTPS_IXR_RXOVR))//接收FIFO触发中断
	{
     
		rx_realnumber = XUartPs_Recv(uart_instance_ptr,&uart_recv[uart_totalnumber],512);//读取FIFO数据到数组,返回实际接收长度
		uart_totalnumber += rx_realnumber;//计算总接收长度
		XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress, XUARTPS_ISR_OFFSET, XUARTPS_IXR_RXOVR) ;//clear 中断
	}
}

串口初始化代码:

int uartps_init(XUartPs* uart_ps)
{
	int status;
	XUartPs_Config *uart_cfg;
	XScuGic_Config *intc_cfg;
	uart_cfg = XUartPs_LookupConfig(UART_DEVICE_ID);
	if (NULL == uart_cfg)
		return XST_FAILURE;
	status = XUartPs_CfgInitialize(uart_ps, uart_cfg, uart_cfg->BaseAddress);
	if (status != XST_SUCCESS)
		return XST_FAILURE;

	XUartPs_SetOperMode(uart_ps, XUARTPS_OPER_MODE_NORMAL);
	XUartPs_SetBaudRate(uart_ps,UART_BAUD);
	XUartPs_SetFifoThreshold(uart_ps,60);
    
	Xil_ExceptionInit();
	intc_cfg = XScuGic_LookupConfig(INTC_DEVICE_ID);
	if (NULL == intc_cfg)
		return XST_FAILURE;
	status = XScuGic_CfgInitialize(&Intc, intc_cfg,intc_cfg->CpuBaseAddress);
	if (status != XST_SUCCESS)
		return XST_FAILURE;
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,(void *)&Intc);
	XScuGic_Connect(&Intc,UART_INT_IRQ_ID,(Xil_ExceptionHandler)uart_handler,(void *)uart_ps);
	//设置 UART 的中断触发方式
	XUartPs_SetInterruptMask(uart_ps,XUARTPS_IXR_RXOVR); //此处没有打开XUARTPS_IXR_TXEMPTY中断
	Xil_ExceptionEnable();
	XScuGic_Enable(&Intc,UART_INT_IRQ_ID);
	return XST_SUCCESS;
}

你可能感兴趣的:(嵌入式)