目录
中断1
SPI中断(来自PL)
中断号
中断配置
寄存器
硬件系统
软件系统
PL中断
函数API
参考
来自PL的中断,接前一篇。
ZYNQ(4) 中断 -- 私有定时器中断
来自PL的中断信号是属于SPI中断,在中断表中可以看到
具体的中断号为61~68和84~91共16个中断,可供给PL使用。
中断信号的敏感表和优先级是可以配置的,修改指定的寄存器即可。
触发敏感表
每个中断信号有2Bit的控制位。
Targeted to CPU
优先级Priority
共24个32位寄存器组成优先级表。每字节只有高5bit可写,低3bit为0,
共有32个等级。
在之前的GPIO的硬件上做修改,在ZYNQ设置页面,勾选中断
选择第一个SPI中断接口。
这里我使用一个16位宽的GPIO连接16根中断引脚。
如果多个使用concat合并连接
初始化中断控制器。打开中断,连接中断操作。
这里我使用一个16位宽的GPIO连接16根中断引脚。
/*
* 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);
}
中断使用的库函数由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