这篇blog主要分为三部分:

1,中断初始化

2,vxbus架构中断的挂接

3,非vxbus架构的中断的挂接

1,中断的初始化
函数调用:
usrInit->sysStart->palInit->palDescInit()

/*为了方便查看,这里对函数 进行了删减
*palDescInit()函数对默认的中断函数进行了初始化
*/

void palDescInit (void)
    {
    int idx;
#ifndef _WRS_MIPS_NONCOMPLIANT_CONFIG_REG
    UINT32 config;
#endif    /* _WRS_MIPS_NONCOMPLIANT_CONFIG_REG */
 
    bzero((char *)&palDesc, sizeof(palDesc));
 
    palDesc.coreNum = 0;
    palDesc.version = "1.1";
 
    /* Hopefully code further down will be able to refine these */
    palDesc.iCache.present = FALSE;
    palDesc.dCache.present = FALSE;
    palDesc.l2Cache.present = FALSE;
    palDesc.l3Cache.present = FALSE;
    if (IS_KSEGM((UINT32) &palDescInit))
    {
    /* executing a mapped kernel */
 
    palDesc.tVec.vectorAddr = (VIRT_ADDR *)T_VEC;
    palDesc.tVec.excHandler = (VIRT_ADDR *)mmuMipsTlbVec;
    palDesc.tVec.excSize    = mmuMipsTlbVecSize;
 
    palDesc.xVec.vectorAddr = (VIRT_ADDR *)X_VEC;
    palDesc.xVec.excHandler = (VIRT_ADDR *)mmuMipsXtlbVec;
    palDesc.xVec.excSize    = (UINT)mmuMipsXtlbVecSize;
 
    palDesc.cVec.vectorAddr = (VIRT_ADDR *)C_VEC;
    palDesc.cVec.excHandler = (VIRT_ADDR*)excCacheVec;
    palDesc.cVec.excSize    = (UINT)excCacheVecSize;
 
    palDesc.eVec.vectorAddr = (VIRT_ADDR *)E_VEC;
    palDesc.eVec.excHandler = (VIRT_ADDR *)excNormVmVec;
    palDesc.eVec.excSize    = (UINT)excNormVmVecSize;
    }
    /* Reasonable defaults */
    palDesc.tlb.supportedPageSizes = MMU_PAGE_MASK_8K;
palDesc.tlb.mmuCacheable=MMU_R4K_STATE_INVALID_STATE >> MMU_R4K_CACHE_START;
    palDesc.tlb.mmuUncacheable = CFG_CCA_UNCACHED;
    palDesc.tlb.mmuCacheCopyback = CFG_CCA_CACHEABLE;
    palDesc.tlb.mmuCacheWritethrough = CFG_CCA_ALIAS_CACHEABLE;
    palDesc.tlb.mmuCacheCoherency =  CFG_CCA_COHERENT;
    palDesc.iCache.modes = CACHE_MODES_SUPPORTED;
    palDesc.dCache.modes = CACHE_MODES_SUPPORTED;
}
 
//重要的结构体说一下
 
#define    T_VEC        K0BASE            /* tlbmiss vector */
#define    X_VEC        (K0BASE+0x80)        /* xtlbmiss vector */
#define    C_VEC        (K1BASE+0x100)        /* cache exception vector */
#define    E_VEC        (K0BASE+0x180)        /* exception vector */
 
#define    R_VEC        (K1BASE+0x1fc00000)    /* reset vector */
#define BEV_VEC        (K1BASE+0x1fc00380)    /* boot exception vector */
 
typedef struct
    {
    char        *version;    /* PAL version string */
    int            coreNum;    /* processor number */
    MIPS_EXC_VECTOR    tVec;           /*tlbmiss中断*/
    MIPS_EXC_VECTOR    xVec;        /*xtlbmiss中断*/
    MIPS_EXC_VECTOR    cVec;        /*cache异常中断*/
    MIPS_EXC_VECTOR    eVec;        /*异常中断,包括中断(根据exccode码判别)*/
    MIPS_MMU_INFO    tlb;          /**/
    MIPS_CACHE_INFO    iCache;        /*指令cache相关*/
    MIPS_CACHE_INFO    dCache;           /*数据cache相关*/
    MIPS_CACHE_INFO    l2Cache;       /*二级cache相关*/
    MIPS_CACHE_INFO    l3Cache;       /*三级cache相关*/
    int            mmuType;    /* CR bits 9:7 */
    BOOL        hasCP2;
    BOOL        hasWatch;
    BOOL        hasFPU;
    } MIPS_PAL_DESC;

默认中断函数的安装:
函数调用:
usrInit->excVecInit
 
/*在这里会安装默认的中断处理函数*/
STATUS excVecInit (void)
    {
    ULONG srValue;        /* status register placeholder */
    /* Load tlb and Xtlb vectors */
    vecInit (&palDesc.tVec);
    vecInit (&palDesc.xVec);
 
    /* Load cache exception vector */
    vecInit (&palDesc.cVec);
 
    /* Load normal/interrupt vector */
    vecInit (&palDesc.eVec);
    srValue = intSRGet();
    srValue &= ~SR_BEV;
    intSRSet(srValue);
 
    return (OK);
    }
 
LOCAL void vecInit
    (
    MIPS_EXC_VECTOR * vectorDesc
    )
    {
    if (vectorDesc->excSize)
    {
    /*把函数拷贝到设置的地址处*/
    bcopy ((const char *) vectorDesc->excHandler,
           (char *) vectorDesc->vectorAddr, vectorDesc->excSize);
     /*刷cache操作*/
    CACHE_TEXT_UPDATE (vectorDesc->vectorAddr, vectorDesc->excSize);
    }
    }
到这里系统默认的中断处理函数就初始化完成。
这里找一个具体的中断控制器的初始化进行说明。(这是一个抽象出来的中断控制器,至于什么是抽象,也就是没有一个具体的物理硬件设备对应这个控制器,这只是一个软件层面的简化,这样对于中断的处理就更明显,直接。)
函数调用关系:
usrInit->sysHwInit->vxbMipsLsnIntCtlrRegister
当这个控制其注册之后:
vxbMipsLsnIntCtlrRegister->vxbDevRegister->vxbNewDriver->vxbDevInitRun

/*vxbDevInitRun函数会调用设备对应的初始化函数对设备进行初始化*/
LOCAL void vxbDevInitRun
    (
    VXB_DEVICE_ID devID,
    struct vxbDevRegInfo * pDrv
    )
    {
    /* first pass */
    if (!(devID->flags & VXB_INST_INIT_DONE))
        {
        if ( pDrv->pDrvBusFuncs->devInstanceInit != NULL )
        (*(pDrv->pDrvBusFuncs->devInstanceInit))(devID);
        devID->flags |= VXB_INST_INIT_DONE;
        }
    /* second pass */
 
    if (vxbInitPhase >= 2 && !(devID->flags & VXB_INST_INIT2_DONE))
        {
        if ( pDrv->pDrvBusFuncs->devInstanceInit2 != NULL )
        (*(pDrv->pDrvBusFuncs->devInstanceInit2))(devID);
        devID->flags |= VXB_INST_INIT2_DONE;
        }
    /* third pass */
 
    if (vxbInitPhase >= 3 && !(devID->flags & VXB_INST_CONNECT_DONE))
        {
        if ( pDrv->pDrvBusFuncs->devInstanceConnect != NULL )
        (*(pDrv->pDrvBusFuncs->devInstanceConnect))(devID);
        devID->flags |= VXB_INST_CONNECT_DONE;
        }
    }

这里的pDrv->pDrvBusFuncs->devInstanceInit函数对应控制器的lsnIntCtlrInstInit函数,在lsnIntCtlrInstInit函数中调用了vxbMipsLsnIntCtlrInit对中断进行初始化。
LOCAL VOID vxbMipsLsnIntCtlrInit
    (
    VXB_DEVICE_ID       pInst
    )
    {
    HCF_DEVICE *pHcf = NULL;
    BOOL icw4Needed = FALSE;
    pVXB_LSN_INT_DRV_CTRL pDrvCtrl = pInst->pDrvCtrl;
/*这里注意intCtlrHwConfGet,这是真正具体的初始化函数*/
    intCtlrHwConfGet(pInst, pHcf, &(pDrvCtrl->isrHandle));
    Loongson2H_interrupt_init();
    return;
    }

intCtlrHwConfGet这个函数比较长,删减以下,可以看出来这个函数所作的工作就是从hwconf.c中得到设备对应的中断信息,并对每一个对应的引脚初始化为一个具体的结构体,结构体中包含的成员可以看一看。
STATUS intCtlrHwConfGet
    (
    VXB_DEVICE_ID               pInst,
    HCF_DEVICE *                pHcf,
    struct intCtlrHwConf *      pEntries
    )
    {
    struct intrCtlrInputs *     pCtlrInputs;  /*中断控制引脚*/
    struct intrCtlrXBar *       pXbar;          /*xbar路由*/
    struct intrCtlrCpu *        pCpuTable;    /*对应那个cpu*/
    struct intrCtlrPriority *   pPrioTable;   /*优先级*/
    struct intrCtlrTrigger *    pTrigTable;   /*引发方式,上升沿,高低电平,下降沿*/
    int                         tableSize;    /*控制引脚数组的大小*/     
    int                         i;
    STATUS                      stat;
    void *                      pValue;
    void **                     ppValue;
 
    /* save intCtlr ID */
    pEntries->ctlrDev = pInst;
    ppValue = &pValue;
/*获取中断控制引脚组成的数组*/
    stat = devResourceGet(pHcf, "input", HCF_RES_ADDR, ppValue);
    pCtlrInputs = (struct intrCtlrInputs *)pValue;
    if ( stat == OK )
        {
    /*获取中断控制引脚数组的大小*/
        stat = devResourceGet(pHcf, "inputTableSize", HCF_RES_INT, ppValue);
        tableSize = (UINT32)pValue;
 
        /*遍历表中的每个元素,并为每一个对应的引脚创建相应的结构体*/
        for ( i = 0 ; i < tableSize ; i++ )
            {
        /*为引脚创建一个结构体*/
            stat = intCtlrTableCreate(pEntries, pCtlrInputs->inputPin);
 
            /*为创建的结构体中的元素进行赋值操作,包括引脚号(硬件上连接的引脚号),驱动名字,drvunit以及drvIndex */
   intCtlrTableUserSet(pEntries, pCtlrInputs->inputPin, pCtlrInputs->drvName,pCtlrInputs->drvUnit, pCtlrInputs->drvIndex);
            pCtlrInputs++;
            }
        }
 
/*获取优先级对应的数组*/
    stat = devResourceGet(pHcf, "priority", HCF_RES_ADDR, ppValue);
    pPrioTable = (struct intrCtlrPriority *)pValue;
    if ( stat == OK )
        {
    /*获取优先级表的大小*/
      stat = devResourceGet(pHcf, "priorityTableSize", HCF_RES_INT, ppValue);
        tableSize = (UINT32)pValue;
    /*遍历表中所有的元素,把值填入到对应的引脚结构体中*/
        for ( i = 0 ; i < tableSize ; i++ )
            {
            /*再次a创建引脚结构体,防止没有创建 */
            stat = intCtlrTableCreate(pEntries, pPrioTable->inputPin);
            /*为结构体填入优先级 */
            intCtlrTablePrioSet(pEntries, pPrioTable->inputPin,pPrioTable->priority);
            pPrioTable++;
            }
        }
/*下面操作基本都是类似的,获取对应的中断信息,并进行遍历填入到引脚结构体中*/
/*获取引脚出发的方式*/
    stat = devResourceGet(pHcf, "trigger", HCF_RES_ADDR, ppValue);
    pTrigTable = (struct intrCtlrTrigger *)pValue;
    if ( stat == OK )
        {
       stat = devResourceGet(pHcf, "triggerTableSize", HCF_RES_INT, ppValue);
        tableSize = (UINT32)pValue;
 
        for ( i = 0 ; i < tableSize ; i++ )
            {
            /* ensure pin record exists */
 
            stat = intCtlrTableCreate(pEntries, pTrigTable->inputPin);
            /* fill in trigger */
 
            intCtlrTableTrigSet(pEntries, pTrigTable->inputPin, pTrigTable->trigger);
            pTrigTable++;
            }
        }
 
/*获取crossbar路由表*/
    stat = devResourceGet(pHcf, "crossBar", HCF_RES_ADDR, ppValue);
    pXbar = (struct intrCtlrXBar *)pValue;
    if ( stat == OK )
        {
        stat = devResourceGet(pHcf, "crossBarTableSize", HCF_RES_INT, ppValue);
        tableSize = (UINT32)pValue;
        for ( i = 0 ; i < tableSize ; i++ )
            {
            /* ensure pin record exists */
            stat = intCtlrTableCreate(pEntries, pXbar->inputPin);
 
            intCtlrTableOutputSet(pEntries, pXbar->inputPin, pXbar->outputPin);
            pXbar++;
            }
        }
 
 
    stat = devResourceGet(pHcf, "cpuRoute", HCF_RES_ADDR, ppValue);
    pCpuTable = (struct intrCtlrCpu *)pValue;
 
#ifdef _WRS_CONFIG_SMP
    if ( stat == OK )
        {
        stat = devResourceGet(pHcf, "cpuRouteTableSize", HCF_RES_INT, ppValue);
        tableSize = (UINT32)pValue;
        /* iterate through table */
 
        for ( i = 0 ; i < tableSize ; i++ )
            {
            /* ensure pin record exists */
            stat = intCtlrTableCreate(pEntries, pCpuTable->inputPin);
 
            /* set destination CPU for this input pin  */
 
            if (stat == OK)
                intCtlrTableCpuSet (pEntries, pCpuTable->inputPin,
                                    pCpuTable->cpuNum);
            pCpuTable++;
            }
        }
#endif /* _WRS_CONFIG_SMP */
    return(OK);
    }

/*创建中断表*/
STATUS intCtlrTableCreate
    (
    struct intCtlrHwConf *    pInputs,
    int                inputPin
    )
    {
    int      tblIndx = VXB_INTCTLRLIB_TBL_IDX(pInputs,inputPin);
    int      startPin = inputPin - (inputPin % VXB_INTCTLRLIB_LOWLVL_SIZE);
    int      i;
 
    if ( pInputs->pTop == NULL )
    {
    /*分配一个结构体vxbIntCtlrInpTop*/
    pInputs->pTop = (struct vxbIntCtlrInpTop *)
            hwMemAlloc(sizeof(struct vxbIntCtlrInpTop));
        }
 
    if ( pInputs->pTop->tbl[tblIndx] == NULL )
    {
    /*分配结构体vxbIntCtlrInput*/
        pInputs->pTop->tbl[tblIndx] = (struct vxbIntCtlrInput *)
            hwMemAlloc(sizeof(struct vxbIntCtlrInput) +
                   VXB_INTCTLRLIB_MIN_CACHE_LINE_SIZE);
    /*进行对齐操作*/
    pInputs->pTop->tbl[tblIndx] = (struct vxbIntCtlrInput *)
            ROUND_UP(pInputs->pTop->tbl[tblIndx],
                 VXB_INTCTLRLIB_MIN_CACHE_LINE_SIZE);
    /*赋值为0*/
    memset(pInputs->pTop->tbl[tblIndx],0,sizeof(struct vxbIntCtlrInput));
 
    /*为每一个引脚结构体中的中断函数以及中断函数参数赋一个系统默认的值 */
    for ( i = 0 ; i < VXB_INTCTLRLIB_NUM_PINS(pInputs) ; i++ )
        {
        pInputs->pTop->tbl[tblIndx]->pins[i].isr = intCtlrStrayISR;
        pInputs->pTop->tbl[tblIndx]->pins[i].pArg = pInputs;
        pInputs->pTop->tbl[tblIndx]->pins[i].pinFlags = startPin + i;
        }
    }
    return(OK);
    }

对应引脚重要的结构体:
 
struct intCtlrHwConf
    {
    VXB_DEVICE_ID      ctlrDev;      /* VXB_DEVICE_ID of int ctlr */
    struct vxbIntCtlrInpTop * pTop;       /* top-level table of entries */
    struct vxbLock         vxbIntCtlrLibLock;
    };
 
struct vxbIntCtlrInpTop
    {
    struct vxbIntCtlrInpTop * pNext;          /* not implemented */
    struct vxbIntCtlrInput *  tbl[VXB_INTCTLRLIB_TOPLVL_SIZE];
    UINT32                    reserved;
    };
#define VXB_INTCTLRLIB_TOPLVL_SIZE    496
 
struct vxbIntCtlrInput
    {
    struct vxbIntCtlrPin      pins[VXB_INTCTLRLIB_LOWLVL_SIZE];
    };
/*最后的运算就是 2^x ,这里的定义也就是8*/
#define VXB_INTCTLRLIB_LOWLVL_SIZE_POW 3 
#define VXB_INTCTLRLIB_LOWLVL_SIZE   ( 1<< VXB_INTCTLRLIB_LOWLVL_SIZE_POW)
 
struct vxbIntCtlrPin
    {
    struct intCtlrMoreDrvName * pMoreNames;
    char *                      drvName;
    int                         drvUnit;
    int                         intIndex;
 
    void                        (*isr)(void * pArg, int inputPin);
    void *                      pArg;
    int                         pinFlags;
    UINT32                      pinPriority;
    UINT32                      pinOutput;
    UINT32                      pinCpu;
    int                reserved [2];
    };
这里就相当于创建了一个两级表,第一级是496的大小,第二级分别对应于第一级的每一个元素,大小为8,到这里中断的创建以及初始化就完成了。

2,中断的挂接
vxWorks中的vxbus架构初始化分为三个阶段,第一第二阶段一般都是对设备进行初始化,到第三阶段一般是中断的挂接和使能。这里举例说明的这个有点特殊,这是在第二阶段进行的中断挂接和使能,也从另一面说名代码没有特定的规定,都是为了方便

函数调用关系:
usrRoot->sysClkInit->sysClkConnect->sysHwInit2->vxbDevInit->vxbDevInitInternal->vxbDevIterate->vxbDevInit2Helper->

LOCAL STATUS vxbDevInit2Helper
    (
    struct vxbDev * pInst,
    void * pArg
    )
    {
    if ( pInst->pDriver->pDrvBusFuncs->devInstanceInit2 == NULL )
        return(OK);
    /*这里调用第二阶段的初始化函数。*/
    (*pInst->pDriver->pDrvBusFuncs->devInstanceInit2)(pInst);
 
    pInst->flags |= VXB_INST_INIT2_DONE;
 
    return(OK);
    }
这里调用的第二阶段初始化函数对应的函数是:
LOCAL VOID lsnIntCtlrInstInit2
    (
    VXB_DEVICE_ID       pInst
    )
    {
     vxbIntConnect(pInst, 0, vxbMipsLsnIntCtrlIsr, (void*)pInst);
    vxbIntEnable(pInst, 0, vxbMipsLsnIntCtrlIsr, (void*)pInst);
    return;
    }
/*可以看出这里所作的工作就只有挂接中断和使能*/
这里中断挂接函数的函数调用关系:
vxbIntConnect->vxbDevIterate->vxbIntCtlrMatch->vxbIntCtlrConnect
直接看函数:熟悉流程即可:

STATUS vxbIntConnect
    (
    struct vxbDev * pDev,       /* Device Information */
    int             index,      /* index of interrupt vector */
    VOIDFUNCPTR     pIsr,       /* ISR */
    void *          pArg        /* parameter */
    )
    {
    VXB_ACCESS_INTERRUPT_INFO   accessIntrInfo;
    struct vxbintCtlrMgmt info;
 
    VXB_ASSERT(pDev!=NULL, ERROR)
 
    info.found = FALSE;
    info.pIntCtlr = NULL;
    info.inputPin = 0;
    info.pDev = pDev;
    info.index = index;
    info.pIsr = pIsr;
    info.pArg = pArg;
    /*这里一次把所有实例化的设备和要注册的info进行匹配*/
    vxbDevIterate(vxbIntCtlrMatch, &info, VXB_ITERATE_INSTANCES);
 
    if ( info.found == TRUE )
        return(OK);
    return (vxbDevControl (pDev, (pVXB_DEVCTL_HDR)&accessIntrInfo));
    }

LOCAL STATUS vxbIntCtlrMatch
    (
    struct vxbDev * pInst,
    void * pArg
    )
    {
    struct vxbintCtlrMgmt * pInfo = (struct vxbintCtlrMgmt *)pArg;
    FUNCPTR   func;
    STATUS    stat;
    struct plbIntrEntry * pIntrEntry;
    int            inputPin;
    struct pIntCtlrTable * pICTab;
    struct plbIntCtlrTable * pICTab2;
    int        x;
    int        y;
    struct plbIntCtlrEntry * pEnt;
    /*在这里会调用匹配到的设备的中断挂接函数,换句话说对不同的中断控制器上的中断挂接会调用对应的中断控制器的额挂接函数*/
    func = vxbDevMethodGet(pInst, DEVMETHOD_CALL(vxbIntCtlrConnect));
    stat = (*func)(pInst, pInfo->pDev, pInfo->index, pInfo->pIsr, pInfo->pArg, &inputPin);
 
    if ( stat != OK )
      return(OK);
 
    pInfo->found = TRUE;
 
    return(OK);
    }

这里对应的中断挂接函数为:
LOCAL STATUS vxbMipsLsnIntCtlrDevIsrConnect
    (
    VXB_DEVICE_ID    pIntCtlr,
    VXB_DEVICE_ID    pDev,
    int            indx,
    void        (*pIsr)(void * pArg),
    void              *    pArg,
    int               *    pInputPin
    )
    {
    pVXB_LSN_INT_DRV_CTRL pDrvCtrl = pIntCtlr->pDrvCtrl;
    int                 inputPin = ERROR;
    struct intCtlrHwConf * pIsrHandle = NULL;
  
    inputPin = intCtlrPinFind (pDev, indx, pIntCtlr, &pDrvCtrl->isrHandle);
 
    pIsrHandle = &(pDrvCtrl->isrHandle);
    
    /*在这里调用intCtlrISRAdd函数,这个函数会真正的挂接用户的中断函数*/
    if (intCtlrISRAdd(pIsrHandle, inputPin, pIsr, pArg) == ERROR)
        return ERROR;
 
    *pInputPin = inputPin;
    return OK;
    }

STATUS intCtlrISRAdd
    (
    struct intCtlrHwConf *    pEntries,
    int                inputPin,
    void             (*isr),
    void *            pArg
    )
    {
    struct intCtlrISRChainEntry * pChain;
    struct intCtlrISRChainEntry * pChain2;
    void *              installedIsr;
 
    /*这里要确保中断表已经创建 */
    intCtlrTableCreate(pEntries, inputPin);
 
    /*这里创建两个结构体,并初始化为用户中断,用于挂接中断时使用*/
    pChain = (struct intCtlrISRChainEntry *)hwMemAlloc(sizeof(*pChain));
 
    pChain2 = (struct intCtlrISRChainEntry *)hwMemAlloc(sizeof(*pChain));
 
    pChain->isr = isr;
    pChain->pArg = pArg;
 
    /*获取目前表中现在挂接的中断函数,如果是函数intCtlrStrayISR说明已经初始化为默认的中断函数,
只需要替换为用户的中断函数即可,如果为函数intCtlrChainISR,说明已经至少挂接了一个用户中断函数(多个中断函数可以挂接在一个中断引脚上),
如果为空,说明没有进行过初始化,这时就使用pChain2保存要挂接的中断函数,并赋值为pChain,然后填写到对应引脚上*/
     installedIsr = intCtlrTableIsrGet(pEntries, inputPin);
    if ( installedIsr == (void *)intCtlrStrayISR )
    {
    intCtlrTableFill(pEntries, inputPin, pChain->isr, pChain->pArg);
    }
    else if ( installedIsr == (void *)intCtlrChainISR )
        {
    pChain->pNext = (struct intCtlrISRChainEntry *)intCtlrTableArgGet(pEntries, inputPin);
    intCtlrTableFill(pEntries, inputPin, intCtlrChainISR, pChain);
    }
    else
        {
    /* create chain, add original entry and the new one */
 
    pChain2->flags = intCtlrTableFlagsGet(pEntries, inputPin);
 
    pChain2->pArg = intCtlrTableArgGet(pEntries, inputPin);
 
    pChain2->isr = installedIsr;
 
    pChain->pNext = pChain2;
    pChain2->pNext = NULL;
 
    intCtlrTableFill(pEntries, inputPin, intCtlrChainISR, pChain);
    }
    return(OK);
    }
struct intCtlrISRChainEntry
    {
    struct intCtlrISRChainEntry * pNext;
    void              (*isr)(void * pArg, int inputPin);
    void *              pArg;
    UINT32              flags;
    };

呼~~,到这里中断的额挂接就完成了。当然了这只是vxWorks系统中属于vxbus架构的函数的挂接,但是这就包含了绝大部分的中断呢。

3,非vxbus中断的挂接
下面说一下不是vxbus结构的中断函数的挂接。
不是vxbus架构的中断函数使用intConnect函数进行挂接,废话少说,看函数:

STATUS intConnect
    (
    VOIDFUNCPTR * vector,    /* interrupt vector to attach to     */
    VOIDFUNCPTR   routine,    /* routine to be called              */
    int           parameter    /* parameter to be passed to routine */
    )
    {
    /*这里首先看到,进行了三次判断,分别代表的三种中断的挂接,是首先第一种_func_isrConnect,
      这是isrobjectn中断的挂接,目前对于isrobject还没有深入分析过,不过这必须打开#INCLUDE_ISR_OBJECT宏定义才可以,
      这里不运行;intArchConnect这个函数就是结构中断的额挂接,一个中断号挂接一个中断,当然了在这里执行不到;
   _func_vxbIntConnect这个函数才是这次的重点,这个函数在vxbLegacyIntInit中被赋值,
    _func_vxbIntConnect = vxbLegacyIntConnect,看一下这个初始化函数*/
 
    if (_func_isrConnect != NULL)
    if (_func_isrConnect (vector, routine, parameter) == OK)
        return (OK);
 
 
    if (_func_vxbIntConnect != NULL)
        if (_func_vxbIntConnect(vector, routine, parameter) == OK)
            return (OK);
 
    return (intArchConnect (vector, (VOIDFUNCPTR) routine, 
                            (int) parameter));        
    }

void vxbLegacyIntInit()
    {
    VXB_DEVICE_ID devID;
    struct plbIntrEntry *       pIntrInfo;
 
    /*申请一个legacy设备(legacy在这里代表不是vxbus架构设备也可以说为遗留设备)*/
    devID = vxbDevStructAlloc(WAIT_FOREVER);
    
    /*初始化设备,主要是名字和总线号,用于之后匹配挂接于那个中断控制器*/
    devID->pName = "legacy";
    devID->pParentBus = pPlbDev->u.pSubordinateBus;
    devID->busID = VXB_BUSID_PLB;
    devID->pRegBase[0] = (void *)1;
 
 
    pIntrInfo = (struct plbIntrEntry *)hwMemAlloc(sizeof(*pIntrInfo)); 
 
    devID->pIntrInfo = pIntrInfo;
 
    /*声明设备已经注册到系统中*/
    if ( vxbDeviceAnnounce(devID) != OK )
    {
    vxbDevStructFree(devID);
        return;
    }
 
    vxbLegacyIntDevice = devID;
    _func_vxbIntConnect = vxbLegacyIntConnect;
    _func_vxbIntDisconnect = vxbLegacyIntDisconnect;
    _func_vxbIntEnable = vxbLegacyIntEnable;
    _func_vxbIntDisable = vxbLegacyIntDisable;
    }

LOCAL STATUS vxbLegacyIntConnect
    (
    VOIDFUNCPTR * vector,       /* interrupt vector to attach to     */
    VOIDFUNCPTR   routine,      /* routine to be called              */
    int           parameter     /* parameter to be passed to routine */
    )
    {
    /*在这里调用vxbIntConnect函数把中断注册进vxbus架构的中断表中*/
    if ((vxbIntConnect(vxbLegacyIntDevice,(int)vector,routine,
           (void *)parameter)) != OK)
        return ERROR;
    
    return(vxbIntEnable(vxbLegacyIntDevice,(int)vector,routine,
           (void *)parameter));
    }

之后就和上面vxbus中断的挂接一样了:
vxbIntConnect->vxbDevIterate->vxbIntCtlrMatch->vxbDevMethodGet->vxbIntCtlrConnect->vxbMipsLsnIntCtlrDevIsrConnect

OK...到这里非vxbus结构的中断挂接也完成了。

这里要说明一下:
func = vxbDevMethodGet(pInst, DEVMETHOD_CALL(vxbIntCtlrConnect));这个函数会调用所有注册进系统并实例化的设备对应的vxbIntCtlrConnect函数来进行挂接,但是这里还有一个函数,确保了中断函数会注册进对应的中断控制器中inputPin = intCtlrPinFind (pDev, indx, pIntCtlr, &pDrvCtrl->isrHandle),这个intCtlrPinFind函数只有在对应中断控制器中才可以找到对应的引脚结构体。这也就保证了会注册到对应的引脚结构体中。

ok~~,分析就先到这里,如果有什么不对地方,请留言。。。

vxworks中断初始化以及挂接分析相关推荐

  1. PowerPC基于vxWorks的中断初始化分析

    1. 本文简介 本文主要介绍P2020芯片中vxWorks中断初始化过程(部分讲解是以linux为例).P2020属于PPC85XX系列,内核为e500v2,它是PowerPC体系结构中主要应用于通信 ...

  2. linux中断子系统(基于imx6ul arm32分析)

    0.说明 本文主要针对linux内核中断整个框架进行梳理,针对的是armv7架构,硬件平台是imx6ul,基于arm GIC控制器来分析. GIC是arm公司设计使用的中断控制器,全称Global I ...

  3. Sun JDK: Hashmap.get非法使用的挂起分析

    Sun JDK: Hashmap.get非法使用的挂起分析 from:http://sdh5724.javaeye.com/blog/619130 最近在查看生产环境时候, 发现了一个很奇怪的现象, ...

  4. vxworks中断的使用

    VxWorks中使用intConnect()挂接中断服务程序,但对于PCI设备,一般采用pciIntConnect()挂接中断,它与intConnect()的主要不同在于intConnect()使用的 ...

  5. rt5350 中断初始化

    linux 下的中断初始化,实际就是对 irq_desc 这个结构体进行初始化,其中最关键莫过于 irq_flow_handler_t    handle_irq            中断处理函数 ...

  6. 初步了解Linux内核中断初始化

    在linux内核中,用struct irq_chip结构体描述一个可编程中断控制器,它的整个结构和调度器中的调度类类似,里面定义了中断控制器的一些操作: 在中断处理中所涉及的几个重要的数据结构:中断描 ...

  7. CC2530中断初始化和中断函数

    相关寄存器在cc2530中文数手册中2.4小节 中断初始化 其实中断的初始化可以参照引脚的初始化,即4个寄存器(PxSEL,PxDIR,PxINP,P2INP).中断同样也要初始化 1)初始化输入信号 ...

  8. linux中断初始化程序,Linux x86_64 内核中断初始化

    Linux x86_64 内核中断初始化 中断分类 Linux 系统中, 中断分为: 硬中断: 由外部设备或者执行异常产生的需要快速处理的中断如缺页中断定时器硬件中断 根据内部产生还是外部产生, 分为 ...

  9. java实现初始化三角形数组_Java基础之数组初始化和数组JVM分析

    什么是数组 所谓数组,是具有相同数据类型的若干变量或者数据按照一定排序规则组合起来的一种数据存储格式.数组中的数据称为数组元素,我们使用索引来标识数组元素在数组中的存储位置,索引从0开始,步长是1,其 ...

  10. Spring初始化加载流程分析

    关于Spring框架的介绍,网上有很多非常好的详细的文章,如果在本篇博客中没有了解到自己想要的东西,个人能力有限,只能使用博客记录一下自己目前了解的知识点了! 本篇博客将大致介绍一下Spring框架的 ...

最新文章

  1. java触发_怎么样让JAVA 设置一秒钟触发一个事件
  2. 10.4 实现关系下的匿名内部类
  3. 代码坏味道 - 耦合
  4. 科大星云诗社动态20210516
  5. 构建测试的体系化思维(进阶篇)
  6. Snabbdom(虚拟dom-5-patch函数)
  7. 关于MySQL的死锁问题
  8. 周三直播丨Oracle 12cR2 ADG LGWR Library Cache案例分享
  9. 如何将cad格式转化为qt可以识别的图像_看BIM技术如何计算土方工程量
  10. Python打地鼠小游戏源代码
  11. Python(十七)- Excel操作:xlsxwriter绘制图表
  12. 电压源和电流的关联参考方向_什么是电流,电压的关联参考方向?
  13. JS实现京东表单注册
  14. ubuntu上通过命令行导出mysql数据库文件到widows系统上
  15. php 正则 英文开头,php 正则表达式 匹配以“XXX”开头不能以“YYY”结尾
  16. 一个程序员的真实故事上
  17. 项目管理中的冲突管理
  18. 通俗讲解 Kademlia 原理
  19. 计算机动画关键技术,计算机动画关键技术综述ppt课件.ppt
  20. Windows权限维持方案(可过360主动防御)

热门文章

  1. Windows XP英文版安装中文语言包来解决无法显示中文的方法(转载)
  2. access做mysql前端,ASP+ACCESS留言板制作详细教程
  3. android音频框架
  4. CAD安装失败Failed Installation aborted, Result=1603
  5. Open3D绘制3D坐标,绘制点云
  6. html5中加入音乐怎么弄,H5秀添加音乐和视频的编辑方式
  7. 老罗Android开发 视频教程
  8. 量化指标公式源码_最牛通达信量化副图指标公式源码.doc
  9. Pycharm配置Git教程
  10. node实现敏感词过滤及敏感词库