croutine.c File Reference

#include "FreeRTOS.h"
#include "task.h"
#include "croutine.h"

Go to the source code of this file.

Defines

#define corINITIAL_STATE   ( 0 )
#define prvAddCoRoutineToReadyQueue(pxCRCB)

Functions

static void prvCheckDelayedList (void)
static void prvCheckPendingReadyList (void)
static void prvInitialiseCoRoutineLists (void)
void vCoRoutineAddToDelayedList (portTickType xTicksToDelay, xList *pxEventList)
void vCoRoutineSchedule (void)
signed portBASE_TYPE xCoRoutineCreate (crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex)
signed portBASE_TYPE xCoRoutineRemoveFromEventList (const xList *pxEventList)

Variables

corCRCBpxCurrentCoRoutine = NULL
static xListpxDelayedCoRoutineList
static xListpxOverflowDelayedCoRoutineList
static xList pxReadyCoRoutineLists [configMAX_CO_ROUTINE_PRIORITIES]
static unsigned portBASE_TYPE uxTopCoRoutineReadyPriority = 0
static portTickType xCoRoutineTickCount = 0
static xList xDelayedCoRoutineList1
static xList xDelayedCoRoutineList2
static portTickType xLastTickCount = 0
static portTickType xPassedTicks = 0
static xList xPendingReadyCoRoutineList


Define Documentation

#define corINITIAL_STATE   ( 0 )

Definition at line 81 of file croutine.c.

Referenced by xCoRoutineCreate().

#define prvAddCoRoutineToReadyQueue ( pxCRCB   ) 

Value:

{                                                                                                                   \
    if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority )                                                          \
    {                                                                                                               \
        uxTopCoRoutineReadyPriority = pxCRCB->uxPriority;                                                           \
    }                                                                                                               \
    vListInsertEnd( ( xList * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) );  \
}

Definition at line 90 of file croutine.c.

Referenced by prvCheckDelayedList(), prvCheckPendingReadyList(), and xCoRoutineCreate().


Function Documentation

static void prvCheckDelayedList ( void   )  [static]

Definition at line 243 of file croutine.c.

References listGET_LIST_ITEM_VALUE, listGET_OWNER_OF_HEAD_ENTRY, portDISABLE_INTERRUPTS, portENABLE_INTERRUPTS, prvAddCoRoutineToReadyQueue, xLIST_ITEM::pvContainer, vListRemove(), xCoRoutineTickCount, corCoRoutineControlBlock::xEventListItem, corCoRoutineControlBlock::xGenericListItem, xLastTickCount, xPassedTicks, and xTaskGetTickCount().

Referenced by vCoRoutineSchedule().

00244 {
00245 corCRCB *pxCRCB;
00246 
00247     xPassedTicks = xTaskGetTickCount() - xLastTickCount;
00248     while( xPassedTicks )
00249     {
00250         xCoRoutineTickCount++;
00251         xPassedTicks--;
00252 
00253         /* If the tick count has overflowed we need to swap the ready lists. */
00254         if( xCoRoutineTickCount == 0 )
00255         {
00256             xList * pxTemp;
00257 
00258             /* Tick count has overflowed so we need to swap the delay lists.  If there are
00259             any items in pxDelayedCoRoutineList here then there is an error! */
00260             pxTemp = pxDelayedCoRoutineList;
00261             pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
00262             pxOverflowDelayedCoRoutineList = pxTemp;
00263         }
00264 
00265         /* See if this tick has made a timeout expire. */
00266         while( ( pxCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ) ) != NULL )
00267         {   
00268             if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )                
00269             {           
00270                 /* Timeout not yet expired. */                                                                          
00271                 break;                                                                              
00272             }                                                                                       
00273 
00274             portDISABLE_INTERRUPTS();
00275             {
00276                 /* The event could have occurred just before this critical
00277                 section.  If this is the case then the generic list item will
00278                 have been moved to the pending ready list and the following
00279                 line is still valid.  Also the pvContainer parameter will have
00280                 been set to NULL so the following lines are also valid. */
00281                 vListRemove( &( pxCRCB->xGenericListItem ) );                                           
00282 
00283                 /* Is the co-routine waiting on an event also? */                                               
00284                 if( pxCRCB->xEventListItem.pvContainer )                                                    
00285                 {                                                           
00286                     vListRemove( &( pxCRCB->xEventListItem ) );                                         
00287                 }
00288             }
00289             portENABLE_INTERRUPTS();
00290 
00291             prvAddCoRoutineToReadyQueue( pxCRCB );                                                  
00292         }                                                                                                   
00293     }
00294 
00295     xLastTickCount = xCoRoutineTickCount;
00296 }

static void prvCheckPendingReadyList ( void   )  [static]

Definition at line 220 of file croutine.c.

References listGET_OWNER_OF_HEAD_ENTRY, listLIST_IS_EMPTY, portDISABLE_INTERRUPTS, portENABLE_INTERRUPTS, prvAddCoRoutineToReadyQueue, vListRemove(), corCoRoutineControlBlock::xEventListItem, and corCoRoutineControlBlock::xGenericListItem.

Referenced by vCoRoutineSchedule().

00221 {
00222     /* Are there any co-routines waiting to get moved to the ready list?  These
00223     are co-routines that have been readied by an ISR.  The ISR cannot access
00224     the ready lists itself. */
00225     while( !listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) )
00226     {
00227         corCRCB *pxUnblockedCRCB;
00228 
00229         /* The pending ready list can be accessed by an ISR. */
00230         portDISABLE_INTERRUPTS();
00231         {   
00232             pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) );           
00233             vListRemove( &( pxUnblockedCRCB->xEventListItem ) );
00234         }
00235         portENABLE_INTERRUPTS();
00236 
00237         vListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
00238         prvAddCoRoutineToReadyQueue( pxUnblockedCRCB ); 
00239     }
00240 }

static void prvInitialiseCoRoutineLists ( void   )  [static]

Definition at line 329 of file croutine.c.

References configMAX_CO_ROUTINE_PRIORITIES, portBASE_TYPE, and vListInitialise().

Referenced by xCoRoutineCreate().

00330 {
00331 unsigned portBASE_TYPE uxPriority;
00332 
00333     for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
00334     {
00335         vListInitialise( ( xList * ) &( pxReadyCoRoutineLists[ uxPriority ] ) );
00336     }
00337 
00338     vListInitialise( ( xList * ) &xDelayedCoRoutineList1 );
00339     vListInitialise( ( xList * ) &xDelayedCoRoutineList2 );
00340     vListInitialise( ( xList * ) &xPendingReadyCoRoutineList );
00341 
00342     /* Start with pxDelayedCoRoutineList using list1 and the
00343     pxOverflowDelayedCoRoutineList using list2. */
00344     pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
00345     pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
00346 }

void vCoRoutineAddToDelayedList ( portTickType  xTicksToDelay,
xList pxEventList 
)

Definition at line 182 of file croutine.c.

References listSET_LIST_ITEM_VALUE, vListInsert(), vListRemove(), xCoRoutineTickCount, corCoRoutineControlBlock::xEventListItem, and corCoRoutineControlBlock::xGenericListItem.

00183 {
00184 portTickType xTimeToWake;
00185 
00186     /* Calculate the time to wake - this may overflow but this is
00187     not a problem. */
00188     xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
00189 
00190     /* We must remove ourselves from the ready list before adding
00191     ourselves to the blocked list as the same list item is used for
00192     both lists. */
00193     vListRemove( ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) );
00194 
00195     /* The list item will be inserted in wake time order. */
00196     listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
00197 
00198     if( xTimeToWake < xCoRoutineTickCount )
00199     {
00200         /* Wake time has overflowed.  Place this item in the
00201         overflow list. */
00202         vListInsert( ( xList * ) pxOverflowDelayedCoRoutineList, ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) );
00203     }
00204     else
00205     {
00206         /* The wake time has not overflowed, so we can use the
00207         current block list. */
00208         vListInsert( ( xList * ) pxDelayedCoRoutineList, ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) );
00209     }
00210 
00211     if( pxEventList )
00212     {
00213         /* Also add the co-routine to an event list.  If this is done then the
00214         function must be called with interrupts disabled. */
00215         vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
00216     }
00217 }

void vCoRoutineSchedule ( void   ) 

Definition at line 299 of file croutine.c.

References listGET_OWNER_OF_NEXT_ENTRY, listLIST_IS_EMPTY, prvCheckDelayedList(), prvCheckPendingReadyList(), corCoRoutineControlBlock::pxCoRoutineFunction, corCoRoutineControlBlock::uxIndex, and uxTopCoRoutineReadyPriority.

00300 {
00301     /* See if any co-routines readied by events need moving to the ready lists. */
00302     prvCheckPendingReadyList();
00303 
00304     /* See if any delayed co-routines have timed out. */
00305     prvCheckDelayedList();
00306 
00307     /* Find the highest priority queue that contains ready co-routines. */
00308     while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) )
00309     {
00310         if( uxTopCoRoutineReadyPriority == 0 )
00311         {
00312             /* No more co-routines to check. */
00313             return;
00314         }
00315         --uxTopCoRoutineReadyPriority;
00316     }
00317 
00318     /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines
00319      of the same priority get an equal share of the processor time. */
00320     listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
00321 
00322     /* Call the co-routine. */
00323     ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
00324 
00325     return;
00326 }

signed portBASE_TYPE xCoRoutineCreate ( crCOROUTINE_CODE  pxCoRoutineCode,
unsigned portBASE_TYPE  uxPriority,
unsigned portBASE_TYPE  uxIndex 
)

Definition at line 125 of file croutine.c.

References configMAX_CO_ROUTINE_PRIORITIES, configMAX_PRIORITIES, corINITIAL_STATE, errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY, listSET_LIST_ITEM_OWNER, listSET_LIST_ITEM_VALUE, pdPASS, portBASE_TYPE, prvAddCoRoutineToReadyQueue, prvInitialiseCoRoutineLists(), pvPortMalloc(), corCoRoutineControlBlock::pxCoRoutineFunction, corCoRoutineControlBlock::uxIndex, corCoRoutineControlBlock::uxPriority, corCoRoutineControlBlock::uxState, vListInitialiseItem(), corCoRoutineControlBlock::xEventListItem, and corCoRoutineControlBlock::xGenericListItem.

Referenced by vStartFlashCoRoutines(), and vStartHookCoRoutines().

00126 {
00127 signed portBASE_TYPE xReturn;
00128 corCRCB *pxCoRoutine;
00129 
00130     /* Allocate the memory that will store the co-routine control block. */
00131     pxCoRoutine = ( corCRCB * ) pvPortMalloc( sizeof( corCRCB ) );
00132     if( pxCoRoutine )
00133     {
00134         /* If pxCurrentCoRoutine is NULL then this is the first co-routine to
00135         be created and the co-routine data structures need initialising. */
00136         if( pxCurrentCoRoutine == NULL )
00137         {
00138             pxCurrentCoRoutine = pxCoRoutine;
00139             prvInitialiseCoRoutineLists();
00140         }
00141 
00142         /* Check the priority is within limits. */
00143         if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES )
00144         {
00145             uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1;
00146         }
00147 
00148         /* Fill out the co-routine control block from the function parameters. */
00149         pxCoRoutine->uxState = corINITIAL_STATE;
00150         pxCoRoutine->uxPriority = uxPriority;
00151         pxCoRoutine->uxIndex = uxIndex;
00152         pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode;
00153 
00154         /* Initialise all the other co-routine control block parameters. */
00155         vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
00156         vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
00157 
00158         /* Set the co-routine control block as a link back from the xListItem.
00159         This is so we can get back to the containing CRCB from a generic item
00160         in a list. */
00161         listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
00162         listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
00163     
00164         /* Event lists are always in priority order. */
00165         listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority );
00166         
00167         /* Now the co-routine has been initialised it can be added to the ready
00168         list at the correct priority. */
00169         prvAddCoRoutineToReadyQueue( pxCoRoutine );
00170 
00171         xReturn = pdPASS;
00172     }
00173     else
00174     {       
00175         xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
00176     }
00177     
00178     return xReturn; 
00179 }

signed portBASE_TYPE xCoRoutineRemoveFromEventList ( const xList pxEventList  ) 

Definition at line 349 of file croutine.c.

References listGET_OWNER_OF_HEAD_ENTRY, pdFALSE, pdTRUE, portBASE_TYPE, corCoRoutineControlBlock::uxPriority, vListInsertEnd(), vListRemove(), and corCoRoutineControlBlock::xEventListItem.

00350 {
00351 corCRCB *pxUnblockedCRCB;
00352 signed portBASE_TYPE xReturn;
00353 
00354     /* This function is called from within an interrupt.  It can only access
00355     event lists and the pending ready list. */
00356     pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
00357     vListRemove( &( pxUnblockedCRCB->xEventListItem ) );
00358     vListInsertEnd( ( xList * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
00359 
00360     if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority )
00361     {
00362         xReturn = pdTRUE;
00363     }
00364     else
00365     {
00366         xReturn = pdFALSE;
00367     }
00368 
00369     return xReturn;
00370 }


Variable Documentation

Definition at line 76 of file croutine.c.

Definition at line 71 of file croutine.c.

Definition at line 72 of file croutine.c.

xList pxReadyCoRoutineLists[configMAX_CO_ROUTINE_PRIORITIES] [static]

Definition at line 68 of file croutine.c.

unsigned portBASE_TYPE uxTopCoRoutineReadyPriority = 0 [static]

Definition at line 77 of file croutine.c.

Referenced by vCoRoutineSchedule().

Definition at line 78 of file croutine.c.

Referenced by prvCheckDelayedList(), and vCoRoutineAddToDelayedList().

Definition at line 69 of file croutine.c.

Definition at line 70 of file croutine.c.

Definition at line 78 of file croutine.c.

Referenced by prvCheckDelayedList().

portTickType xPassedTicks = 0 [static]

Definition at line 78 of file croutine.c.

Referenced by prvCheckDelayedList().

Definition at line 73 of file croutine.c.


Generated on Thu Dec 17 20:02:00 2009 for AVR32 UC3 - FreeRTOS Real Time Kernel by  doxygen 1.5.5