Add back croutines by reverting PR#590 (#685)

* Add croutines to the code base

* Add croutine changes to cmake, lexicon and readme

* Add croutine file to portable cmake file

* Add back more references from PR 591
diff --git a/queue.c b/queue.c
index 662052f..27776f0 100644
--- a/queue.c
+++ b/queue.c
@@ -38,6 +38,10 @@
 #include "task.h"
 #include "queue.h"
 
+#if ( configUSE_CO_ROUTINES == 1 )
+    #include "croutine.h"
+#endif
+
 /* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified
  * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
  * for the header files above, but not in this file, in order to generate the
@@ -2523,6 +2527,293 @@
 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
 /*-----------------------------------------------------------*/
 
+#if ( configUSE_CO_ROUTINES == 1 )
+
+    BaseType_t xQueueCRSend( QueueHandle_t xQueue,
+                             const void * pvItemToQueue,
+                             TickType_t xTicksToWait )
+    {
+        BaseType_t xReturn;
+        Queue_t * const pxQueue = xQueue;
+
+        /* If the queue is already full we may have to block.  A critical section
+         * is required to prevent an interrupt removing something from the queue
+         * between the check to see if the queue is full and blocking on the queue. */
+        portDISABLE_INTERRUPTS();
+        {
+            if( prvIsQueueFull( pxQueue ) != pdFALSE )
+            {
+                /* The queue is full - do we want to block or just leave without
+                 * posting? */
+                if( xTicksToWait > ( TickType_t ) 0 )
+                {
+                    /* As this is called from a coroutine we cannot block directly, but
+                     * return indicating that we need to block. */
+                    vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
+                    portENABLE_INTERRUPTS();
+                    return errQUEUE_BLOCKED;
+                }
+                else
+                {
+                    portENABLE_INTERRUPTS();
+                    return errQUEUE_FULL;
+                }
+            }
+        }
+        portENABLE_INTERRUPTS();
+
+        portDISABLE_INTERRUPTS();
+        {
+            if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
+            {
+                /* There is room in the queue, copy the data into the queue. */
+                prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
+                xReturn = pdPASS;
+
+                /* Were any co-routines waiting for data to become available? */
+                if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+                {
+                    /* In this instance the co-routine could be placed directly
+                     * into the ready list as we are within a critical section.
+                     * Instead the same pending ready list mechanism is used as if
+                     * the event were caused from within an interrupt. */
+                    if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+                    {
+                        /* The co-routine waiting has a higher priority so record
+                         * that a yield might be appropriate. */
+                        xReturn = errQUEUE_YIELD;
+                    }
+                    else
+                    {
+                        mtCOVERAGE_TEST_MARKER();
+                    }
+                }
+                else
+                {
+                    mtCOVERAGE_TEST_MARKER();
+                }
+            }
+            else
+            {
+                xReturn = errQUEUE_FULL;
+            }
+        }
+        portENABLE_INTERRUPTS();
+
+        return xReturn;
+    }
+
+#endif /* configUSE_CO_ROUTINES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_CO_ROUTINES == 1 )
+
+    BaseType_t xQueueCRReceive( QueueHandle_t xQueue,
+                                void * pvBuffer,
+                                TickType_t xTicksToWait )
+    {
+        BaseType_t xReturn;
+        Queue_t * const pxQueue = xQueue;
+
+        /* If the queue is already empty we may have to block.  A critical section
+         * is required to prevent an interrupt adding something to the queue
+         * between the check to see if the queue is empty and blocking on the queue. */
+        portDISABLE_INTERRUPTS();
+        {
+            if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 )
+            {
+                /* There are no messages in the queue, do we want to block or just
+                 * leave with nothing? */
+                if( xTicksToWait > ( TickType_t ) 0 )
+                {
+                    /* As this is a co-routine we cannot block directly, but return
+                     * indicating that we need to block. */
+                    vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
+                    portENABLE_INTERRUPTS();
+                    return errQUEUE_BLOCKED;
+                }
+                else
+                {
+                    portENABLE_INTERRUPTS();
+                    return errQUEUE_FULL;
+                }
+            }
+            else
+            {
+                mtCOVERAGE_TEST_MARKER();
+            }
+        }
+        portENABLE_INTERRUPTS();
+
+        portDISABLE_INTERRUPTS();
+        {
+            if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
+            {
+                /* Data is available from the queue. */
+                pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize;
+
+                if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail )
+                {
+                    pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead;
+                }
+                else
+                {
+                    mtCOVERAGE_TEST_MARKER();
+                }
+
+                --( pxQueue->uxMessagesWaiting );
+                ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
+
+                xReturn = pdPASS;
+
+                /* Were any co-routines waiting for space to become available? */
+                if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+                {
+                    /* In this instance the co-routine could be placed directly
+                     * into the ready list as we are within a critical section.
+                     * Instead the same pending ready list mechanism is used as if
+                     * the event were caused from within an interrupt. */
+                    if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
+                    {
+                        xReturn = errQUEUE_YIELD;
+                    }
+                    else
+                    {
+                        mtCOVERAGE_TEST_MARKER();
+                    }
+                }
+                else
+                {
+                    mtCOVERAGE_TEST_MARKER();
+                }
+            }
+            else
+            {
+                xReturn = pdFAIL;
+            }
+        }
+        portENABLE_INTERRUPTS();
+
+        return xReturn;
+    }
+
+#endif /* configUSE_CO_ROUTINES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_CO_ROUTINES == 1 )
+
+    BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue,
+                                    const void * pvItemToQueue,
+                                    BaseType_t xCoRoutinePreviouslyWoken )
+    {
+        Queue_t * const pxQueue = xQueue;
+
+        /* Cannot block within an ISR so if there is no space on the queue then
+         * exit without doing anything. */
+        if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
+        {
+            prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
+
+            /* We only want to wake one co-routine per ISR, so check that a
+             * co-routine has not already been woken. */
+            if( xCoRoutinePreviouslyWoken == pdFALSE )
+            {
+                if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+                {
+                    if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+                    {
+                        return pdTRUE;
+                    }
+                    else
+                    {
+                        mtCOVERAGE_TEST_MARKER();
+                    }
+                }
+                else
+                {
+                    mtCOVERAGE_TEST_MARKER();
+                }
+            }
+            else
+            {
+                mtCOVERAGE_TEST_MARKER();
+            }
+        }
+        else
+        {
+            mtCOVERAGE_TEST_MARKER();
+        }
+
+        return xCoRoutinePreviouslyWoken;
+    }
+
+#endif /* configUSE_CO_ROUTINES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_CO_ROUTINES == 1 )
+
+    BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue,
+                                       void * pvBuffer,
+                                       BaseType_t * pxCoRoutineWoken )
+    {
+        BaseType_t xReturn;
+        Queue_t * const pxQueue = xQueue;
+
+        /* We cannot block from an ISR, so check there is data available. If
+         * not then just leave without doing anything. */
+        if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
+        {
+            /* Copy the data from the queue. */
+            pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize;
+
+            if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail )
+            {
+                pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead;
+            }
+            else
+            {
+                mtCOVERAGE_TEST_MARKER();
+            }
+
+            --( pxQueue->uxMessagesWaiting );
+            ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
+
+            if( ( *pxCoRoutineWoken ) == pdFALSE )
+            {
+                if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+                {
+                    if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
+                    {
+                        *pxCoRoutineWoken = pdTRUE;
+                    }
+                    else
+                    {
+                        mtCOVERAGE_TEST_MARKER();
+                    }
+                }
+                else
+                {
+                    mtCOVERAGE_TEST_MARKER();
+                }
+            }
+            else
+            {
+                mtCOVERAGE_TEST_MARKER();
+            }
+
+            xReturn = pdPASS;
+        }
+        else
+        {
+            xReturn = pdFAIL;
+        }
+
+        return xReturn;
+    }
+
+#endif /* configUSE_CO_ROUTINES */
+/*-----------------------------------------------------------*/
+
 #if ( configQUEUE_REGISTRY_SIZE > 0 )
 
     void vQueueAddToRegistry( QueueHandle_t xQueue,