vxWorks系统中(MIPS架构)的中断分发分析

这里单独分析中断分发函数,大部分是基于汇编,初始化过程在另一个博客单独分析。

首先当中断来了之后硬件会自动跳转到函数:

(这里进行了部分删减,方便进行查看过程。)

	.ent	excNormVmVec
	.set	noat
FUNC_LABEL(excNormVmVec)
	.set	noreorder
#ifdef _WRS_MIPS_VR4131_ERRATA
	nop			/* 延时作用 */
#endif	/* _WRS_MIPS_VR4131_ERRATA */
	mfc0	k0, C0_CAUSE		/*取cause寄存器的值	*/
	HAZARD_CP_READ
	and	k0, CAUSE_EXCMASK	/*取cause code码 */
	bne	k0, zero, 1f		/*如果code码==0说明是中断 */
	nop
	la	k0, excIntVmStub
	j	k0			/*中断跳转到excIntVmStub函数,进行具体的分发 */
	nop
excNormVmVecEnd:
	.set	at
	.set	reorder
	FUNC_END(excNormVmVec)
	.end	excNormVmVec
        .sdata
        .align    4
excNormVmVecSize:
    .word    excNormVmVecEnd-excNormVmVec
    .text

这是excIntVmStub函数:

	.globl	excIntVmStub
	.ent	excIntVmStub
FUNC_LABEL(excIntVmStub)
//保存相关的寄存器值
	SW	AT, EXCPAGE_EXCSTUB_AT(zero)
	SW	t7, EXCPAGE_EXCSTUB_T7(zero)
	SW	t8, EXCPAGE_EXCSTUB_T8(zero)
	SW	t9, EXCPAGE_EXCSTUB_T9(zero)

	.set	noreorder
	mfc0	t7, C0_EPC	/*读取epc的值*/
	mfc0	t8, C0_SR	/*读取SR寄存器*/
	mfc0	t9, C0_CAUSE	/*读取cause寄存器*/

	HAZARD_CP_READ
	.set	reorder
	sw	t7, EXCPAGE_EXCSTUB_PC(zero) /*保存epc*/
	sw	t8, EXCPAGE_EXCSTUB_SR(zero) /*保存SR*/
	sw	t9, EXCPAGE_EXCSTUB_CR(zero) /*保存cause*/
	/*关中断,并清楚exl
	*注意:在清中断前清楚exl,interrupts could be re-enabled here
	* for one or more cycles。所以在做完其他操作后,在去清楚exl位
	*/
	and  t9, t8, ~(SR_KSUMASK|SR_IE) /*关中断,并清除用户权限位进入特权级 */
	.set	noreorder
	mtc0	t9, C0_SR  
	HAZARD_INTERRUPT
	.set	reorder
	and	t9, ~SR_EXL		/*清除exl */
	.set	noreorder
	mtc0	t9, C0_SR
	HAZARD_CP_WRITE
	.set	reorder

	 /*检查是否在中断栈中,增加areWeNested的值并保存
	 */
	_MIPS_PER_CPU_ARCH_VALUE_AND_ADRS_GET(t7,t8,areWeNested)
	.set noreorder
	bnez    t7, nestedVm            /* if in isr don't reset sp      */
	move    t9, sp
	.set reorder

	/*如果没有在中断栈上,获取中断栈的值 */
	_MIPS_PER_CPU_VALUE_GET(t9,vxIntStackBase)
nestedVm:
	subu    t9, ESTKSIZE            /* make room for frame           */
	SW      sp, E_STK_SP(t9)        /* save sp on int stack          */
	move    sp, t9                  /* init new int stack ptr        */

	/* save areWeNested */
	add     t9, t7, 1
	sw      t9, 0(t8)

	SW      gp, E_STK_GP(sp)
	la	gp, _gp

#ifdef _WRS_CONFIG_SMP
	_MIPS_PER_CPU_VALUE_GET(t8,errno)
#else /* _WRS_CONFIG_SMP */
	lw	t8, _WRS_MIPS_SDA_OFFSET(errno)
#endif /* _WRS_CONFIG_SMP */
	sw	t8, E_ERRNO(sp)

/*保存必要的值*/
	LW	t9, EXCPAGE_EXCSTUB_AT(zero)
	SW	t9, E_STK_AT(sp)
	LW	t7, EXCPAGE_EXCSTUB_T7(zero)
	LW	t8, EXCPAGE_EXCSTUB_T8(zero)
	LW	t9, EXCPAGE_EXCSTUB_T9(zero)
	SW	t7, E_STK_T7(sp)
	SW	t8, E_STK_T8(sp)
	SW	t9, E_STK_T9(sp)
	SW	t0, E_STK_T0(sp)	/* t0 saved here so a sputious int
					 * won't lead it possibly getting
					 * corrupted
					 */

	SW	zero, E_STK_K0(sp)	/* dummy value to k0 	*/
	SW	zero, E_STK_K1(sp)	/* dummy value to k1 	*/
	SW	v0, E_STK_V0(sp)	/* save func return 0, used */
					/* to hold cause	    */
	lw	t9, EXCPAGE_EXCSTUB_PC(zero)
	lw	t8, EXCPAGE_EXCSTUB_SR(zero)
	lw	v0, EXCPAGE_EXCSTUB_CR(zero)
	sw	t9, E_STK_EPC(sp)	/* save EPC on stack		*/
	sw	t8, E_STK_SR(sp)	/* save status on stack		*/
	sw	v0, E_STK_CAUSE(sp)	/* save cause on stack		*/

	b	commonExcIntStubCode  /*跳转到正常中断处理函数中*/

	FUNC_END(excIntVmStub)
	.end	excIntVmStub
最后会跳转到C函数进行分发:、

commonExcIntStubCode:
	SW	ra, E_STK_RA(sp)	/* save RA on stack		*/
	SW	t0, E_STK_T0(sp)	/* save temp reg 0 (early)	 */
	SW	t1, E_STK_T1(sp)	/* save temp reg 1 (early)	 */
	SW	t2, E_STK_T2(sp)	/* save temp reg 2 (early)	 */
	SW	t3, E_STK_T3(sp)	/* save temp reg 3 (early)	 */

	_MIPS_PER_CPU_VALUE_AND_ADRS_GET(t2,t1,intCnt)
	addu    t2, 1                   /* increment intCnt */
	sw      t2, 0(t1)
excIntStubNormal:
	/* now t8 has STATUS and v0 has CAUSE */
	and     t2, v0, SR_IMASK        /* check for spurious interrupt  */
	and     v0, t8, t2              /* v0 = ints enabled and pending */
	.set noreorder
	beqz    v0, restoreVolatile     /* return if no interrupt */
	move	t1, zero		/* flag only volatile restore
					 * if branch is taken */
/* vxbus interrupt handler processing */
	sll	t1, 4			/* mult by Prio table size       */
	lw	t2, intPrioTable+8(t1)	/* get user mask                 */
  	or	v0, v0, t2		/* add user mask                 */
	not	v0			/* invert interrupt mask         */
	and	t8, v0, t8		/* apply interrupt mask to t8    */
excIntStubCommonExit:
	and	v0, t8, ~(SR_KSUMASK|SR_EXL|SR_IE)
	.set	noreorder
	mtc0	v0, C0_SR
	HAZARD_INTERRUPT
	.set	reorder
	and 	t8, ~(SR_KSUMASK|SR_EXL)
	mtc0	t8, C0_SR		/* enable interrupts w/ new mask */
	HAZARD_CP_WRITE
/*
 * Begin state save
 */
intStateSave:
	SW	zero,E_STK_ZERO(sp)	/* init zero reg storage	 */
	SW	v1,E_STK_V1(sp)		/* save func return 1		 */
	SW	a0,E_STK_A0(sp)		/* save passed param 0        	 */
	SW	a1,E_STK_A1(sp)		/* save passed param 1		 */
	SW	a2,E_STK_A2(sp)		/* save passed param 2		 */
	SW	a3,E_STK_A3(sp)		/* save passed param 3		 */
	SW	t0,E_STK_T0(sp)		/* save temp reg 0		 */
					/* save temp reg 1 (above)	 */
					/* save temp reg 2 (above)	 */
					/* save temp reg 3 (above)	 */
	SW	t4,E_STK_T4(sp)		/* save temp reg 4		 */
	SW	t5,E_STK_T5(sp)		/* save temp reg 5		 */
	SW	t6,E_STK_T6(sp)		/* save temp reg 6		 */
					/* save temp reg 7 (above)       */
					/* save temp reg 8 (above)       */
					/* save temp reg 9 (above)       */
					/* save return address (above)   */
	mflo	t2			/* read int mult lo reg		 */
	SW	t2,E_STK_LO(sp)		/* save int mult lo reg        	 */
	mfhi	t2			/* read int mult hi reg		 */
	SW	t2,E_STK_HI(sp)		/* save int mult hi reg		 */
        /* flag full context is being saved */
        sw      zero, E_STK_ULEXTRA1(sp)
	MFC0	t2,C0_TLBHI		/* read tlb entryHi reg		 */
	HAZARD_CP_READ
	SW	t2,E_STK_TLBHI(sp)	/* save tlb entryHi reg		 */
/*进入C函数,进行中断的分发*/
	lw	t2, _WRS_MIPS_SDA_OFFSET(_func_vxBusIntHdlr)
	beq     t2, zero, 1f

	move    a0, t9          /* pass pin number of interrupt */
	.set noreorder
	jal	t2		/* call registered vxBus ISR */
	move	a1, sp          /* pass exc stack frame		 */
	b	Restore

在vxbMipsIntCtlrInstInit函数中对_func_vxBusIntHdlr进行了赋值操作:
 _func_vxBusIntHdlr = vxbMipsIntCtlrISR。也就是说真正的分发函数是:vxbMipsIntCtlrISR
void vxbMipsIntCtlrISR 
    (
    int pinNum,
    ESFMIPS * pEsf
    )
    {
#ifdef _WRS_CONFIG_SMP
    int cpunum = vxCpuIndexGet ();
#else
    int cpunum = 0; /* UP and AMP always use zero cpu number */
#endif /* _WRS_CONFIG_SMP */
    struct vxbIntCtlrPin * pPin = vxbIntCtlrPinEntryGet(
                    &(pVxbMipsIntCtlrDrvCtrl [cpunum]->isrHandle), pinNum);

    (*pPin->isr) ((void *)(pPin->pArg), (int)pEsf);
    }

在对中断进行初始化时,每个引脚对初始化为一个结构体,这个结构体包含了中断处理函数,所有最后分发时,只需要得到对应引脚的机构体,也就找到了具体的中断函数。

当然了每个中断函数的挂接,都是在中断初始化时所做的工作。后面对中断初始化分析时,会详细说明中断的挂接,以及相关结构体的初始化。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值