基于ZYNQ的中断的使用(1)

参考文献

[1]、V3学院
[2]、 judyzhong

项目简述

接触过单片机、ARM的同学应该都了解中断,因为这是保证CPU实时性的前提。学到这里的同学会不免发出疑惑,为什么FPGA没事有实时性的要求呢,因为FPGA本身就是并发执行,这也是其本身最重要的特性。ZYNQ中有两个CPU,又分为不同的中断类型,将在下面的文章中一一介绍。如果学不会中断,那么ZYNQ的学习将没有意义。

工程描述:运行ZYNQ的两个ARM核,利用ZYNQ的软中断,用CPU0中断CPU1,同时CPU1中断CPU0。

本次实验所用到的软硬件环境如下:
1、VIVADO 2019.1
2、米联客MZ7015FA开发板

ZYNQ中断描述

ZYNQ中的中断主要包括三种类型,如下:
在这里插入图片描述
从上面可以看出三种终端类型包括:
1.软件中断(SGI,Software generatedinterrupts,中断号0-15)(16–26 reserved) :被路由到一个或者两个CPU上,通过写ICDSGIR寄存器产生SGI.
2.私有外设中断(PPI,private peripheralinterrupts ,中断号27-31):每个CPU都有一组PPI,包括全局定时器、私有看门狗定时器、私有定时器和来自PL的FIQ/IRQ.
3.共享外设中断(SPI,shared peripheralinterrupts,中断号32-95):由PS和PL上的各种I/O控制器和存储器控制器产生,这些中断信号被路由到相应的CPU. 其中共享中断包括外设中断和PL中断

中断控制器(GIC,generic interrupt controller ):用于集中管理从PS和PL产生的中断信号的资源集合。控制器可以使能、关使能、屏蔽中断源和改变中断源的优先级,并且会将中断送到对应的CPU中,CPU通过私有总线访问这些寄存器。

PL和PS之间的中断有:
在这里插入图片描述
两个CPU都具有各自16个软件中断,CPU可以中断自己,也可以中断其他CPU,上升沿触发,不可修改
在这里插入图片描述
CPU的私有中断,这些中断都是固定死的,不能修改:
在这里插入图片描述
共享中断就是一些端口共用一个中断请求线, PL部分有16个共享中断,他们的触发方式可以设置
在这里插入图片描述
这些中断的使用在接下来的文章中都会进行相应的讲解,本篇文章我们主要讲解软中断,软中断CPU可以中断自己,也可以中断其他CPU,上升沿触发,不可修改。

ZYNQ中断的整个注册流程如下,上面三种类型的中断都遵循下面的过程,只是稍许细节不一样,详细的情况可以观察我们下面给出的代码:
在这里插入图片描述

PL端设计

因为我们这篇文章主要讲解两个CPU之间的中断,那么关于PL侧的设计将没有什么重要设计,只需要例化相应的ZYNQ IP核,然后分配相应的DDR3即可。相应的Block Design如下:
在这里插入图片描述

PS端设计

这里因为要跑双核程序,那么就需要进行相应的设置,详细的设置可以观察博主的这篇文章基于ZYNQ的双核CPU之间的通信,注意这里的设置特别重要,否则ZYNQ的双核无法正常工作。

CPU0代码

这里我们废话不多说直接给出CPU0的代码:
这里使用了13,14软中断

#include <stdio.h>
#include "xscugic.h"
#include "xparameters.h"
#include "sleep.h"

#define GIC_ID XPAR_PS7_SCUGIC_0_DEVICE_ID
#define CPU0_SW_INTR 0x0d
#define CPU1_SW_INTR 0x0e

static XScuGic ScuGic;
static XScuGic_Config * ScuGicCfgPtr;

//initial gic & software intr
int initSwIntr();
//callback func
void cpu0IntrHandler(void * callbackref);


int main()
{
	int status;
	status = initSwIntr();
	if(status != XST_SUCCESS){
		return status;
	}

	while(1){
		usleep(100000);
		XScuGic_SoftwareIntr(&ScuGic,CPU1_SW_INTR,XSCUGIC_SPI_CPU1_MASK);
	}
    return 0;
}


int initSwIntr(){
	int status;
	Xil_ExceptionInit();
	ScuGicCfgPtr = XScuGic_LookupConfig(GIC_ID);
	status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
	if(status != XST_SUCCESS){
		return status;
	}
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
	status = XScuGic_Connect(&ScuGic,CPU0_SW_INTR,(Xil_ExceptionHandler)cpu0IntrHandler,&ScuGic);
	if(status != XST_SUCCESS){
			return status;
	}
	XScuGic_Enable(&ScuGic,CPU0_SW_INTR);
	Xil_ExceptionEnable();
	return XST_SUCCESS;
}


void cpu0IntrHandler(void * callbackref){
	printf("cpu1 interrupt cpu0 success! \n\r");
}

这里需要特别注意软中断的触发函数:
在这里插入图片描述
第二个参数是软中断编号,第三个参数是CPU编号。

CPU1代码

CPU1的代码如下:

#include <stdio.h>
#include "xscugic.h"
#include "xparameters.h"
#include "sleep.h"

#define GIC_ID XPAR_PS7_SCUGIC_0_DEVICE_ID
#define CPU0_SW_INTR 0x0d
#define CPU1_SW_INTR 0x0e

static XScuGic ScuGic;
static XScuGic_Config * ScuGicCfgPtr;

//initial gic & software intr
int initSwIntr();
//callback func
void cpu1IntrHandler(void * callbackref);

int main()
{
		int status;
		status = initSwIntr();
		if(status != XST_SUCCESS){
			return status;
		}
		while(1){
			XScuGic_SoftwareIntr(&ScuGic,CPU0_SW_INTR,XSCUGIC_SPI_CPU0_MASK);
			usleep(100000);
		}

    return 0;
}

int initSwIntr(){
	int status;
	Xil_ExceptionInit();
	ScuGicCfgPtr = XScuGic_LookupConfig(GIC_ID);
	status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
	if(status != XST_SUCCESS){
		return status;
	}
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
	status = XScuGic_Connect(&ScuGic,CPU1_SW_INTR,(Xil_ExceptionHandler)cpu1IntrHandler,&ScuGic);
	if(status != XST_SUCCESS){
			return status;
	}
	XScuGic_Enable(&ScuGic,CPU1_SW_INTR);
	Xil_ExceptionEnable();
	return XST_SUCCESS;
}


void cpu1IntrHandler(void * callbackref){
	printf("cpu0 interrupt cpu1 success! \n\r");
}

这里特别提醒何为中断,中断的频率肯定不会太高,因为那样就不是中断了,当频率特别高的时候中断会因为响应不及时而出现错误。

测试结果

我们将代码进行双核运行的必要控制,并且下板可以观察到如下现象:
在这里插入图片描述
从上面的实验结果我们可以看出我们的软中断实验成功执行,进而验证了我们实验的正确性。

总结

创作不易,认为文章有帮助的同学们可以关注、点赞、转发支持。为行业贡献及其微小的一部分。或者对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群:
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章