小虎技术分享站 - zynq
type: channel
link: https://www.xtigerkin.com/tag/zynq/
items: ZYNQ PL端向PS端发出中断

ZYNQ PL端向PS端发出中断
type: item
date: 2025-05-07T11:00:05+08:00
description: 在之前的项目中知道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_CNhttps://adaptivesupport.amd.com/s/article/70347?language=en_US