Port of TI's CC3100 Websock camera demo. Using FreeRTOS, mbedTLS, also parts of Arducam for cams ov5642 and 0v2640. Can also use MT9D111. Work in progress. Be warned some parts maybe a bit flacky. This is for Seeed Arch max only, for an M3, see the demo for CM3 using the 0v5642 aducam mini.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers croutine.c Source File

croutine.c

00001 /*
00002     FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd.
00003     All rights reserved
00004 
00005     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
00006 
00007     This file is part of the FreeRTOS distribution.
00008 
00009     FreeRTOS is free software; you can redistribute it and/or modify it under
00010     the terms of the GNU General Public License (version 2) as published by the
00011     Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
00012 
00013     ***************************************************************************
00014     >>!   NOTE: The modification to the GPL is included to allow you to     !<<
00015     >>!   distribute a combined work that includes FreeRTOS without being   !<<
00016     >>!   obliged to provide the source code for proprietary components     !<<
00017     >>!   outside of the FreeRTOS kernel.                                   !<<
00018     ***************************************************************************
00019 
00020     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
00021     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00022     FOR A PARTICULAR PURPOSE.  Full license text is available on the following
00023     link: http://www.freertos.org/a00114.html
00024 
00025     ***************************************************************************
00026      *                                                                       *
00027      *    FreeRTOS provides completely free yet professionally developed,    *
00028      *    robust, strictly quality controlled, supported, and cross          *
00029      *    platform software that is more than just the market leader, it     *
00030      *    is the industry's de facto standard.                               *
00031      *                                                                       *
00032      *    Help yourself get started quickly while simultaneously helping     *
00033      *    to support the FreeRTOS project by purchasing a FreeRTOS           *
00034      *    tutorial book, reference manual, or both:                          *
00035      *    http://www.FreeRTOS.org/Documentation                              *
00036      *                                                                       *
00037     ***************************************************************************
00038 
00039     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
00040     the FAQ page "My application does not run, what could be wrong?".  Have you
00041     defined configASSERT()?
00042 
00043     http://www.FreeRTOS.org/support - In return for receiving this top quality
00044     embedded software for free we request you assist our global community by
00045     participating in the support forum.
00046 
00047     http://www.FreeRTOS.org/training - Investing in training allows your team to
00048     be as productive as possible as early as possible.  Now you can receive
00049     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
00050     Ltd, and the world's leading authority on the world's leading RTOS.
00051 
00052     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
00053     including FreeRTOS+Trace - an indispensable productivity tool, a DOS
00054     compatible FAT file system, and our tiny thread aware UDP/IP stack.
00055 
00056     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
00057     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
00058 
00059     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
00060     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
00061     licenses offer ticketed support, indemnification and commercial middleware.
00062 
00063     http://www.SafeRTOS.com - High Integrity Systems also provide a safety
00064     engineered and independently SIL3 certified version for use in safety and
00065     mission critical applications that require provable dependability.
00066 
00067     1 tab == 4 spaces!
00068 */
00069 
00070 #include "FreeRTOS.h"
00071 #include "task.h"
00072 #include "croutine.h"
00073 
00074 /* Remove the whole file is co-routines are not being used. */
00075 #if( configUSE_CO_ROUTINES != 0 )
00076 
00077 /*
00078  * Some kernel aware debuggers require data to be viewed to be global, rather
00079  * than file scope.
00080  */
00081 #ifdef portREMOVE_STATIC_QUALIFIER
00082     #define static
00083 #endif
00084 
00085 
00086 /* Lists for ready and blocked co-routines. --------------------*/
00087 static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */
00088 static List_t xDelayedCoRoutineList1;                                   /*< Delayed co-routines. */
00089 static List_t xDelayedCoRoutineList2;                                   /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
00090 static List_t * pxDelayedCoRoutineList;                                 /*< Points to the delayed co-routine list currently being used. */
00091 static List_t * pxOverflowDelayedCoRoutineList;                         /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
00092 static List_t xPendingReadyCoRoutineList;                               /*< Holds co-routines that have been readied by an external event.  They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
00093 
00094 /* Other file private variables. --------------------------------*/
00095 CRCB_t * pxCurrentCoRoutine = NULL;
00096 static UBaseType_t uxTopCoRoutineReadyPriority = 0;
00097 static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
00098 
00099 /* The initial state of the co-routine when it is created. */
00100 #define corINITIAL_STATE    ( 0 )
00101 
00102 /*
00103  * Place the co-routine represented by pxCRCB into the appropriate ready queue
00104  * for the priority.  It is inserted at the end of the list.
00105  *
00106  * This macro accesses the co-routine ready lists and therefore must not be
00107  * used from within an ISR.
00108  */
00109 #define prvAddCoRoutineToReadyQueue( pxCRCB )                                                                       \
00110 {                                                                                                                   \
00111     if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority )                                                          \
00112     {                                                                                                               \
00113         uxTopCoRoutineReadyPriority = pxCRCB->uxPriority;                                                           \
00114     }                                                                                                               \
00115     vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \
00116 }
00117 
00118 /*
00119  * Utility to ready all the lists used by the scheduler.  This is called
00120  * automatically upon the creation of the first co-routine.
00121  */
00122 static void prvInitialiseCoRoutineLists( void );
00123 
00124 /*
00125  * Co-routines that are readied by an interrupt cannot be placed directly into
00126  * the ready lists (there is no mutual exclusion).  Instead they are placed in
00127  * in the pending ready list in order that they can later be moved to the ready
00128  * list by the co-routine scheduler.
00129  */
00130 static void prvCheckPendingReadyList( void );
00131 
00132 /*
00133  * Macro that looks at the list of co-routines that are currently delayed to
00134  * see if any require waking.
00135  *
00136  * Co-routines are stored in the queue in the order of their wake time -
00137  * meaning once one co-routine has been found whose timer has not expired
00138  * we need not look any further down the list.
00139  */
00140 static void prvCheckDelayedList( void );
00141 
00142 /*-----------------------------------------------------------*/
00143 
00144 BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex )
00145 {
00146 BaseType_t xReturn;
00147 CRCB_t *pxCoRoutine;
00148 
00149     /* Allocate the memory that will store the co-routine control block. */
00150     pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
00151     if( pxCoRoutine )
00152     {
00153         /* If pxCurrentCoRoutine is NULL then this is the first co-routine to
00154         be created and the co-routine data structures need initialising. */
00155         if( pxCurrentCoRoutine == NULL )
00156         {
00157             pxCurrentCoRoutine = pxCoRoutine;
00158             prvInitialiseCoRoutineLists();
00159         }
00160 
00161         /* Check the priority is within limits. */
00162         if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES )
00163         {
00164             uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1;
00165         }
00166 
00167         /* Fill out the co-routine control block from the function parameters. */
00168         pxCoRoutine->uxState = corINITIAL_STATE;
00169         pxCoRoutine->uxPriority = uxPriority;
00170         pxCoRoutine->uxIndex = uxIndex;
00171         pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode;
00172 
00173         /* Initialise all the other co-routine control block parameters. */
00174         vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
00175         vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
00176 
00177         /* Set the co-routine control block as a link back from the ListItem_t.
00178         This is so we can get back to the containing CRCB from a generic item
00179         in a list. */
00180         listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
00181         listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
00182 
00183         /* Event lists are always in priority order. */
00184         listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) );
00185 
00186         /* Now the co-routine has been initialised it can be added to the ready
00187         list at the correct priority. */
00188         prvAddCoRoutineToReadyQueue( pxCoRoutine );
00189 
00190         xReturn = pdPASS;
00191     }
00192     else
00193     {
00194         xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
00195     }
00196 
00197     return xReturn;
00198 }
00199 /*-----------------------------------------------------------*/
00200 
00201 void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList )
00202 {
00203 TickType_t xTimeToWake;
00204 
00205     /* Calculate the time to wake - this may overflow but this is
00206     not a problem. */
00207     xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
00208 
00209     /* We must remove ourselves from the ready list before adding
00210     ourselves to the blocked list as the same list item is used for
00211     both lists. */
00212     ( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
00213 
00214     /* The list item will be inserted in wake time order. */
00215     listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
00216 
00217     if( xTimeToWake < xCoRoutineTickCount )
00218     {
00219         /* Wake time has overflowed.  Place this item in the
00220         overflow list. */
00221         vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
00222     }
00223     else
00224     {
00225         /* The wake time has not overflowed, so we can use the
00226         current block list. */
00227         vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
00228     }
00229 
00230     if( pxEventList )
00231     {
00232         /* Also add the co-routine to an event list.  If this is done then the
00233         function must be called with interrupts disabled. */
00234         vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
00235     }
00236 }
00237 /*-----------------------------------------------------------*/
00238 
00239 static void prvCheckPendingReadyList( void )
00240 {
00241     /* Are there any co-routines waiting to get moved to the ready list?  These
00242     are co-routines that have been readied by an ISR.  The ISR cannot access
00243     the ready lists itself. */
00244     while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
00245     {
00246         CRCB_t *pxUnblockedCRCB;
00247 
00248         /* The pending ready list can be accessed by an ISR. */
00249         portDISABLE_INTERRUPTS();
00250         {
00251             pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) );
00252             ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
00253         }
00254         portENABLE_INTERRUPTS();
00255 
00256         ( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
00257         prvAddCoRoutineToReadyQueue( pxUnblockedCRCB );
00258     }
00259 }
00260 /*-----------------------------------------------------------*/
00261 
00262 static void prvCheckDelayedList( void )
00263 {
00264 CRCB_t *pxCRCB;
00265 
00266     xPassedTicks = xTaskGetTickCount() - xLastTickCount;
00267     while( xPassedTicks )
00268     {
00269         xCoRoutineTickCount++;
00270         xPassedTicks--;
00271 
00272         /* If the tick count has overflowed we need to swap the ready lists. */
00273         if( xCoRoutineTickCount == 0 )
00274         {
00275             List_t * pxTemp;
00276 
00277             /* Tick count has overflowed so we need to swap the delay lists.  If there are
00278             any items in pxDelayedCoRoutineList here then there is an error! */
00279             pxTemp = pxDelayedCoRoutineList;
00280             pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
00281             pxOverflowDelayedCoRoutineList = pxTemp;
00282         }
00283 
00284         /* See if this tick has made a timeout expire. */
00285         while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE )
00286         {
00287             pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList );
00288 
00289             if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
00290             {
00291                 /* Timeout not yet expired. */
00292                 break;
00293             }
00294 
00295             portDISABLE_INTERRUPTS();
00296             {
00297                 /* The event could have occurred just before this critical
00298                 section.  If this is the case then the generic list item will
00299                 have been moved to the pending ready list and the following
00300                 line is still valid.  Also the pvContainer parameter will have
00301                 been set to NULL so the following lines are also valid. */
00302                 ( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
00303 
00304                 /* Is the co-routine waiting on an event also? */
00305                 if( pxCRCB->xEventListItem.pvContainer )
00306                 {
00307                     ( void ) uxListRemove( &( pxCRCB->xEventListItem ) );
00308                 }
00309             }
00310             portENABLE_INTERRUPTS();
00311 
00312             prvAddCoRoutineToReadyQueue( pxCRCB );
00313         }
00314     }
00315 
00316     xLastTickCount = xCoRoutineTickCount;
00317 }
00318 /*-----------------------------------------------------------*/
00319 
00320 void vCoRoutineSchedule( void )
00321 {
00322     /* See if any co-routines readied by events need moving to the ready lists. */
00323     prvCheckPendingReadyList();
00324 
00325     /* See if any delayed co-routines have timed out. */
00326     prvCheckDelayedList();
00327 
00328     /* Find the highest priority queue that contains ready co-routines. */
00329     while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) )
00330     {
00331         if( uxTopCoRoutineReadyPriority == 0 )
00332         {
00333             /* No more co-routines to check. */
00334             return;
00335         }
00336         --uxTopCoRoutineReadyPriority;
00337     }
00338 
00339     /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines
00340      of the same priority get an equal share of the processor time. */
00341     listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
00342 
00343     /* Call the co-routine. */
00344     ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
00345 
00346     return;
00347 }
00348 /*-----------------------------------------------------------*/
00349 
00350 static void prvInitialiseCoRoutineLists( void )
00351 {
00352 UBaseType_t uxPriority;
00353 
00354     for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
00355     {
00356         vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) );
00357     }
00358 
00359     vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 );
00360     vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 );
00361     vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList );
00362 
00363     /* Start with pxDelayedCoRoutineList using list1 and the
00364     pxOverflowDelayedCoRoutineList using list2. */
00365     pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
00366     pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
00367 }
00368 /*-----------------------------------------------------------*/
00369 
00370 BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList )
00371 {
00372 CRCB_t *pxUnblockedCRCB;
00373 BaseType_t xReturn;
00374 
00375     /* This function is called from within an interrupt.  It can only access
00376     event lists and the pending ready list.  This function assumes that a
00377     check has already been made to ensure pxEventList is not empty. */
00378     pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
00379     ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
00380     vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
00381 
00382     if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority )
00383     {
00384         xReturn = pdTRUE;
00385     }
00386     else
00387     {
00388         xReturn = pdFALSE;
00389     }
00390 
00391     return xReturn;
00392 }
00393 
00394 #endif /* configUSE_CO_ROUTINES == 0 */
00395 
00396