|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
2 f/ m: T- n* g( ~# m# N: a0,前言背景$ R" l# E- ^& ~6 j6 D
这节课讲了中断。可能很多人和我一样不理解什么是中断。其实这个概念说起来很好理解,就是简单的停下来。可是又有什么用处?在系统设计中又处于什么样的一个地位呢?4 J+ \$ l, c" t4 M3 K
这里引荐博文(不知道不翻墙能不能看)中断解析1 n5 o f5 x/ {( c4 t, @4 Y3 [
这里先综合百度维基百科中的,加上我的理解,说说什么是中断。中断简单的来理解就是一种技术,这种技术可以显著提高计算机的工作效率。因此有比较重要的作用。这么重要,那么到底什么是中断???这里不用教科书中的定义(中断指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这个新的情况的过程就叫做中断。)。简单的打一个比方。假设我正在敲的博文是我正在执行的系统。那么我点击Ctrl + S就可以理解为一个中断。因为CSDN官方不可能随时每隔1us给我保存一次我的数据,而我的保存指令可以理解为一个中断,这个时候,系统就会将我的数据上传至服务器。而在我写博文没有点击保存的时间,服务器就可猥琐欲为的去做任何事情。这就是所谓的中断。下图就是博文中的图,用以借鉴。中断回调函数可以就是异常处理,而回调函数就是我们CPU响应中断所执行的内容。用前面那个例子,就是保存我的博文至服务器,就是我的中断回调函数。
1 a; @3 w( i1 P! g
0 f- Q( D1 r6 W4 q1 {
$ n r9 D4 s3 v$ {: L: b6 M
1,中断详解与设计实现
9 A8 q& [# ^2 q0 v软中断,由CPU0或者CPU1发起,可以相互中断。
' w6 s0 Y6 r( t. n8 `7 L, V# ?GIC(Generic Interrupt Controller)通用中断控制器。通关软终端进行控制核间的中断,控制出发那个CPU。( }: S6 D. H4 M1 }9 {
0 p# `0 W! G% e. _
下面是老师总结的一般处理过程
5 G9 v9 ^6 ] c4 w
/ [1 W" O0 v' u7 P% Q+ f
中断回调函数是什么。由于外部请求触发的一个中断,而CPU中断的这段时间所做的事情,就是中断回调函数的执行的。中断也有其优先级,可以进行设置。
5 P4 N5 D/ l# O+ F( R7 v6 Z* R) P+ _# o- [
接下来就是代码分析首先定义一个初始化函数用于主函数调用。我们先看初始化函数$ r" ~+ j) W9 `7 P/ ?. w# B! f9 G" _
先看这个函数Xil_ExceptionInit();就是初始化,打开handler
6 S. x) |# t2 x0 M0 Z: U, X$ G该函数是一个公共API,用于跨所有受支持的ARM处理器初始化异常处理程序。对于ARM Cortex-A53、Cortex-R5和Cortex-A9,异常处理程序正在被静态初始化,而这个函数什么也不做。但是,它仍然用于处理向后兼容性问题(在早期版本的bsp中,这个API用于初始化异常处理程序)。
8 V* x# T# r0 Z U1 ]其次就和GPIO中的类似了。先得到期间地址,在初始化。% C ~& _& a q" _% N* r! q
4 l: O8 q& j$ r% E* W
status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);9 W2 ~: ^+ ~6 J5 P% t, e1 O
if(status != XST_SUCCESS){6 Z0 p# `2 E! ^! @" K7 {
return status;
' q9 ]; y" ?0 U' D- v) J4 t } K, n. h1 d) `* I! A; H" r( l, F
/ B% h* A5 G& e
一般这种写法是由于返回值是一个状态,我们定义一个变量,用于判断返回值是否正确,用于调试程序。
; x+ G) G7 `* h5 k2 n" g. k接下来是Xil_ExceptionRegisterHandler。异常注册管理器。(Xil_ExceptionHandler)XScuGic_InterruptHandler这是一个强制类型转换,其中的函数是用于设置中段优先级的。这里没有用到,因为只有一个中断。这里就将信息传回到CPU了。接下来就是连接软中断回调函数。XScuGic_Connect就是我们的连接函数。3 T3 w& i2 Z" T$ M: z0 B/ p J
9 |0 l. |3 f0 A m& Q9 B1 k
& S+ s4 |0 m$ c& S+ ^) _这是函数的说明。函数有返回值。我们使用同样的方式。方便调试。
' i- _" b' R2 ?; D接下来使能软中断。(连接之后,需要使能才能使用)传递进去参数就是连接的。首先是实例化的XScuGic的指针其次是中断ID。
X2 R1 t& @ G9 y& x' t) h最后是使能处理过程。, Z: O9 d% v2 Z* @0 [. L
, p- M8 q* U/ `. ]. Z0 z //initial gic & software intr
1 E- u& [2 r+ d' |% | int initSwIntr(){
2 h% F" a* `) U int status;: s+ P8 s) p( d) W' f
Xil_ExceptionInit();//打开系统异常
0 s9 h0 F; f1 N) S8 Q; d- a1 O( A ScuGicCfgPtr = XScuGic_LookupConfig(GIC_ID);
& T4 ] }5 Z" C3 S+ {' M. ~ status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
. i; B: e; m9 U8 ]% A! V( n if(status != XST_SUCCESS){
1 c5 X1 O5 r0 _" Q y: R6 c return status;$ s ?- S9 L& [
}
9 v. p# w* r$ Z% ], Y$ x8 m Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);8 C9 M0 e( x9 f/ i \% ^) b, U
status = XScuGic_Connect(&ScuGic,CPU0_SW_INTR,(Xil_ExceptionHandler)cpu0IntrHandler,&ScuGic);
6 K$ t: l3 ]8 v# b3 Q" O } if(status != XST_SUCCESS){% j. X( Q' j- d! J0 j' J- Z
return status;
: n; M2 X1 I% F7 a7 B' s }
% H. ~9 G1 P r% v3 I XScuGic_Enable(&ScuGic,CPU0_SW_INTR);2 D* l! ~' k2 a. b% `7 H( B% P' R
Xil_ExceptionEnable();8 p* J1 f2 {. a3 s" w- U" }
return XST_SUCCESS;) E1 N' x3 x( D; o; I9 b
}
5 a) i+ @5 y7 N6 G1 S" v! j$ B$ W# p" e3 W4 r9 {4 Z4 G* J' C" s I
接下来对回调函数内容进行编写。、3 y# L; c" Y" c- Y
3 ]- ^9 x0 |! h. V9 d //callback function6 Q( H9 d$ O9 o- Y) R3 T; H
void cpu0IntrHandler(void * Callbackref){
) t/ {0 l$ w9 ~$ `. K v printf("cpu1 interrupt cpu0 success ! \n\r");) H" R. @7 b! S
}+ S) h) r; {& E g
, S5 b' v3 q- `
接下来就是主函数
; _2 W, ~* l5 k2 z' y* R, H主函数进行初始化中断。然后就可以使用中断了。- ^$ X% l D* _: l) _
0 m$ \* }- l% m& e% y: i' sint main()
+ c8 c8 G" C9 A' x9 q{- o9 m: ]; C( D* C: P$ v# g Z
COMM_VAL = 0;
5 K7 R0 h* p, D) n; y# ` Xil_SetTlbAttributes(0xffff0000,0x14de2);2 c0 V! E/ i0 f2 i
int status;
3 I( Q/ h9 X4 t, n2 z" u" z status = initSwIntr();
( Q9 b: K$ A' q! V' w4 Z C) ` if(status != XST_SUCCESS){2 s: y8 ] a$ e7 r9 x+ O
return status;
) w F( K- ^; T, R }5 G/ M! R: u; A) L
while(1) {: e4 s4 H* r* T' e
print("Hello CPU0\n\r");
: w2 i7 X# ?( `. e% \ XScuGic_SoftwareIntr(&ScuGic,CPU1_SW_INTR,XSCUGIC_SPI_CPU1_MASK);
. i# C$ k# k1 C% o usleep(2000000);
: k g: P/ d) ?' [. G, j' n0 Z COMM_VAL = 1;
) z, ^# A/ ?+ R k }! ~4 B: V, ^2 I7 w/ t
return 0;% s6 I- Z' |8 ? y) _' ^' Z
}
9 }& R8 A5 S! Z4 r1 N: Y7 Q
- X. B: `( R1 A' A) d' d4 I这里的中断使用方式就是调用这个函数。XScuGic_SoftwareIntr
( a( m% t* H$ s结构体指针,初始化ID,CPUID。
, i- N$ b, X" V$ T) V5 y, A8 f5 F' H这里的中断只是发起,至于执行什么,完全是由中断函数决定的
/ R) p* C. D7 y3 T$ q: D2 _& u2 t$ |# j
- M: D+ ^; F' i8 W! J: B
& _+ J$ u _' `/ T/ U同样使用一样的代码。对CPU1进行中断的测试。7 }6 X& I9 e! y* R0 }, P% j* ]% [
这里只有修改CPU1-CPU0即可。
" ?% y9 _5 n% [! {8 y( _* t- D# L x' T x8 S; t
最后可以看到结果。两秒发送一次,使能中断成功!!!
( i7 |2 V0 f1 l. r* y
$ h# n4 X# X! V
|
|