|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
8 K; X1 T$ N9 R! V3 ]( l7 h6 l" m6 j
0,前言背景
+ M* a: j0 B/ N1 _* K这节课讲了中断。可能很多人和我一样不理解什么是中断。其实这个概念说起来很好理解,就是简单的停下来。可是又有什么用处?在系统设计中又处于什么样的一个地位呢?1 z+ ]. P% U4 t8 ?; \
这里引荐博文(不知道不翻墙能不能看)中断解析2 X1 m" h& v" A% e; X0 J* h! a1 Q
这里先综合百度维基百科中的,加上我的理解,说说什么是中断。中断简单的来理解就是一种技术,这种技术可以显著提高计算机的工作效率。因此有比较重要的作用。这么重要,那么到底什么是中断???这里不用教科书中的定义(中断指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这个新的情况的过程就叫做中断。)。简单的打一个比方。假设我正在敲的博文是我正在执行的系统。那么我点击Ctrl + S就可以理解为一个中断。因为CSDN官方不可能随时每隔1us给我保存一次我的数据,而我的保存指令可以理解为一个中断,这个时候,系统就会将我的数据上传至服务器。而在我写博文没有点击保存的时间,服务器就可猥琐欲为的去做任何事情。这就是所谓的中断。下图就是博文中的图,用以借鉴。中断回调函数可以就是异常处理,而回调函数就是我们CPU响应中断所执行的内容。用前面那个例子,就是保存我的博文至服务器,就是我的中断回调函数。. \% e L" s6 n) P; B; r
% T( |% J( x6 I. f
3 Q/ @% k; L2 M1 T6 Y1,中断详解与设计实现
3 i& A9 D1 @* a软中断,由CPU0或者CPU1发起,可以相互中断。& s$ Y b; [3 K
GIC(Generic Interrupt Controller)通用中断控制器。通关软终端进行控制核间的中断,控制出发那个CPU。1 T- j5 I, l- t4 D
1 O( k H3 g! P: S" W下面是老师总结的一般处理过程
! j0 O/ f; a% b1 d8 i3 Z
( @6 d6 \# g( D x K
中断回调函数是什么。由于外部请求触发的一个中断,而CPU中断的这段时间所做的事情,就是中断回调函数的执行的。中断也有其优先级,可以进行设置。
' {( W4 E) M1 L5 Z) L7 w3 o. `7 ]3 K) a3 V/ J
接下来就是代码分析首先定义一个初始化函数用于主函数调用。我们先看初始化函数
7 ` }; U$ o( J4 E先看这个函数Xil_ExceptionInit();就是初始化,打开handler
$ B; U& l% U, b( f) _1 k该函数是一个公共API,用于跨所有受支持的ARM处理器初始化异常处理程序。对于ARM Cortex-A53、Cortex-R5和Cortex-A9,异常处理程序正在被静态初始化,而这个函数什么也不做。但是,它仍然用于处理向后兼容性问题(在早期版本的bsp中,这个API用于初始化异常处理程序)。
, J% k" B) | {' i( L+ [+ b其次就和GPIO中的类似了。先得到期间地址,在初始化。: ]7 ]. H0 {! L1 f$ h' U* H& Q$ b, Z
9 I5 G: q. m8 T4 H, t status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);6 C& r y. J$ c+ q% q6 Q6 Z
if(status != XST_SUCCESS){
p/ o& _/ |3 c4 d) } return status;* H- y( @$ | B
}
1 k: {- C, ?+ v x' x* d) l# I
: V+ p6 \- `0 i+ S一般这种写法是由于返回值是一个状态,我们定义一个变量,用于判断返回值是否正确,用于调试程序。
# `$ q7 x3 U, B$ R. Z接下来是Xil_ExceptionRegisterHandler。异常注册管理器。(Xil_ExceptionHandler)XScuGic_InterruptHandler这是一个强制类型转换,其中的函数是用于设置中段优先级的。这里没有用到,因为只有一个中断。这里就将信息传回到CPU了。接下来就是连接软中断回调函数。XScuGic_Connect就是我们的连接函数。" E3 w( N4 S( N6 I5 d
7 |& O( V: [ F
[ W+ Y4 @9 S# n这是函数的说明。函数有返回值。我们使用同样的方式。方便调试。! G! @) d/ Q# W5 Z$ R7 Y- }- S
接下来使能软中断。(连接之后,需要使能才能使用)传递进去参数就是连接的。首先是实例化的XScuGic的指针其次是中断ID。+ {" W+ y2 b% S# O
最后是使能处理过程。
$ F% s* U& U' v; u4 J) i/ V
$ K$ [8 O- i% U& @ //initial gic & software intr
- ~; ~- h/ C1 h+ m int initSwIntr(){
; j5 r% ]" e4 y( ]; y* s+ _" T0 ?" b int status;
7 A9 c& ]0 I; N# Q+ C Xil_ExceptionInit();//打开系统异常. D; {0 S6 w" {2 ]7 a
ScuGicCfgPtr = XScuGic_LookupConfig(GIC_ID);
, s5 h, x* t, J- x* ~5 e7 j6 B status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
- K' B) K1 s- s" r$ m7 s if(status != XST_SUCCESS){
: @3 v( J1 w8 W0 L return status;
- A e7 R$ E" e1 q }
5 r2 p/ X; ~* N5 u1 ~& z Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);6 P: F8 `5 H. ?$ M. O6 j
status = XScuGic_Connect(&ScuGic,CPU0_SW_INTR,(Xil_ExceptionHandler)cpu0IntrHandler,&ScuGic);! S( z! L5 }6 B+ U3 f9 d' T5 g
if(status != XST_SUCCESS){
' _1 }9 W* c- z8 A return status;9 J, B7 m) b3 v
}
. E1 F2 X0 p& |$ W/ e XScuGic_Enable(&ScuGic,CPU0_SW_INTR);) ^0 h* C& E5 b( }2 @
Xil_ExceptionEnable(); N( ]$ n' n$ Z7 N$ Z0 }, K; ]8 V
return XST_SUCCESS;+ j( i# |6 u$ Z8 t0 S
}, S* x. o: J, h7 f
h6 X# A7 r7 H# l, K) R
接下来对回调函数内容进行编写。、$ Y! H1 v1 N! X4 J1 @6 ~
) e& ^$ i2 E, G, {; T# [
//callback function
0 r1 u- E# C; t void cpu0IntrHandler(void * Callbackref){' h; N! z3 p* e/ r
printf("cpu1 interrupt cpu0 success ! \n\r");1 e8 ~0 o' Y- a
}
* v$ R g+ y q9 b7 l: c) `* S& G2 c' x1 M% q2 X$ {& f
接下来就是主函数, C3 Q$ d# L( r/ y
主函数进行初始化中断。然后就可以使用中断了。
% ^3 Z% a- j8 a: C5 d$ ^+ ~
. T2 ], \+ N6 E9 \int main()
. g! E8 x( G% j* u{% p* ?* B/ {) J
COMM_VAL = 0;
( }1 Q* g3 t9 U1 P7 m Xil_SetTlbAttributes(0xffff0000,0x14de2);
8 p+ a2 t# ?' s$ o, d! N int status;4 `5 ?+ F1 O. `) R8 E0 }
status = initSwIntr();2 f' D$ |. i; f. b7 n8 z" m! [
if(status != XST_SUCCESS){
; N* ?0 S; D# q* l) \" M- v return status;, e0 L8 ]) U. h9 a. ?
}+ S$ `% x5 Q; ]# _% a5 N
while(1) {7 C8 N! b- }" ~! p0 o5 t
print("Hello CPU0\n\r");
! C. a( g$ D1 I! _/ f1 [& K XScuGic_SoftwareIntr(&ScuGic,CPU1_SW_INTR,XSCUGIC_SPI_CPU1_MASK);
- ~8 h+ s; H+ O2 @7 L! @4 F! e4 n" L- @ usleep(2000000);
0 ^/ H% L5 ~' J COMM_VAL = 1;! K2 V" Q8 C W+ c6 f4 f8 e
}
: [+ p0 z4 p1 { return 0;5 f4 }+ {6 [" Y
} ?9 Q$ }8 e* p2 a- L
8 q9 o4 P7 @# s' x% o
这里的中断使用方式就是调用这个函数。XScuGic_SoftwareIntr4 i" c N5 i* m2 h
结构体指针,初始化ID,CPUID。, Z- u, x% G& `) X+ {+ ~ I8 m
这里的中断只是发起,至于执行什么,完全是由中断函数决定的8 e0 ~, N: l6 w* b
; `3 p5 E! L% h: {& T( S) r, ^# M
+ T8 R' t8 d' [& r, K# J- D
3 l" T4 Q5 B* u( P, R7 B+ F W同样使用一样的代码。对CPU1进行中断的测试。
5 f0 J8 e- @' s: h这里只有修改CPU1-CPU0即可。
5 g& L" |' d) }3 X( [) S5 j
- W- W! l& Q5 E. F5 u/ _7 F最后可以看到结果。两秒发送一次,使能中断成功!!!! M# F% ^: h* w. h# b
- C$ a8 N- o7 l$ _) O. @+ o |
|