转自:http://hi.bccn.net/202661/viewspace-9733.html
这两个猜想是我在用程序模拟HWI时(利用几个IRQ_开头的函数,具体查看CCS的帮助文件),多次测试之后的一点想法,不保证正确,因为TI的帮助文档没去看(因为讨厌鸟语).
使用软件是CCS3.1,利用其DSP/BIOS系统,这个系统的确方便.
=======================================================
先介绍一下几个和中断有关的寄存器
硬件中断总开关,CSR(Control Status Register)寄存器中的第0位GIE(Global interrupt enable),1表示允许中断(相当于打开大门),0表示禁止中断(关上大门)
单个中断开关,IER(Interrupt Enable Register)寄存器,其低16位对应了16个中断的开关情况,相当于16个小门,1表示门开,0表示门关
只有这两个开关都打开的时候,中断才能起作用(这是对可屏蔽中断来说的,有些中断是不能被屏蔽的,这两个开关就都没用)
中断状态寄存器,IFR(Interrupt Flag Register),记录有哪些待响应的中断,低16位对应16个中断,如果为1说明这个中断需要被响应.0表示不需要.
中断返回地址,IRP(Interrupt Return Pointer Register),记录中断调用后的返回地址,如果中断嵌套,那么后面的返回地址会覆盖前面的.不过这个不影响中断返回,我测试过中断嵌套,可以正常返回,经过查看堆栈的地址(B15寄存器是堆栈指针sp),可以看出返回地址还是放在堆栈里面了.这个IRP寄存器,应该就相当于一个窗口,让用户可以看看中断返回的地址,而程序自己在返回的时候,是不从这里读取的,而是从堆栈中读取,读取之后也不会更新IRP寄存器.IRP寄存器只有在中断生效的时候被修改.
--------------------------------------------------------------------------------------------
猜想1:
在中断服务程序(ISR,Interrupt service routine),在被调用之前,BIOS应该还偷偷做了两件事,
第一件是将全局中断开关(GIE,Global Interrupt Enable)关闭,也就是不再响应所有可屏蔽的硬件中断.(GIE是CSR寄存器的第0位)
第二件是将IFR(Interrupt Flag Register)中和这个中断对应的位置0,以等待下次使用IRQ_set(中断号)函数将这个位置1
本来这第一件事也没什么,但是奇怪的就是在ISR(中断服务程序)结束的时候,并没有自动把GIE位恢复,而是就让GIE位一直为0,那么所有的中断就都被屏蔽了,所以只能在自定义的ISR函数最后,自己手动加上IRQ_globalEnable()函数.
不知道是我猜想有误还是哪个设置没设置好.
猜想2. 关于硬件中断的执行顺序
我猜想的中断处理流程:
0.初始化的时候,先打开大门GIE(利用IRQ_globalEnable函数),接着打开需要的中断的小门(利用IRQ_enable函数),这样才能响应中断,不然出现中断的时候,只会置位IFR,而不会调用到ISR.
1.程序运行期间,出现硬件中断信号(由于只是软件模拟,没有实际的硬件,所以只能调用IRQ_set函数来虚拟一个硬件中断,这个跟实际的硬件中断是否相同还没法验证.),这个时候将IFR寄存器中对应的位置1.
2.程序每个指令周期,都检测IFR,如果发现其中有某一位为1,那么再查看GIE和IER中对应的位,如果发现门没开,那就不管,继续执行当前的指令.(具体是先看IFR还是先看GIE和IER我就不清楚了,总之结果是一样的)
3.如果门开了(GIE为1,IER中对应的位也为1),那么将下一条指令的地址,还有一个不知道什么值,都存入堆栈中,同时改变IRP的值为下一条指令的地址.这就是保护现场.
4.做好现场保护后,查看中断向量表,找到该中断对应的跳转地址,然后跳转到已经定义好的中断处理程序(ISR)
5.在运行ISR之前,先是将GIE置0,IFR中对应的位置0,IER的位不变.然后执行程序.
6.程序执行完毕后,从堆栈中找到返回的地址,返回到中断前执行的指令,继续向下执行.
我想HWI执行的顺序应该就是上面这样,另外有几点需要补充:
1.不同的HWI没有优先级之分,只要GIE,IER,IFR条件满足,即使是在一个中断中,新出来的中断会打断当前的ISR,优先执行(无论是不是同样的中断,比如INT4打断INT4,INT5打断INT4,INT4打断INT5都是可以的),这就需要在编程的时候注意了,如果不希望在处理一个中断的时候,被另一个中断打断,就应该是在中断返回之前,再调用IRQ_globalEnable函数,这样处理那些不能被屏蔽的中断,其它中断就不会响应
2.如果GIE位是0,出现中断的时候,就只会在IFR的对应位置1,如果这个时候再来一个同样的中断,这个位还是1,等到GIE为1的时候,这个中断只运行一次,而不是两次.
3.如果GIE位是0,这个时候来了几个不同的中断,在IFR的不同位置了1,那么等到GIE为1的时候,会按照从小到大的顺序执行,而不是按照中断出现的顺序执行.
HWI_enter and HWI_exit both take four parameters on the C6000 platform:
❏ The first two, ABMASK and CMASK, specify which A, B, and control
registers are to be saved and restored by the ISR.
❏ The third parameter on the C6000 platform, IEMASK, is a mask of those
interrupts that are to be disabled between the HWI_enter and HWI_exit
macro calls.
When an interrupt is triggered, the processor disables interrupts globally
(by clearing the GIE bit in the control status register (CSR)) and then
jumps to the ISR set up in the interrupt service table. The HWI_enter
macro reenables interrupts by setting the GIE in the CSR. Before doing
so, HWI_enter selectively disables bits in the interrupt enable register
(IER) determined by the IEMASK parameter. Hence, HWI_enter gives
you control to select what interrupts can and cannot preempt the current
HWI function.
When HWI_exit is called, the bit pattern in the IEMASK determines what
interrupts are restored by HWI_exit by setting the corresponding bits in
the IER. Of the interrupts in IEMASK, HWI_exit restores only those that
were disabled with HWI_enter. If upon exiting the ISR you do not want to
restore one of the interrupts that was disabled with HWI_enter, do not set
that interrupt bit in IEMASK in HWI_exit. HWI_exit does not affect the
status of interrupt bits that are not in IEMASK.
The fourth parameter on the C6000 platform, CCMASK, specifies the
value to place in the cache control field of the CSR. This cache state
remains in effect for the duration of code executed between the
HWI_enter and HWI_exit calls. Some typical values for this mask are
defined in c62.h62 (for example, C62_PCC_ENABLE). You can OR the
PCC code and DCC code together to generate CCMASK. If you use 0 as
CCMASK, a default value is used. You set this value using GBL
properties in the Tconf configuration.
CLK_F_isr, which handles one of the on-device timer interrupts when the
Clock Manager is enabled, also uses the cache value set in the
configuration. HWI_enter saves the current CSR status before it sets the
cache bits as defined by CCMASK. HWI_exit restores CSR to its value at
the interrupted context.