Please see my note book http://mbed.org/users/kenjiArai/notebook/freertos-on-mbed-board-with-mbed-cloud-ide--never-/

This is too old.
Below is another FreeRTOS on mbed.
http://developer.mbed.org/users/rgrover1/code/FreeRTOS/
I don't know it works well or not.
I have not evaluated it.

Revision:
0:d4960fcea8ff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FreeRTOS/Source/tasks.c	Sat Jan 01 11:17:45 2011 +0000
@@ -0,0 +1,2340 @@
+/*
+    FreeRTOS V6.0.3 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public 
+    License and the FreeRTOS license exception along with FreeRTOS; if not it 
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained 
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers.  That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "StackMacros.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#if 0
+/*
+ * Macro to define the amount of stack available to the idle task.
+ */
+#define tskIDLE_STACK_SIZE    configMINIMAL_STACK_SIZE
+#endif
+
+/*
+ * Task control block.  A task control block (TCB) is allocated to each task,
+ * and stores the context of the task.
+ */
+typedef struct tskTaskControlBlock
+{
+    volatile portSTACK_TYPE    *pxTopOfStack;        /*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */
+
+    #if ( portUSING_MPU_WRAPPERS == 1 )
+        xMPU_SETTINGS xMPUSettings;                /*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */
+    #endif    
+    
+    xListItem                xGenericListItem;    /*< List item used to place the TCB in ready and blocked queues. */
+    xListItem                xEventListItem;        /*< List item used to place the TCB in event lists. */
+    unsigned portBASE_TYPE    uxPriority;            /*< The priority of the task where 0 is the lowest priority. */
+    portSTACK_TYPE            *pxStack;            /*< Points to the start of the stack. */
+    signed char                pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */
+
+    #if ( portSTACK_GROWTH > 0 )
+        portSTACK_TYPE *pxEndOfStack;            /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */
+    #endif
+
+    #if ( portCRITICAL_NESTING_IN_TCB == 1 )
+        unsigned portBASE_TYPE uxCriticalNesting;
+    #endif
+
+    #if ( configUSE_TRACE_FACILITY == 1 )
+        unsigned portBASE_TYPE    uxTCBNumber;    /*< This is used for tracing the scheduler and making debugging easier only. */
+    #endif
+
+    #if ( configUSE_MUTEXES == 1 )
+        unsigned portBASE_TYPE uxBasePriority;    /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
+    #endif
+
+    #if ( configUSE_APPLICATION_TASK_TAG == 1 )
+        pdTASK_HOOK_CODE pxTaskTag;
+    #endif
+
+    #if ( configGENERATE_RUN_TIME_STATS == 1 )
+        unsigned long ulRunTimeCounter;        /*< Used for calculating how much CPU time each task is utilising. */
+    #endif
+
+} tskTCB;
+
+
+/*
+ * Some kernel aware debuggers require data to be viewed to be global, rather
+ * than file scope.
+ */
+#ifdef portREMOVE_STATIC_QUALIFIER
+    #define static
+#endif
+
+/*lint -e956 */
+PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL;
+
+/* Lists for ready and blocked tasks. --------------------*/
+
+PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ];    /*< Prioritised ready tasks. */
+PRIVILEGED_DATA static xList xDelayedTaskList1;                            /*< Delayed tasks. */
+PRIVILEGED_DATA static xList xDelayedTaskList2;                            /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
+PRIVILEGED_DATA static xList * volatile pxDelayedTaskList ;                /*< Points to the delayed task list currently being used. */
+PRIVILEGED_DATA static xList * volatile pxOverflowDelayedTaskList;        /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
+PRIVILEGED_DATA static xList xPendingReadyList;                            /*< Tasks that have been readied while the scheduler was suspended.  They will be moved to the ready queue when the scheduler is resumed. */
+
+#if ( INCLUDE_vTaskDelete == 1 )
+
+    PRIVILEGED_DATA static volatile xList xTasksWaitingTermination;        /*< Tasks that have been deleted - but the their memory not yet freed. */
+    PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0;
+
+#endif
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+    PRIVILEGED_DATA static xList xSuspendedTaskList;                    /*< Tasks that are currently suspended. */
+
+#endif
+
+/* File private variables. --------------------------------*/
+PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks     = ( unsigned portBASE_TYPE ) 0;
+PRIVILEGED_DATA static volatile portTickType xTickCount                         = ( portTickType ) 0;
+PRIVILEGED_DATA static unsigned portBASE_TYPE uxTopUsedPriority                     = tskIDLE_PRIORITY;
+PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority         = tskIDLE_PRIORITY;
+PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning             = pdFALSE;
+PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended         = ( unsigned portBASE_TYPE ) pdFALSE;
+PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxMissedTicks             = ( unsigned portBASE_TYPE ) 0;
+PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield                         = ( portBASE_TYPE ) pdFALSE;
+PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows                     = ( portBASE_TYPE ) 0;
+PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber                         = ( unsigned portBASE_TYPE ) 0;
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+
+    PRIVILEGED_DATA static char pcStatsString[ 50 ] ;
+    PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL;    /*< Holds the value of a timer/counter the last time a task was switched in. */
+    static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime ) PRIVILEGED_FUNCTION;
+
+#endif
+
+/* Debugging and trace facilities private variables and macros. ------------*/
+
+/*
+ * The value used to fill the stack of a task when the task is created.  This
+ * is used purely for checking the high water mark for tasks.
+ */
+#define tskSTACK_FILL_BYTE    ( 0xa5 )
+
+/*
+ * Macros used by vListTask to indicate which state a task is in.
+ */
+#define tskBLOCKED_CHAR        ( ( signed char ) 'B' )
+#define tskREADY_CHAR        ( ( signed char ) 'R' )
+#define tskDELETED_CHAR        ( ( signed char ) 'D' )
+#define tskSUSPENDED_CHAR    ( ( signed char ) 'S' )
+
+/*
+ * Macros and private variables used by the trace facility.
+ */
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+    #define tskSIZE_OF_EACH_TRACE_LINE            ( ( unsigned long ) ( sizeof( unsigned long ) + sizeof( unsigned long ) ) )
+    PRIVILEGED_DATA static volatile signed char * volatile pcTraceBuffer;
+    PRIVILEGED_DATA static signed char *pcTraceBufferStart;
+    PRIVILEGED_DATA static signed char *pcTraceBufferEnd;
+    PRIVILEGED_DATA static signed portBASE_TYPE xTracing = pdFALSE;
+    static unsigned portBASE_TYPE uxPreviousTask = 255;
+    PRIVILEGED_DATA static char pcStatusString[ 50 ];
+
+#endif
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Macro that writes a trace of scheduler activity to a buffer.  This trace
+ * shows which task is running when and is very useful as a debugging tool.
+ * As this macro is called each context switch it is a good idea to undefine
+ * it if not using the facility.
+ */
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+    #define vWriteTraceToBuffer()                                                                    \
+    {                                                                                                \
+        if( xTracing )                                                                                \
+        {                                                                                            \
+            if( uxPreviousTask != pxCurrentTCB->uxTCBNumber )                                        \
+            {                                                                                        \
+                if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd )                \
+                {                                                                                    \
+                    uxPreviousTask = pxCurrentTCB->uxTCBNumber;                                        \
+                    *( unsigned long * ) pcTraceBuffer = ( unsigned long ) xTickCount;        \
+                    pcTraceBuffer += sizeof( unsigned long );                                    \
+                    *( unsigned long * ) pcTraceBuffer = ( unsigned long ) uxPreviousTask;    \
+                    pcTraceBuffer += sizeof( unsigned long );                                    \
+                }                                                                                    \
+                else                                                                                \
+                {                                                                                    \
+                    xTracing = pdFALSE;                                                                \
+                }                                                                                    \
+            }                                                                                        \
+        }                                                                                            \
+    }
+
+#else
+
+    #define vWriteTraceToBuffer()
+
+#endif
+/*-----------------------------------------------------------*/
+
+/*
+ * Place the task represented by pxTCB into the appropriate ready queue for
+ * the task.  It is inserted at the end of the list.  One quirk of this is
+ * that if the task being inserted is at the same priority as the currently
+ * executing task, then it will only be rescheduled after the currently
+ * executing task has been rescheduled.
+ */
+#define prvAddTaskToReadyQueue( pxTCB )                                                                            \
+{                                                                                                                \
+    if( pxTCB->uxPriority > uxTopReadyPriority )                                                                \
+    {                                                                                                            \
+        uxTopReadyPriority = pxTCB->uxPriority;                                                                    \
+    }                                                                                                            \
+    vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) );    \
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * Macro that looks at the list of tasks that are currently delayed to see if
+ * any require waking.
+ *
+ * Tasks are stored in the queue in the order of their wake time - meaning
+ * once one tasks has been found whose timer has not expired we need not look
+ * any further down the list.
+ */
+#define prvCheckDelayedTasks()                                                                                        \
+{                                                                                                                    \
+register tskTCB *pxTCB;                                                                                                \
+                                                                                                                    \
+    while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL )                        \
+    {                                                                                                                \
+        if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) )                                    \
+        {                                                                                                            \
+            break;                                                                                                    \
+        }                                                                                                            \
+        vListRemove( &( pxTCB->xGenericListItem ) );                                                                \
+        /* Is the task waiting on an event also? */                                                                    \
+        if( pxTCB->xEventListItem.pvContainer )                                                                        \
+        {                                                                                                            \
+            vListRemove( &( pxTCB->xEventListItem ) );                                                                \
+        }                                                                                                            \
+        prvAddTaskToReadyQueue( pxTCB );                                                                            \
+    }                                                                                                                \
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * Several functions take an xTaskHandle parameter that can optionally be NULL,
+ * where NULL is used to indicate that the handle of the currently executing
+ * task should be used in place of the parameter.  This macro simply checks to
+ * see if the parameter is NULL and returns a pointer to the appropriate TCB.
+ */
+#define prvGetTCBFromHandle( pxHandle ) ( ( pxHandle == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) pxHandle )
+
+
+/* File private functions. --------------------------------*/
+
+/*
+ * Utility to ready a TCB for a given task.  Mainly just copies the parameters
+ * into the TCB structure.
+ */
+static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION;
+
+/*
+ * Utility to ready all the lists used by the scheduler.  This is called
+ * automatically upon the creation of the first task.
+ */
+static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * The idle task, which as all tasks is implemented as a never ending loop.
+ * The idle task is automatically created and added to the ready lists upon
+ * creation of the first user task.
+ *
+ * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
+ * language extensions.  The equivalent prototype for this function is:
+ *
+ * void prvIdleTask( void *pvParameters );
+ *
+ */
+//static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
+#ifdef __cplusplus
+extern "C" {
+#endif
+    static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
+#ifdef __cplusplus
+}
+#endif
+/*
+ * Utility to free all memory allocated by the scheduler to hold a TCB,
+ * including the stack pointed to by the TCB.
+ *
+ * This does not free memory allocated by the task itself (i.e. memory
+ * allocated by calls to pvPortMalloc from within the tasks application code).
+ */
+#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) )
+
+    static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*
+ * Used only by the idle task.  This checks to see if anything has been placed
+ * in the list of tasks waiting to be deleted.  If so the task is cleaned up
+ * and its TCB deleted.
+ */
+static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Allocates memory from the heap for a TCB and associated stack.  Checks the
+ * allocation was successful.
+ */
+static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION;
+
+/*
+ * Called from vTaskList.  vListTasks details all the tasks currently under
+ * control of the scheduler.  The tasks may be in one of a number of lists.
+ * prvListTaskWithinSingleList accepts a list and details the tasks from
+ * within just that list.
+ *
+ * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
+ * NORMAL APPLICATION CODE.
+ */
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+    static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus ) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*
+ * When a task is created, the stack of the task is filled with a known value.
+ * This function determines the 'high water mark' of the task stack by
+ * determining how much of the stack remains at the original preset value.
+ */
+#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
+
+    static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION;
+
+#endif
+
+
+/*lint +e956 */
+
+
+
+/*-----------------------------------------------------------
+ * TASK CREATION API documented in task.h
+ *----------------------------------------------------------*/
+
+signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions )
+{
+signed portBASE_TYPE xReturn;
+tskTCB * pxNewTCB;
+
+    /* Allocate the memory required by the TCB and stack for the new task,
+    checking that the allocation was successful. */
+    pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
+
+    if( pxNewTCB != NULL )
+    {
+        portSTACK_TYPE *pxTopOfStack;
+
+        #if( portUSING_MPU_WRAPPERS == 1 )
+            /* Should the task be created in privileged mode? */
+            portBASE_TYPE xRunPrivileged;
+            if( ( uxPriority & portPRIVILEGE_BIT ) != 0x00 )
+            {
+                xRunPrivileged = pdTRUE;
+            }
+            else
+            {
+                xRunPrivileged = pdFALSE;
+            }
+            uxPriority &= ~portPRIVILEGE_BIT;
+        #endif /* portUSING_MPU_WRAPPERS == 1 */
+
+        /* Calculate the top of stack address.  This depends on whether the
+        stack grows from high memory to low (as per the 80x86) or visa versa.
+        portSTACK_GROWTH is used to make the result positive or negative as
+        required by the port. */
+        #if( portSTACK_GROWTH < 0 )
+        {
+            pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
+            pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( unsigned long ) pxTopOfStack ) & ( ( unsigned long ) ~portBYTE_ALIGNMENT_MASK  ) );
+        }
+        #else
+        {
+            pxTopOfStack = pxNewTCB->pxStack;
+
+            /* If we want to use stack checking on architectures that use
+            a positive stack growth direction then we also need to store the
+            other extreme of the stack space. */
+            pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
+        }
+        #endif
+
+        /* Setup the newly allocated TCB with the initial state of the task. */
+        prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );
+
+        /* Initialize the TCB stack to look as if the task was already running,
+        but had been interrupted by the scheduler.  The return address is set
+        to the start of the task function. Once the stack has been initialised
+        the    top of stack variable is updated. */
+        #if( portUSING_MPU_WRAPPERS == 1 )
+        {
+            pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
+        }
+        #else
+        {
+            pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
+        }
+        #endif
+
+        /* We are going to manipulate the task queues to add this task to a
+        ready list, so must make sure no interrupts occur. */
+        portENTER_CRITICAL();
+        {
+            uxCurrentNumberOfTasks++;
+            if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 )
+            {
+                /* As this is the first task it must also be the current task. */
+                pxCurrentTCB =  pxNewTCB;
+
+                /* This is the first task to be created so do the preliminary
+                initialisation required.  We will not recover if this call
+                fails, but we will report the failure. */
+                prvInitialiseTaskLists();
+            }
+            else
+            {
+                /* If the scheduler is not already running, make this task the
+                current task if it is the highest priority task to be created
+                so far. */
+                if( xSchedulerRunning == pdFALSE )
+                {
+                    if( pxCurrentTCB->uxPriority <= uxPriority )
+                    {
+                        pxCurrentTCB = pxNewTCB;
+                    }
+                }
+            }
+
+            /* Remember the top priority to make context switching faster.  Use
+            the priority in pxNewTCB as this has been capped to a valid value. */
+            if( pxNewTCB->uxPriority > uxTopUsedPriority )
+            {
+                uxTopUsedPriority = pxNewTCB->uxPriority;
+            }
+
+            #if ( configUSE_TRACE_FACILITY == 1 )
+            {
+                /* Add a counter into the TCB for tracing only. */
+                pxNewTCB->uxTCBNumber = uxTaskNumber;
+            }
+            #endif
+            uxTaskNumber++;
+
+            prvAddTaskToReadyQueue( pxNewTCB );
+
+            xReturn = pdPASS;
+            traceTASK_CREATE( pxNewTCB );
+        }
+        portEXIT_CRITICAL();
+    }
+    else
+    {
+        xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+        traceTASK_CREATE_FAILED( pxNewTCB );
+    }
+
+    if( xReturn == pdPASS )
+    {
+        if( ( void * ) pxCreatedTask != NULL )
+        {
+            /* Pass the TCB out - in an anonymous way.  The calling function/
+            task can use this as a handle to delete the task later if
+            required.*/
+            *pxCreatedTask = ( xTaskHandle ) pxNewTCB;
+        }
+
+        if( xSchedulerRunning != pdFALSE )
+        {
+            /* If the created task is of a higher priority than the current task
+            then it should run now. */
+            if( pxCurrentTCB->uxPriority < uxPriority )
+            {
+                portYIELD_WITHIN_API();
+            }
+        }
+    }
+
+    return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskDelete == 1 )
+
+    void vTaskDelete( xTaskHandle pxTaskToDelete )
+    {
+    tskTCB *pxTCB;
+
+        portENTER_CRITICAL();
+        {
+            /* Ensure a yield is performed if the current task is being
+            deleted. */
+            if( pxTaskToDelete == pxCurrentTCB )
+            {
+                pxTaskToDelete = NULL;
+            }
+
+            /* If null is passed in here then we are deleting ourselves. */
+            pxTCB = prvGetTCBFromHandle( pxTaskToDelete );
+
+            /* Remove task from the ready list and place in the    termination list.
+            This will stop the task from be scheduled.  The idle task will check
+            the termination list and free up any memory allocated by the
+            scheduler for the TCB and stack. */
+            vListRemove( &( pxTCB->xGenericListItem ) );
+
+            /* Is the task waiting on an event also? */
+            if( pxTCB->xEventListItem.pvContainer )
+            {
+                vListRemove( &( pxTCB->xEventListItem ) );
+            }
+
+            vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
+
+            /* Increment the ucTasksDeleted variable so the idle task knows
+            there is a task that has been deleted and that it should therefore
+            check the xTasksWaitingTermination list. */
+            ++uxTasksDeleted;
+
+            /* Increment the uxTaskNumberVariable also so kernel aware debuggers
+            can detect that the task lists need re-generating. */
+            uxTaskNumber++;
+
+            traceTASK_DELETE( pxTCB );
+        }
+        portEXIT_CRITICAL();
+
+        /* Force a reschedule if we have just deleted the current task. */
+        if( xSchedulerRunning != pdFALSE )
+        {
+            if( ( void * ) pxTaskToDelete == NULL )
+            {
+                portYIELD_WITHIN_API();
+            }
+        }
+    }
+
+#endif
+
+
+
+
+
+
+/*-----------------------------------------------------------
+ * TASK CONTROL API documented in task.h
+ *----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskDelayUntil == 1 )
+
+    void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement )
+    {
+    portTickType xTimeToWake;
+    portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE;
+
+        vTaskSuspendAll();
+        {
+            /* Generate the tick time at which the task wants to wake. */
+            xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
+
+            if( xTickCount < *pxPreviousWakeTime )
+            {
+                /* The tick count has overflowed since this function was
+                lasted called.  In this case the only time we should ever
+                actually delay is if the wake time has also    overflowed,
+                and the wake time is greater than the tick time.  When this
+                is the case it is as if neither time had overflowed. */
+                if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xTickCount ) )
+                {
+                    xShouldDelay = pdTRUE;
+                }
+            }
+            else
+            {
+                /* The tick time has not overflowed.  In this case we will
+                delay if either the wake time has overflowed, and/or the
+                tick time is less than the wake time. */
+                if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xTickCount ) )
+                {
+                    xShouldDelay = pdTRUE;
+                }
+            }
+
+            /* Update the wake time ready for the next call. */
+            *pxPreviousWakeTime = xTimeToWake;
+
+            if( xShouldDelay )
+            {
+                traceTASK_DELAY_UNTIL();
+
+                /* We must remove ourselves from the ready list before adding
+                ourselves to the blocked list as the same list item is used for
+                both lists. */
+                vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
+
+                /* The list item will be inserted in wake time order. */
+                listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
+
+                if( xTimeToWake < xTickCount )
+                {
+                    /* Wake time has overflowed.  Place this item in the
+                    overflow list. */
+                    vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
+                }
+                else
+                {
+                    /* The wake time has not overflowed, so we can use the
+                    current block list. */
+                    vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
+                }
+            }
+        }
+        xAlreadyYielded = xTaskResumeAll();
+
+        /* Force a reschedule if xTaskResumeAll has not already done so, we may
+        have put ourselves to sleep. */
+        if( !xAlreadyYielded )
+        {
+            portYIELD_WITHIN_API();
+        }
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskDelay == 1 )
+
+    void vTaskDelay( portTickType xTicksToDelay )
+    {
+    portTickType xTimeToWake;
+    signed portBASE_TYPE xAlreadyYielded = pdFALSE;
+
+        /* A delay time of zero just forces a reschedule. */
+        if( xTicksToDelay > ( portTickType ) 0 )
+        {
+            vTaskSuspendAll();
+            {
+                traceTASK_DELAY();
+
+                /* A task that is removed from the event list while the
+                scheduler is suspended will not get placed in the ready
+                list or removed from the blocked list until the scheduler
+                is resumed.
+
+                This task cannot be in an event list as it is the currently
+                executing task. */
+
+                /* Calculate the time to wake - this may overflow but this is
+                not a problem. */
+                xTimeToWake = xTickCount + xTicksToDelay;
+
+                /* We must remove ourselves from the ready list before adding
+                ourselves to the blocked list as the same list item is used for
+                both lists. */
+                vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
+
+                /* The list item will be inserted in wake time order. */
+                listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
+
+                if( xTimeToWake < xTickCount )
+                {
+                    /* Wake time has overflowed.  Place this item in the
+                    overflow list. */
+                    vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
+                }
+                else
+                {
+                    /* The wake time has not overflowed, so we can use the
+                    current block list. */
+                    vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
+                }
+            }
+            xAlreadyYielded = xTaskResumeAll();
+        }
+
+        /* Force a reschedule if xTaskResumeAll has not already done so, we may
+        have put ourselves to sleep. */
+        if( !xAlreadyYielded )
+        {
+            portYIELD_WITHIN_API();
+        }
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_uxTaskPriorityGet == 1 )
+
+    unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask )
+    {
+    tskTCB *pxTCB;
+    unsigned portBASE_TYPE uxReturn;
+
+        portENTER_CRITICAL();
+        {
+            /* If null is passed in here then we are changing the
+            priority of the calling function. */
+            pxTCB = prvGetTCBFromHandle( pxTask );
+            uxReturn = pxTCB->uxPriority;
+        }
+        portEXIT_CRITICAL();
+
+        return uxReturn;
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskPrioritySet == 1 )
+
+    void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority )
+    {
+    tskTCB *pxTCB;
+    unsigned portBASE_TYPE uxCurrentPriority, xYieldRequired = pdFALSE;
+
+        /* Ensure the new priority is valid. */
+        if( uxNewPriority >= configMAX_PRIORITIES )
+        {
+            uxNewPriority = configMAX_PRIORITIES - 1;
+        }
+
+        portENTER_CRITICAL();
+        {
+            if( pxTask == pxCurrentTCB )
+            {
+                pxTask = NULL;
+            }
+
+            /* If null is passed in here then we are changing the
+            priority of the calling function. */
+            pxTCB = prvGetTCBFromHandle( pxTask );
+
+            traceTASK_PRIORITY_SET( pxTask, uxNewPriority );
+
+            #if ( configUSE_MUTEXES == 1 )
+            {
+                uxCurrentPriority = pxTCB->uxBasePriority;
+            }
+            #else
+            {
+                uxCurrentPriority = pxTCB->uxPriority;
+            }
+            #endif
+
+            if( uxCurrentPriority != uxNewPriority )
+            {
+                /* The priority change may have readied a task of higher
+                priority than the calling task. */
+                if( uxNewPriority > uxCurrentPriority )
+                {
+                    if( pxTask != NULL )
+                    {
+                        /* The priority of another task is being raised.  If we
+                        were raising the priority of the currently running task
+                        there would be no need to switch as it must have already
+                        been the highest priority task. */
+                        xYieldRequired = pdTRUE;
+                    }
+                }
+                else if( pxTask == NULL )
+                {
+                    /* Setting our own priority down means there may now be another
+                    task of higher priority that is ready to execute. */
+                    xYieldRequired = pdTRUE;
+                }
+
+
+
+                #if ( configUSE_MUTEXES == 1 )
+                {
+                    /* Only change the priority being used if the task is not
+                    currently using an inherited priority. */
+                    if( pxTCB->uxBasePriority == pxTCB->uxPriority )
+                    {
+                        pxTCB->uxPriority = uxNewPriority;
+                    }
+
+                    /* The base priority gets set whatever. */
+                    pxTCB->uxBasePriority = uxNewPriority;
+                }
+                #else
+                {
+                    pxTCB->uxPriority = uxNewPriority;
+                }
+                #endif
+
+                listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) );
+
+                /* If the task is in the blocked or suspended list we need do
+                nothing more than change it's priority variable. However, if
+                the task is in a ready list it needs to be removed and placed
+                in the queue appropriate to its new priority. */
+                if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) )
+                {
+                    /* The task is currently in its ready list - remove before adding
+                    it to it's new ready list.  As we are in a critical section we
+                    can do this even if the scheduler is suspended. */
+                    vListRemove( &( pxTCB->xGenericListItem ) );
+                    prvAddTaskToReadyQueue( pxTCB );
+                }
+
+                if( xYieldRequired == pdTRUE )
+                {
+                    portYIELD_WITHIN_API();
+                }
+            }
+        }
+        portEXIT_CRITICAL();
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+    void vTaskSuspend( xTaskHandle pxTaskToSuspend )
+    {
+    tskTCB *pxTCB;
+
+        portENTER_CRITICAL();
+        {
+            /* Ensure a yield is performed if the current task is being
+            suspended. */
+            if( pxTaskToSuspend == pxCurrentTCB )
+            {
+                pxTaskToSuspend = NULL;
+            }
+
+            /* If null is passed in here then we are suspending ourselves. */
+            pxTCB = prvGetTCBFromHandle( pxTaskToSuspend );
+
+            traceTASK_SUSPEND( pxTCB );
+
+            /* Remove task from the ready/delayed list and place in the    suspended list. */
+            vListRemove( &( pxTCB->xGenericListItem ) );
+
+            /* Is the task waiting on an event also? */
+            if( pxTCB->xEventListItem.pvContainer )
+            {
+                vListRemove( &( pxTCB->xEventListItem ) );
+            }
+
+            vListInsertEnd( ( xList * ) &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
+        }
+        portEXIT_CRITICAL();
+
+        /* We may have just suspended the current task. */
+        if( ( void * ) pxTaskToSuspend == NULL )
+        {
+            portYIELD_WITHIN_API();
+        }
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+    signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask )
+    {
+    portBASE_TYPE xReturn = pdFALSE;
+    const tskTCB * const pxTCB = ( tskTCB * ) xTask;
+
+        /* Is the task we are attempting to resume actually in the
+        suspended list? */
+        if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
+        {
+            /* Has the task already been resumed from within an ISR? */
+            if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )
+            {
+                /* Is it in the suspended list because it is in the
+                Suspended state?  It is possible to be in the suspended
+                list because it is blocked on a task with no timeout
+                specified. */
+                if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) == pdTRUE )
+                {
+                    xReturn = pdTRUE;
+                }
+            }
+        }
+
+        return xReturn;
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+    void vTaskResume( xTaskHandle pxTaskToResume )
+    {
+    tskTCB *pxTCB;
+
+        /* Remove the task from whichever list it is currently in, and place
+        it in the ready list. */
+        pxTCB = ( tskTCB * ) pxTaskToResume;
+
+        /* The parameter cannot be NULL as it is impossible to resume the
+        currently executing task. */
+        if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
+        {
+            portENTER_CRITICAL();
+            {
+                if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
+                {
+                    traceTASK_RESUME( pxTCB );
+
+                    /* As we are in a critical section we can access the ready
+                    lists even if the scheduler is suspended. */
+                    vListRemove(  &( pxTCB->xGenericListItem ) );
+                    prvAddTaskToReadyQueue( pxTCB );
+
+                    /* We may have just resumed a higher priority task. */
+                    if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
+                    {
+                        /* This yield may not cause the task just resumed to run, but
+                        will leave the lists in the correct state for the next yield. */
+                        portYIELD_WITHIN_API();
+                    }
+                }
+            }
+            portEXIT_CRITICAL();
+        }
+    }
+
+#endif
+
+/*-----------------------------------------------------------*/
+
+#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
+
+    portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume )
+    {
+    portBASE_TYPE xYieldRequired = pdFALSE;
+    tskTCB *pxTCB;
+
+        pxTCB = ( tskTCB * ) pxTaskToResume;
+
+        if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
+        {
+            traceTASK_RESUME_FROM_ISR( pxTCB );
+
+            if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
+            {
+                xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );
+                vListRemove(  &( pxTCB->xGenericListItem ) );
+                prvAddTaskToReadyQueue( pxTCB );
+            }
+            else
+            {
+                /* We cannot access the delayed or ready lists, so will hold this
+                task pending until the scheduler is resumed, at which point a
+                yield will be performed if necessary. */
+                vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
+            }
+        }
+
+        return xYieldRequired;
+    }
+
+#endif
+
+
+
+
+/*-----------------------------------------------------------
+ * PUBLIC SCHEDULER CONTROL documented in task.h
+ *----------------------------------------------------------*/
+
+// Modified by  Kenji Arai / JH1PJL, October 30th,2010
+// move to port_asm.c
+#if 0
+void vTaskStartScheduler( void )
+{
+portBASE_TYPE xReturn;
+
+    /* Add the idle task at the lowest priority. */
+    xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), ( xTaskHandle * ) NULL );
+
+    if( xReturn == pdPASS )
+    {
+        /* Interrupts are turned off here, to ensure a tick does not occur
+        before or during the call to xPortStartScheduler().  The stacks of
+        the created tasks contain a status word with interrupts switched on
+        so interrupts will automatically get re-enabled when the first task
+        starts to run.
+
+        STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE
+        DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */
+        portDISABLE_INTERRUPTS();
+
+        xSchedulerRunning = pdTRUE;
+        xTickCount = ( portTickType ) 0;
+
+        /* If configGENERATE_RUN_TIME_STATS is defined then the following
+        macro must be defined to configure the timer/counter used to generate
+        the run time counter time base. */
+        portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
+
+        /* Setting up the timer tick is hardware specific and thus in the
+        portable interface. */
+        if( xPortStartScheduler() )
+        {
+            /* Should not reach here as if the scheduler is running the
+            function will not return. */
+        }
+        else
+        {
+            /* Should only reach here if a task calls xTaskEndScheduler(). */
+        }
+    }
+}
+/*-----------------------------------------------------------*/
+
+void vTaskEndScheduler( void )
+{
+    /* Stop the scheduler interrupts and call the portable scheduler end
+    routine so the original ISRs can be restored if necessary.  The port
+    layer must ensure interrupts enable    bit is left in the correct state. */
+    portDISABLE_INTERRUPTS();
+    xSchedulerRunning = pdFALSE;
+    vPortEndScheduler();
+}
+/*----------------------------------------------------------*/
+#endif
+
+void vTaskSuspendAll( void )
+{
+    /* A critical section is not required as the variable is of type
+    portBASE_TYPE. */
+    ++uxSchedulerSuspended;
+}
+/*----------------------------------------------------------*/
+
+signed portBASE_TYPE xTaskResumeAll( void )
+{
+register tskTCB *pxTCB;
+signed portBASE_TYPE xAlreadyYielded = pdFALSE;
+
+    /* It is possible that an ISR caused a task to be removed from an event
+    list while the scheduler was suspended.  If this was the case then the
+    removed task will have been added to the xPendingReadyList.  Once the
+    scheduler has been resumed it is safe to move all the pending ready
+    tasks from this list into their appropriate ready list. */
+    portENTER_CRITICAL();
+    {
+        --uxSchedulerSuspended;
+
+        if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
+        {
+            if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0 )
+            {
+                portBASE_TYPE xYieldRequired = pdFALSE;
+
+                /* Move any readied tasks from the pending list into the
+                appropriate ready list. */
+                while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY(  ( ( xList * ) &xPendingReadyList ) ) ) != NULL )
+                {
+                    vListRemove( &( pxTCB->xEventListItem ) );
+                    vListRemove( &( pxTCB->xGenericListItem ) );
+                    prvAddTaskToReadyQueue( pxTCB );
+
+                    /* If we have moved a task that has a priority higher than
+                    the current task then we should yield. */
+                    if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
+                    {
+                        xYieldRequired = pdTRUE;
+                    }
+                }
+
+                /* If any ticks occurred while the scheduler was suspended then
+                they should be processed now.  This ensures the tick count does not
+                slip, and that any delayed tasks are resumed at the correct time. */
+                if( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 )
+                {
+                    while( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 )
+                    {
+                        vTaskIncrementTick();
+                        --uxMissedTicks;
+                    }
+
+                    /* As we have processed some ticks it is appropriate to yield
+                    to ensure the highest priority task that is ready to run is
+                    the task actually running. */
+                    #if configUSE_PREEMPTION == 1
+                    {
+                        xYieldRequired = pdTRUE;
+                    }
+                    #endif
+                }
+
+                if( ( xYieldRequired == pdTRUE ) || ( xMissedYield == pdTRUE ) )
+                {
+                    xAlreadyYielded = pdTRUE;
+                    xMissedYield = pdFALSE;
+                    portYIELD_WITHIN_API();
+                }
+            }
+        }
+    }
+    portEXIT_CRITICAL();
+
+    return xAlreadyYielded;
+}
+
+
+
+
+
+
+/*-----------------------------------------------------------
+ * PUBLIC TASK UTILITIES documented in task.h
+ *----------------------------------------------------------*/
+
+
+
+portTickType xTaskGetTickCount( void )
+{
+portTickType xTicks;
+
+    /* Critical section required if running on a 16 bit processor. */
+    portENTER_CRITICAL();
+    {
+        xTicks = xTickCount;
+    }
+    portEXIT_CRITICAL();
+
+    return xTicks;
+}
+/*-----------------------------------------------------------*/
+
+unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
+{
+    /* A critical section is not required because the variables are of type
+    portBASE_TYPE. */
+    return uxCurrentNumberOfTasks;
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+    void vTaskList( signed char *pcWriteBuffer )
+    {
+    unsigned portBASE_TYPE uxQueue;
+
+        /* This is a VERY costly function that should be used for debug only.
+        It leaves interrupts disabled for a LONG time. */
+
+        vTaskSuspendAll();
+        {
+            /* Run through all the lists that could potentially contain a TCB and
+            report the task name, state and stack high water mark. */
+
+            pcWriteBuffer[ 0 ] = ( signed char ) 0x00;
+            strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" );
+
+            uxQueue = uxTopUsedPriority + 1;
+
+            do
+            {
+                uxQueue--;
+
+                if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) )
+                {
+                    prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), tskREADY_CHAR );
+                }
+            }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY );
+
+            if( !listLIST_IS_EMPTY( pxDelayedTaskList ) )
+            {
+                prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, tskBLOCKED_CHAR );
+            }
+
+            if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) )
+            {
+                prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, tskBLOCKED_CHAR );
+            }
+
+            #if( INCLUDE_vTaskDelete == 1 )
+            {
+                if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) )
+                {
+                    prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, tskDELETED_CHAR );
+                }
+            }
+            #endif
+
+            #if ( INCLUDE_vTaskSuspend == 1 )
+            {
+                if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )
+                {
+                    prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, tskSUSPENDED_CHAR );
+                }
+            }
+            #endif
+        }
+        xTaskResumeAll();
+    }
+
+#endif
+/*----------------------------------------------------------*/
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+
+    void vTaskGetRunTimeStats( signed char *pcWriteBuffer )
+    {
+    unsigned portBASE_TYPE uxQueue;
+    unsigned long ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
+
+        /* This is a VERY costly function that should be used for debug only.
+        It leaves interrupts disabled for a LONG time. */
+
+        vTaskSuspendAll();
+        {
+            /* Run through all the lists that could potentially contain a TCB,
+            generating a table of run timer percentages in the provided
+            buffer. */
+
+            pcWriteBuffer[ 0 ] = ( signed char ) 0x00;
+            strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" );
+
+            uxQueue = uxTopUsedPriority + 1;
+
+            do
+            {
+                uxQueue--;
+
+                if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) )
+                {
+                    prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), ulTotalRunTime );
+                }
+            }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY );
+
+            if( !listLIST_IS_EMPTY( pxDelayedTaskList ) )
+            {
+                prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, ulTotalRunTime );
+            }
+
+            if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) )
+            {
+                prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, ulTotalRunTime );
+            }
+
+            #if ( INCLUDE_vTaskDelete == 1 )
+            {
+                if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) )
+                {
+                    prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, ulTotalRunTime );
+                }
+            }
+            #endif
+
+            #if ( INCLUDE_vTaskSuspend == 1 )
+            {
+                if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )
+                {
+                    prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, ulTotalRunTime );
+                }
+            }
+            #endif
+        }
+        xTaskResumeAll();
+    }
+
+#endif
+/*----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+    void vTaskStartTrace( signed char * pcBuffer, unsigned long ulBufferSize )
+    {
+        portENTER_CRITICAL();
+        {
+            pcTraceBuffer = ( signed char * )pcBuffer;
+            pcTraceBufferStart = pcBuffer;
+            pcTraceBufferEnd = pcBuffer + ( ulBufferSize - tskSIZE_OF_EACH_TRACE_LINE );
+            xTracing = pdTRUE;
+        }
+        portEXIT_CRITICAL();
+    }
+
+#endif
+/*----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+    unsigned long ulTaskEndTrace( void )
+    {
+    unsigned long ulBufferLength;
+
+        portENTER_CRITICAL();
+            xTracing = pdFALSE;
+        portEXIT_CRITICAL();
+
+        ulBufferLength = ( unsigned long ) ( pcTraceBuffer - pcTraceBufferStart );
+
+        return ulBufferLength;
+    }
+
+#endif
+
+
+
+/*-----------------------------------------------------------
+ * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
+ * documented in task.h
+ *----------------------------------------------------------*/
+
+
+void vTaskIncrementTick( void )
+{
+    /* Called by the portable layer each time a tick interrupt occurs.
+    Increments the tick then checks to see if the new tick value will cause any
+    tasks to be unblocked. */
+    if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
+    {
+        ++xTickCount;
+        if( xTickCount == ( portTickType ) 0 )
+        {
+            xList *pxTemp;
+
+            /* Tick count has overflowed so we need to swap the delay lists.
+            If there are any items in pxDelayedTaskList here then there is
+            an error! */
+            pxTemp = pxDelayedTaskList;
+            pxDelayedTaskList = pxOverflowDelayedTaskList;
+            pxOverflowDelayedTaskList = pxTemp;
+            xNumOfOverflows++;
+        }
+
+        /* See if this tick has made a timeout expire. */
+        prvCheckDelayedTasks();
+    }
+    else
+    {
+        ++uxMissedTicks;
+
+        /* The tick hook gets called at regular intervals, even if the
+        scheduler is locked. */
+        #if ( configUSE_TICK_HOOK == 1 )
+        {
+            extern void vApplicationTickHook( void );
+
+            vApplicationTickHook();
+        }
+        #endif
+    }
+
+    #if ( configUSE_TICK_HOOK == 1 )
+    {
+        extern void vApplicationTickHook( void );
+
+        /* Guard against the tick hook being called when the missed tick
+        count is being unwound (when the scheduler is being unlocked. */
+        if( uxMissedTicks == 0 )
+        {
+            vApplicationTickHook();
+        }
+    }
+    #endif
+
+    traceTASK_INCREMENT_TICK( xTickCount );
+}
+/*-----------------------------------------------------------*/
+
+#if ( ( INCLUDE_vTaskCleanUpResources == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
+
+    void vTaskCleanUpResources( void )
+    {
+    unsigned short usQueue;
+    volatile tskTCB *pxTCB;
+
+        usQueue = ( unsigned short ) uxTopUsedPriority + ( unsigned short ) 1;
+
+        /* Remove any TCB's from the ready queues. */
+        do
+        {
+            usQueue--;
+
+            while( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ usQueue ] ) ) )
+            {
+                listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &( pxReadyTasksLists[ usQueue ] ) );
+                vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
+
+                prvDeleteTCB( ( tskTCB * ) pxTCB );
+            }
+        }while( usQueue > ( unsigned short ) tskIDLE_PRIORITY );
+
+        /* Remove any TCB's from the delayed queue. */
+        while( !listLIST_IS_EMPTY( &xDelayedTaskList1 ) )
+        {
+            listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xDelayedTaskList1 );
+            vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
+
+            prvDeleteTCB( ( tskTCB * ) pxTCB );
+        }
+
+        /* Remove any TCB's from the overflow delayed queue. */
+        while( !listLIST_IS_EMPTY( &xDelayedTaskList2 ) )
+        {
+            listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xDelayedTaskList2 );
+            vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
+
+            prvDeleteTCB( ( tskTCB * ) pxTCB );
+        }
+
+        while( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )
+        {
+            listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xSuspendedTaskList );
+            vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
+
+            prvDeleteTCB( ( tskTCB * ) pxTCB );
+        }
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+
+    void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxTagValue )
+    {
+    tskTCB *xTCB;
+
+        /* If xTask is NULL then we are setting our own task hook. */
+        if( xTask == NULL )
+        {
+            xTCB = ( tskTCB * ) pxCurrentTCB;
+        }
+        else
+        {
+            xTCB = ( tskTCB * ) xTask;
+        }
+
+        /* Save the hook function in the TCB.  A critical section is required as
+        the value can be accessed from an interrupt. */
+        portENTER_CRITICAL();
+            xTCB->pxTaskTag = pxTagValue;
+        portEXIT_CRITICAL();
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+
+    pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask )
+    {
+    tskTCB *xTCB;
+    pdTASK_HOOK_CODE xReturn;
+
+        /* If xTask is NULL then we are setting our own task hook. */
+        if( xTask == NULL )
+        {
+            xTCB = ( tskTCB * ) pxCurrentTCB;
+        }
+        else
+        {
+            xTCB = ( tskTCB * ) xTask;
+        }
+
+        /* Save the hook function in the TCB.  A critical section is required as
+        the value can be accessed from an interrupt. */
+        portENTER_CRITICAL();
+            xReturn = xTCB->pxTaskTag;
+        portEXIT_CRITICAL();
+
+        return xReturn;
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+
+    portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter )
+    {
+    tskTCB *xTCB;
+    portBASE_TYPE xReturn;
+
+        /* If xTask is NULL then we are calling our own task hook. */
+        if( xTask == NULL )
+        {
+            xTCB = ( tskTCB * ) pxCurrentTCB;
+        }
+        else
+        {
+            xTCB = ( tskTCB * ) xTask;
+        }
+
+        if( xTCB->pxTaskTag != NULL )
+        {
+            xReturn = xTCB->pxTaskTag( pvParameter );
+        }
+        else
+        {
+            xReturn = pdFAIL;
+        }
+
+        return xReturn;
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+void vTaskSwitchContext( void )
+{
+    if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )
+    {
+        /* The scheduler is currently suspended - do not allow a context
+        switch. */
+        xMissedYield = pdTRUE;
+        return;
+    }
+
+    traceTASK_SWITCHED_OUT();
+
+    #if ( configGENERATE_RUN_TIME_STATS == 1 )
+    {
+        unsigned long ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE();
+
+            /* Add the amount of time the task has been running to the accumulated
+            time so far.  The time the task started running was stored in
+            ulTaskSwitchedInTime.  Note that there is no overflow protection here
+            so count values are only valid until the timer overflows.  Generally
+            this will be about 1 hour assuming a 1uS timer increment. */
+            pxCurrentTCB->ulRunTimeCounter += ( ulTempCounter - ulTaskSwitchedInTime );
+            ulTaskSwitchedInTime = ulTempCounter;
+    }
+    #endif
+
+    taskFIRST_CHECK_FOR_STACK_OVERFLOW();
+    taskSECOND_CHECK_FOR_STACK_OVERFLOW();
+
+    /* Find the highest priority queue that contains ready tasks. */
+    while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )
+    {
+        --uxTopReadyPriority;
+    }
+
+    /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the
+    same priority get an equal share of the processor time. */
+    listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );
+    #if 0
+    //#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )
+    {
+        xList * const pxConstList = &( pxReadyTasksLists[ uxTopReadyPriority ] );
+        /* Increment the index to the next item and return the item, ensuring */
+        /* we don't return the marker used at the end of the list.  */
+        ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;
+        if( ( pxConstList )->pxIndex == ( xListItem * ) &( ( pxConstList )->xListEnd ) )
+        {
+            ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;
+        }
+        pxCurrentTCB = (tskTCB *) (( pxConstList )->pxIndex->pvOwner);      // Error then added (tskTCB *)()
+    }
+    #endif
+
+    traceTASK_SWITCHED_IN();
+    vWriteTraceToBuffer();
+}
+/*-----------------------------------------------------------*/
+
+void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait )
+{
+portTickType xTimeToWake;
+
+    /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
+    SCHEDULER SUSPENDED. */
+
+    /* Place the event list item of the TCB in the appropriate event list.
+    This is placed in the list in priority order so the highest priority task
+    is the first to be woken by the event. */
+    vListInsert( ( xList * ) pxEventList, ( xListItem * ) &( pxCurrentTCB->xEventListItem ) );
+
+    /* We must remove ourselves from the ready list before adding ourselves
+    to the blocked list as the same list item is used for both lists.  We have
+    exclusive access to the ready lists as the scheduler is locked. */
+    vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
+
+
+    #if ( INCLUDE_vTaskSuspend == 1 )
+    {
+        if( xTicksToWait == portMAX_DELAY )
+        {
+            /* Add ourselves to the suspended task list instead of a delayed task
+            list to ensure we are not woken by a timing event.  We will block
+            indefinitely. */
+            vListInsertEnd( ( xList * ) &xSuspendedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
+        }
+        else
+        {
+            /* Calculate the time at which the task should be woken if the event does
+            not occur.  This may overflow but this doesn't matter. */
+            xTimeToWake = xTickCount + xTicksToWait;
+
+            listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
+
+            if( xTimeToWake < xTickCount )
+            {
+                /* Wake time has overflowed.  Place this item in the overflow list. */
+                vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
+            }
+            else
+            {
+                /* The wake time has not overflowed, so we can use the current block list. */
+                vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
+            }
+        }
+    }
+    #else
+    {
+            /* Calculate the time at which the task should be woken if the event does
+            not occur.  This may overflow but this doesn't matter. */
+            xTimeToWake = xTickCount + xTicksToWait;
+
+            listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
+
+            if( xTimeToWake < xTickCount )
+            {
+                /* Wake time has overflowed.  Place this item in the overflow list. */
+                vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
+            }
+            else
+            {
+                /* The wake time has not overflowed, so we can use the current block list. */
+                vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
+            }
+    }
+    #endif
+}
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList )
+{
+tskTCB *pxUnblockedTCB;
+portBASE_TYPE xReturn;
+
+    /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
+    SCHEDULER SUSPENDED.  It can also be called from within an ISR. */
+
+    /* The event list is sorted in priority order, so we can remove the
+    first in the list, remove the TCB from the delayed list, and add
+    it to the ready list.
+
+    If an event is for a queue that is locked then this function will never
+    get called - the lock count on the queue will get modified instead.  This
+    means we can always expect exclusive access to the event list here. */
+    pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
+    vListRemove( &( pxUnblockedTCB->xEventListItem ) );
+
+    if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
+    {
+        vListRemove( &( pxUnblockedTCB->xGenericListItem ) );
+        prvAddTaskToReadyQueue( pxUnblockedTCB );
+    }
+    else
+    {
+        /* We cannot access the delayed or ready lists, so will hold this
+        task pending until the scheduler is resumed. */
+        vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
+    }
+
+    if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority )
+    {
+        /* Return true if the task removed from the event list has
+        a higher priority than the calling task.  This allows
+        the calling task to know if it should force a context
+        switch now. */
+        xReturn = pdTRUE;
+    }
+    else
+    {
+        xReturn = pdFALSE;
+    }
+
+    return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut )
+{
+    pxTimeOut->xOverflowCount = xNumOfOverflows;
+    pxTimeOut->xTimeOnEntering = xTickCount;
+}
+/*-----------------------------------------------------------*/
+
+portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait )
+{
+portBASE_TYPE xReturn;
+
+    portENTER_CRITICAL();
+    {
+        #if ( INCLUDE_vTaskSuspend == 1 )
+            /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
+            the maximum block time then the task should block indefinitely, and
+            therefore never time out. */
+            if( *pxTicksToWait == portMAX_DELAY )
+            {
+                xReturn = pdFALSE;
+            }
+            else /* We are not blocking indefinitely, perform the checks below. */
+        #endif
+
+        if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( ( portTickType ) xTickCount >= ( portTickType ) pxTimeOut->xTimeOnEntering ) )
+        {
+            /* The tick count is greater than the time at which vTaskSetTimeout()
+            was called, but has also overflowed since vTaskSetTimeOut() was called.
+            It must have wrapped all the way around and gone past us again. This
+            passed since vTaskSetTimeout() was called. */
+            xReturn = pdTRUE;
+        }
+        else if( ( ( portTickType ) ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ) ) < ( portTickType ) *pxTicksToWait )
+        {
+            /* Not a genuine timeout. Adjust parameters for time remaining. */
+            *pxTicksToWait -= ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering );
+            vTaskSetTimeOutState( pxTimeOut );
+            xReturn = pdFALSE;
+        }
+        else
+        {
+            xReturn = pdTRUE;
+        }
+    }
+    portEXIT_CRITICAL();
+
+    return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vTaskMissedYield( void )
+{
+    xMissedYield = pdTRUE;
+}
+
+/*
+ * -----------------------------------------------------------
+ * The Idle task.
+ * ----------------------------------------------------------
+ *
+ * The portTASK_FUNCTION() macro is used to allow port/compiler specific
+ * language extensions.  The equivalent prototype for this function is:
+ *
+ * void prvIdleTask( void *pvParameters );
+ *
+ */
+static portTASK_FUNCTION( prvIdleTask, pvParameters )
+{
+    /* Stop warnings. */
+    ( void ) pvParameters;
+
+    for( ;; )
+    {
+        /* See if any tasks have been deleted. */
+        prvCheckTasksWaitingTermination();
+
+        #if ( configUSE_PREEMPTION == 0 )
+        {
+            /* If we are not using preemption we keep forcing a task switch to
+            see if any other task has become available.  If we are using
+            preemption we don't need to do this as any task becoming available
+            will automatically get the processor anyway. */
+            taskYIELD();
+        }
+        #endif
+
+        #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
+        {
+            /* When using preemption tasks of equal priority will be
+            timesliced.  If a task that is sharing the idle priority is ready
+            to run then the idle task should yield before the end of the
+            timeslice.
+
+            A critical region is not required here as we are just reading from
+            the list, and an occasional incorrect value will not matter.  If
+            the ready list at the idle priority contains more than one task
+            then a task other than the idle task is ready to execute. */
+            if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 )
+            {
+                taskYIELD();
+            }
+        }
+        #endif
+
+        #if ( configUSE_IDLE_HOOK == 1 )
+        {
+            extern void vApplicationIdleHook( void );
+
+            /* Call the user defined function from within the idle task.  This
+            allows the application designer to add background functionality
+            without the overhead of a separate task.
+            NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
+            CALL A FUNCTION THAT MIGHT BLOCK. */
+            vApplicationIdleHook();
+        }
+        #endif
+    }
+} /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */
+
+
+
+
+
+
+
+/*-----------------------------------------------------------
+ * File private functions documented at the top of the file.
+ *----------------------------------------------------------*/
+
+
+
+static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth )
+{
+    /* Store the function name in the TCB. */
+    #if configMAX_TASK_NAME_LEN > 1
+    {
+        /* Don't bring strncpy into the build unnecessarily. */
+        strncpy( ( char * ) pxTCB->pcTaskName, ( const char * ) pcName, ( unsigned short ) configMAX_TASK_NAME_LEN );
+    }
+    #endif
+    pxTCB->pcTaskName[ ( unsigned short ) configMAX_TASK_NAME_LEN - ( unsigned short ) 1 ] = '\0';
+
+    /* This is used as an array index so must ensure it's not too large.  First
+    remove the privilege bit if one is present. */
+    if( uxPriority >= configMAX_PRIORITIES )
+    {
+        uxPriority = configMAX_PRIORITIES - 1;
+    }
+
+    pxTCB->uxPriority = uxPriority;
+    #if ( configUSE_MUTEXES == 1 )
+    {
+        pxTCB->uxBasePriority = uxPriority;
+    }
+    #endif
+
+    vListInitialiseItem( &( pxTCB->xGenericListItem ) );
+    vListInitialiseItem( &( pxTCB->xEventListItem ) );
+
+    /* Set the pxTCB as a link back from the xListItem.  This is so we can get
+    back to    the containing TCB from a generic item in a list. */
+    listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );
+
+    /* Event lists are always in priority order. */
+    listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority );
+    listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
+
+    #if ( portCRITICAL_NESTING_IN_TCB == 1 )
+    {
+        pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0;
+    }
+    #endif
+
+    #if ( configUSE_APPLICATION_TASK_TAG == 1 )
+    {
+        pxTCB->pxTaskTag = NULL;
+    }
+    #endif
+
+    #if ( configGENERATE_RUN_TIME_STATS == 1 )
+    {
+        pxTCB->ulRunTimeCounter = 0UL;
+    }
+    #endif
+
+    #if ( portUSING_MPU_WRAPPERS == 1 )
+    {
+        vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
+    }
+    #else
+    {
+        ( void ) xRegions;
+        ( void ) usStackDepth;
+    }
+    #endif
+}
+/*-----------------------------------------------------------*/
+
+#if ( portUSING_MPU_WRAPPERS == 1 )
+
+    void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions )
+    {
+    tskTCB *pxTCB;
+    
+        if( xTaskToModify == pxCurrentTCB )
+        {
+            xTaskToModify = NULL;
+        }
+
+        /* If null is passed in here then we are deleting ourselves. */
+        pxTCB = prvGetTCBFromHandle( xTaskToModify );
+
+        vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
+    }
+    /*-----------------------------------------------------------*/
+#endif
+
+static void prvInitialiseTaskLists( void )
+{
+unsigned portBASE_TYPE uxPriority;
+
+    for( uxPriority = 0; uxPriority < configMAX_PRIORITIES; uxPriority++ )
+    {
+        vListInitialise( ( xList * ) &( pxReadyTasksLists[ uxPriority ] ) );
+    }
+
+    vListInitialise( ( xList * ) &xDelayedTaskList1 );
+    vListInitialise( ( xList * ) &xDelayedTaskList2 );
+    vListInitialise( ( xList * ) &xPendingReadyList );
+
+    #if ( INCLUDE_vTaskDelete == 1 )
+    {
+        vListInitialise( ( xList * ) &xTasksWaitingTermination );
+    }
+    #endif
+
+    #if ( INCLUDE_vTaskSuspend == 1 )
+    {
+        vListInitialise( ( xList * ) &xSuspendedTaskList );
+    }
+    #endif
+
+    /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
+    using list2. */
+    pxDelayedTaskList = &xDelayedTaskList1;
+    pxOverflowDelayedTaskList = &xDelayedTaskList2;
+}
+/*-----------------------------------------------------------*/
+
+static void prvCheckTasksWaitingTermination( void )
+{
+    #if ( INCLUDE_vTaskDelete == 1 )
+    {
+        portBASE_TYPE xListIsEmpty;
+
+        /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
+        too often in the idle task. */
+        if( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0 )
+        {
+            vTaskSuspendAll();
+                xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
+            xTaskResumeAll();
+
+            if( !xListIsEmpty )
+            {
+                tskTCB *pxTCB;
+
+                portENTER_CRITICAL();
+                {
+                    pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xTasksWaitingTermination ) );
+                    vListRemove( &( pxTCB->xGenericListItem ) );
+                    --uxCurrentNumberOfTasks;
+                    --uxTasksDeleted;
+                }
+                portEXIT_CRITICAL();
+
+                prvDeleteTCB( pxTCB );
+            }
+        }
+    }
+    #endif
+}
+/*-----------------------------------------------------------*/
+
+static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer )
+{
+tskTCB *pxNewTCB;
+
+    /* Allocate space for the TCB.  Where the memory comes from depends on
+    the implementation of the port malloc function. */
+    pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) );
+
+    if( pxNewTCB != NULL )
+    {
+        /* Allocate space for the stack used by the task being created.
+        The base of the stack memory stored in the TCB so the task can
+        be deleted later if required. */
+        pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMallocAligned( ( ( ( size_t )usStackDepth ) * sizeof( portSTACK_TYPE ) ), puxStackBuffer );
+
+        if( pxNewTCB->pxStack == NULL )
+        {
+            /* Could not allocate the stack.  Delete the allocated TCB. */
+            vPortFree( pxNewTCB );
+            pxNewTCB = NULL;
+        }
+        else
+        {
+            /* Just to help debugging. */
+            memset( pxNewTCB->pxStack, tskSTACK_FILL_BYTE, usStackDepth * sizeof( portSTACK_TYPE ) );
+        }
+    }
+
+    return pxNewTCB;
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+    static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus )
+    {
+    volatile tskTCB *pxNextTCB, *pxFirstTCB;
+    unsigned short usStackRemaining;
+
+        /* Write the details of all the TCB's in pxList into the buffer. */
+        listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
+        do
+        {
+            listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
+            #if ( portSTACK_GROWTH > 0 )
+            {
+                usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack );
+            }
+            #else
+            {
+                usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack );
+            }
+            #endif            
+            
+            sprintf( pcStatusString, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, ( unsigned int ) pxNextTCB->uxPriority, usStackRemaining, ( unsigned int ) pxNextTCB->uxTCBNumber );
+            strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatusString );
+
+        } while( pxNextTCB != pxFirstTCB );
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+
+    static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime )
+    {
+    volatile tskTCB *pxNextTCB, *pxFirstTCB;
+    unsigned long ulStatsAsPercentage;
+
+        /* Write the run time stats of all the TCB's in pxList into the buffer. */
+        listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
+        do
+        {
+            /* Get next TCB in from the list. */
+            listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
+
+            /* Divide by zero check. */
+            if( ulTotalRunTime > 0UL )
+            {
+                /* Has the task run at all? */
+                if( pxNextTCB->ulRunTimeCounter == 0 )
+                {
+                    /* The task has used no CPU time at all. */
+                    sprintf( pcStatsString, ( char * ) "%s\t\t0\t\t0%%\r\n", pxNextTCB->pcTaskName );
+                }
+                else
+                {
+                    /* What percentage of the total run time as the task used?
+                    This will always be rounded down to the nearest integer. */
+                    ulStatsAsPercentage = ( 100UL * pxNextTCB->ulRunTimeCounter ) / ulTotalRunTime;
+
+                    if( ulStatsAsPercentage > 0UL )
+                    {
+                        sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
+                    }
+                    else
+                    {
+                        /* If the percentage is zero here then the task has
+                        consumed less than 1% of the total run time. */
+                        sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter );
+                    }
+                }
+
+                strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatsString );
+            }
+
+        } while( pxNextTCB != pxFirstTCB );
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
+
+    static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte )
+    {
+    register unsigned short usCount = 0;
+
+        while( *pucStackByte == tskSTACK_FILL_BYTE )
+        {
+            pucStackByte -= portSTACK_GROWTH;
+            usCount++;
+        }
+
+        usCount /= sizeof( portSTACK_TYPE );
+
+        return usCount;
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
+
+    unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask )
+    {
+    tskTCB *pxTCB;
+    unsigned char *pcEndOfStack;
+    unsigned portBASE_TYPE uxReturn;
+
+        pxTCB = prvGetTCBFromHandle( xTask );
+
+        #if portSTACK_GROWTH < 0
+        {
+            pcEndOfStack = ( unsigned char * ) pxTCB->pxStack;
+        }
+        #else
+        {
+            pcEndOfStack = ( unsigned char * ) pxTCB->pxEndOfStack;
+        }
+        #endif
+
+        uxReturn = ( unsigned portBASE_TYPE ) usTaskCheckFreeStackSpace( pcEndOfStack );
+
+        return uxReturn;
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) )
+
+    static void prvDeleteTCB( tskTCB *pxTCB )
+    {
+        /* Free up the memory allocated by the scheduler for the task.  It is up to
+        the task to free any memory allocated at the application level. */
+        vPortFreeAligned( pxTCB->pxStack );
+        vPortFree( pxTCB );
+    }
+
+#endif
+
+
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_xTaskGetCurrentTaskHandle == 1 )
+
+    xTaskHandle xTaskGetCurrentTaskHandle( void )
+    {
+    xTaskHandle xReturn;
+
+        /* A critical section is not required as this is not called from
+        an interrupt and the current TCB will always be the same for any
+        individual execution thread. */
+        xReturn = pxCurrentTCB;
+
+        return xReturn;
+    }
+
+#endif
+
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_xTaskGetSchedulerState == 1 )
+
+    portBASE_TYPE xTaskGetSchedulerState( void )
+    {
+    portBASE_TYPE xReturn;
+
+        if( xSchedulerRunning == pdFALSE )
+        {
+            xReturn = taskSCHEDULER_NOT_STARTED;
+        }
+        else
+        {
+            if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
+            {
+                xReturn = taskSCHEDULER_RUNNING;
+            }
+            else
+            {
+                xReturn = taskSCHEDULER_SUSPENDED;
+            }
+        }
+
+        return xReturn;
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_MUTEXES == 1 )
+
+    void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder )
+    {
+    tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
+
+        if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
+        {
+            /* Adjust the mutex holder state to account for its new priority. */
+            listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority );
+
+            /* If the task being modified is in the ready state it will need to
+            be moved in to a new list. */
+            if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) )
+            {
+                vListRemove( &( pxTCB->xGenericListItem ) );
+
+                /* Inherit the priority before being moved into the new list. */
+                pxTCB->uxPriority = pxCurrentTCB->uxPriority;
+                prvAddTaskToReadyQueue( pxTCB );
+            }
+            else
+            {
+                /* Just inherit the priority. */
+                pxTCB->uxPriority = pxCurrentTCB->uxPriority;
+            }
+        }
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_MUTEXES == 1 )
+
+    void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder )
+    {
+    tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
+
+        if( pxMutexHolder != NULL )
+        {
+            if( pxTCB->uxPriority != pxTCB->uxBasePriority )
+            {
+                /* We must be the running task to be able to give the mutex back.
+                Remove ourselves from the ready list we currently appear in. */
+                vListRemove( &( pxTCB->xGenericListItem ) );
+
+                /* Disinherit the priority before adding ourselves into the new
+                ready list. */
+                pxTCB->uxPriority = pxTCB->uxBasePriority;
+                listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority );
+                prvAddTaskToReadyQueue( pxTCB );
+            }
+        }
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( portCRITICAL_NESTING_IN_TCB == 1 )
+
+    void vTaskEnterCritical( void )
+    {
+        portDISABLE_INTERRUPTS();
+
+        if( xSchedulerRunning != pdFALSE )
+        {
+            pxCurrentTCB->uxCriticalNesting++;
+        }
+    }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( portCRITICAL_NESTING_IN_TCB == 1 )
+
+void vTaskExitCritical( void )
+{
+    if( xSchedulerRunning != pdFALSE )
+    {
+        if( pxCurrentTCB->uxCriticalNesting > 0 )
+        {
+            pxCurrentTCB->uxCriticalNesting--;
+
+            if( pxCurrentTCB->uxCriticalNesting == 0 )
+            {
+                portENABLE_INTERRUPTS();
+            }
+        }
+    }
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+
+
+