由于项目需要多个UART,所以在用了两个IP核实现UART的功能。
开发板环境:vivado 2017.4 ,开发板型号xc7z020clg400-1,这个工程主要功能是自定义两个axi_uartlite IP核,实现他们的中断接收。
在实验中遇到的问题(在网上查找了很多资料,花了不少时间才填完的坑):
1:两个IP核的中断怎么连接到PS端
2:在Xilinx SDK中如何对axi_uartlite IP核的中断如何进行配置
PS端的代码放到github上了:
Zynq7020 two uartlite interrupt test, PS side source code.
下面是简要步骤:
1:两个IP核的中断怎么连接到PS端:
添加zynq7000 Block后,在配置时需要打开PL到PS端的中断
添加两个axi_uartlite后,在system中添加Concat IP核
Concat IP核的功能是:把几个零散的中断信号合并成bus,连到系统中断总线上。
配置完的系统图如下图所示:
配置完成后,添加引脚约束:
其中有两种方法:
(一):在RTL ANALYSIS中的Open Elaborated Design中进行引脚的选择
(二):在Constarins中添加.XDC文件
2:在Xilinx SDK中如何对axi_uartlite IP核的中断如何进行配置
在官方例程xuartlite_intr_tapp_example(大概在Xilinx SDK的example目录下)的基础上进行修改,配置串口分为两个步骤:
(1)初始化串口
int UartLiteIntrExample(INTC *IntcInstancePtr,
XUartLite *UartLiteInstPtr,
u16 UartLiteDeviceId,
u16 UartLiteIntrId)
{
int Status;
//u32 Index;
/*
* Initialize the UartLite driver so that it's ready to use.
*/
Status = XUartLite_Initialize(UartLiteInstPtr, UartLiteDeviceId);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to ensure that the hardware was built correctly.
*/
Status = XUartLite_SelfTest(UartLiteInstPtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*2020.07.01 while ((TotalSentCount != TEST_BUFFER_SIZE)) {
}
UartLiteDisableIntrSystem(IntcInstancePtr, UartLiteIntrId); */
return XST_SUCCESS;
}
(2)配置中断
int UartLiteSetupIntrSystem(INTC *IntcInstancePtr,
XUartLite *UartLiteInstPtr,
u16 UartLiteIntrId)
{
int Status;
#ifdef XPAR_INTC_0_DEVICE_ID
#ifndef TESTAPP_GEN
/*
* Initialize the interrupt controller driver so that it is ready
* to use. 初始化中断控制器
*/
Status = XIntc_Initialize(IntcInstancePtr, INTC_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
#endif
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the specific
* interrupt processing for the device.
*/
Status = XIntc_Connect(IntcInstancePtr, UartLiteIntrId,
(XInterruptHandler)XUartLite_InterruptHandler,
(void *)UartLiteInstPtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
#ifndef TESTAPP_GEN
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that
* the UART can cause interrupts thru the interrupt controller.
*/
Status = XIntc_Start(IntcInstancePtr, XIN_REAL_MODE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
#endif
/*
* Enable the interrupt for the UartLite.
*/
XIntc_Enable(IntcInstancePtr, UartLiteIntrId);
#else
#ifndef TESTAPP_GEN
XScuGic_Config *IntcConfig;
/*初始化中断控制器
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
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;
}
#endif /* TESTAPP_GEN */
//Sets the interrupt priority and trigger type for the specificd IRQ source.
//2020.7.2 XScuGic_SetPriorityTriggerType(IntcInstancePtr, UartLiteIntrId,
// 0xA0, 0x3);
case 62U:
XScuGic_SetPriorityTriggerType(IntcInstancePtr, UartLiteIntrId,
0xA0, 0x3); break;
case 61U:
XScuGic_SetPriorityTriggerType(IntcInstancePtr, UartLiteIntrId,
0xA1, 0x3); break;
default:
XScuGic_SetPriorityTriggerType(IntcInstancePtr, UartLiteIntrId,
0xA0, 0x3); break; break;
}
#endif /* XPAR_INTC_0_DEVICE_ID */
#ifndef TESTAPP_GEN
//设置并打开中断异常处理功能
/*
* Initialize the exception table. 初始化异常表
*/
Xil_ExceptionInit();
/*注册中断控制器处理程序
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)INTC_HANDLER,
IntcInstancePtr);
/*
* Enable exceptions.
*/
Xil_ExceptionEnable();
/**************************2020.7.1******************/
/*
* Connect the interrupt handler that will be called when an
* interrupt occurs for the device.
*/
//为中断设置中断处理函数XUartLite_InterruptHandler
switch(UartLiteIntrId){
case 62U:
Status = XScuGic_Connect(IntcInstancePtr, UartLiteIntrId,
(Xil_ExceptionHandler)RS232_intr_handler,/*XUartLite_InterruptHandler,*/
UartLiteInstPtr); break;
case 61U:
Status = XScuGic_Connect(IntcInstancePtr, UartLiteIntrId,
(Xil_ExceptionHandler)RS422_intr_handler,/*XUartLite_InterruptHandler,*/
UartLiteInstPtr); break;
default:
Status = XScuGic_Connect(IntcInstancePtr, UartLiteIntrId,
(Xil_ExceptionHandler)RS422_intr_handler,/*XUartLite_InterruptHandler,*/
UartLiteInstPtr); break;
}
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Enable the interrupt for the Timer device.
*/
//使能GIC中的串口中断
XScuGic_Enable(IntcInstancePtr, UartLiteIntrId);
/*
* Enable the interrupt of the UartLite so that the interrupts
* will occur.
*/
XUartLite_EnableInterrupt(UartLiteInstPtr);
#endif /* TESTAPP_GEN */
return XST_SUCCESS;
}
中断处理函数代码:
void RS422_intr_handler(void *CallBackRef){
u8 buff,buff1;
static u8 i=0;
xil_printf("test success\r\n");
//清除中断位
//读取中断ID寄存器,判断触发的是哪种中断
buff=XUartLite_RecvByte(XPAR_AXI_UARTLITE_1_BASEADDR);
buff1=buff+1;
XUartLite_SendByte(XPAR_AXI_UARTLITE_1_BASEADDR,++i);
XUartLite_SendByte(XPAR_AXI_UARTLITE_1_BASEADDR,buff1);
}
实际运行结果: