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