sdk例程:ps与pl交互,用vio直接触发中断 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki

1)block设计

image

用VIO直接驱动ZYNQ的IRQ_F2P

2)程序设计

#include <stdio.h>
#include "xscugic.h"
#include "xil_exception.h"
#include "xparameters.h"
#include "xparameters_ps.h"

#define INTC_DEVICE_ID          XPAR_PS7_SCUGIC_0_DEVICE_ID

static XScuGic INTCInst;

static void SW0_intr_Handler();
static void SW1_intr_Handler();
static void SW2_intr_Handler();

static int IntcInitFunction(u16 DeviceId);

// 中断服务函数
static void SW0_intr_Handler()
{
	printf("function1: SW0 Pressed.\r\n");
}
static void SW1_intr_Handler()
{
	printf("function2: SW1 Pressed.\r\n");
}
static void SW2_intr_Handler()
{
	printf("function3: SW2 Pressed.\r\n");
}

int IntcInitFunction(u16 DeviceId)
{
    XScuGic_Config *IntcConfig;
    int status;

    // Interrupt controller initialisation
    IntcConfig = XScuGic_LookupConfig(DeviceId);
    status = XScuGic_CfgInitialize(&INTCInst, IntcConfig, IntcConfig->CpuBaseAddress);
    if(status != XST_SUCCESS) return XST_FAILURE;

    // Call to interrupt setup
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                                 (Xil_ExceptionHandler)XScuGic_InterruptHandler,
                                 &INTCInst);
    Xil_ExceptionEnable();
/*********************************(begin)****************************************/
    // Connect SW0 interrupt to handler
    status = XScuGic_Connect(&INTCInst,
    		XPS_FPGA0_INT_ID,
                             (Xil_ExceptionHandler)SW0_intr_Handler,
                             (void *)1);
    if(status != XST_SUCCESS) return XST_FAILURE;
    // Connect SW1 interrupt to handler
    status = XScuGic_Connect(&INTCInst,
    		XPS_FPGA1_INT_ID,
                             (Xil_ExceptionHandler)SW1_intr_Handler,
                             (void *)1);
    if(status != XST_SUCCESS) return XST_FAILURE;
    // Connect SW2 interrupt to handler
    status = XScuGic_Connect(&INTCInst,
    		XPS_FPGA2_INT_ID,
                             (Xil_ExceptionHandler)SW2_intr_Handler,
                             (void *)1);
    if(status != XST_SUCCESS) return XST_FAILURE;

    // Set interrupt type of SW0 to rising edge
    XScuGic_SetPriorityTriggerType(&INTCInst, XPS_FPGA0_INT_ID, 0x00, 0x03);
    // Set interrupt type of SW1 to rising edge
    XScuGic_SetPriorityTriggerType(&INTCInst, XPS_FPGA1_INT_ID, 0x00, 0x03);
    // Set interrupt type of SW2 to rising edge
    XScuGic_SetPriorityTriggerType(&INTCInst, XPS_FPGA2_INT_ID, 0x00, 0x03);

    // Enable SW0 interrupts in the controller
    XScuGic_Enable(&INTCInst, XPS_FPGA0_INT_ID);
    // Enable SW1 interrupts in the controller
    XScuGic_Enable(&INTCInst, XPS_FPGA1_INT_ID);
    // Enable SW2 interrupts in the controller
    XScuGic_Enable(&INTCInst, XPS_FPGA2_INT_ID);

/*********************************(end)****************************************/
    return XST_SUCCESS;
}


int main(void)
{
	printf("This is PL IRQ Test!\r\n");
    IntcInitFunction(INTC_DEVICE_ID);
    while(1);

    return 0;
}

说明,用的是FPGA的Fabric中断,中断编号在xparameters_ps.h中定义

/* Shared Peripheral Interrupts (SPI) */
#define XPS_CORE_PARITY0_INT_ID		32U
#define XPS_CORE_PARITY1_INT_ID		33U
#define XPS_L2CC_INT_ID			34U
#define XPS_OCMINTR_INT_ID		35U
#define XPS_ECC_INT_ID			36U
#define XPS_PMU0_INT_ID			37U
#define XPS_PMU1_INT_ID			38U
#define XPS_SYSMON_INT_ID		39U
#define XPS_DVC_INT_ID			40U
#define XPS_WDT_INT_ID			41U
#define XPS_TTC0_0_INT_ID		42U
#define XPS_TTC0_1_INT_ID		43U
#define XPS_TTC0_2_INT_ID 		44U
#define XPS_DMA0_ABORT_INT_ID		45U
#define XPS_DMA0_INT_ID			46U
#define XPS_DMA1_INT_ID			47U
#define XPS_DMA2_INT_ID			48U
#define XPS_DMA3_INT_ID			49U
#define XPS_SMC_INT_ID			50U
#define XPS_QSPI_INT_ID			51U
#define XPS_GPIO_INT_ID			52U
#define XPS_USB0_INT_ID			53U
#define XPS_GEM0_INT_ID			54U
#define XPS_GEM0_WAKE_INT_ID		55U
#define XPS_SDIO0_INT_ID		56U
#define XPS_I2C0_INT_ID			57U
#define XPS_SPI0_INT_ID			58U
#define XPS_UART0_INT_ID		59U
#define XPS_CAN0_INT_ID			60U
#define XPS_FPGA0_INT_ID		61U
#define XPS_FPGA1_INT_ID		62U
#define XPS_FPGA2_INT_ID		63U
#define XPS_FPGA3_INT_ID		64U
#define XPS_FPGA4_INT_ID		65U
#define XPS_FPGA5_INT_ID		66U
#define XPS_FPGA6_INT_ID		67U
#define XPS_FPGA7_INT_ID		68U
#define XPS_TTC1_0_INT_ID		69U
#define XPS_TTC1_1_INT_ID		70U
#define XPS_TTC1_2_INT_ID		71U
#define XPS_DMA4_INT_ID			72U
#define XPS_DMA5_INT_ID			73U
#define XPS_DMA6_INT_ID			74U
#define XPS_DMA7_INT_ID			75U
#define XPS_USB1_INT_ID			76U
#define XPS_GEM1_INT_ID			77U
#define XPS_GEM1_WAKE_INT_ID		78U
#define XPS_SDIO1_INT_ID		79U
#define XPS_I2C1_INT_ID			80U
#define XPS_SPI1_INT_ID			81U
#define XPS_UART1_INT_ID		82U
#define XPS_CAN1_INT_ID			83U
#define XPS_FPGA8_INT_ID		84U
#define XPS_FPGA9_INT_ID		85U
#define XPS_FPGA10_INT_ID		86U
#define XPS_FPGA11_INT_ID		87U
#define XPS_FPGA12_INT_ID		88U
#define XPS_FPGA13_INT_ID		89U
#define XPS_FPGA14_INT_ID		90U
#define XPS_FPGA15_INT_ID		91U

3)运行结果

image image

4)补充说明(关于中断控制器设置)

第1部分是通用的,所有都一样

image

第2部分是设置中断控制器的来源,需要针对需要的外设设置。

3个函数搞定:XScuGic_Connect, XScuGic_SetPriorityTriggerType, XScuGic_Enable。
可以看到每个源都要使用这3个函数设置一遍。

image image

5)将中断控制器设置函数修改为通用函数

#include <stdio.h>
#include "xscugic.h"
#include "xil_exception.h"
#include "xparameters.h"
#include "xparameters_ps.h"


static void SW0_intr_Handler();
static void SW1_intr_Handler();
static void SW2_intr_Handler();


// 中断服务函数
static void SW0_intr_Handler()
{
	printf("function1: SW0 Pressed.\r\n");
}
static void SW1_intr_Handler()
{
	printf("function2: SW1 Pressed.\r\n");
}
static void SW2_intr_Handler()
{
	printf("function3: SW2 Pressed.\r\n");
}

int IntcInitFunction(u32 Int_Id, Xil_InterruptHandler Handler)
{
    static XScuGic INTCInst;
    XScuGic_Config *IntcConfig;
    int status;

    // Interrupt controller initialisation
    IntcConfig = XScuGic_LookupConfig(XPAR_PS7_SCUGIC_0_DEVICE_ID);
    status = XScuGic_CfgInitialize(&INTCInst, IntcConfig, IntcConfig->CpuBaseAddress);
    if(status != XST_SUCCESS) return XST_FAILURE;

    // Call to interrupt setup
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                                 (Xil_ExceptionHandler)XScuGic_InterruptHandler,
                                 &INTCInst);
    Xil_ExceptionEnable();
/*********************************(begin)****************************************/
    // Connect SW0 interrupt to handler
    status = XScuGic_Connect(&INTCInst,
    			     Int_Id,
                             (Xil_ExceptionHandler)Handler,
                             (void *)1);
    if(status != XST_SUCCESS) return XST_FAILURE;


    // Set interrupt type of SW0 to rising edge
    XScuGic_SetPriorityTriggerType(&INTCInst, Int_Id, 0x00, 0x03);

    // Enable SW0 interrupts in the controller
    XScuGic_Enable(&INTCInst, Int_Id);

/*********************************(end)****************************************/
    return XST_SUCCESS;
}


int main(void)
{
    printf("This is PL IRQ Test!\r\n");
    IntcInitFunction(XPS_FPGA0_INT_ID, SW0_intr_Handler);
    IntcInitFunction(XPS_FPGA1_INT_ID, SW1_intr_Handler);
    IntcInitFunction(XPS_FPGA2_INT_ID, SW2_intr_Handler);
    while(1);

    return 0;
}

运行结果是一样的。

⚠️ **GitHub.com Fallback** ⚠️