uclinux-2008r1-rc8(bf561)的中断处理(4):_evt_ivhw

来源:互联网 发布:汪涵人设崩 知乎 编辑:程序博客网 时间:2024/04/30 21:39
 
  
这部分代码在arch/blackfin/mach-common/interrupt.S中,用于处理Hardware Error Interrupt,VDSP文档对此错误的解释是:
The Hardware Error Interrupt is generated by:
 
Bus parity errors
Internal error conditions within the core, such as Performance Monitor overflow
Peripheral errors
Bus timeout errors
看看uclinux的处理:
/* interrupt routine for ivhw - 5 */
ENTRY(_evt_ivhw)
     SAVE_ALL_SYS
 
     //# We are going to dump something out, so make sure we print IPEND properly
     p2.l = lo(IPEND);
     p2.h = hi(IPEND);
     r0 = [p2];
     [sp + PT_IPEND] = r0;
 
     /* set the EXCAUSE to HWERR for trap_c */
     r0 = [sp + PT_SEQSTAT];
     R1.L = LO(VEC_HWERR);
     R1.H = HI(VEC_HWERR);
     R0 = R0 | R1;
     [sp + PT_SEQSTAT] = R0;
 
     r0 = sp;        /* stack frame pt_regs pointer argument ==> r0 */
     SP += -12;
     call _trap_c;
     SP += 12;
 
     call _ret_from_exception;
.Lcommon_restore_all_sys:
     RESTORE_ALL_SYS
     rti;
 
ENDPROC(_evt_ivhw)
在这里,SAVE_ALL_SYS将系统的大部分寄存器的值都压到栈中,且入栈的顺序是和pt_regs这个结构体的成员一一对应的,因此最后可以将此结构体的指针传给函数trap_c。
PT_IPENDPT_SEQSTAT分别定义了保存IPEND和SEQSTAT这两个寄存器值的成员相应于pt_regs这个结构体的偏移量,因而使用[sp + PT_IPEND]这样的方式可以取得相应寄存器的值。
VEC_HWERR则是定义好的一个常数:
/* The hardware reserves (63) for future use - we use it to tell our
 * normal exception handling code we have a hardware error
 */
#define VEC_HWERR (63)
因为出错的原因保存在SEQSTAT寄存器的低5位中,因此通过取或的方式将pt_regs->seqstat的值设置为EXCAUSE,而不是原来的32位整数。
然后调用trap_c进行处理,此函数将决定输出错误信息后返回原位置执行,或者中止执行。
最后调用了_ret_from_exception函数,这个函数的实现在arch/blackfin/mach-common/entry.S中,我们来看看它的实现:
ENTRY(_ret_from_exception)
     p2.l = lo(IPEND);
     p2.h = hi(IPEND);
 
     csync;
     r0 = [p2];
     [sp + PT_IPEND] = r0;
 
_ret_from_exception_1:
     r2 = LO(~0x37) (Z);
     r0 = r2 & r0;
     cc = r0 == 0;
     if !cc jump _ret_from_exception_4;   /* if not return to user mode, get out */
 
     /* Make sure any pending system call or deferred exception
      * return in ILAT for this process to get executed, otherwise
      * in case context switch happens, system call of
      * first process (i.e in ILAT) will be carried
      * forward to the switched process
      */
 
     p2.l = lo(ILAT);
     p2.h = hi(ILAT);
     r0 = [p2];
     r1 = (EVT_IVG14 | EVT_IVG15) (z);
     r0 = r0 & r1;
     cc = r0 == 0;
     if !cc jump _ret_from_exception_5;
 
     /* Set the stack for the current process */
     r7 = sp;
     r4.l = lo(ALIGN_PAGE_MASK);
     r4.h = hi(ALIGN_PAGE_MASK);
     r7 = r7 & r4;      /* thread_info->flags */
     p5 = r7;
     r7 = [p5 + TI_FLAGS];
     r4.l = lo(_TIF_WORK_MASK);
     r4.h = hi(_TIF_WORK_MASK);
     r7 = r7 & r4;
     cc = r7 == 0;
     if cc jump _ret_from_exception_4;
 
     p0.l = lo(EVT15);
     p0.h = hi(EVT15);
     p1.l = _schedule_and_signal;
     p1.h = _schedule_and_signal;
     [p0] = p1;
     csync;
     raise 15;     /* raise evt14 to do signal or reschedule */
_ret_from_exception_4:
     r0 = syscfg;
     bitclr(r0, 0);
     syscfg = r0;
_ret_from_exception_5:
     rts;
ENDPROC(_ret_from_exception)
在此入口的开始,直接取IPEND寄存器的值判断0x37指定的掩码位置的状态,如果为1则直接跳转到_ret_from_exception_4,查一下IPEND这几位的意义:
The IPEND register keeps track of all currently nested interrupts (see Figure 4-12). Each bit in IPEND indicates that the corresponding interrupt is currently active or nested at some level. It may be read in Supervisor mode, but not written. The IPEND[4] bit is used by the Event Controller to temporarily disable interrupts on entry and exit to an interrupt service routine.
When an event is processed, the corresponding bit in IPEND is set. The least significant bit in IPEND that is currently set indicates the interrupt that is currently being serviced. At any given time, IPEND holds the current status of all nested events.
0:EMU中断
1:RST中断
2:NMI
4:Global Interrupt Disable
5:IVHW
当发生上述状况时,内核直接跳转到_ret_from_exception_4
_ret_from_exception_4:
     r0 = syscfg;
     bitclr(r0, 0);
     syscfg = r0;
_ret_from_exception_5:
     rts;
在这里syscfg的最低位表示Supervisor Single Step,如果置1,则每执行一条指令将中断一次,似乎是用于程序调试的,但是不是很明白。
原创粉丝点击