示例#1
0
void  OSSemPend (OS_EVENT  *pevent,
                 INT32U     timeout,
                 INT8U     *perr)
{
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
    OS_CPU_SR  cpu_sr = 0u;
#endif



#ifdef OS_SAFETY_CRITICAL
    if (perr == (INT8U *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    }
#endif

#if OS_ARG_CHK_EN > 0u
    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
        *perr = OS_ERR_PEVENT_NULL;
        return;
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
        *perr = OS_ERR_EVENT_TYPE;
        return;
    }
    if (OSIntNesting > 0u) {                          /* See if called from ISR ...                    */
        *perr = OS_ERR_PEND_ISR;                      /* ... can't PEND from an ISR                    */
        return;
    }
    if (OSLockNesting > 0u) {                         /* See if called with scheduler locked ...       */
        *perr = OS_ERR_PEND_LOCKED;                   /* ... can't PEND when locked                    */
        return;
    }
    OS_ENTER_CRITICAL();
    if (pevent->OSEventCnt > 0u) {                    /* If sem. is positive, resource available ...   */
        pevent->OSEventCnt--;                         /* ... decrement semaphore only if positive.     */
        OS_EXIT_CRITICAL();
        *perr = OS_ERR_NONE;
        return;
    }
                                                      /* Otherwise, must wait until event occurs       */
    OSTCBCur->OSTCBStat     |= OS_STAT_SEM;           /* Resource not available, pend on semaphore     */
    OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;
    OSTCBCur->OSTCBDly       = timeout;               /* Store pend timeout in TCB                     */
    OS_EventTaskWait(pevent);                         /* Suspend task until event or timeout occurs    */
    OS_EXIT_CRITICAL();
    OS_Sched();                                       /* Find next highest priority task ready         */
    OS_ENTER_CRITICAL();
    switch (OSTCBCur->OSTCBStatPend) {                /* See if we timed-out or aborted                */
        case OS_STAT_PEND_OK:
             *perr = OS_ERR_NONE;
             break;

        case OS_STAT_PEND_ABORT:
             *perr = OS_ERR_PEND_ABORT;               /* Indicate that we aborted                      */
             break;

        case OS_STAT_PEND_TO:
        default:
             OS_EventTaskRemove(OSTCBCur, pevent);
             *perr = OS_ERR_TIMEOUT;                  /* Indicate that we didn't get event within TO   */
             break;
    }
    OSTCBCur->OSTCBStat          =  OS_STAT_RDY;      /* Set   task  status to ready                   */
    OSTCBCur->OSTCBStatPend      =  OS_STAT_PEND_OK;  /* Clear pend  status                            */
    OSTCBCur->OSTCBEventPtr      = (OS_EVENT  *)0;    /* Clear event pointers                          */
#if (OS_EVENT_MULTI_EN > 0u)
    OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endif
    OS_EXIT_CRITICAL();
}
示例#2
0
void  *OSQPend (OS_EVENT  *pevent,
                INT32U     timeout,
                INT8U     *perr)
{
    void      *pmsg;
    OS_Q      *pq;
#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0u;
#endif



#ifdef OS_SAFETY_CRITICAL
    if (perr == (INT8U *)0)
    {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return ((void *)0);
    }
#endif

#if OS_ARG_CHK_EN > 0u
    if (pevent == (OS_EVENT *)0)                 /* Validate 'pevent'                                  */
    {
        *perr = OS_ERR_PEVENT_NULL;
        return ((void *)0);
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_Q)  /* Validate event block type                          */
    {
        *perr = OS_ERR_EVENT_TYPE;
        return ((void *)0);
    }
    if (OSIntNesting > 0u)                       /* See if called from ISR ...                         */
    {
        *perr = OS_ERR_PEND_ISR;                 /* ... can't PEND from an ISR                         */
        return ((void *)0);
    }
    if (OSLockNesting > 0u)                      /* See if called with scheduler locked ...            */
    {
        *perr = OS_ERR_PEND_LOCKED;              /* ... can't PEND when locked                         */
        return ((void *)0);
    }
    OS_ENTER_CRITICAL();
    pq = (OS_Q *)pevent->OSEventPtr;             /* Point at queue control block                       */
    if (pq->OSQEntries > 0u)                     /* See if any messages in the queue                   */
    {
        pmsg = *pq->OSQOut++;                    /* Yes, extract oldest message from the queue         */
        pq->OSQEntries--;                        /* Update the number of entries in the queue          */
        if (pq->OSQOut == pq->OSQEnd)            /* Wrap OUT pointer if we are at the end of the queue */
        {
            pq->OSQOut = pq->OSQStart;
        }
        OS_EXIT_CRITICAL();
        *perr = OS_ERR_NONE;
        return (pmsg);                           /* Return message received                            */
    }
    OSTCBCur->OSTCBStat     |= OS_STAT_Q;        /* Task will have to pend for a message to be posted  */
    OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;
    OSTCBCur->OSTCBDly       = timeout;          /* Load timeout into TCB                              */
    OS_EventTaskWait(pevent);                    /* Suspend task until event or timeout occurs         */
    OS_EXIT_CRITICAL();
    OS_Sched();                                  /* Find next highest priority task ready to run       */
    OS_ENTER_CRITICAL();
    switch (OSTCBCur->OSTCBStatPend)                  /* See if we timed-out or aborted                */
    {
    case OS_STAT_PEND_OK:                         /* Extract message from TCB (Put there by QPost) */
        pmsg =  OSTCBCur->OSTCBMsg;
        *perr =  OS_ERR_NONE;
        break;

    case OS_STAT_PEND_ABORT:
        pmsg = (void *)0;
        *perr =  OS_ERR_PEND_ABORT;               /* Indicate that we aborted                      */
        break;

    case OS_STAT_PEND_TO:
    default:
        OS_EventTaskRemove(OSTCBCur, pevent);
        pmsg = (void *)0;
        *perr =  OS_ERR_TIMEOUT;                  /* Indicate that we didn't get event within TO   */
        break;
    }
    OSTCBCur->OSTCBStat          =  OS_STAT_RDY;      /* Set   task  status to ready                   */
    OSTCBCur->OSTCBStatPend      =  OS_STAT_PEND_OK;  /* Clear pend  status                            */
    OSTCBCur->OSTCBEventPtr      = (OS_EVENT *)0;     /* Clear event pointers                          */
#if (OS_EVENT_MULTI_EN > 0u)
    OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endif
    OSTCBCur->OSTCBMsg           = (void *)0;         /* Clear  received message                       */
    OS_EXIT_CRITICAL();
    return (pmsg);                                    /* Return received message                       */
}
示例#3
0
文件: os_mbox.c 项目: Gewin/vc_uCos
/*$PAGE*/
void  *OSMboxPend (OS_EVENT  *pevent,
                   INT32U     timeout,
                   INT8U     *perr)
{
    void      *pmsg;
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
    OS_CPU_SR  cpu_sr = 0u;
#endif



#ifdef OS_SAFETY_CRITICAL
    if (perr == (INT8U *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
    }
#endif

#if OS_ARG_CHK_EN > 0u
    if (pevent == (OS_EVENT *)0) {                    /*事件控制块指针是否有效        */
        *perr = OS_ERR_PEVENT_NULL;
        return ((void *)0);
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  /* 事件控制块类型是否有效     */
        *perr = OS_ERR_EVENT_TYPE;
        return ((void *)0);
    }
    if (OSIntNesting > 0u) {                          /* 查看是否在中断服务程序ISR中调用本函数                    */
        *perr = OS_ERR_PEND_ISR;                      /* ... can't PEND from an ISR                    */
        return ((void *)0);
    }
    if (OSLockNesting > 0u) {                         /* See if called with scheduler locked ...       */
        *perr = OS_ERR_PEND_LOCKED;                   /* ... can't PEND when locked                    */
        return ((void *)0);
    }
    OS_ENTER_CRITICAL();
    pmsg = pevent->OSEventPtr;
    if (pmsg != (void *)0) {                          /* See if there is already a message             */
        pevent->OSEventPtr = (void *)0;               /* 清邮箱       */
        OS_EXIT_CRITICAL();
        *perr = OS_ERR_NONE;
        return (pmsg);                                /* 返回获得的消息(或空指针)      */
    }
    OSTCBCur->OSTCBStat     |= OS_STAT_MBOX;          /* Message not available, task will pend         */
    OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;
    OSTCBCur->OSTCBDly       = timeout;               /* Load timeout in TCB                           */
    OS_EventTaskWait(pevent);                         /* Suspend task until event or timeout occurs    */
    OS_EXIT_CRITICAL();
    OS_Sched();                                       /* Find next highest priority task ready to run  */
    OS_ENTER_CRITICAL();
    switch (OSTCBCur->OSTCBStatPend) {                /* See if we timed-out or aborted                */
        case OS_STAT_PEND_OK:
             pmsg =  OSTCBCur->OSTCBMsg;
            *perr =  OS_ERR_NONE;
             break;

        case OS_STAT_PEND_ABORT:
             pmsg = (void *)0;
            *perr =  OS_ERR_PEND_ABORT;               /* Indicate that we aborted                      */
             break;

        case OS_STAT_PEND_TO:
        default:
             OS_EventTaskRemove(OSTCBCur, pevent);
             pmsg = (void *)0;
            *perr =  OS_ERR_TIMEOUT;                  /* Indicate that we didn't get event within TO   */
             break;
    }
    OSTCBCur->OSTCBStat          =  OS_STAT_RDY;      /* Set   task  status to ready                   */
    OSTCBCur->OSTCBStatPend      =  OS_STAT_PEND_OK;  /* Clear pend  status                            */
    OSTCBCur->OSTCBEventPtr      = (OS_EVENT  *)0;    /* Clear event pointers                          */
#if (OS_EVENT_MULTI_EN > 0u)
    OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endif
    OSTCBCur->OSTCBMsg           = (void      *)0;    /* 清除获得的消息        */
    OS_EXIT_CRITICAL();
    return (pmsg);                                    /* 返回获得的消息        */
}
示例#4
0
// CODE_SECTION(OSTaskDel,".UserProgramCode")
INT8U  OSTaskDel( INT8U prio )
{
#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
	OS_FLAG_NODE *pnode;
#endif
	OS_TCB       *ptcb;
#if OS_CRITICAL_METHOD == 3                             /* Allocate storage for CPU status register    */
	OS_CPU_SR     cpu_sr = 0;
#endif



	if ( OSIntNesting > 0 )                             /* See if trying to delete from ISR            */
	{
		return ( OS_ERR_TASK_DEL_ISR );
	}
	if ( prio == OS_TASK_IDLE_PRIO )                    /* Not allowed to delete idle task             */
	{
		return ( OS_ERR_TASK_DEL_IDLE );
	}
#if OS_ARG_CHK_EN > 0
	if ( prio >= OS_LOWEST_PRIO )                       /* Task priority valid ?                       */
	{
		if ( prio != OS_PRIO_SELF )
		{
			return ( OS_ERR_PRIO_INVALID );
		}
	}
#endif

	/*$PAGE*/
	OS_ENTER_CRITICAL();
	if ( prio == OS_PRIO_SELF )                         /* See if requesting to delete self            */
	{
		prio = OSTCBCur->OSTCBPrio;                     /* Set priority to delete to current           */
	}
	ptcb = OSTCBPrioTbl[prio];
	if ( ptcb == ( OS_TCB * )0 )                        /* Task to delete must exist                   */
	{
		OS_EXIT_CRITICAL();
		return ( OS_ERR_TASK_NOT_EXIST );
	}
	if ( ptcb == OS_TCB_RESERVED )                      /* Must not be assigned to Mutex               */
	{
		OS_EXIT_CRITICAL();
		return ( OS_ERR_TASK_DEL );
	}

	OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX;
	if ( OSRdyTbl[ptcb->OSTCBY] == 0 )                  /* Make task not ready                         */
	{
		OSRdyGrp           &= ~ptcb->OSTCBBitY;
	}

#if (OS_EVENT_EN)
	if ( ptcb->OSTCBEventPtr != ( OS_EVENT * )0 )
	{
		OS_EventTaskRemove( ptcb, ptcb->OSTCBEventPtr );  /* Remove this task from any event   wait list */
	}
#if (OS_EVENT_MULTI_EN > 0)
	if ( ptcb->OSTCBEventMultiPtr != ( OS_EVENT ** )0 ) /* Remove this task from any events' wait lists*/
	{
		OS_EventTaskRemoveMulti( ptcb, ptcb->OSTCBEventMultiPtr );
	}
#endif
#endif

#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
	pnode = ptcb->OSTCBFlagNode;
	if ( pnode != ( OS_FLAG_NODE * )0 )                 /* If task is waiting on event flag            */
	{
		OS_FlagUnlink( pnode );                         /* Remove from wait list                       */
	}
#endif

	ptcb->OSTCBDly      = 0;                            /* Prevent OSTimeTick() from updating          */
	ptcb->OSTCBStat     = OS_STAT_RDY;                  /* Prevent task from being resumed             */
	ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
	if ( OSLockNesting < 255u )                         /* Make sure we don't context switch           */
	{
		OSLockNesting++;
	}
	OS_EXIT_CRITICAL();                                 /* Enabling INT. ignores next instruc.         */
	OS_Dummy();                                         /* ... Dummy ensures that INTs will be         */
	OS_ENTER_CRITICAL();                                /* ... disabled HERE!                          */
	if ( OSLockNesting > 0 )                            /* Remove context switch lock                  */
	{
		OSLockNesting--;
	}
	OSTaskDelHook( ptcb );                              /* Call user defined hook                      */
	OSTaskCtr--;                                        /* One less task being managed                 */
	OSTCBPrioTbl[prio] = ( OS_TCB * )0;                 /* Clear old priority entry                    */
	if ( ptcb->OSTCBPrev == ( OS_TCB * )0 )             /* Remove from TCB chain                       */
	{
		ptcb->OSTCBNext->OSTCBPrev = ( OS_TCB * )0;
		OSTCBList                  = ptcb->OSTCBNext;
	}
	else
	{
		ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;
		ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;
	}
	ptcb->OSTCBNext   = OSTCBFreeList;                  /* Return TCB to free TCB list                 */
	OSTCBFreeList     = ptcb;
#if OS_TASK_NAME_SIZE > 1
	ptcb->OSTCBTaskName[0] = '?';                       /* Unknown name                                */
	ptcb->OSTCBTaskName[1] = OS_ASCII_NUL;
#endif
	OS_EXIT_CRITICAL();
	if ( OSRunning == OS_TRUE )
	{
		OS_Sched();                                     /* Find new highest priority task              */
	}
	return ( OS_ERR_NONE );
}
示例#5
0
/*$PAGE*/
void  OSSemPend (OS_EVENT  *pevent,
                 INT32U     timeout,
                 INT8U     *perr)
{
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
    OS_CPU_SR  cpu_sr = 0u;
#endif



#ifdef OS_SAFETY_CRITICAL
    if (perr == (INT8U *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    }
#endif

#if OS_ARG_CHK_EN > 0u
    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
        *perr = OS_ERR_PEVENT_NULL;
        return;
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
        *perr = OS_ERR_EVENT_TYPE;
        return;
    }
    if (OSIntNesting > 0u) {                          /* See if called from ISR ...                    */
        *perr = OS_ERR_PEND_ISR;                      /* ... can't PEND from an ISR                    */
        return;
    }
    if (OSLockNesting > 0u) {                         /* See if called with scheduler locked ...       */
        *perr = OS_ERR_PEND_LOCKED;                   /* ... can't PEND when locked                    */
        return;
    }
    OS_ENTER_CRITICAL();
	/* 信号量大于0,则信号量减1,返回 */
    if (pevent->OSEventCnt > 0u) {                    /* If sem. is positive, resource available ...   */
        pevent->OSEventCnt--;                         /* ... decrement semaphore only if positive.     */
        OS_EXIT_CRITICAL();
        *perr = OS_ERR_NONE;
        return;
    }
	
	/* 信号量为0,则把TCB中的状态设置为等待信号量,并设置请求状态为请求OK */
                                                      /* Otherwise, must wait until event occurs       */
    OSTCBCur->OSTCBStat     |= OS_STAT_SEM;           /* Resource not available, pend on semaphore     */
    OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;
	/* 把等待时限写入TCB */
    OSTCBCur->OSTCBDly       = timeout;               /* Store pend timeout in TCB                     */
	/* 设置TCB中等待的事件
	 * 设置事件控制块中等待任务列表
	 * 取消当前任务的就绪状态 
	 */
    OS_EventTaskWait(pevent);                         /* Suspend task until event or timeout occurs    */
    OS_EXIT_CRITICAL();
	/* 查找最高优先级的就绪任务,并调度运行 */
    OS_Sched();                                       /* Find next highest priority task ready         */
	/* 执行OS_Sched()后,已经切换到其他任务。执行这里时,已经是信号量有效或者是等待超时了 */
    OS_ENTER_CRITICAL();
	/* 根据状态设置函数返回值 */
    switch (OSTCBCur->OSTCBStatPend) {                /* See if we timed-out or aborted                */
        case OS_STAT_PEND_OK:
             *perr = OS_ERR_NONE;
             break;

        case OS_STAT_PEND_ABORT:
             *perr = OS_ERR_PEND_ABORT;               /* Indicate that we aborted                      */
             break;

        case OS_STAT_PEND_TO:
        default:
			/* 清除事件等待列表中的当前任务 
			 * 因为OSSemPost()而退出等待状态的任务,会在OSSemPost()中清除事件等待列表中的该任务对应位
			 * 因为超时而退出等待状态的任务,对应的事件控制块的事件等待列表中该任务不会被清除,需要在这里清除
			 */
             OS_EventTaskRemove(OSTCBCur, pevent);
             *perr = OS_ERR_TIMEOUT;                  /* Indicate that we didn't get event within TO   */
             break;
    }
	/* 设置当前任务控制块状态 */
    OSTCBCur->OSTCBStat          =  OS_STAT_RDY;      /* Set   task  status to ready                   */
    OSTCBCur->OSTCBStatPend      =  OS_STAT_PEND_OK;  /* Clear pend  status                            */
    OSTCBCur->OSTCBEventPtr      = (OS_EVENT  *)0;    /* Clear event pointers                          */
#if (OS_EVENT_MULTI_EN > 0u)
    OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endif
    OS_EXIT_CRITICAL();
}