ZYNQ PL端向PS端发出中断
在之前的项目中知道zynq的PS端可以通过AXI总线向PL端的IP核写入数据,而PL端也可以通过AXI总线去访问PS端的DDR等设备。然而当PL端的IP在接收到PS端的指令完成操作后,该如何告知PS端我已经完成操作了呢?有一种方式是PS端使用AXI总线轮询,不停地访问AXI总线直到出现预期的标志位。另外一种方式则是使用PL端到PS端的中断,在完成操作后发出一个中断通知PS端可以进行后续的处理了。
PL端向PS端发出触发的方式
在zynq上有16个PL到PS端的常规中断接到双核心的PS端,每个CPU又有独立的1个常规中断和快速中断。在这里我们先介绍使用F2P的这一组中断。
从PL端发出这个中断的方式非常简单,就是从模块上给出一个信号然后连接到zynq PS的F2P端口上。当需要触发这个中断时将模块的这个信号由低拉高即可。
PS端F2P支持高电平触发或者是上升沿触发,可以根据实际的需求进行配置。
PS端的中断处理
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xil_io.h"
#include "xscugic.h"
#include "xparameters.h"
#define PL_DDR_BASE_ADDR 0x10000000
#define INT_ID 61U
#define XIL_EXCEPTION_ID_INIT 5U
XScuGic ScuGic;
void irq_handler(void* data) {
u32 id;
id = XScuGic_ReadReg(XPAR_SCUGIC_CPU_BASEADDR, XSCUGIC_INT_ACK_OFFSET);
id = id & XSCUGIC_ACK_INTID_MASK;
xil_printf("irq occur, id: %d\r\n", id);
XScuGic_WriteReg(XPAR_SCUGIC_CPU_BASEADDR, XSCUGIC_EOI_OFFSET, id);
}
int pl_irq_init() {
XScuGic_Config* pScuGicCfg;
pScuGicCfg = XScuGic_LookupConfig(XPAR_PS7_SCUGIC_0_DEVICE_ID);
XScuGic_CfgInitialize(&ScuGic, pScuGicCfg, pScuGicCfg->CpuBaseAddress);
XScuGic_Connect(&ScuGic, INT_ID, (Xil_ExceptionHandler)irq_handler, NULL);
XScuGic_SetPriorityTriggerType(&ScuGic, INT_ID, 0xA0, 0x03);
XScuGic_Enable(&ScuGic, INT_ID);
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INIT, (Xil_ExceptionHandler)irq_handler, &ScuGic);
Xil_ExceptionEnable();
}
int main()
{
init_platform();
pl_irq_init();
print("read ddr app\n\r");
while(1);
cleanup_platform();
return 0;
}
参考链接
https://adaptivesupport.amd.com/s/question/0D52E00006iHoxcSAC/irqf2p-width-mismatch?language=zh_CN
https://adaptivesupport.amd.com/s/article/70347?language=en_US
感谢扫码支持

