|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
. L- v7 X/ D$ S" F6 _7 J' Q. l
0,前言背景
& r, y0 }, y$ n9 m8 J9 w& D这节课讲了中断。可能很多人和我一样不理解什么是中断。其实这个概念说起来很好理解,就是简单的停下来。可是又有什么用处?在系统设计中又处于什么样的一个地位呢?
' D; q$ x# B7 y; {8 ?这里引荐博文(不知道不翻墙能不能看)中断解析) l0 T) w9 z, x- e3 K
这里先综合百度维基百科中的,加上我的理解,说说什么是中断。中断简单的来理解就是一种技术,这种技术可以显著提高计算机的工作效率。因此有比较重要的作用。这么重要,那么到底什么是中断???这里不用教科书中的定义(中断指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这个新的情况的过程就叫做中断。)。简单的打一个比方。假设我正在敲的博文是我正在执行的系统。那么我点击Ctrl + S就可以理解为一个中断。因为CSDN官方不可能随时每隔1us给我保存一次我的数据,而我的保存指令可以理解为一个中断,这个时候,系统就会将我的数据上传至服务器。而在我写博文没有点击保存的时间,服务器就可猥琐欲为的去做任何事情。这就是所谓的中断。下图就是博文中的图,用以借鉴。中断回调函数可以就是异常处理,而回调函数就是我们CPU响应中断所执行的内容。用前面那个例子,就是保存我的博文至服务器,就是我的中断回调函数。 p8 u9 y) J( a: r/ v
* b8 j% y- Y6 D
3 e' R# W$ [% z/ ^1,中断详解与设计实现% ]7 O9 a- s, c2 f2 C, B r
软中断,由CPU0或者CPU1发起,可以相互中断。
' b$ a( P5 h* Y# U$ d# s. ~GIC(Generic Interrupt Controller)通用中断控制器。通关软终端进行控制核间的中断,控制出发那个CPU。
7 C( U$ v8 C& R& [! M
/ U- i, j3 q0 K8 l下面是老师总结的一般处理过程: z. v+ b) H2 w9 }
% C* n5 h1 x/ X! p$ a
中断回调函数是什么。由于外部请求触发的一个中断,而CPU中断的这段时间所做的事情,就是中断回调函数的执行的。中断也有其优先级,可以进行设置。
9 B/ C; C& R" p( w& a
8 \6 g f" `5 n6 V接下来就是代码分析首先定义一个初始化函数用于主函数调用。我们先看初始化函数
/ K5 X: _# E, R. ^5 H; B先看这个函数Xil_ExceptionInit();就是初始化,打开handler
. f/ `2 p$ P# e: d) f$ z: k+ f( J该函数是一个公共API,用于跨所有受支持的ARM处理器初始化异常处理程序。对于ARM Cortex-A53、Cortex-R5和Cortex-A9,异常处理程序正在被静态初始化,而这个函数什么也不做。但是,它仍然用于处理向后兼容性问题(在早期版本的bsp中,这个API用于初始化异常处理程序)。2 z6 Y! R, g! Y- Z5 y
其次就和GPIO中的类似了。先得到期间地址,在初始化。
5 ?& ]) W# D5 j, Z6 k. B2 J
! m4 G u2 m/ n. n* v- L status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);* \3 T) \. D9 C5 P9 F5 H' t5 a
if(status != XST_SUCCESS){! i4 f" ]/ B B0 w; i& F$ _3 h
return status;6 Q& S; ~& d c b. z4 d
}6 g9 w( g& Z$ K! L4 ]& F' h
# V/ f8 N, Q- B& ?
一般这种写法是由于返回值是一个状态,我们定义一个变量,用于判断返回值是否正确,用于调试程序。
) n: Y7 ~# T5 P! a接下来是Xil_ExceptionRegisterHandler。异常注册管理器。(Xil_ExceptionHandler)XScuGic_InterruptHandler这是一个强制类型转换,其中的函数是用于设置中段优先级的。这里没有用到,因为只有一个中断。这里就将信息传回到CPU了。接下来就是连接软中断回调函数。XScuGic_Connect就是我们的连接函数。
+ ^" F6 I; x1 O" _
1 z0 S: @7 c- e7 S# S
5 D# M6 J9 m1 T- |3 D8 {( T& h) [ d
这是函数的说明。函数有返回值。我们使用同样的方式。方便调试。
! J( c6 W) F% {5 C1 S4 ~7 j接下来使能软中断。(连接之后,需要使能才能使用)传递进去参数就是连接的。首先是实例化的XScuGic的指针其次是中断ID。
9 N! r7 q% ^9 e* C* L! g最后是使能处理过程。
2 m3 L6 c8 W2 f
: d* m2 j) y& O8 O* u$ P //initial gic & software intr
, I( J2 C5 p* m+ B2 Q int initSwIntr(){# P ~# _% L1 r! j$ ^
int status;0 \3 r' t- n6 X: {* z. K8 ?' j
Xil_ExceptionInit();//打开系统异常
7 N! D( k7 N' y8 ~$ v) I9 J7 L ScuGicCfgPtr = XScuGic_LookupConfig(GIC_ID);& b: D% Q% f( q- B& r1 w
status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);3 z7 U! o/ M8 s
if(status != XST_SUCCESS){
Q5 }- w+ N8 P" x return status;2 H1 [3 o* \5 Y; j
}, h- V$ C1 h. E$ y& q1 A4 d6 r
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);' ?2 S; L6 U" g. v
status = XScuGic_Connect(&ScuGic,CPU0_SW_INTR,(Xil_ExceptionHandler)cpu0IntrHandler,&ScuGic);
! ~+ U, f; ]0 R- z7 x0 [ if(status != XST_SUCCESS){6 O* p' p* f2 T$ S0 m/ i
return status; v J) I3 e5 @6 m. G& h
}. j5 v7 `+ j9 \& Y! _
XScuGic_Enable(&ScuGic,CPU0_SW_INTR);
" c$ s5 ^8 P8 z' {4 [ Xil_ExceptionEnable();
, t( Q" k) g' O! }5 y! E4 }- ^ return XST_SUCCESS; Z1 @1 |/ E3 L! u+ x4 [
}% S' Z, U% f4 G
" K0 }: A& c6 d) b; n9 i
接下来对回调函数内容进行编写。、
- E! `* }6 `/ M7 ]0 [! N
" X& Y' N* N: [8 F3 M //callback function
4 k' I! O* ~3 O% U8 b void cpu0IntrHandler(void * Callbackref){ \4 X1 F' w- N" `8 o) W9 R
printf("cpu1 interrupt cpu0 success ! \n\r");/ N) @, k) Q! o( g6 C$ A
}
9 F7 A% v% j% w% G
7 F/ L) ]+ r# l1 ?2 b M7 y3 k5 y接下来就是主函数
, v( f" g0 C4 R3 B5 G5 m7 R# h* ^5 R主函数进行初始化中断。然后就可以使用中断了。
$ `, E: y+ q2 i; C2 f
& ~8 G8 @. _7 n7 _4 n+ o) Q- aint main()8 L( w9 [! a; g' G1 K6 O( e5 M
{ O' F0 U2 J0 F
COMM_VAL = 0;
& L. f$ P6 f: F1 g% f( d8 B Xil_SetTlbAttributes(0xffff0000,0x14de2);7 R& P% c1 U+ o* w
int status;7 c3 H8 ] b t; t
status = initSwIntr();3 n- Q* d' D, `5 ]
if(status != XST_SUCCESS){
0 H/ d( o3 U" q return status;
; O" E5 t5 O& W1 }" { }
4 }* c+ l7 _2 A# V7 ~5 `# Y% f while(1) {
, I. B: p8 K! ~& V. s/ K4 i print("Hello CPU0\n\r");( n1 D! T6 T3 i {, o: w
XScuGic_SoftwareIntr(&ScuGic,CPU1_SW_INTR,XSCUGIC_SPI_CPU1_MASK);
* w& l4 ?' D# D, P; T& q; V! W usleep(2000000);
* E' ^" T# O* |4 Z3 I) u+ s COMM_VAL = 1; ? \* [: ]# z1 c+ _
}: M( Z. Y/ S7 Z( |# Q3 G7 K2 t
return 0;
; q+ K) F/ b# f}
+ p) R/ Z- z" P! E, l5 P$ G- R- J2 u f$ M+ K0 E
这里的中断使用方式就是调用这个函数。XScuGic_SoftwareIntr. f$ J0 g4 \$ i c+ M( B3 g# e. A
结构体指针,初始化ID,CPUID。$ \: d- U$ ?* {: Z+ n9 O
这里的中断只是发起,至于执行什么,完全是由中断函数决定的
" g4 E j, h& ^" a9 n/ C2 h- W& _; A( N8 y) y
' ~2 e5 C4 _" ], A
& e6 P! d9 z# e+ r2 x5 x; w+ n
同样使用一样的代码。对CPU1进行中断的测试。- t9 ~ [- w+ u4 A( a3 W
这里只有修改CPU1-CPU0即可。* s% v; L- m; w
3 _( Z( v4 s; r* Q& z最后可以看到结果。两秒发送一次,使能中断成功!!!
% A# @1 K$ K, F. m
/ B) C' ~8 s0 o H6 ~6 p
|
|