ZYNQ基本使用(5) 中断 -- 来自PL的中断

目录

中断1

SPI中断(来自PL)

中断号

中断配置

寄存器

硬件系统

软件系统

PL中断

函数API

参考


中断1

来自PL的中断,接前一篇。

ZYNQ(4) 中断 -- 私有定时器中断

SPI中断(来自PL)

中断号

来自PL的中断信号是属于SPI中断,在中断表中可以看到

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第1张图片

具体的中断号为61~68和84~91共16个中断,可供给PL使用。

中断配置

中断信号的敏感表和优先级是可以配置的,修改指定的寄存器即可。

触发敏感表

每个中断信号有2Bit的控制位。

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第2张图片

Targeted to CPU

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第3张图片

 

优先级Priority

共24个32位寄存器组成优先级表。每字节只有高5bit可写,低3bit为0,

共有32个等级。

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第4张图片

 

寄存器

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第5张图片

 

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第6张图片

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第7张图片

 

 

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第8张图片

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第9张图片

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第10张图片

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第11张图片

 

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第12张图片

 

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第13张图片

 

硬件系统

在之前的GPIO的硬件上做修改,在ZYNQ设置页面,勾选中断

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第14张图片

选择第一个SPI中断接口。

这里我使用一个16位宽的GPIO连接16根中断引脚。

 

ZYNQ基本使用(5) 中断 -- 来自PL的中断_第15张图片

如果多个使用concat合并连接

 

 

软件系统

PL中断

初始化中断控制器。打开中断,连接中断操作。

这里我使用一个16位宽的GPIO连接16根中断引脚。

code

/*
 * main.c
 *
 *  Created on: 2020/06/01
 *      Author: liny
 */

#include 
#include "platform.h"
#include "xil_printf.h"

#include "xparameters.h"
#include "xstatus.h"
#include "xgpio.h"

#include "time.h"
#include "sleep.h"

// interrupt library
#include 
#include "xil_io.h"
#include "xscugic.h"
#include "xil_exception.h"

// AXI GPIO
#define AXI_GPIO    XPAR_AXI_GPIO_0_BASEADDR

// INTERRUPT
// spi_status_0[31:29]
#define PL_RE_INTR_0_ID  61
#define PL_RE_INTR_1_ID  62
#define PL_RE_INTR_2_ID  63
// spi_status_1[4:0]
#define PL_RE_INTR_3_ID  64
#define PL_RE_INTR_4_ID  65
#define PL_RE_INTR_5_ID  66
#define PL_RE_INTR_6_ID  67
#define PL_RE_INTR_7_ID  68
// spi_status_1[27:20]
#define PL_RE_INTR_8_ID  84
#define PL_RE_INTR_9_ID  85
#define PL_RE_INTR_10_ID 86
#define PL_RE_INTR_11_ID 87
#define PL_RE_INTR_12_ID 88
#define PL_RE_INTR_13_ID 89
#define PL_RE_INTR_14_ID 90
#define PL_RE_INTR_15_ID 91

#define INTR_CTRL_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID


#define EN_INTR_0  0x0001
#define EN_INTR_1  0x0002
#define EN_INTR_2  0x0004
#define EN_INTR_3  0x0008
#define EN_INTR_4  0x0010
#define EN_INTR_5  0x0020
#define EN_INTR_6  0x0040
#define EN_INTR_7  0x0080
#define EN_INTR_8  0x0100
#define EN_INTR_9  0x0200
#define EN_INTR_10 0x0400
#define EN_INTR_11 0x0800
#define EN_INTR_12 0x0100
#define EN_INTR_13 0x0200
#define EN_INTR_14 0x0400
#define EN_INTR_15 0x0800

/************************** Variable Definitions *****************************/

XScuGic IntrCtrller; 	     /* Instance of the Interrupt Controller */
static XScuGic_Config *GicConfig;    /* The configuration parameters of the
                                       controller */

static void PL_intr_handler(void *param);
static void PL_intr1_handler(void *param);
static void PL_intr2_handler(void *param);
static void PL_intr3_handler(void *param);
static void PL_intr4_handler(void *param);
static void PL_intr5_handler(void *param);
static void PL_intr6_handler(void *param);
int SetUpInterruptSystem(XScuGic *XScuGicInstancePtr);
int IntrCtrller_Init(u16 DevceId);
void intrSet(XScuGic *InstancePtr, u32 Int_Id,
		u8 Priority, u8 Trigger);

int main()
{
    int Status ;
    u64 count = 0;
	init_platform();

    printf("\n\r--- PL interrupt test start---\n\r");

    Status = IntrCtrller_Init(INTR_CTRL_DEVICE_ID);
    if(Status == XST_FAILURE){
    	printf("Initialize failed\r");
    }
	else if(Status == XST_SUCCESS){
    	printf("Initialize Success\r");
	}

    XGpio_WriteReg(AXI_GPIO, 0, 0);
    XGpio_WriteReg(AXI_GPIO, 0, EN_INTR_0);
    XGpio_WriteReg(AXI_GPIO, 0, 0x00);
    sleep(1);

    XGpio_WriteReg(AXI_GPIO, 0, EN_INTR_1|EN_INTR_4);
    XGpio_WriteReg(AXI_GPIO, 0, 0x00);
    sleep(1);

    XGpio_WriteReg(AXI_GPIO, 0, EN_INTR_2);
    XGpio_WriteReg(AXI_GPIO, 0, 0x00);
    sleep(1);

    XGpio_WriteReg(AXI_GPIO, 0, EN_INTR_3);
    XGpio_WriteReg(AXI_GPIO, 0, 0x00);

    // loop
    while(1){
    	printf("\n\r--- loop : %lld ---\n\r", count++);
    	sleep(1);
    }

    printf("\n\r--- PL interrupt test end---\n\r");

    cleanup_platform();
    return 0;
}


// interrupt controller initial
int IntrCtrller_Init(u16 DevceId){
	int Status ;

	/*
	 * Initialize the interrupt controller driver so that it is ready to
	 * use.
	 */
	GicConfig = XScuGic_LookupConfig(DevceId);
	if (NULL == GicConfig) {
		return XST_FAILURE;
	}

	Status = XScuGic_CfgInitialize(&IntrCtrller, GicConfig,
					GicConfig->CpuBaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
	printf("initial end \n\r");

	/*
	 * Perform a self-test to ensure that the hardware was built
	 * correctly
	 */
	Status = XScuGic_SelfTest(&IntrCtrller);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}


	printf("selftest end \n\r");

	/*
	 * Setup the Interrupt System
	 */
	Status = SetUpInterruptSystem(&IntrCtrller);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * 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 = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_0_ID , 
                            (Xil_ExceptionHandler)PL_intr_handler, 
                            (void *)0);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

                             
	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_1_ID , 
                            (Xil_ExceptionHandler)PL_intr1_handler, 
                            (void *)1);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_2_ID , 
                            (Xil_ExceptionHandler)PL_intr2_handler, 
                            (void *)2);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_3_ID , 
                            (Xil_ExceptionHandler)PL_intr3_handler, 
                            (void *)3);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_4_ID , 
                            (Xil_ExceptionHandler)PL_intr4_handler, 
                            (void *)4);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_5_ID , 
                            (Xil_ExceptionHandler)PL_intr5_handler, 
                            (void *)5);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_6_ID , 
                            (Xil_ExceptionHandler)PL_intr6_handler, 
                            (void *)6);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_7_ID , 
                            (Xil_ExceptionHandler)PL_intr_handler, 
                            (void *)7);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_8_ID , 
                            (Xil_ExceptionHandler)PL_intr_handler, 
                            (void *)8);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_9_ID , 
                            (Xil_ExceptionHandler)PL_intr_handler, 
                            (void *)9);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_10_ID, 
                            (Xil_ExceptionHandler)PL_intr_handler, 
                            (void *)10);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_11_ID, 
                            (Xil_ExceptionHandler)PL_intr_handler, 
                            (void *)11);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_12_ID, 
                            (Xil_ExceptionHandler)PL_intr_handler, 
                            (void *)12);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_13_ID, 
                            (Xil_ExceptionHandler)PL_intr_handler, 
                            (void *)13);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_14_ID, 
                            (Xil_ExceptionHandler)PL_intr_handler, 
                            (void *)14);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	Status = XScuGic_Connect(&IntrCtrller, 
                            PL_RE_INTR_15_ID, 
                            (Xil_ExceptionHandler)PL_intr_handler, 
                            (void *)15);
	if (Status != XST_SUCCESS) { 
        return XST_FAILURE; 
    }

	/* Set */
	u8 intr0_priority = 0;
	u8 intr0_trigger  = 0;
	u8 intr1_priority = 0;
	u8 intr1_trigger  = 0;
	u8 intr2_priority = 0;
	u8 intr2_trigger  = 0;
	u8 intr3_priority = 0;
	u8 intr3_trigger  = 0;
	u8 intr4_priority = 0;
	u8 intr4_trigger  = 0;
	u8 intr5_priority = 0;
	u8 intr5_trigger  = 0;
	u8 intr6_priority = 0;
	u8 intr6_trigger  = 0;
	intrSet(&IntrCtrller, PL_RE_INTR_0_ID, intr0_priority, intr0_trigger);
	intrSet(&IntrCtrller, PL_RE_INTR_1_ID, intr1_priority, intr1_trigger);
	intrSet(&IntrCtrller, PL_RE_INTR_2_ID, intr2_priority, intr2_trigger);
	intrSet(&IntrCtrller, PL_RE_INTR_3_ID, intr3_priority, intr3_trigger);
	intrSet(&IntrCtrller, PL_RE_INTR_4_ID, intr4_priority, intr4_trigger);
	intrSet(&IntrCtrller, PL_RE_INTR_5_ID, intr5_priority, intr5_trigger);
	intrSet(&IntrCtrller, PL_RE_INTR_6_ID, intr6_priority, intr6_trigger);
	/*
	XScuGic_GetPriorityTriggerType(&IntrCtrller, PL_RE_INTR_0_ID,
						&intr0_priority,
						&intr0_trigger);
	XScuGic_GetPriorityTriggerType(&IntrCtrller, PL_RE_INTR_0_ID,
						&intr1_priority,
						&intr1_trigger);
	XScuGic_GetPriorityTriggerType(&IntrCtrller, PL_RE_INTR_0_ID,
						&intr2_priority,
						&intr2_trigger);
	XScuGic_GetPriorityTriggerType(&IntrCtrller, PL_RE_INTR_0_ID,
						&intr3_priority,
						&intr3_trigger);
	XScuGic_GetPriorityTriggerType(&IntrCtrller, PL_RE_INTR_0_ID,
						&intr4_priority,
						&intr4_trigger);
	XScuGic_GetPriorityTriggerType(&IntrCtrller, PL_RE_INTR_0_ID,
						&intr5_priority,
						&intr5_trigger);
	XScuGic_GetPriorityTriggerType(&IntrCtrller, PL_RE_INTR_0_ID,
						&intr6_priority,
						&intr6_trigger);

	printf("setting --- intr0 priority:%x , trigger: %x \n", intr0_priority, intr0_trigger);
	printf("setting --- intr1 priority:%x , trigger: %x \n", intr1_priority, intr1_trigger);
	printf("setting --- intr2 priority:%x , trigger: %x \n", intr2_priority, intr2_trigger);
	printf("setting --- intr3 priority:%x , trigger: %x \n", intr3_priority, intr3_trigger);
	printf("setting --- intr4 priority:%x , trigger: %x \n", intr4_priority, intr4_trigger);
	printf("setting --- intr5 priority:%x , trigger: %x \n", intr5_priority, intr5_trigger);
	printf("setting --- intr6 priority:%x , trigger: %x \n", intr6_priority, intr6_trigger);
*/
	/*
	 * Enable the interrupt for the device and then cause (simulate) an
	 * interrupt so the handlers will be called
	 */
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_0_ID );
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_1_ID );
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_2_ID );
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_3_ID );
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_4_ID );
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_5_ID );
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_6_ID );
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_7_ID );
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_8_ID );
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_9_ID );
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_10_ID);
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_11_ID);
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_12_ID);
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_13_ID);
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_14_ID);
	XScuGic_Enable(&IntrCtrller, PL_RE_INTR_15_ID);

	printf("interrupt enabled \n\r");
//	/*
//	 *  Simulate the Interrupt
//	 */
//	Status = XScuGic_SoftwareIntr(&IntrCtrller,
//					PL_RE_INTR_0_ID,
//					XSCUGIC_SPI_CPU0_MASK);
//	if (Status != XST_SUCCESS) {
//		return XST_FAILURE;
//	}

	return XST_SUCCESS;
}


int SetUpInterruptSystem(XScuGic *XScuGicInstancePtr)
{

	/*
	 * Connect the interrupt controller interrupt handler to the hardware
	 * interrupt handling logic in the ARM processor.
	 */
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
			(Xil_ExceptionHandler) XScuGic_InterruptHandler,
			XScuGicInstancePtr);

	/*
	 * Enable interrupts in the ARM
	 */
	Xil_ExceptionEnable();

	return XST_SUCCESS;
}


// interrupt handler
static void PL_intr_handler(void *param){
	int intr_id = (int)param ;
	printf("Interrupt ---- PL_INTR_ID : %d \n", intr_id);
	//XGpio_WriteReg(AXI_GPIO, 0, 0x00);
}

static void PL_intr1_handler(void *param){
	int intr_id = (int)param ;
	printf("Interrupt 1 ---- PL_INTR_ID : %d \n", intr_id);
	//XGpio_WriteReg(AXI_GPIO, 0, 0x00);
}
static void PL_intr2_handler(void *param){
	int intr_id = (int)param ;
	printf("Interrupt 2 ---- PL_INTR_ID : %d \n", intr_id);
	//XGpio_WriteReg(AXI_GPIO, 0, 0x00);
}
static void PL_intr3_handler(void *param){
	int intr_id = (int)param ;
	printf("Interrupt 3 ---- PL_INTR_ID : %d \n", intr_id);
	//XGpio_WriteReg(AXI_GPIO, 0, 0x00);
}
static void PL_intr4_handler(void *param){
	int intr_id = (int)param ;
	printf("Interrupt 4 ---- PL_INTR_ID : %d \n", intr_id);
	//XGpio_WriteReg(AXI_GPIO, 0, 0x00);
}
static void PL_intr5_handler(void *param){
	int intr_id = (int)param ;
	printf("Interrupt 5 ---- PL_INTR_ID : %d \n", intr_id);
	//XGpio_WriteReg(AXI_GPIO, 0, 0x00);
}
static void PL_intr6_handler(void *param){
	int intr_id = (int)param ;
	printf("Interrupt 6 ---- PL_INTR_ID : %d \n", intr_id);
	//XGpio_WriteReg(AXI_GPIO, 0, 0x00);
}

void intrSet(XScuGic *InstancePtr, u32 Int_Id,
		u8 Priority, u8 Trigger){


	XScuGic_GetPriorityTriggerType(InstancePtr, Int_Id,
						&Priority,
						&Trigger);

	printf("getting --- intr id:%ld --> priority:%d , trigger: %d \n", Int_Id, Priority, Trigger);


}

函数API

中断使用的库函数由xscugic.h和xscugic_hw.h和xil_exception.h两个。

函数库xscugic.h和xscugic_hw.h提供通用中断控制器的操作函数

 

s32  XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id,

                     Xil_InterruptHandler Handler, void *CallBackRef);

连接中断源的中断号和中断程序,第四个参数为回调函数参数。

void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id);

使能中断控制器关联的中断号中断。

 

函数库xil_exception.h提供异常处理的操作函数

extern void Xil_ExceptionInit(void);

初始化异常处理程序

extern void Xil_ExceptionRegisterHandler(u32 Exception_id,

                                    Xil_ExceptionHandler Handler,

                                    void *Data);

注册异常处理程序

Xil_ExceptionEnable();

使能IRQ异常

参考

UG585:Zynq-7000 SoC Technical Reference Manual

 

 

 

你可能感兴趣的:(Zynq)