|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
0 g- F" D& P, ~0 Q* M v0,前言背景
% ]+ K1 q+ t) Q. ^这节课讲了中断。可能很多人和我一样不理解什么是中断。其实这个概念说起来很好理解,就是简单的停下来。可是又有什么用处?在系统设计中又处于什么样的一个地位呢?
2 a& Z5 I! t% r; i7 T; S这里引荐博文(不知道不翻墙能不能看)中断解析
% M4 \8 Z/ `, b3 b/ ~0 H- q( C这里先综合百度维基百科中的,加上我的理解,说说什么是中断。中断简单的来理解就是一种技术,这种技术可以显著提高计算机的工作效率。因此有比较重要的作用。这么重要,那么到底什么是中断???这里不用教科书中的定义(中断指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这个新的情况的过程就叫做中断。)。简单的打一个比方。假设我正在敲的博文是我正在执行的系统。那么我点击Ctrl + S就可以理解为一个中断。因为CSDN官方不可能随时每隔1us给我保存一次我的数据,而我的保存指令可以理解为一个中断,这个时候,系统就会将我的数据上传至服务器。而在我写博文没有点击保存的时间,服务器就可猥琐欲为的去做任何事情。这就是所谓的中断。下图就是博文中的图,用以借鉴。中断回调函数可以就是异常处理,而回调函数就是我们CPU响应中断所执行的内容。用前面那个例子,就是保存我的博文至服务器,就是我的中断回调函数。
! g: q8 w! m# r
* P- l$ C3 ?+ ?* F
) y3 D" r" i" e5 q! _ v
1,中断详解与设计实现
: y8 j3 T9 q6 r+ U软中断,由CPU0或者CPU1发起,可以相互中断。0 y; W4 C7 }$ L% L
GIC(Generic Interrupt Controller)通用中断控制器。通关软终端进行控制核间的中断,控制出发那个CPU。
) }# ~! X) z9 B5 A- F; y
9 r o! r/ c. H4 [
下面是老师总结的一般处理过程
2 f; A4 q) p! h& S' z3 S2 t
4 ~+ P; _3 f% C& `; j
中断回调函数是什么。由于外部请求触发的一个中断,而CPU中断的这段时间所做的事情,就是中断回调函数的执行的。中断也有其优先级,可以进行设置。
2 i' t/ N1 u, D: I7 P4 [7 C
) L9 m" d, P/ h- L8 y2 W/ N接下来就是代码分析首先定义一个初始化函数用于主函数调用。我们先看初始化函数
' [* c7 [) Z, H先看这个函数Xil_ExceptionInit();就是初始化,打开handler
5 j: X- ~& {( ~/ B4 L% @) e该函数是一个公共API,用于跨所有受支持的ARM处理器初始化异常处理程序。对于ARM Cortex-A53、Cortex-R5和Cortex-A9,异常处理程序正在被静态初始化,而这个函数什么也不做。但是,它仍然用于处理向后兼容性问题(在早期版本的bsp中,这个API用于初始化异常处理程序)。( F* r- e1 {0 o! I6 f
其次就和GPIO中的类似了。先得到期间地址,在初始化。
- w0 h$ a1 P& q, g% i+ F( @, f d- l) H3 G6 C5 i
status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);7 Q3 G* y+ R0 h* Q; s6 W
if(status != XST_SUCCESS){
7 W6 v4 E K4 h- J; E4 V7 J6 o2 F return status;
4 j, Z! `3 T: _% E3 [ }
3 E7 e! F6 l& {+ ]8 P3 }5 z& s' o4 x* k1 P2 G( ^; o- @% l
一般这种写法是由于返回值是一个状态,我们定义一个变量,用于判断返回值是否正确,用于调试程序。
& m' ?. a3 F1 k t. N: I1 I( f接下来是Xil_ExceptionRegisterHandler。异常注册管理器。(Xil_ExceptionHandler)XScuGic_InterruptHandler这是一个强制类型转换,其中的函数是用于设置中段优先级的。这里没有用到,因为只有一个中断。这里就将信息传回到CPU了。接下来就是连接软中断回调函数。XScuGic_Connect就是我们的连接函数。
; d# n# v2 `4 ~. g. d" x m
, l1 k v7 [" d- h* z, F
+ j8 q9 z& R& m$ k9 I这是函数的说明。函数有返回值。我们使用同样的方式。方便调试。: {+ O: m9 N0 f3 u1 f- k3 }, M
接下来使能软中断。(连接之后,需要使能才能使用)传递进去参数就是连接的。首先是实例化的XScuGic的指针其次是中断ID。; |- K, o7 T4 h
最后是使能处理过程。
3 i% ?0 n8 j. g& t
6 }4 Z6 J8 _9 M1 |$ s //initial gic & software intr
1 Y' ?7 p: S/ s+ w, J" P+ @4 j int initSwIntr(){# S R7 N& [* A1 U1 e3 ~; M5 @( w
int status;
f% v6 M) n% b0 ]/ t2 v Xil_ExceptionInit();//打开系统异常
. T+ J, j1 A2 t' q& a5 h ScuGicCfgPtr = XScuGic_LookupConfig(GIC_ID);
7 Y$ C" y; u! I4 q6 B, o4 a! ? status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
1 I; k3 k2 _4 E! R if(status != XST_SUCCESS){3 H# G6 J% [2 ^8 J J% L- w' f
return status;
3 N& u" y5 p% `6 v V! y6 H, L }
4 B( I# D. _: n* Z. @6 F8 K) _/ u Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);' D3 e1 g! U" P5 q6 i: O, `
status = XScuGic_Connect(&ScuGic,CPU0_SW_INTR,(Xil_ExceptionHandler)cpu0IntrHandler,&ScuGic);& W! d+ Y% i" }: r/ ]# y/ X
if(status != XST_SUCCESS){, J1 Z8 g1 F! e* x; R
return status;
3 Y. z" G, o6 i! X0 R$ f }% W7 _7 ^# y* n- a. K" T; z6 r
XScuGic_Enable(&ScuGic,CPU0_SW_INTR);
9 p4 e% h' o' Z m: Q# z- s Z Xil_ExceptionEnable();8 s/ Y6 H1 H5 ]+ g
return XST_SUCCESS;! V6 c; p8 G' M" _
}- Z c. K! M, E, T- Z ~& @
; s( S- }! c/ s. C接下来对回调函数内容进行编写。、
8 C, U: J! s# T, ]% L6 p. G. \1 k5 s( G0 b5 c
, K2 u n7 T0 S l' E //callback function
) X2 ?/ f3 q2 S' ~3 Y. l5 A void cpu0IntrHandler(void * Callbackref){
" I: Z7 g( _# X! v* Z+ o1 C1 K. ] printf("cpu1 interrupt cpu0 success ! \n\r");
" R! ~- p0 A4 J0 u2 { }: t+ c! ~' A' \. H1 e. P
: e1 c( v; X. X" ~' n. e8 _
接下来就是主函数8 N3 Z1 i. R' y# t
主函数进行初始化中断。然后就可以使用中断了。
6 p0 d5 L/ ]7 h; K6 C/ c( k9 I6 V4 p4 A: b, j. }% _
int main(). t2 l' p& A+ v8 k4 g& c
{
* a* ~ L, R5 o- E COMM_VAL = 0;
: N" j: m* s) ?. w/ H% E Xil_SetTlbAttributes(0xffff0000,0x14de2);
$ q7 J( R( o: u* U* l) w int status;0 @- z& _) I+ |. [) d8 N
status = initSwIntr();
/ V4 p% I% \* z s4 R) M- a if(status != XST_SUCCESS){
$ S' J) {6 U' n return status;, O' K4 L$ H. H! E9 ^
}
( x! T/ k0 A& h# _9 j while(1) {. Y3 o2 _2 f/ X/ l$ a) n( Z
print("Hello CPU0\n\r");, e0 C; ] [9 J7 @: H9 ~) U2 i
XScuGic_SoftwareIntr(&ScuGic,CPU1_SW_INTR,XSCUGIC_SPI_CPU1_MASK);
; I0 R: M. e$ S# G7 F usleep(2000000);
" N3 q( k2 b5 R1 c COMM_VAL = 1;
f0 Q! [" P1 |% E" N! x }* f r. X8 W% o0 i8 x* |$ K
return 0;
# f# ~: Q1 g. V+ `}0 p2 N% ^ s9 ^% Y. m( B0 e! r
5 @0 @4 Y# W) F- h这里的中断使用方式就是调用这个函数。XScuGic_SoftwareIntr
7 W* b3 _/ t# y% M6 [/ Q" h" Y结构体指针,初始化ID,CPUID。6 ~5 w R/ @: z; C+ u5 I( T& |
这里的中断只是发起,至于执行什么,完全是由中断函数决定的
- `9 ]; |9 A ?/ I% j
& ^! m- a; P! V4 c
+ T2 z: p0 q P
" O$ u; s# B0 s; U7 E& O) T7 v4 t( j同样使用一样的代码。对CPU1进行中断的测试。- h# o8 w( S7 S( |1 _) U9 d
这里只有修改CPU1-CPU0即可。. }0 W% @8 I" ~* C
, o& j: j" B! X/ l* W$ x最后可以看到结果。两秒发送一次,使能中断成功!!!
! K2 i! D- |2 m7 `
2 ]& Y+ b3 ]* p. t% w; I3 _
|
|