tIsr作为一个系统任务,看其注释,知道其有两种使用方式:
This module operates in two distinct modes depending on the module's
configuration. If the mode is configured for "per-CPU" deferral
tasks, this module creates (as needed) a single deferral task on each
CPU in the system. This single queue handles all deferral operations
performed by device drivers that are servicing their interrupts on
that CPU.
If the mode is configured for "per-ISR" deferral tasks, this module
creates a unique deferral task for each requester, and sets the CPU
affinity for the created task to the requested CPU index.
这个任务具体做什么任务呢?
举一个例子:
ns16550vxInt串口中断处理函数中使用到了。
当这个串口处理函数去读取这个串口中的值时,如果出现了超时没有读取完成的情况,就会把这个中断函数延后执行。
LOCAL void ns16550vxbInt ( VXB_DEVICE_ID pDev ) { FAST NS16550VXB_CHAN * pChan = (NS16550VXB_CHAN *)(pDev->pDrvCtrl); /* pointer to channel */ FAST volatile char intStatus; UINT8 iirValue, lsrValue; while ( pChan != NULL ) { VXB_NS16550_ISR_SET(pChan); switch (intStatus) { case IIR_RLS: REG_GET(LSR, pChan, lsrValue);/*read LSR to reset interrupt */ intStatus = (char)lsrValue; break; case IIR_RDA: /* received data available */ case IIR_TIMEOUT: { pChan->ier &= ~(RxFIFO_BIT); /* indicate to disable Rx Int */ REG_SET(IER, pChan, pChan->ier); VXB_NS16550_ISR_CLEAR(pChan); /*把这个任务延后,继续处理下一个,剩下的任务交给tIsr系统任务执行*/ isrDeferJobAdd (pChan->queueId, &pChan->isrDefRd); goto nextChan; } .... .... }
这相当于就是把一个中断上下文转换为任务上下文来继续执行。
初始化过程
usrRoot--->usrIosCoreInit--->usrIsrDeferInit--->isrDeferLibInit
STATUS isrDeferLibInit ( int mode /* global deferral queue mode */ ) { /*记录要使用的模式*/ isrDeferLibMode = mode; /*如果是ISR_DEFER_MODE_PER_CPU模式,就为每一个cpu创建一个队列,来处理这个cpu上所有的延后函数*/ if (isrDeferLibMode == ISR_DEFER_MODE_PER_CPU) { pCpuQueueId = (ISR_DEFER_QUEUE_ID *) calloc (vxCpuConfiguredGet (), sizeof(*pCpuQueueId)); if (pCpuQueueId == NULL) return ERROR; } return OK; }
/*创建处理延后队列函数*/ LOCAL ISR_DEFER_QUEUE * isrDeferQueueCreate ( VXB_DEVICE_ID pInst, /* VxBus device id of requester */ int intIdx, /* interrupt source index */ int logicalCpuIndex /* logical CPU index for deferral task */ ) { char taskName[32]; char *pT; cpuset_t affinity; ISR_DEFER_QUEUE *pQueue = malloc(sizeof(*pQueue)); lstInit (&pQueue->list); semBInit (&pQueue->syncSem, SEM_Q_PRIORITY, SEM_EMPTY); SPIN_LOCK_ISR_INIT (&pQueue->lock, 0); /*根据不同的cpu号,设置一个独一无二的名字,cpu0---tIsr0,cpu1---tIsr1*/ strcpy (taskName, "tIsr"); pT = taskName + 4; if (pInst == NULL) /* use CPU index only */ { *pT++ = '0' + logicalCpuIndex % 10; *pT = '\0'; } else /* use device unit number and interrupt index */ { *pT++ = '0' + pInst->unitNumber % 10; *pT++ = '0' + intIdx % 10; strcpy (pT, pInst->pName); } /*创建对应处理的系统任务*/ pQueue->tid = taskSpawn (taskName, ISR_DEFER_TASK_PRIO, ISR_DEFER_TASK_OPTS, 8192, (FUNCPTR) isrDeferTask, (int) pQueue, 0, 0, 0, 0, 0, 0, 0, 0, 0); ..... }
/*具体的处理函数*/ LOCAL void isrDeferTask ( ISR_DEFER_QUEUE_ID queueId /* queue for incoming deferred work */ ) { ISR_DEFER_JOB *pJob; /*死循环,一直等待任务的到来*/ FOREVER { semBTake (&queueId->syncSem, WAIT_FOREVER); /*获取任务,并执行*/ FOREVER { SPIN_LOCK_ISR_TAKE (&queueId->lock); pJob = (ISR_DEFER_JOB *) lstGet (&queueId->list); SPIN_LOCK_ISR_GIVE (&queueId->lock); pJob->func (pJob->pData); } } }
/*把一个任务添加到延迟队列上来*/ void isrDeferJobAdd ( ISR_DEFER_QUEUE_ID queueId, /* queue allocated by isrDeferQueueGet */ ISR_DEFER_JOB * pJob /* job to enqueue */ ) { SPIN_LOCK_ISR_TAKE (&queueId->lock); lstAdd (&queueId->list, &pJob->node); SPIN_LOCK_ISR_GIVE (&queueId->lock); /*添加完成后,通知isrDeferTask有任务到来了*/ semGive (&queueId->syncSem); } /*从队列获取一个任务*/ ISR_DEFER_QUEUE_ID isrDeferQueueGet ( VXB_DEVICE_ID pInst, /* VxBus device ID of requester */ int intIdx, /* interrupt source index */ int logicalCpuIndex, /* logical CPU index for deferral task */ int mode /* deferral queue mode(for future use) */ ) { /*如果是ISR_DEFER_MODE_PER_CPU模式,就返回对应cpu的那个队列*/ if (isrDeferLibMode == ISR_DEFER_MODE_PER_CPU) { if (pCpuQueueId [logicalCpuIndex] == NULL) pCpuQueueId [logicalCpuIndex] = isrDeferQueueCreate (0, 0, logicalCpuIndex); return pCpuQueueId [logicalCpuIndex]; } /*如果是另一种模式,就创建这个设备对应的队列*/ return isrDeferQueueCreate (pInst, intIdx, logicalCpuIndex); }