Skip to content

File croutine.h

File List > FreeRTOS > include > croutine.h

Go to the documentation of this file.

/*
 * FreeRTOS Kernel V10.3.1
 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * http://www.FreeRTOS.org
 * http://aws.amazon.com/freertos
 *
 * 1 tab == 4 spaces!
 */

#ifndef CO_ROUTINE_H
#define CO_ROUTINE_H

#ifndef INC_FREERTOS_H
    #error "include FreeRTOS.h must appear in source files before include croutine.h"
#endif

#include "list.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Used to hide the implementation of the co-routine control block.  The
control block structure however has to be included in the header due to
the macro implementation of the co-routine functionality. */
typedef void * CoRoutineHandle_t;

/* Defines the prototype to which co-routine functions must conform. */
typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t );

typedef struct corCoRoutineControlBlock
{
    crCOROUTINE_CODE    pxCoRoutineFunction;
    ListItem_t          xGenericListItem;   /*< List item used to place the CRCB in ready and blocked queues. */
    ListItem_t          xEventListItem;     /*< List item used to place the CRCB in event lists. */
    UBaseType_t         uxPriority;         /*< The priority of the co-routine in relation to other co-routines. */
    UBaseType_t         uxIndex;            /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */
    uint16_t            uxState;            /*< Used internally by the co-routine implementation. */
} CRCB_t; /* Co-routine control block.  Note must be identical in size down to uxPriority with TCB_t. */

BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex );


void vCoRoutineSchedule( void );

#define crSTART( pxCRCB ) switch( ( ( CRCB_t * )( pxCRCB ) )->uxState ) { case 0:

#define crEND() }

/*
 * These macros are intended for internal use by the co-routine implementation
 * only.  The macros should not be used directly by application writers.
 */
#define crSET_STATE0( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2):
#define crSET_STATE1( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1):

#define crDELAY( xHandle, xTicksToDelay )                                               \
    if( ( xTicksToDelay ) > 0 )                                                         \
    {                                                                                   \
        vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL );                          \
    }                                                                                   \
    crSET_STATE0( ( xHandle ) );

#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult )         \
{                                                                                       \
    *( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) );   \
    if( *( pxResult ) == errQUEUE_BLOCKED )                                             \
    {                                                                                   \
        crSET_STATE0( ( xHandle ) );                                                    \
        *pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 );                  \
    }                                                                                   \
    if( *pxResult == errQUEUE_YIELD )                                                   \
    {                                                                                   \
        crSET_STATE1( ( xHandle ) );                                                    \
        *pxResult = pdPASS;                                                             \
    }                                                                                   \
}

#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult )           \
{                                                                                       \
    *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) );     \
    if( *( pxResult ) == errQUEUE_BLOCKED )                                             \
    {                                                                                   \
        crSET_STATE0( ( xHandle ) );                                                    \
        *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 );                \
    }                                                                                   \
    if( *( pxResult ) == errQUEUE_YIELD )                                               \
    {                                                                                   \
        crSET_STATE1( ( xHandle ) );                                                    \
        *( pxResult ) = pdPASS;                                                         \
    }                                                                                   \
}

#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) )


#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) )

/*
 * This function is intended for internal use by the co-routine macros only.
 * The macro nature of the co-routine implementation requires that the
 * prototype appears here.  The function should not be used by application
 * writers.
 *
 * Removes the current co-routine from its ready list and places it in the
 * appropriate delayed list.
 */
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList );

/*
 * This function is intended for internal use by the queue implementation only.
 * The function should not be used by application writers.
 *
 * Removes the highest priority co-routine from the event list and places it in
 * the pending ready list.
 */
BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList );

#ifdef __cplusplus
}
#endif

#endif /* CO_ROUTINE_H */