DSP(TMS320C6713)入门之旅三、中断的理解和使用.doc
《DSP(TMS320C6713)入门之旅三、中断的理解和使用.doc》由会员分享,可在线阅读,更多相关《DSP(TMS320C6713)入门之旅三、中断的理解和使用.doc(7页珍藏版)》请在冰豆网上搜索。
学习一个芯片的功能时,我的建议是先学会如何用C语言点亮一个LED灯,然后就是学习一下使用他的中断,因为在做芯片的时候,各个厂家有自己的一套自己的方法。
所以使用中断的就必须了解很多概念,比如如何打开中断,如何安装自己的中断子服务程序,等等!
先介绍一下什么叫中断:
你在下象棋,突然电话响了,你回屋接电话,然后回来继续下象棋,这个过程就叫做中断响应过程(中断过程)。
CPU执行正常任务———————下象棋
保护现场———————————-你已经想好要“将军”,先在脑海中记下来。
中断发生———————————-电话响-
中断服务程序—————————-接电话
恢复现场———————————-回来后恢复刚才想法
中断返回———————————-你回来继续下象棋
中断屏蔽———————————-Boss正在训话,要求所有电话关机,你不能接电话了。
非屏蔽中断——————————-你内急,即使是Boss在训话,你还是得到外面去嘘嘘。
可屏蔽中断——————————-你在“闭关修炼”,可以不受外界干扰
所以我们在使用中断之前先得告诉CPU,我们要使用那个中断,当中断发生的时候,你的执行程序的去向(也就是中断服务子程序),最后在返回我们被中断的函数。
这样就完成了我们的中断历程!
看看6713执行中断的流程:
一、使能了全局中断和子中断,那么CPU每执行一条指令之前就去查询一下有没有中断被置位,如果有产生的,那么CPU就要跳转!
二、软件把CPU内部的寄存器A0~A15,B0~B15,等等这些寄存器的值推入堆栈保存,把当前PC寄存器的值放入IRP寄存器中以备中断返回能找到当前被打断的位置(保存现场,中断函数前面得加interrupt关键字)
三、CPU的PC指针读出中断向量表的地址,也就是把(ISTP寄存器的值+子中断向量偏移量)装入PC寄存器,这样就执行跳转。
四、在中断向量表里一般有就用跳转指令,这样就可以跳转到我们用C语言编写的中断服务子程序中。
由于我们在一般的中断服务子程序函数前面加入了interrupt关键字。
那么编译器就会在函数返回的语句改成BIRP,这样就把IRP的值送给PC寄存器。
(中断服务)
五、CPU在执行跳转之前会把堆栈中以前保存的那些值出栈到自己的相应的寄存器中。
(恢复现场)
OK,明白了中断执行的一个大概流程,我们就来看看6713或者说是C6000系列的中断如何安装和使用(以上一章的timer1中断为实例)。
由于本来6713有32个中断源,也就是中断CPU的信号可以来自这个32信号源。
但是DSP却安排了在同一时刻置最多服务16个中断号,但是有一个reset,nmi和2个保留的,这些我们不能使用其他的中断源占用,所以我们外设能占用的中断号为4~15。
那么怎么办呢,TI在次想了一个办法,就是使用多路选择开关来决定哪个中断源连接到我们的某一中断号上。
MUXL和MUXH两个寄存器,就是这个选择开关!
由于我们使用的是Timer1中断,从图中可以看出15号中断号默认为Timer1的中断服务号,但是我这儿想用14号来服务我们的中断,这样以后大家想用其他的就依样画葫芦了。
那么我这儿就得把MUXH[26:
21]=0×02;这样就把14号中断和我们的timer1中断源接上了。
当定时器到时时就CPU就会跳转到中断向量表的14号向量那儿。
接下来我就来安装和使用定时器中断吧。
1、安装中断向量表,一般用汇编编写:
取名为vector.asm
*——————————————————————————
*Globalsymbolsdefinedhereandexportedoutofthisfile
*——————————————————————————
.global_vectors//全局标号,可以在别处使用.
.global_c_int00
.global_vector1
.global_vector2
.global_vector3
.global_vector4
.global_vector5
.global_vector6
.global_vector7
.global_vector8
.global_vector9
.global_vector10
.global_vector11
.global_vector12
.global_vector13
.global_TimerHandler ;Hookupthe TimerHandler ISRinmain()汇编中的C语言函数要加“_”
.global_vector15
*——————————————————————————
*Globalsymbolsreferencedinthisfilebutdefinedsomewhereelse.
*Rememberthatyourinterruptserviceroutinesneedtobereferencedhere.
*——————————————————————————
.ref_c_int00//相当于extern,在这里引用,在别处定义
*——————————————————————————
*Thisisamacrothatinstantiatesoneentryintheinterruptservicetable.
*——————————————————————————
VEC_ENTRY.macroaddr//定义中断向量入口地址
STW B0,*–B15 ;保存B0内容,中断产生后执行的第一条指令
MVKL addr,B0;
MVKH addr,B0 ;把地址装入B0
B B0 ;跳转至B0中存储的地址
LDW *B15++,B0 ;恢复B0内容;由于C6000流水线的原因,跳转后仍然可以执行多条指令
NOP 2
NOP
NOP
.endm
*——————————————————————————
*ThisisadummyinterruptserviceroutineusedtoinitializetheIST.
*——————————————————————————
_vec_dummy:
未定义中断服务程序
B B3;其他没有定义的中断跳转至B3存储的地址
NOP 5
*——————————————————————————
*Thisistheactualinterruptservicetable(IST).Itisproperlyalignedand
*islocatedinthesubsection.text:
vecs.Thismeansifyoudon’texplicitly
*specifythissectioninyourlinkercommandfile,itwilldefaultandlink
*intothe.textsection.RemembertosettheISTPregistertopointtothis
*table.
*——————————————————————————
.sect“.text:
vecs”;定义段
.align1024;1024字节对边界对齐
_vectors:
_vector0:
VEC_ENTRY_c_int00 ;RESET 跳转到_c_int00,_c_int00是c语言程序的入口
_vector1:
VEC_ENTRY_vec_dummy ;NMI
_vector2:
VEC_ENTRY_vec_dummy ;RSVD
_vector3:
VEC_ENTRY_vec_dummy; 所有未定义中断均跳转到同一地址
_vector4:
VEC_ENTRY_vec_dummy
_vector5:
VEC_ENTRY_vec_dummy
_vector6:
VEC_ENTRY_vec_dummy
_vector7:
VEC_ENTRY_vec_dummy
_vector8:
VEC_ENTRY_vec_dummy
_vector9:
VEC_ENTRY_vec_dummy
_vector10:
VEC_ENTRY_vec_dummy
_vector11:
VEC_ENTRY_vec_dummy
_vector12:
VEC_ENTRY_vec_dummy
_vector13:
VEC_ENTRY_vec_dummy
_vector14:
VEC_ENTRY_TimerHandler ;HookuptheTimerHandler ISRinmain() 定时中断中断向量
_vector15:
VEC_ENTRY_vec_dummy
2、初始化中断:
先关闭全局中断(即使有新中断也不相应),然后在清除所有中断号的中断标志位,把timer1中断映射到14号中断,设置14号中断为使能,安装中断向量表,最后打开全局中断。
TimerEventId=TIMER_getEventId(Htimer); //取得定时事件ID 返回为0×02
IRQ_setVecs(vectors); //重新设置中断向量 ISTP= (unsignedint)vectors
IRQ_globalEnable(); //全局中断使能 IER|=1<<14
IRQ_nmiEnable();
IRQ_map(TimerEventId,14); //把定时中断重新映射到14 MUXH[25:
21]=0×02
IRQ_reset(TimerEventId); /
IRQ_ena