|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
1 `) i: I. `0 }6 u7 f. v/ K0,前言背景$ a0 B. A! @% U/ G* k3 o @
这节课讲了中断。可能很多人和我一样不理解什么是中断。其实这个概念说起来很好理解,就是简单的停下来。可是又有什么用处?在系统设计中又处于什么样的一个地位呢?' {2 L @+ C S+ L9 B
这里引荐博文(不知道不翻墙能不能看)中断解析% @! {& E; Y* K. I& I5 o4 @& i4 w
这里先综合百度维基百科中的,加上我的理解,说说什么是中断。中断简单的来理解就是一种技术,这种技术可以显著提高计算机的工作效率。因此有比较重要的作用。这么重要,那么到底什么是中断???这里不用教科书中的定义(中断指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这个新的情况的过程就叫做中断。)。简单的打一个比方。假设我正在敲的博文是我正在执行的系统。那么我点击Ctrl + S就可以理解为一个中断。因为CSDN官方不可能随时每隔1us给我保存一次我的数据,而我的保存指令可以理解为一个中断,这个时候,系统就会将我的数据上传至服务器。而在我写博文没有点击保存的时间,服务器就可猥琐欲为的去做任何事情。这就是所谓的中断。下图就是博文中的图,用以借鉴。中断回调函数可以就是异常处理,而回调函数就是我们CPU响应中断所执行的内容。用前面那个例子,就是保存我的博文至服务器,就是我的中断回调函数。
: p- T5 b7 X/ s2 X5 v
4 {" T0 g6 r$ F6 t+ K
6 P$ c1 y0 R" ^% [. r- M
1,中断详解与设计实现
! G( f! i4 H- G6 x, b7 B* x, p软中断,由CPU0或者CPU1发起,可以相互中断。
" s. ]: `5 c8 jGIC(Generic Interrupt Controller)通用中断控制器。通关软终端进行控制核间的中断,控制出发那个CPU。: }% D& u5 d G! }
9 e5 k, c' [( I1 t# g* G
下面是老师总结的一般处理过程
2 H' m( R( n+ e' m) B9 r( K/ Y
% C: T3 T" U3 F7 T- l0 C中断回调函数是什么。由于外部请求触发的一个中断,而CPU中断的这段时间所做的事情,就是中断回调函数的执行的。中断也有其优先级,可以进行设置。
0 E# I* {4 }$ o' c- _* y& F& g5 {7 W7 U) T* m# k, {
接下来就是代码分析首先定义一个初始化函数用于主函数调用。我们先看初始化函数. p6 M# X" k; a) F8 ]
先看这个函数Xil_ExceptionInit();就是初始化,打开handler" Z& T& A2 R4 u
该函数是一个公共API,用于跨所有受支持的ARM处理器初始化异常处理程序。对于ARM Cortex-A53、Cortex-R5和Cortex-A9,异常处理程序正在被静态初始化,而这个函数什么也不做。但是,它仍然用于处理向后兼容性问题(在早期版本的bsp中,这个API用于初始化异常处理程序)。
9 Z8 u# P0 y3 M: Q9 ]& _其次就和GPIO中的类似了。先得到期间地址,在初始化。
8 T6 R0 K x$ q, K* o
, _: J- b6 q) X( g% Q status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);# I# _3 [; C" e- f9 U0 x4 i
if(status != XST_SUCCESS){3 t- D; Y+ `& V4 E1 |0 f# G
return status;
6 z. r0 t! c% x( O }
$ a2 {7 a# |0 }* R) v0 }2 z) n7 c! o/ G# Z5 S7 I9 J J
一般这种写法是由于返回值是一个状态,我们定义一个变量,用于判断返回值是否正确,用于调试程序。* Z1 ^1 j2 w1 Z# I2 X; x
接下来是Xil_ExceptionRegisterHandler。异常注册管理器。(Xil_ExceptionHandler)XScuGic_InterruptHandler这是一个强制类型转换,其中的函数是用于设置中段优先级的。这里没有用到,因为只有一个中断。这里就将信息传回到CPU了。接下来就是连接软中断回调函数。XScuGic_Connect就是我们的连接函数。
( L! u: _2 u* z! S G, E8 ]2 }
/ ?7 P7 p( }0 D7 V/ T+ d
3 ?. u% v% a! j6 g4 @, [这是函数的说明。函数有返回值。我们使用同样的方式。方便调试。
2 p0 o* G- ]4 K$ [* ]2 t/ s$ G接下来使能软中断。(连接之后,需要使能才能使用)传递进去参数就是连接的。首先是实例化的XScuGic的指针其次是中断ID。
7 H# M' Z+ i# r( b2 j4 Q3 T最后是使能处理过程。
8 O( t" s2 e, Q/ B$ v
; `5 |5 E, e& C. k) z: }% @, \, b //initial gic & software intr
2 V h7 r5 y4 g) A o int initSwIntr(){
; J8 }) l) J: X0 |- N int status;
/ t$ g( {2 y! d$ C" ], n' O, W Xil_ExceptionInit();//打开系统异常8 v% [$ Q. G* H
ScuGicCfgPtr = XScuGic_LookupConfig(GIC_ID);
/ d; u1 x3 A7 [' F" @' m status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);$ x! l. n9 b- \: a) Y
if(status != XST_SUCCESS){
1 q5 ]0 h ~& P& C g6 J: o1 V return status;
: P7 M' c% S, n U1 L) w* y }# L' T) Y" X0 ]4 P& p# ?) ~
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);" J5 W1 D3 ~7 F
status = XScuGic_Connect(&ScuGic,CPU0_SW_INTR,(Xil_ExceptionHandler)cpu0IntrHandler,&ScuGic);
3 v- K9 E4 N$ h% B if(status != XST_SUCCESS){, j0 y# n; S7 |; p2 J2 B
return status;
, Z) w8 }& u ^1 f, ` }
2 [( t# w& N& E) B8 {& a XScuGic_Enable(&ScuGic,CPU0_SW_INTR);- @2 h3 U% t* A2 R, z
Xil_ExceptionEnable();2 m. x6 {* ^$ M- t' J3 F6 v# [
return XST_SUCCESS;1 Z' I) M I: Y' Z4 y
}
: D: g6 v1 H o2 K. e5 w0 r; `7 W* H& L2 k
接下来对回调函数内容进行编写。、: c5 T$ D% I1 z7 \( E% P
9 Z" w8 u" G! J //callback function# h g/ v2 _4 P5 A
void cpu0IntrHandler(void * Callbackref){
! e6 G. z- Z4 W- Z4 g5 K printf("cpu1 interrupt cpu0 success ! \n\r");
1 e' g0 B8 J6 S! w, I }( ?- P( O$ i7 S* w2 M5 A
. c4 S9 D I- N' A4 M- ^/ g: X
接下来就是主函数
^# c/ W" m$ x G) R主函数进行初始化中断。然后就可以使用中断了。2 O. p& p/ y/ [
0 I" O- Z' d1 c zint main()
6 }. o1 g* ], A6 Q3 L; R& S{, `7 u g: Q! R8 v4 v; O
COMM_VAL = 0;
8 |1 ~+ @' N4 _. n3 C' t4 S3 o' K Xil_SetTlbAttributes(0xffff0000,0x14de2);
! ^$ c9 G+ W: Y `' T int status;
- v" y! V1 m: t7 o! t status = initSwIntr();/ i& @1 _1 H$ q4 `: X
if(status != XST_SUCCESS){
& [3 ]+ E3 B* i return status;. D$ b/ `2 ^9 \8 E% c9 n
}& @! U0 X& u9 O& `4 r
while(1) {
/ W! q0 Y9 K! a0 h8 M' u$ R print("Hello CPU0\n\r");
0 K$ i" ?) s6 n2 \4 c. I# }. b XScuGic_SoftwareIntr(&ScuGic,CPU1_SW_INTR,XSCUGIC_SPI_CPU1_MASK);, m m: q" _4 k$ z0 D# t
usleep(2000000);8 U4 ^) ?3 ]0 Z' D
COMM_VAL = 1;
& d4 n/ {1 x' V8 Q }
+ B4 ?- k7 p+ h. \- p1 l. |/ \" U return 0;
' ?9 q" ~7 a( R5 X7 c- x}
& }3 j G' A8 q; v, D6 R/ ^8 c6 d2 g" E- Z H" z$ ?
这里的中断使用方式就是调用这个函数。XScuGic_SoftwareIntr$ @& W' C. E3 I3 m! Y+ `
结构体指针,初始化ID,CPUID。- N( t0 h: n9 ^- G6 C
这里的中断只是发起,至于执行什么,完全是由中断函数决定的
8 ^3 u& ?0 w- i( i3 D
: h2 y( L, y; M1 A% o
" v4 Q; A; H A5 ]2 b3 g- B/ ]
/ d/ m4 E' C6 ?. C0 J ^3 P# z% v同样使用一样的代码。对CPU1进行中断的测试。
: U! k: x, a w* E这里只有修改CPU1-CPU0即可。
0 z7 m' h" W# N4 A
& ~3 P; K3 J* |' s! q% E. K7 c! \& H最后可以看到结果。两秒发送一次,使能中断成功!!!
2 w- \2 @5 n/ ? ]9 C) @" D
. D- _" r- v( |4 u6 ]. @! ^! F
|
|