Beispiel #1
0
/**
 *******************************************************************************
 * @brief      Change task priority	   
 * @param[in]  taskID     Specify task id.
 * @param[in]  priority   New priority.	 
 * @param[out] None		   
 * @retval     E_OK              Change priority successful.
 * @retval     E_INVALID_ID      Invalid id,change priority fail.
 * @retval     E_PROTECTED_TASK  Can't change idle task priority.		 
 *
 * @par Description
 * @details    This function is called to change priority for a specify task. 	
 *******************************************************************************
 */
StatusType CoSetPriority(OS_TID taskID,U8 priority)
{			
    P_OSTCB ptcb;
#if CFG_MUTEX_EN >0
    U8 prio;
    P_MUTEX	pMutex;
#endif
#if CFG_EVENT_EN >0
    P_ECB pecb;
#endif

    if(taskID == 0)                     /* Is idle task?                      */
    {											 
        return E_PROTECTED_TASK;        /* Yes,error return                   */
    }   
	
#if CFG_PAR_CHECKOUT_EN >0              /* Check validity of parameter        */
    if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM)
    {
        return E_INVALID_ID;
    }
#endif
	ptcb = &TCBTbl[taskID];             /* Get TCB of task ID                 */
#if CFG_PAR_CHECKOUT_EN >0    
    if(ptcb->state == TASK_DORMANT)
    {
        return E_INVALID_ID;
    }
    if(priority > CFG_LOWEST_PRIO)
    {
        return E_INVALID_ID;
    }
#endif

    if(ptcb->prio != priority)          /* Is PRI equal to original PRI?      */
    {                                   /* No                                 */
#if CFG_MUTEX_EN >0
        if(ptcb->mutexID != INVALID_ID)
        {
            pMutex = &MutexTbl[ptcb->mutexID];
            if(pMutex->taskID == ptcb->taskID)  /* Task hold mutex?               */
            {
                 pMutex->originalPrio= priority;/* Yes,change original PRI in mutex*/
                 if(ptcb->prio < priority)     /* Is task priority higher than set?*/
                 {
                     return E_OK;                /* Yes,do nothing,return OK       */
                 }
            }		
         }

#endif	

#if CFG_ORDER_LIST_SCHEDULE_EN ==0
		DeleteTaskPri(ptcb->prio);
		ActiveTaskPri(priority);	
#endif	

        ptcb->prio = priority;              /* Change task PRI                */
        if(ptcb->state == TASK_READY)       /* Is task in READY list?         */
        {
            OsSchedLock();                  /* Yes,reorder task in READY list */
            RemoveFromTCBRdyList(ptcb);
            InsertToTCBRdyList(ptcb);	
            OsSchedUnlock();
        }
        else if(ptcb->state == TASK_RUNNING)/* Is task running?               */
        {
            if(ptcb->prio > TCBRdy->prio)   /* Yes,Is PRI higher than TCBRdy? */
            {
				OsSchedLock();              /* Yes,reorder task in READY list */
				TaskSchedReq = Co_TRUE;
                OsSchedUnlock();
            }
        }
        else
        {                                   /* No,task in WAITING list        */
#if CFG_MUTEX_EN >0
            if(ptcb->mutexID != INVALID_ID) /* Is task in mutex WAITING list? */
            {
                /* Yes,reset the highest PRI in the list */
				OsSchedLock(); 
				pMutex = &MutexTbl[ptcb->mutexID];
                ptcb = pMutex->waittingList;  
                prio = pMutex->originalPrio; 
                pMutex->hipriTaskID = pMutex->taskID;
                while(ptcb != Co_NULL)
                {
                    if(ptcb->prio < prio)
                    {
                        prio = ptcb->prio;
                        pMutex->hipriTaskID = ptcb->taskID;
                    }
                    ptcb = ptcb->TCBnext;			
                }
				OsSchedUnlock();
                if(pMutex->originalPrio != prio)
                {
                    CoSetPriority(pMutex->taskID,prio);	
                }	
            }
#endif

#if CFG_EVENT_EN >0
			ptcb = &TCBTbl[taskID];
            if(ptcb->eventID != INVALID_ID) /* Is task in event WAITING list? */
            {								    
                pecb = &EventTbl[ptcb->eventID];
                
                /* Yes,is event sort type as preemptive PRI?                  */
                if(pecb->eventSortType == EVENT_SORT_TYPE_PRIO)
                {	  
                    /* Yes,reorder task in the list                           */
                    RemoveEventWaittingList(ptcb);
                    EventTaskToWait(pecb,ptcb);
                }	
            }
#endif
        }
    }
    return E_OK;
}
Beispiel #2
0
/**
 *******************************************************************************
 * @brief      Pend for a mail	 
 * @param[in]  id       Event ID.	 
 * @param[in]  timeout  The longest time for writting mail.	
 * @param[out] perr     A pointer to error code.   
 * @retval     NULL	
 * @retval     A pointer to mail accept.	 
 *
 * @par Description
 * @details    This function is called to wait for a mail.		   	
 * @note 
 *******************************************************************************
 */
void* CoPendQueueMail(OS_EventID id,U32 timeout,StatusType* perr)
{
    P_ECB   pecb;
    P_QCB   pqcb;
    P_OSTCB curTCB;
    void*   pmail;
    if(OSIntNesting > 0)                /* If the caller is ISR               */
    {
        *perr = E_CALL;
        return NULL;
    }
#if CFG_PAR_CHECKOUT_EN >0
    if(id >= CFG_MAX_EVENT)	         
    {
        *perr = E_INVALID_ID;           /* Invalid event id,return error      */
        return NULL;
    }
#endif

    pecb = &EventTbl[id];
#if CFG_PAR_CHECKOUT_EN >0
    if(pecb->eventType != EVENT_TYPE_QUEUE) /* The event type is not queue    */
    {
        *perr = E_INVALID_ID;
        return NULL;	
    }
#endif	
    if(OSSchedLock != 0)                /* Judge schedule is locked or not?   */
    {	
        *perr = E_OS_IN_LOCK;           /* Schedule is locked,return error    */								 
        return NULL;          
    }	
    pqcb = (P_QCB)pecb->eventPtr;       /* Point at queue control block       */
	 
    if(pqcb->qSize != 0)            /* If there are any messages in the queue */
    {
        /* Extract oldest message from the queue                              */
        pmail = *(pqcb->qStart + pqcb->head);   
        pqcb->head++;                   /* Update the queue head              */ 
        pqcb->qSize--;          /* Update the number of messages in the queue */  
        if(pqcb->head == pqcb->qMaxSize)/* Check queue head                   */
        {
            pqcb->head = 0;	
        }
        *perr = E_OK;
        return pmail;                   /* Return message received            */
    }
    else                                /* If there is no message in the queue*/
    {
        curTCB = TCBRunning;
        if(timeout == 0)                /* If time-out is not configured      */
        {
            /* Block current task until the event occur                       */
            EventTaskToWait(pecb,curTCB); 
            
            /* Have recived message or the queue have been deleted            */
            pmail = curTCB->pmail;              
            curTCB->pmail = NULL;
            *perr = E_OK;
            return pmail;               /* Return message received or NULL    */
        }
        else                            /* If time-out is configured          */
        {
            OsSchedLock(); 
            
            /* Block current task until event or timeout occurs               */           
            EventTaskToWait(pecb,curTCB);       
            InsertDelayList(curTCB,timeout);
            OsSchedUnlock();
            if(curTCB->pmail == NULL)   /* If time-out occurred               */
            {
                *perr = E_TIMEOUT;
                return NULL;
            }
            else                        /* If event occured                   */
            {
                pmail = curTCB->pmail;
                curTCB->pmail = NULL;
                *perr = E_OK;
                return pmail;           /* Return message received or NULL    */
            }				
        }	
    }
}
Beispiel #3
0
/**
 *******************************************************************************
 * @brief       wait for a semaphore	   
 * @param[in]   id       Event ID.	
 * @param[in]   timeout  The longest time for writting semaphore.
 * @para        0        
 * @para        0x1~0xff 	 
 * @param[out]  None  
 * @retval      E_CALL         Error call in ISR.   
 * @retval      E_INVALID_ID   Invalid event ID.	
 * @retval      E_TIMEOUT      Semaphore was not received within the specified 
 *                             'timeout' time.
 * @retval      E_OK           The call was successful and your task owns the 
 *                             resource,or the event you are waiting for occurred.	
 * 
 * @par Description
 * @details    This function is called to waits for a semaphore. 
 * @note       IF this function is called in ISR,nothing to do and return immediately.
 *******************************************************************************
 */
StatusType CoPendSem(OS_EventID id,U32 timeout)
{
    P_ECB 	 pecb;
    P_OSTCB  curTCB;
    if(OSIntNesting > 0)                /* If the caller is ISR               */
    {
        return E_CALL;
    }
#if CFG_PAR_CHECKOUT_EN >0
    if(id >= CFG_MAX_EVENT)	            
    {
        return E_INVALID_ID;
    }
#endif

	  pecb = &EventTbl[id];
#if CFG_PAR_CHECKOUT_EN >0
    if(pecb->eventType != EVENT_TYPE_SEM)     
    {
       return E_INVALID_ID;	
    }
#endif
    if(OSSchedLock != 0)                /* Schdule is locked?                 */
    {
        return E_OS_IN_LOCK;            /* Yes,error return                   */
    }
    OsSchedLock();
    if(pecb->eventCounter > 0) /* If semaphore is positive,resource available */       
    {	
        pecb->eventCounter--;         /* Decrement semaphore only if positive */
        OsSchedUnlock();
        return E_OK;	
    }
    else                                /* Resource is not available          */
    {
        curTCB = TCBRunning;
        if(timeout == 0)                /* If time-out is not configured      */
        {
            EventTaskToWait(pecb,curTCB); /* Block task until event occurs    */ 
            pecb->eventCounter--;             
            curTCB->pmail = Co_NULL;
            OsSchedUnlock();
            return E_OK;
        }
        else                            /* If time-out is configured          */
        {
            /* Block task until event or timeout occurs                       */
            EventTaskToWait(pecb,curTCB);
            InsertDelayList(curTCB,timeout);
            
            OsSchedUnlock();
            if (curTCB->pmail == Co_NULL)  /* If pmail is Co_NULL, time-out occurred*/
            {
              return E_TIMEOUT;	
            }                               
            else                  /* Event occurred or event have been deleted*/    
            {
                OsSchedLock();
                curTCB->pmail = Co_NULL;
                pecb->eventCounter--; 
                OsSchedUnlock();
                return E_OK;	
            }				
        }		
    }
}
Beispiel #4
0
/**	
 *******************************************************************************		 	
 * @brief      Enter a critical area  
 * @param[in]  mutexID    Specify mutex. 	 
 * @param[out] None   
 * @retval     E_INVALID_ID  Invalid mutex id. 	
 * @retval     E_CALL        Error call in ISR.
 * @retval     E_OK          Enter critical area successful.
 *
 * @par Description
 * @details    This function is called when entering a critical area.	 
 * @note 
 *******************************************************************************
 */
StatusType CoEnterMutexSection(OS_MutexID mutexID)
{
    P_OSTCB ptcb,pCurTcb;
    P_MUTEX pMutex;

#if CFG_EVENT_EN >0
    P_ECB pecb;
#endif

    if(OSIntNesting > 0)                /* If the caller is ISR               */
    {
        return E_CALL;
    }
    if(OSSchedLock != 0)                /* Is OS lock?                        */
    {								 
        return E_OS_IN_LOCK;            /* Yes,error return                   */
    }	

#if CFG_PAR_CHECKOUT_EN >0
    if(mutexID >= MutexFreeID)          /* Invalid 'mutexID'                  */
    {
        return E_INVALID_ID;	
    }
#endif

    OsSchedLock();
    pCurTcb = TCBRunning;
    pMutex  = &MutexTbl[mutexID];
    
    pCurTcb->mutexID = mutexID;
    if(pMutex->mutexFlag == MUTEX_FREE)       /* If mutex is available        */	 
    {
        pMutex->originalPrio = pCurTcb->prio; /* Save priority of owning task */   
        pMutex->taskID       = pCurTcb->taskID;   /* Acquire the resource     */
        pMutex->hipriTaskID  = pCurTcb->taskID;
        pMutex->mutexFlag    = MUTEX_OCCUPY;      /* Occupy the mutex resource*/
    }
    /* If the mutex resource had been occupied                                */
    else if(pMutex->mutexFlag == MUTEX_OCCUPY)	 	
    {	
		ptcb = &TCBTbl[pMutex->taskID];
        if(ptcb->prio > pCurTcb->prio)  /* Need to promote priority of owner? */
        {
#if CFG_ORDER_LIST_SCHEDULE_EN ==0
			DeleteTaskPri(ptcb->prio);
			ActiveTaskPri(pCurTcb->prio);
#endif	
            ptcb->prio = pCurTcb->prio;	    /* Promote prio of owner          */
            
            /* Upgarde the highest priority about the mutex                   */
            pMutex->hipriTaskID	= pCurTcb->taskID;	
            if(ptcb->state == TASK_READY)   /* If the task is ready to run    */
            {
                RemoveFromTCBRdyList(ptcb); /* Remove the task from READY list*/
                InsertToTCBRdyList(ptcb);   /* Insert the task into READY list*/
            }
#if CFG_EVENT_EN >0
            /* If the task is waiting on a event                              */
            else if(ptcb->eventID != INVALID_ID) 
            {
                pecb = &EventTbl[ptcb->eventID];
                
                /* If the event waiting type is preemptive Priority           */
                if(pecb->eventSortType == EVENT_SORT_TYPE_PRIO)	
                {
                    /* Remove the task from event waiting list                */
                    RemoveEventWaittingList(ptcb);
                    
                    /* Insert the task into event waiting list                */ 	
                    EventTaskToWait(pecb,ptcb);		
                }	
            }
#endif	
        }
        
        pCurTcb->state   = TASK_WAITING;    /* Block current task             */
		TaskSchedReq     = Co_TRUE;
        pCurTcb->TCBnext = Co_NULL;
        pCurTcb->TCBprev = Co_NULL;
        
        ptcb = pMutex->waittingList;
        if(ptcb == Co_NULL)               /* If the event waiting list is empty  */
        {
            pMutex->waittingList = pCurTcb; /* Insert the task to head        */
        }
        else                        /* If the event waiting list is not empty */
        {            	
            while(ptcb->TCBnext != Co_NULL)    /* Insert the task to tail        */
            {
                ptcb = ptcb->TCBnext;		
            }
            ptcb->TCBnext    = pCurTcb;
            pCurTcb->TCBprev = ptcb;
            pCurTcb->TCBnext = Co_NULL;
        }
    }
    OsSchedUnlock();
    return E_OK;			
}
Beispiel #5
0
/**
 *******************************************************************************
 * @brief      Wait for a mailbox	 
 * @param[in]  id       Event ID.	 
 * @param[in]  timeout  The longest time for writting mail.	    
 * @param[out] perr     A pointer to error code.	  
 * @retval     NULL	
 * @retval     A pointer to mailbox accept.
 *
 * @par Description
 * @details    This function is called to wait a mailbox.	 
 * @note 
 *******************************************************************************
 */
void* CoPendMail(OS_EventID id,U32 timeout,StatusType* perr)
{
    P_ECB pecb;
    void* pmail;
    P_OSTCB  curTCB;
     
    if(OSIntNesting > 0)                /* If the caller is ISR               */
    {
        *perr = E_CALL;
        return NULL;
    }
    
#if CFG_PAR_CHECKOUT_EN >0
    if(id >= CFG_MAX_EVENT)              
    {
        *perr = E_INVALID_ID;           /* Invalid 'id',retrun error          */
        return NULL;
    }
#endif

    pecb = &EventTbl[id];
#if CFG_PAR_CHECKOUT_EN >0
    if(pecb->eventType != EVENT_TYPE_MBOX)
    {
        *perr = E_INVALID_ID;       /* Invalid event type,not EVENT_TYPE_MBOX */
        return NULL;
    }
#endif

    if(OSSchedLock != 0)                /* Judge schedule is locked or not?   */
    {	
        *perr = E_OS_IN_LOCK;           /* Schedule is locked                 */								 
        return NULL;                    /* return NULL                        */
    }	
    if( pecb->eventCounter == 1)        /* If there is already a message      */
    {
        *perr = E_OK;
        pmail = pecb->eventPtr;         /* Get the message                    */
        pecb->eventPtr     = NULL;      /* Clear the mailbox                  */
        pecb->eventCounter = 0;             
        return pmail;                   /* Return the message received        */
    }
    else                       /* If message is not available, task will pend */ 
    {
        curTCB = TCBRunning;
        if(timeout == 0)                /* If time-out is not configured      */
        {
            EventTaskToWait(pecb,curTCB); /* Block task until event occurs    */
            *perr = E_OK;
            
            /* Have recived a message or the mailbox have been deleted        */
            pmail = curTCB->pmail;          
            curTCB->pmail = NULL;
            return pmail;               /* Return received message or NULL    */
        }
        else                            /* If time-out is configured          */
        {
            OsSchedLock();
            
            /* Block task until event or timeout occurs                       */
            EventTaskToWait(pecb,curTCB);   
            InsertDelayList(curTCB,timeout);
            OsSchedUnlock();
            if( curTCB->pmail == NULL)  /* Time-out occurred                  */
            {
                *perr = E_TIMEOUT;
                return NULL;	
            }
            else    /* Have recived a message or the mailbox have been deleted*/
            {
                *perr = E_OK;
                pmail = curTCB->pmail;
                curTCB->pmail = NULL;
                return pmail;           /* Return received message or NULL    */	
            }			
        }	
    }
}