这节课讲了中断。可能很多人和我一样不理解什么是中断。其实这个概念说起来很好理解,就是简单的停下来。可是又有什么用处?在系统设计中又处于什么样的一个地位呢?
这里先综合百度维基百科中的,加上我的理解,说说什么是中断。中断简单的来理解就是一种技术,这种技术可以显著提高计算机的工作效率。因此有比较重要的作用。这么重要,那么到底什么是中断???这里不用教科书中的定义(中断指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这个新的情况的过程就叫做中断。)。简单的打一个比方。假设我正在敲的博文是我正在执行的系统。那么我点击Ctrl + S就可以理解为一个中断。因为官方不可能随时每隔1us给我保存一次我的数据,而我的保存指令可以理解为一个中断,这个时候,系统就会将我的数据上传至服务器。而在我写博文没有点击保存的时间,服务器就可猥琐欲为的去做任何事情。这就是所谓的中断。下图就是博文中的图,用以借鉴。中断回调函数可以就是异常处理,而回调函数就是我们CPU响应中断所执行的内容。用前面那个例子,就是保存我的博文至服务器,就是我的中断回调函数。
1,中断详解与设计实现
软中断,由CPU0或者CPU1发起,可以相互中断。
GIC(Generic Interrupt Controller)通用中断控制器。通关软终端进行控制核间的中断,控制出发那个CPU。
下面是老师总结的一般处理过程
中断回调函数是什么。由于外部请求触发的一个中断,而CPU中断的这段时间所做的事情,就是中断回调函数的执行的。中断也有其优先级,可以进行设置。
接下来就是代码分析首先定义一个初始化函数用于主函数调用。我们先看初始化函数
先看这个函数Xil_Excep
tionInit();就是初始化,打开handler
该函数是一个公共API,用于跨所有受支持的arm处理器初始化异常处理程序。对于ARM Cortex-A53、Cortex-R5和Cortex-A9,异常处理程序正在被静态初始化,而这个函数什么也不做。但是,它仍然用于处理向后兼容性问题(在早期版本的bsp中,这个API用于初始化异常处理程序)。
其次就和GPIO中的类似了。先得到期间地址,在初始化。
status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
if(status != XST_SUCCESS){
return status;
}
一般这种写法是由于返回值是一个状态,我们定义一个变量,用于判断返回值是否正确,用于调试程序。
接下来是Xil_ExceptionRegisterHandler。异常注册管理器。(Xil_ExceptionHandler)XScuGic_InterruptHandler这是一个强制类型转换,其中的函数是用于设置中段优先级的。这里没有用到,因为只有一个中断。这里就将信息传回到CPU了。接下来就是连接软中断回调函数。XScuGic_Connect就是我们的连接函数。
这是函数的说明。函数有返回值。我们使用同样的方式。方便调试。
接下来使能软中断。(连接之后,需要使能才能使用)传递进去参数就是连接的。首先是实例化的XScuGic的指针其次是中断ID。
最后是使能处理过程。
//initial gic & software intr
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;
}
接下来对回调函数内容进行编写。、
//callback function
void cpu0IntrHandler(void * Callbackref){
printf("cpu1 interrupt cpu0 success !
");
}
接下来就是主函数
主函数进行初始化中断。然后就可以使用中断了。
int main()
{
COMM_VAL = 0;
Xil_SetTlbAttributes(0xffff0000,0x14de2);
int status;
status = initSwIntr();
if(status != XST_SUCCESS){
return status;
}
while(1) {
print("Hello CPU0
");
XScuGic_SoftwareIntr(&ScuGic,CPU1_SW_INTR,XSCUGIC_SPI_CPU1_MASK);
usleep(2000000);
COMM_VAL = 1;
}
return 0;
}
这里的中断使用方式就是调用这个函数。XScuGic_SoftwareIntr
结构体指针,初始化ID,CPUID。
这里的中断只是发起,至于执行什么,完全是由中断函数决定的
同样使用一样的代码。对CPU1进行中断的测试。
这里只有修改CPU1-CPU0即可。
最后可以看到结果。两秒发送一次,使能中断成功!!!
原作者:ty_xiumud