|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
: O* A- e& D5 l( f3 j
0,前言背景1 r* E" H5 C8 n( p- A
这节课讲了中断。可能很多人和我一样不理解什么是中断。其实这个概念说起来很好理解,就是简单的停下来。可是又有什么用处?在系统设计中又处于什么样的一个地位呢?- S+ B# l3 o$ e; G8 V0 A" I1 z2 B
这里引荐博文(不知道不翻墙能不能看)中断解析; W; l7 Y! O c# G7 `
这里先综合百度维基百科中的,加上我的理解,说说什么是中断。中断简单的来理解就是一种技术,这种技术可以显著提高计算机的工作效率。因此有比较重要的作用。这么重要,那么到底什么是中断???这里不用教科书中的定义(中断指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这个新的情况的过程就叫做中断。)。简单的打一个比方。假设我正在敲的博文是我正在执行的系统。那么我点击Ctrl + S就可以理解为一个中断。因为CSDN官方不可能随时每隔1us给我保存一次我的数据,而我的保存指令可以理解为一个中断,这个时候,系统就会将我的数据上传至服务器。而在我写博文没有点击保存的时间,服务器就可猥琐欲为的去做任何事情。这就是所谓的中断。下图就是博文中的图,用以借鉴。中断回调函数可以就是异常处理,而回调函数就是我们CPU响应中断所执行的内容。用前面那个例子,就是保存我的博文至服务器,就是我的中断回调函数。3 L6 y0 g6 W; n* Z
" G$ S' Q7 N/ i, q
Q5 g" P( L# l1,中断详解与设计实现
' Y: W8 y/ l y. S软中断,由CPU0或者CPU1发起,可以相互中断。5 P) r1 k; z! b
GIC(Generic Interrupt Controller)通用中断控制器。通关软终端进行控制核间的中断,控制出发那个CPU。
: j: g* N! m$ ?
/ U% O9 I% H7 @# g- x下面是老师总结的一般处理过程
8 p- Q( T3 }/ s+ l7 B
4 B r' A4 D0 H4 g' R( a
中断回调函数是什么。由于外部请求触发的一个中断,而CPU中断的这段时间所做的事情,就是中断回调函数的执行的。中断也有其优先级,可以进行设置。; t* W6 M2 a9 a& x# X- e* v
8 ~6 V2 D4 E8 F2 q K% Y% {2 J
接下来就是代码分析首先定义一个初始化函数用于主函数调用。我们先看初始化函数8 q1 u8 Q, V7 C; H) B S
先看这个函数Xil_ExceptionInit();就是初始化,打开handler$ K) Q: G7 k- v7 ~( J
该函数是一个公共API,用于跨所有受支持的ARM处理器初始化异常处理程序。对于ARM Cortex-A53、Cortex-R5和Cortex-A9,异常处理程序正在被静态初始化,而这个函数什么也不做。但是,它仍然用于处理向后兼容性问题(在早期版本的bsp中,这个API用于初始化异常处理程序)。& ~; Q4 C z; T p1 ~
其次就和GPIO中的类似了。先得到期间地址,在初始化。
+ O& ]" F5 L, V) k5 m; m" y7 G. C" |- @; G: z
status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
4 V* T+ b- d6 c& @ if(status != XST_SUCCESS){
5 _; ^8 u7 r$ j/ a return status;. O3 c4 x1 p$ {5 \
}2 g& Y Z4 a8 `* j
9 W1 C9 P$ T6 J7 J0 h5 v
一般这种写法是由于返回值是一个状态,我们定义一个变量,用于判断返回值是否正确,用于调试程序。) I4 E1 | Q4 }% J2 T
接下来是Xil_ExceptionRegisterHandler。异常注册管理器。(Xil_ExceptionHandler)XScuGic_InterruptHandler这是一个强制类型转换,其中的函数是用于设置中段优先级的。这里没有用到,因为只有一个中断。这里就将信息传回到CPU了。接下来就是连接软中断回调函数。XScuGic_Connect就是我们的连接函数。& V) p# `7 y% R( v7 E) `8 a
) ?+ Y7 f1 W( o [# @; a# t3 y5 h+ ~3 o4 F4 B! Y
这是函数的说明。函数有返回值。我们使用同样的方式。方便调试。/ q. I2 A2 U. M5 C# t" h8 _2 ]
接下来使能软中断。(连接之后,需要使能才能使用)传递进去参数就是连接的。首先是实例化的XScuGic的指针其次是中断ID。) m7 l3 e6 W" y
最后是使能处理过程。! V; x, W$ x- W+ b7 H5 b
) Y; N* _6 T8 s% t
//initial gic & software intr
. g0 J2 r5 d* M% g+ v }8 i' @ int initSwIntr(){8 c6 y2 q; e T
int status;
% r" I h- j4 C8 A/ E) o: p( j Xil_ExceptionInit();//打开系统异常
! s, Q: w( s. ~4 f" H/ N4 `: \ ScuGicCfgPtr = XScuGic_LookupConfig(GIC_ID);/ m" V# y3 S8 F, f9 t7 C+ J7 T
status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);' L) @4 @5 x4 w9 A5 t3 |
if(status != XST_SUCCESS){
% h2 Z' |: Q4 ?6 W0 u return status;
& a# c! h8 _ } z }' X! G; _- D5 D- o( T! I. H, O
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
; s$ S v. j3 u status = XScuGic_Connect(&ScuGic,CPU0_SW_INTR,(Xil_ExceptionHandler)cpu0IntrHandler,&ScuGic);. Q% W5 Y, d2 D4 A$ ~+ s
if(status != XST_SUCCESS){( K0 A. s& W5 t9 t
return status;# a& N$ ?' O2 i; {2 b* k, n6 p
}
; M7 t. l; m8 ?/ V; f% D XScuGic_Enable(&ScuGic,CPU0_SW_INTR);: c* Q- [ Q# x2 w7 f( j
Xil_ExceptionEnable();) v6 s; Q* J2 m9 d
return XST_SUCCESS;
( b3 K: @, \4 B2 F; k j) w9 C# d }) ^% |$ t7 ^% N# G( ^2 o
" \( u5 v9 A; r0 B' p接下来对回调函数内容进行编写。、
* a/ G2 V5 F- u) j
% P2 Q% x. J' K+ V! y+ ]2 f* ? //callback function
T* j) p( d6 k) A! { void cpu0IntrHandler(void * Callbackref){4 W* `. v1 v- a- U+ a: X) ]
printf("cpu1 interrupt cpu0 success ! \n\r");7 d% f$ y: L+ y1 i
}
4 _7 x- [ G9 K$ c/ D A
4 z q* A' @; f9 [接下来就是主函数6 _# }; Y* @' `
主函数进行初始化中断。然后就可以使用中断了。
# h- ` m1 m( f+ ?. C7 }
P% b, E. c% B6 u6 z. ]int main()+ e9 ? Z) \+ Z* @) |/ G5 K* S6 K0 o
{
[4 F3 a1 J* f9 N COMM_VAL = 0;
* h" O8 v% F9 Z7 H8 \2 p m4 x Xil_SetTlbAttributes(0xffff0000,0x14de2);
+ N* s: y5 Q+ ?- ~5 Y& E* E int status;: R; S. ~) c3 o1 `1 j/ }3 r2 m" Y
status = initSwIntr();
/ I9 \' c% [6 y( k e if(status != XST_SUCCESS){1 p& D" P" @6 @9 e _, P
return status;
6 S& r4 p z. L% @: q( Z }
. ~! ?9 y7 u; o) l4 p8 \. A while(1) {/ g8 x5 ?/ A3 N5 I6 l
print("Hello CPU0\n\r");- ~+ D0 v, W' K
XScuGic_SoftwareIntr(&ScuGic,CPU1_SW_INTR,XSCUGIC_SPI_CPU1_MASK);
8 A9 w1 n, |, ]0 s5 A- ~ usleep(2000000);
+ Q% U3 a1 w+ I+ r+ g/ k COMM_VAL = 1;
$ D: r4 e0 _7 x! n/ [. M+ [ }0 O" { p/ i2 e
return 0;
3 `+ B% w9 q5 d$ Q}8 t- {4 _$ Y$ h; P) h' g
8 [4 ]3 b8 t/ h( s2 i
这里的中断使用方式就是调用这个函数。XScuGic_SoftwareIntr
1 e8 O! M* }1 A& x4 E( ?7 @" Y结构体指针,初始化ID,CPUID。3 R3 F$ t+ ^- g' ]# M; Y# G/ q
这里的中断只是发起,至于执行什么,完全是由中断函数决定的
1 Y* H* z/ E5 ?3 A) @* c/ b8 a% D) I y. o o/ Z
4 g- M' ~ T8 R" o5 t! t/ f: \4 F- l) x. r& {) }1 A
同样使用一样的代码。对CPU1进行中断的测试。7 ~1 X# x5 [& T6 K9 G0 Z
这里只有修改CPU1-CPU0即可。
4 b, n6 X6 c' }# |
" o6 V; s z! ?7 r6 y最后可以看到结果。两秒发送一次,使能中断成功!!!: X' g( \" @ i
/ @ k( B% I3 F/ q- o |
|