网站公告列表

  没有公告

加入收藏
设为首页
联系本站
您现在的位置: Analog安诺电子网 >> 文章 >> 技术交流 >> 文章正文
  uclinux-2008r1-rc8(bf561)的中断处理(4):_evt_ivhw           ★★★ 【字体:
uclinux-2008r1-rc8(bf561)的中断处理(4):_evt_ivhw
作者:快乐虾    文章来源:http://blog.csdn.net/lights_joy    点击数:    更新时间:2008-5-17    
这部分代码在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,则每执行一条指令将中断一次,似乎是用于程序调试的,但是不是很明白。
文章录入:admin    责任编辑:admin 
  • 上一篇文章:

  • 下一篇文章: 没有了
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
    uclinux-2008r1-rc8(bf561)的
    uclinux-2008r1-rc8(bf561)的
    uclinux-2008r1-rc8(bf561)的
    uclinux-2008R1-RC8(bf561)到
    ADI AD5751 I/V输出驱动方案
    UBUNTU下建立BLACKFIN的UCLI
    怎样避免在DSP系统中出现噪声
    恰当使用D类功放有利于便携设
    细分市场需要产品具有更长的
    uclinux-2008R1-RC8(bf561)到
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    版权所有:Analog安诺电子网 湘ICP备06016315号