CooCox 1.1.4 on mbed with simple blinky example

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers event.c Source File

event.c

Go to the documentation of this file.
00001 /**
00002  *******************************************************************************
00003  * @file       event.c
00004  * @version    V1.1.4    
00005  * @date       2011.04.20
00006  * @brief      event management implementation code of CooCox CoOS kernel.    
00007  *******************************************************************************
00008  * @copy
00009  *
00010  * INTERNAL FILE,DON'T PUBLIC.
00011  * 
00012  * <h2><center>&copy; COPYRIGHT 2009 CooCox </center></h2>
00013  *******************************************************************************
00014  */ 
00015 
00016 
00017 /*---------------------------- Include ---------------------------------------*/
00018 #include <coocox.h>
00019 
00020 
00021 /*---------------------------- Variable Define -------------------------------*/
00022 #if CFG_EVENT_EN > 0
00023 
00024 ECB    EventTbl [CFG_MAX_EVENT]= {{0}};/*!< Table which save event control block.*/
00025 P_ECB  FreeEventList  = 0;        /*!< Pointer to free event control block. */
00026 
00027 
00028 /**
00029  *******************************************************************************
00030  * @brief      Create a empty list of event control block        
00031  * @param[in]  None      
00032  * @param[out] None       
00033  * @retval     None     
00034  *
00035  * @par Description
00036  * @details    This function is called by OSInit() API to create a ECB list,supply
00037  *             a  pointer to next event control block that not used.                     
00038  *******************************************************************************
00039  */
00040 void CreateEventList(void)
00041 {    
00042     U8  i;
00043     P_ECB pecb1;
00044 #if CFG_MAX_EVENT > 1
00045     P_ECB pecb2;
00046 #endif
00047     i=0;
00048     pecb1 = &EventTbl[0];               /* Get first item                     */
00049 #if CFG_MAX_EVENT == 1                  /* Build event list for only one item */                                       
00050     pecb1->eventPtr   = Co_NULL;
00051     pecb1->id         = i;               /* Assign ID.                         */
00052     pecb1->eventType  = EVENT_TYPE_INVALID;  /* Sign that not to use.          */
00053 #endif
00054     
00055 #if CFG_MAX_EVENT > 1             /* Build event list for more than one item  */                                   
00056     pecb2 = &EventTbl[1];
00057     for(;i< (CFG_MAX_EVENT-1);i++ )
00058     {
00059         pecb1->eventPtr   = (void*)pecb2;      /* Set link for list            */
00060         pecb1->id         = i;                 /* Assign ID.                   */
00061         pecb1->eventType  = EVENT_TYPE_INVALID;/* Sign that not to use.        */
00062         pecb1++;                              /* Get next item                */
00063         pecb2++;    
00064     }
00065     pecb1->eventType  = EVENT_TYPE_INVALID;    /* Sign that not to use.        */
00066     pecb1->eventPtr   = Co_NULL;                  /* Set link for last item       */
00067     pecb1->id         = i;    
00068 #endif
00069     
00070     FreeEventList    = &EventTbl[0];          /* Set free event item          */    
00071 }
00072 
00073 
00074 
00075 /**
00076  *******************************************************************************
00077  * @brief      Release a ECB     
00078  * @param[in]  pecb     A pointer to event control block which be released.     
00079  * @param[out] None 
00080  * @retval     None     
00081  *
00082  * @par Description
00083  * @details    This function is called to release a event control block when a 
00084  *             event be deleted.
00085  *******************************************************************************
00086  */
00087 static void ReleaseECB(P_ECB pecb)
00088 {
00089     pecb->eventType  = EVENT_TYPE_INVALID;     /* Sign that not to use.        */ 
00090     OsSchedLock();                            /* Lock schedule                */
00091     pecb->eventPtr   = FreeEventList ;          /* Release ECB that event hold  */
00092     FreeEventList   = pecb;                   /* Reset free event item        */
00093     OsSchedUnlock();                          /* Unlock schedule              */
00094 }
00095 
00096 
00097 
00098 /**
00099  *******************************************************************************
00100  * @brief      Create a event      
00101  * @param[in]  eventType       The type of event which    being created.
00102  * @param[in]  eventSortType   Event sort type.
00103  * @param[in]  eventCounter    Event counter,ONLY for EVENT_TYPE_SEM.
00104  * @param[in]  eventPtr        Event struct pointer,ONLY for Queue.Co_NULL for other
00105  *                             event type.        
00106  * @param[out] None  
00107  * @retval     Co_NULL     Invalid pointer,create event fail.
00108  * @retval     others   Pointer to event control block which had assigned right now.
00109  *
00110  * @par Description
00111  * @details    This function is called by CreateSem(),...
00112  *             to get a event control block and initial the event content. 
00113  *
00114  * @note       This is a internal function of CooCox CoOS,User can't call.
00115  *******************************************************************************
00116  */
00117 P_ECB CreatEvent(U8 eventType,U8 eventSortType,void* eventPtr)
00118 {
00119     P_ECB pecb;
00120     
00121     OsSchedLock();                      /* Lock schedule                      */
00122     if(FreeEventList == Co_NULL)           /* Is there no free evnet item        */
00123     {
00124         OsSchedUnlock();                /* Yes,unlock schedule                */
00125         return 0;                    /* Return error                       */
00126     }
00127     pecb          = FreeEventList ;/* Assign the free event item to this event */
00128     FreeEventList = (P_ECB)FreeEventList->eventPtr ;  /* Reset free event item        */
00129     OsSchedUnlock();                    /* Unlock schedul                     */
00130     
00131     pecb->eventType      = eventType;    /* Initialize event item as user set  */
00132     pecb->eventSortType  = eventSortType;
00133     pecb->eventPtr       = eventPtr;
00134     pecb->eventTCBList   = 0;
00135     return pecb;                        /* Return event item pointer          */
00136 }
00137 
00138 
00139 /**
00140  *******************************************************************************
00141  * @brief      Delete a event      
00142  * @param[in]  pecb     Pointer to event control block which will be deleted. 
00143  * @param[in]  opt      Delete option.
00144  * @arg        == OPT_DEL_ANYWAY     Delete event always   
00145  * @arg        == OPT_DEL_NO_PEND     Delete event only when no task pending on.
00146  * @param[out] None       
00147  * @retval     E_INVALID_PARAMETER   Parameter passed is invalid,deleted fail.
00148  * @retval     E_TASK_WAITTING       These are one more tasks waitting event.  
00149  * @retval     E_OK                  Delete event control block successful.
00150  *              
00151  * @par Description
00152  * @details    This function is called to delete a event from the event wait list
00153  *             use specify option.
00154  *
00155  * @note       This is a internal function of Coocox CoOS,user can't call.        
00156  *******************************************************************************
00157  */
00158 StatusType DeleteEvent(P_ECB pecb,U8 opt)
00159 {
00160     P_OSTCB ptcb;
00161     if(opt == OPT_DEL_NO_PEND)          /* Do delete event when no task pend? */
00162     {
00163         if(pecb->eventTCBList  != Co_NULL)  /* Yes,is there task pend this event? */
00164         {
00165             return E_TASK_WAITING;      /* Yes,error return                   */
00166         }
00167         else
00168         {
00169             ReleaseECB(pecb);           /* No,release resource that event hold*/
00170         }
00171     }
00172     else if(opt == OPT_DEL_ANYWAY)      /* Do delete event anyway?            */
00173     {
00174         OsSchedLock();                      /* Lock schedule                  */
00175         while(pecb->eventTCBList  != Co_NULL)   /* Is there task pend this event? */
00176         {                                   /* Yes,remove it                  */
00177             ptcb = pecb->eventTCBList ;/* Get first task in event waiting list */
00178             if(ptcb->delayTick  != INVALID_VALUE) /* Is task in delay list?    */
00179             {
00180                 RemoveDelayList(ptcb);    /* Yes,remove task from delay list  */
00181             }
00182 
00183             /* Set next item as event waiting list head */
00184             pecb->eventTCBList  = ptcb->waitNext ; 
00185             ptcb->waitNext      = 0;  /* Clear link for event waiting list  */
00186             ptcb->eventID       = INVALID_ID;  /* Sign that not to use.        */
00187 
00188             InsertToTCBRdyList(ptcb);         /* Insert task into ready list  */
00189         }
00190         OsSchedUnlock();                  /* Unlock schedule                  */
00191         ReleaseECB(pecb);                 /* Release resource that event hold */
00192     }
00193     return E_OK;                          /* Return OK                        */
00194 }
00195 
00196 
00197 /**
00198  *******************************************************************************
00199  * @brief      Insert a task to event wait list                                 
00200  * @param[in]  pecb    Pointer to event control block corresponding to the event.     
00201  * @param[in]  ptcb    Pointer to task that will be insert to event wait list.     
00202  * @param[out] None   
00203  * @retval     None     
00204  *
00205  * @par Description
00206  * @details   This function is called to insert a task by fllowing manner:
00207  *            opt == EVENT_SORT_TYPE_FIFO   By FIFO.
00208  *            opt == EVENT_SORT_TYPE_PRIO   By priority order,hghest priority 
00209  *                                          as head,lowest priority as end.
00210  *                                          (Highest-->...-->Lowest-->Co_NULL)
00211  *******************************************************************************
00212  */
00213 void EventTaskToWait(P_ECB pecb,P_OSTCB ptcb)
00214 {
00215     P_OSTCB ptcb1;
00216 #if (CFG_EVENT_SORT == 2) || (CFG_EVENT_SORT == 3)
00217     P_OSTCB ptcb2;
00218 #endif
00219     
00220     OsSchedLock();                  /* Lock schedule                          */
00221     ptcb1 = pecb->eventTCBList ;     /* Get first task in event waiting list   */
00222     ptcb->eventID  = pecb->id ;       /* Set event ID for task                  */
00223     
00224 #if CFG_EVENT_SORT == 3             /* Does event waiting list sort as FIFO?  */
00225                               
00226     if(pecb->eventSortType  == EVENT_SORT_TYPE_FIFO)    
00227 #endif
00228     
00229 #if (CFG_EVENT_SORT == 1) || (CFG_EVENT_SORT == 3)
00230     {
00231         if(ptcb1 == Co_NULL)                 /* Is no item in event waiting list?*/
00232         {
00233             pecb->eventTCBList  = ptcb;    /* Yes,set task as first item       */
00234         }
00235         else
00236         {                                
00237             while(ptcb1->waitNext  != Co_NULL)/* No,insert task in last           */
00238             {
00239                 ptcb1 = ptcb1->waitNext ;    
00240             }    
00241             ptcb1->waitNext  = ptcb;       /* Set link for list                */
00242             ptcb->waitPrev   = ptcb1;    
00243         }
00244     }
00245 #endif
00246     
00247 #if CFG_EVENT_SORT ==3 /* Does event waiting list sort as preemptive priority?*/                           
00248     else if(pecb->eventSortType  == EVENT_SORT_TYPE_PRIO)
00249 #endif  
00250 #if (CFG_EVENT_SORT == 2) || (CFG_EVENT_SORT == 3)
00251     {
00252         if(ptcb1 == Co_NULL)               /* Is no item in event waiting list?  */
00253         {
00254             pecb->eventTCBList  = ptcb;  /* Yes,set task as first item         */
00255         }
00256         /* Is PRI of task higher than list first item?                        */
00257         else if(ptcb1->prio  > ptcb->prio ) 
00258         {
00259             pecb->eventTCBList  = ptcb;  /* Reset task as first item           */
00260             ptcb->waitNext      = ptcb1; /* Set link for list                  */
00261             ptcb1->waitPrev     = ptcb;    
00262         }
00263         else                            /* No,find correct place to insert    */
00264         {                                
00265             ptcb2 = ptcb1->waitNext ;
00266             while(ptcb2 != Co_NULL)        /* Is last item?                      */
00267             {                              
00268                 if(ptcb2->prio  > ptcb->prio )  /* No,is correct place?         */
00269                 { 
00270                     break;                    /* Yes,break Circulation        */
00271                 }
00272                 ptcb1 = ptcb2;                /* Save current item            */
00273                 ptcb2 = ptcb2->waitNext ;      /* Get next item                */
00274             }
00275             ptcb1->waitNext  = ptcb;           /* Set link for list            */
00276             ptcb->waitPrev   = ptcb1;
00277             ptcb->waitNext   = ptcb2;
00278             if(ptcb2 != Co_NULL)
00279             {
00280                 ptcb2->waitPrev  = ptcb;    
00281             }
00282         }        
00283     }
00284 #endif
00285     ptcb->state  = TASK_WAITING;     /* Set task status to TASK_WAITING state  */
00286     TaskSchedReq = Co_TRUE;
00287     OsSchedUnlock();                /* Unlock schedule,and call task schedule */
00288 }
00289 
00290 
00291 /**
00292  *******************************************************************************
00293  * @brief      Move a task from event WAITING list to the DELAY list      
00294  * @param[in]  pecb    Pointer to event control block corresponding to the event.                
00295  * @param[out] None  
00296  * @retval     None     
00297  *
00298  * @par Description
00299  * @details    This function is called to remove a task from event wait list,and     
00300  *             then insert it into the READY list.
00301  *******************************************************************************
00302  */
00303 void EventTaskToRdy(P_ECB pecb)
00304 {
00305     P_OSTCB ptcb;
00306 #if CFG_QUEUE_EN >0
00307     P_QCB   pqcb;
00308 #endif
00309     ptcb = pecb->eventTCBList ;
00310     if(ptcb == 0)
00311         return;
00312     
00313     pecb->eventTCBList  = ptcb->waitNext ;/* Get first task in event waiting list*/
00314     if(pecb->eventTCBList  != Co_NULL)      /* Is no item in event waiting list?  */
00315     {
00316         pecb->eventTCBList ->waitPrev  = 0; /* No,clear link for first item  */
00317     }
00318     
00319     ptcb->waitNext  = 0;                /* Clear event waiting link for task*/
00320     ptcb->eventID   = INVALID_ID;          /* Sign that not to use.            */
00321     
00322     if(ptcb->delayTick  != INVALID_VALUE)  /* Is task in delay list?           */                 
00323     {
00324         RemoveDelayList(ptcb);            /* Yes,remove task from DELAY list  */
00325     }
00326     if(pecb->eventType  == EVENT_TYPE_MBOX)/* Is it a mailbox event?           */
00327     {
00328         ptcb->pmail     = pecb->eventPtr ;  /* Yes,send mail to task            */
00329         pecb->eventPtr  = Co_NULL;            /* Clear event sign                 */
00330         pecb->eventCounter --;
00331     }
00332 #if CFG_QUEUE_EN >0
00333     else if(pecb->eventType  == EVENT_TYPE_QUEUE)  /* Is it a queue event?     */
00334     {                                           
00335         pqcb        = (P_QCB)pecb->eventPtr ;      /* Yes,get queue pointer    */
00336         ptcb->pmail  = *(pqcb->qStart  + pqcb->head );   /* Send mail to task    */
00337         pqcb->head ++;                             /* Clear event sign         */
00338         pqcb->qSize --;
00339         if(pqcb->head  == pqcb->qMaxSize )
00340         {
00341             pqcb->head  = 0;    
00342         }
00343     }
00344 #endif
00345 
00346 #if CFG_MAILBOX_EN >0
00347     else if(pecb->eventType  == EVENT_TYPE_SEM)/* Is it a semaphore event?     */
00348     {
00349         pecb->eventCounter --;                 /* Yes,clear event sign         */
00350         ptcb->pmail  = (void*)0xffffffff;      /* Indicate task woke by event  */
00351     }
00352 #endif
00353     if(ptcb == TCBRunning )
00354     {
00355         ptcb->state  = TASK_RUNNING;
00356     } 
00357     else
00358     {
00359         InsertToTCBRdyList(ptcb);            /* Insert task into ready list  */
00360     }
00361 }
00362 
00363 
00364 
00365 /**
00366  *******************************************************************************
00367  * @brief      Move a task from event wait list to the ready list      
00368  * @param[in]  pecb    Pointer to event control block corresponding to the event.                
00369  * @param[out] None  
00370  * @retval     None     
00371  *
00372  * @par Description
00373  * @details    This function is called to remove a task from event wait list,and     
00374  *             then insert it to the ready list.
00375  *******************************************************************************
00376  */
00377 void RemoveEventWaittingList(P_OSTCB ptcb)
00378 {
00379     P_ECB pecb;
00380     pecb = &EventTbl[ptcb->eventID ];    /* Get event control block            */
00381     
00382     /* Is there only one item in event waiting list?                          */
00383     if((ptcb->waitNext  == 0) && (ptcb->waitPrev  == 0))
00384     {
00385         pecb->eventTCBList  = 0;      /* Yes,set event waiting list as Co_NULL */
00386     }
00387     else if(ptcb->waitPrev  == 0)/* Is the first item in event waiting list?*/
00388     {
00389         /* Yes,remove task from list,and reset event waiting list             */
00390         ptcb->waitNext ->waitPrev  = 0;
00391         pecb->eventTCBList  = ptcb->waitNext ;    
00392         ptcb->waitNext  = 0;
00393     }
00394     else if(ptcb->waitNext  == 0)/* Is the last item in event waiting list? */
00395     {
00396         ptcb->waitPrev ->waitNext  = 0;  /* Yes,remove task form list        */
00397         ptcb->waitPrev  = 0;
00398     }
00399     else                                  /* No, remove task from list        */
00400     {                                        
00401         ptcb->waitPrev ->waitNext  = ptcb->waitNext ;
00402         ptcb->waitNext ->waitPrev  = ptcb->waitPrev ;
00403         ptcb->waitPrev  = 0;
00404         ptcb->waitNext  = 0;
00405     }
00406     ptcb->eventID   = INVALID_ID;          /* Sign that not to use.            */
00407 }
00408 
00409 #endif     //CFG_EVENT_EN
00410