Co-routine YoonMo, Yeon
Co-routine generalize subroutines multiple entry points suspending and resuming of execution at certain locations more generic and flexible than subroutines less widely used in practice recently added to FreeRTOS v4.0.0
State of co-routine Running Ready Blocked crDELAY()
Priority of co-routine min : 0 max : ( configMAX_CO_ROUTINE_PRIORITIES -1 ) defined within FreeRTOSConfig.h tasktask is always prior to co-routine
Implementation void vACoRoutineFunction( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) { crSTART( xHandle ); for( ;; ) { -- co-routine application code here. -- } crEND(); }
CRCB (co-routine control block) typedef struct corCoRoutineControlBlock { crCOROUTINE_CODE pxCoRoutineFunction; xListItem xGenericListItem; xListItem xEventListItem; unsigned portBASE_TYPE uxPriority; unsigned portBASE_TYPE uxIndex; unsigned portSHORT uxState; } corCRCB;
crSTART() and crEND() #define crSTART( pxCRCB ) switch( ( ( corCRCB * )pxCRCB )->uxState ) { case 0: #define crEND() }
lists for co-routine static xList pxReadyCoRoutineLists [ configMAX_CO_ROUTINE_PRIORITIES ] ; static xList xDelayedCoRoutineList1 ; static xList xDelayedCoRoutineList2 ; static xList * pxDelayedCoRoutineList ; static xList * pxOverflowDelayedCoRoutineList; static xList xPendingReadyList ;
xCoRoutineCreate()
xCoRoutineCreate() cont.
Scheduling of co-routine call vCoRoutineSchedule() repeatedly best within the idle task hook void vApplicationIdleHook( void ) { vCoRoutineSchedule( void ); }
vCoRoutineSchedule()
Limitations and Restrictions Sharing a stack variables must be declared as ‘static’ void vACoRoutineFunction( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) { static char c = 'a'; crSTART( xHandle ); for( ;; ) { c = 'b'; crDELAY( xHandle, 10 ); } crEND(); }
Limitations and Restrictions Sharing a stack (more) calls to API functions that could cause the co-routine to block can only be made from the co-routine function itself void vACoRoutineFunction( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) { crSTART( xHandle ); for( ;; ) { crDELAY( xHandle, 10 ); vACalledFunction(); } crEND(); } void vACalledFunction( void ) { // Cannot make a blocking call here! }
Limitations and Restrictions Use of switch statements FreeRTOS does not permit a blocking call to be made from within a ‘switch’ statement void vACoRoutineFunction( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) { crSTART( xHandle ); for( ;; ) { crDELAY( xHandle, 10 ); switch( aVariable ) { case 1 : break; default: } crEND(); }
Example #include "task.h" #include "croutine.h" #define PRIORITY_0 0 #define NUM_COROUTINES 8 void main( void ) { int i; for( i = 0; i < NUM_COROUTINES; i++ ) { xCoRoutineCreate( vFlashCoRoutine, PRIORITY_0, i ); } vTaskStartScheduler(); }
Example (cont.) const int iFlashRates[ NUM_COROUTINES ] = { 10, 20, 30, 40, 50, 60, 70, 80 }; const int iLEDToFlash[ NUM_COROUTINES ] = { 0, 1, 2, 3, 4, 5, 6, 7 }; void vFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) { crSTART( xHandle ); for( ;; ) { crDELAY( xHandle, iFlashRate[ uxIndex ] ); vParTestToggleLED( iLEDToFlash[ uxIndex ] ); } crEND(); }
co-routine API xCoRoutineHandle xCoRoutineCreate crDELAY crQUEUE_SEND crQUEUE_SEND_FROM_ISR crQUEUE_RECEIVE_FROM_ISR vCoRoutineSchedule
xCoRoutineHandle Type by which co-routines are referenced
crDELAY macro delay co-routine by number of ticks