FreeRTOS官方文件分析(三)API(1)-Task Creation(任务创建)

建议由条件看FreeRTOS的官方英文参考。


目录

xTaskCreate

Returns

Example usage

函数代码

xTaskCreateStatic

Returns

Example usage

函数代码

xTaskCreateRestructedStatic

TaskParameters_t结构体

Example usage

vTaskDelete

Example usage

函数代码


xTaskCreate

创建一个新任务并将其添加到准备运行的任务列表中。configSUPPORT_DYNAMIC_ALLOCATION必须在FreeRTOSConfig.h中设置为 1,或者未定义(在这种情况下它将 默认为 1),以便此 RTOS API 函数可用。

每个任务都需要用于保存任务状态并由任务使用的 RAM 作为它的堆栈。 如果使用创建任务xTaskCreate()那么所需的 RAM 会自动 从 FreeRTOS堆。如果创建了任务使用xTaskCreateStatic()那么 RAM 是 由应用程序编写者提供,因此可以在编译时静态分配。

//task.h
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
    BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
                            const char * const pcName,     /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
                                                           /*仅允许字符串和单个字符使用非限定字符类型。 */
                            const configSTACK_DEPTH_TYPE usStackDepth,
                            void * const pvParameters,
                            UBaseType_t uxPriority,
                            TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
#endif

pxTaskCode指向任务入口函数的指针。

pcName任务的描述性名称。主要是为了方便调试,也可以用于获取任务句柄。

usStackDepthThe number of words (not bytes!) to allocate for use as the task's stack. 栈大小

pvParameters作为参数传递给创建的任务的值。

uxPriority任务优先级。

PRIVILEGED_FUNCTION用于将句柄传递给创建的任务 xTaskCreate() 功能。 pxCreatedTask是可选的,可以设置为 NULL。

Returns

If the task was created successfully then pdPASS is returned.

Otherwise errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY is returned.

如果任务创建成功,那么pdPASS被返回。

否则errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY被返回。

Example usage

//Example usage:

/* Task to be created. */
/* 要创建的任务。  */
void vTaskCode( void * pvParameters )
{ 
    /* The parameter value is expected to be 1 as 1 is passed in the
    pvParameters value in the call to xTaskCreate() below. */
    configASSERT( ( ( uint32_t ) pvParameters ) == 1 );  //断言

    for( ;; )
    {
        /* Task code goes here. */
    }
}

/* Function that creates a task. */
/* 创建任务的函数。  */ 

void vOtherFunction( void )
{
BaseType_t xReturned;
TaskHandle_t xHandle = NULL;

    /* Create the task, storing the handle. */
    xReturned = xTaskCreate(
                    vTaskCode,       /* Function that implements the task. */
                    "NAME",          /* Text name for the task. */
                    STACK_SIZE,      /* Stack size in words, not bytes. */
                    ( void * ) 1,    /* Parameter passed into the task. */
                    tskIDLE_PRIORITY,/* Priority at which the task is created. */
                    &xHandle );      /* Used to pass out the created task's handle. */

    if( xReturned == pdPASS )
    {
        /* The task was created.  Use the task's handle to delete the task. */
        /* 任务已创建。  使用任务的句柄删除任务。  */
        vTaskDelete( xHandle );
    }
}

函数代码

//tasks.c
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )

    BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
                            const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
                            const configSTACK_DEPTH_TYPE usStackDepth,
                            void * const pvParameters,
                            UBaseType_t uxPriority,
                            TaskHandle_t * const pxCreatedTask )
    {
        TCB_t * pxNewTCB;
        BaseType_t xReturn;

        /* If the stack grows down then allocate the stack then the TCB so the stack
         * does not grow into the TCB.  Likewise if the stack grows up then allocate
         * the TCB then the stack. */
        #if ( portSTACK_GROWTH > 0 )
            {
                /* Allocate space for the TCB.  Where the memory comes from depends on
                 * the implementation of the port malloc function and whether or not static
                 * allocation is being used. */
                pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );

                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 = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */

                    if( pxNewTCB->pxStack == NULL )
                    {
                        /* Could not allocate the stack.  Delete the allocated TCB. */
                        vPortFree( pxNewTCB );
                        pxNewTCB = NULL;
                    }
                }
            }
        #else /* portSTACK_GROWTH */
            {
                StackType_t * pxStack;

                /* Allocate space for the stack used by the task being created. */
                pxStack = pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */

                if( pxStack != NULL )
                {
                    /* Allocate space for the TCB. */
                    pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */

                    if( pxNewTCB != NULL )
                    {
                        /* Store the stack location in the TCB. */
                        pxNewTCB->pxStack = pxStack;
                    }
                    else
                    {
                        /* The stack cannot be used as the TCB was not created.  Free
                         * it again. */
                        vPortFree( pxStack );
                    }
                }
                else
                {
                    pxNewTCB = NULL;
                }
            }
        #endif /* portSTACK_GROWTH */

        if( pxNewTCB != NULL )
        {
            #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */
                {
                    /* Tasks can be created statically or dynamically, so note this
                     * task was created dynamically in case it is later deleted. */
                    pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
                }
            #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */

            prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
            prvAddNewTaskToReadyList( pxNewTCB );
            xReturn = pdPASS;
        }
        else
        {
            xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
        }

        return xReturn;
    }

#endif /* configSUPPORT_DYNAMIC_ALLOCATION */

 

xTaskCreateStatic

创建一个新任务并将其添加到准备运行的任务列表中。configSUPPORT_STATIC_ALLOCATION 必须设置为 1 在 FreeRTOSConfig.h使此 RTOS API 功能可用。

每个任务都需要用于保存任务状态的 RAM,并被任务用作其堆栈。 创建任务,则会 xTaskCreate() 从 FreeRTOS 堆中 。 如果使用创建任务 xTaskCreateStatic()那么 RAM 由应用程序编写器提供,这会导致更多的参数,但允许在编译时静态分配 RAM。

//task.h
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
    TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
                                    const char * const pcName,     /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
                                    const uint32_t ulStackDepth,
                                    void * const pvParameters,
                                    UBaseType_t uxPriority,
                                    StackType_t * const puxStackBuffer,
                                    StaticTask_t * const pxTaskBuffer ) PRIVILEGED_FUNCTION;
#endif /* configSUPPORT_STATIC_ALLOCATION */

pxTaskCode指向任务入口函数的指针。

pcName任务的描述性名称。主要是为了方便调试,也可以用于获取任务句柄。

ulStackDepthThe puxStackBuffer parameter is used to pass an array of StackType_t variables into xTaskCreateStatic(). ulStackDepth must be set to the number of indexes in the array.

puxStackBuffer参数用于将StackType_t变量数组传递到xTaskCreateStatic()。 ulStackDepth必须设置为数组中的索引数。

pvParameters作为参数传递给创建的任务的值。

uxPriority任务优先级。

puxStackBuffer必须指向一个 StackType_t至少有的数组 ulStackDepth指数(见 ulStackDepth上面的参数) - 该数组将用作任务的堆栈,因此它必须是持久的(未在函数的堆栈上声明)。

pxTaskBuffer必须指向类型的变量 StaticTask_t。该变量将用于保存新任务的数据结构 (TCB),因此它必须是持久的(未在函数的堆栈上声明)。

Returns

If neither puxStackBuffer or pxTaskBuffer are NULL then the task will be created, and the task's handle is returned. If either puxStackBuffer or pxTaskBuffer is NULL then the task will not be created and NULL will be returned.

如果puxStackBuffer或pxTaskBuffer均不为空,则将创建该任务,并返回该任务的句柄。 如果puxStackBuffer或pxTaskBuffer为NULL,则不会创建任务,并返回NULL。

Example usage

//Example usage 
   /* Dimensions of the buffer that the task being created will use as its stack.
    正在创建的任务将用作其堆栈的缓冲区的维度。 
    NOTE:  This is the number of words the stack will hold, not the number of
    bytes.  For example, if each stack item is 32-bits, and this is set to 100,
    then 400 bytes (100 * 32-bits) will be allocated. */
    #define STACK_SIZE 200

    /* Structure that will hold the TCB of the task being created. */
    /* 将保存正在创建的任务的 TCB 的结构。  */ 
    StaticTask_t xTaskBuffer;

    /* Buffer that the task being created will use as its stack.  Note this is
    an array of StackType_t variables.  The size of StackType_t is dependent on
    the RTOS port. */
    /*正在创建的任务将用作其堆栈的缓冲区。 注意这是StackType_t变量的数组。 
      StackType_UT的大小取决于RTOS端口*/ 
    StackType_t xStack[ STACK_SIZE ];

    /* Function that implements the task being created. */
    void vTaskCode( void * pvParameters )
    {
        /* The parameter value is expected to be 1 as 1 is passed in the
        pvParameters value in the call to xTaskCreateStatic(). */
        configASSERT( ( uint32_t ) pvParameters == 1UL );    //断言

        for( ;; )
        {
            /* Task code goes here. */
        }
    }

    /* Function that creates a task. */
    void vOtherFunction( void )
    {
        TaskHandle_t xHandle = NULL;

        /* Create the task without using any dynamic memory allocation. */
        /* 创建任务而不使用任何动态内存分配。  */
        xHandle = xTaskCreateStatic(
                      vTaskCode,       /* Function that implements the task. */
                      "NAME",          /* Text name for the task. */
                      STACK_SIZE,      /* Number of indexes in the xStack array. */
                      ( void * ) 1,    /* Parameter passed into the task. */
                      tskIDLE_PRIORITY,/* Priority at which the task is created. */
                      xStack,          /* Array to use as the task's stack. */
                      &xTaskBuffer );  /* Variable to hold the task's data structure. */

        /* puxStackBuffer and pxTaskBuffer were not NULL, so the task will have
        been created, and xHandle will be the task's handle.  Use the handle
        to suspend the task. */
        /*puxStackBuffer和pxTaskBuffer不为NULL,因此任务将被创建,
          xHandle将是任务的句柄。 使用句柄挂起任务*/ 
        vTaskSuspend( xHandle );
    }

函数代码

//tasks.c
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )

    TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
                                    const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
                                    const uint32_t ulStackDepth,
                                    void * const pvParameters,
                                    UBaseType_t uxPriority,
                                    StackType_t * const puxStackBuffer,
                                    StaticTask_t * const pxTaskBuffer )
    {
        TCB_t * pxNewTCB;
        TaskHandle_t xReturn;

        configASSERT( puxStackBuffer != NULL );
        configASSERT( pxTaskBuffer != NULL );

        #if ( configASSERT_DEFINED == 1 )
            {
                /* Sanity check that the size of the structure used to declare a
                 * variable of type StaticTask_t equals the size of the real task
                 * structure. */
                volatile size_t xSize = sizeof( StaticTask_t );
                configASSERT( xSize == sizeof( TCB_t ) );
                ( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */
            }
        #endif /* configASSERT_DEFINED */

        if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
        {
            /* The memory used for the task's TCB and stack are passed into this
             * function - use them. */
            pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
            pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;

            #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
                {
                    /* Tasks can be created statically or dynamically, so note this
                     * task was created statically in case the task is later deleted. */
                    pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
                }
            #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */

            prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );
            prvAddNewTaskToReadyList( pxNewTCB );
        }
        else
        {
            xReturn = NULL;
        }

        return xReturn;
    }

#endif /* SUPPORT_STATIC_ALLOCATION */

xTaskCreateRestructedStatic

FreeRTOS-MPU特定程序

创建一个新的内存保护单元 (MPU) 受限任务并将其添加到准备运行的任务列表中。 configSUPPORT_STATIC_ALLOCATION 必须设置为 1 在 FreeRTOSConfig.h使此 RTOS API 功能可用。

在内部,在 FreeRTOS 实现中,每个任务都需要两个内存块。 第一个块是 用于保存任务的数据结构。 第二个块用作任务的堆栈。 如果创建了任务 使用 xTaskCreateRestricted() 则任务堆栈的内存由应用程序编写者提供,并且 任务数据结构的内存是从 FreeRTOS 堆 。 如果使用 xTaskCreateRestrictedStatic() 创建任务,则 应用程序编写者也必须为任务的数据结构提供内存。 xTaskCreateRestrictedStatic() 因此允许在不使用任何动态内存分配的情况下创建内存保护任务

//task.h
#if ( portUSING_MPU_WRAPPERS == 1 )
    BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition,
                                      TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION;
#endif

pxTaskDefinition指向定义任务的结构的指针。

pxCreatedTask用于传回一个句柄,通过该句柄可以引用创建的任务。

TaskParameters_t结构体

//task.h
typedef struct xMEMORY_REGION
{
    void * pvBaseAddress;
    uint32_t ulLengthInBytes;
    uint32_t ulParameters;
} MemoryRegion_t;

typedef struct xTASK_PARAMETERS
{
    TaskFunction_t pvTaskCode;
    const char * pcName;     /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
    configSTACK_DEPTH_TYPE usStackDepth;
    void * pvParameters;
    UBaseType_t uxPriority;
    StackType_t * puxStackBuffer;
    MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ];
    #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
        StaticTask_t * const pxTaskBuffer;
    #endif
} TaskParameters_t;

pvTaskCode指向任务入口函数的指针。

pcName任务的描述性名称。主要是为了方便调试,也可以用于获取任务句柄。

usStackDepthThe number of words (not bytes!) to allocate for use as the task's stack. 栈大小

pvParameters作为参数传递给创建的任务的值。

uxPriority任务优先级。

puxStackBuffer每次切换任务时,都会动态重新配置 MPU 以定义提供任务的区域 对其自己的堆栈的读写访问。 MPU 区域必须满足许多约束 - 特别是, 所有此类区域的大小和对齐方式必须等于两个值的相同幂。

每次创建任务时,标准 FreeRTOS 端口使用 pvPortMalloc() 分配一个新堆栈。 提供 处理 MPU 数据对齐要求的 pvPortMalloc() 实现是可能的,但是 它的 RAM 使用也会很复杂且效率低下。 为了消除对这种复杂性的需求,FreeRTOS-MPU 允许在编译时静态声明堆栈。 这允许使用编译器管理对齐 由链接器管理的扩展和 RAM 使用效率。 例如,如果使用 GCC,堆栈可以是 使用以下代码声明并正确对齐:

char cTaskStack[1024] __attribute__((aligned(1024));

puxStackBuffer 通常会设置为静态声明的堆栈的地址。 作为备选 puxStackBuffer 可以设置为 NULL - 在这种情况下,将调用 pvPortMallocAligned() 来分配任务 堆栈,应用程序编写者有责任提供 pvPortMallocAligned() 的实现 满足 MPU 的对齐要求。

xRegionsxRegions 是 MemoryRegion_t 结构的数组,每个结构都定义了一个用户可定义的 供正在创建的任务使用的内存区域。 ARM Cortex-M3 FreeRTOS-MPU 端口定义 portNUM_CONFIGURABLE_REGIONS 为 3。

pvBaseAddress 和 ulLengthInBytes 成员作为内存的开始是不言自明的 区域和内存区域的长度。 ulParameters 定义任务的方式 允许访问内存区域,并且可以对以下值进行按位或:

    portMPU_REGION_READ_WRITE
    portMPU_REGION_PRIVILEGED_READ_ONLY
    portMPU_REGION_READ_ONLY
    portMPU_REGION_PRIVILEGED_READ_WRITE
    portMPU_REGION_CACHEABLE_BUFFERABLE
    portMPU_REGION_EXECUTE_NEVER

pxTaskBuffer任务缓冲区。必须指向类型的变量 StaticTask_t. 该变量将用于保存新任务的 数据结构,因此它必须是持久的(不在函数的堆栈上声明)。

Example usage

/* Create an TaskParameters_t structure that defines the task to be created.
 * The StaticTask_t variable is only included in the structure when
 * configSUPPORT_STATIC_ALLOCATION is set to 1.  The PRIVILEGED_DATA macro can
 * be used to force the variable into the RTOS kernel's privileged data area. */
static PRIVILEGED_DATA StaticTask_t xTaskBuffer;
static const TaskParameters_t xCheckTaskParameters =
{
  vATask,     /* pvTaskCode - the function that implements the task. */
  "ATask",    /* pcName - just a text name for the task to assist debugging. */
  100,        /* usStackDepth - the stack size DEFINED IN WORDS. */
  NULL,       /* pvParameters - passed into the task function as the function parameters. */
  ( 1UL | portPRIVILEGE_BIT ),/* uxPriority - task priority, set the portPRIVILEGE_BIT 
                                   if the task should run in a privileged state. */
  cStackBuffer,/* puxStackBuffer - the buffer to be used as the task stack. */

  /* xRegions - Allocate up to three separate memory regions for access by
   * the task, with appropriate access permissions.  Different processors have
   * different memory alignment requirements - refer to the FreeRTOS documentation
   * for full information. */
  {
      /* Base address                 Length  Parameters */
      { cReadWriteArray,              32,     portMPU_REGION_READ_WRITE },
      { cReadOnlyArray,               32,     portMPU_REGION_READ_ONLY },
      { cPrivilegedOnlyAccessArray,   128,    portMPU_REGION_PRIVILEGED_READ_WRITE }
  }

  &xTaskBuffer; /* Holds the task's data structure. */
 };

 int main( void )
 {
 TaskHandle_t xHandle;

  /* Create a task from the const structure defined above.  The task handle
   * is requested (the second parameter is not NULL) but in this case just for
   * demonstration purposes as its not actually used. */
  xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );

  /* Start the scheduler. */
  vTaskStartScheduler();

  /* Will only get here if there was insufficient memory to create the idle
   * and/or timer task. */
  for( ;; );
 }

vTaskDelete

INCLUDE_vTaskDelete 必须定义为 1 才能使该函数可用。

从 RTOS 内核管理中删除任务。 正在删除的任务将从所有就绪、阻止、暂停和事件列表中删除。

注意:空闲任务负责从已删除的任务中释放 RTOS 内核分配的内存。 因此,如果您的应用程序对 vTaskDelete () 进行任何调用,空闲任务不会因微控制器处理时间而不足,这一点很重要。 任务代码分配的内存不会自动释放,应该在删除任务之前释放。

//task.h
void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION;

xTaskToDelete要删除的任务的句柄。 传递 NULL 将导致调用任务被删除。

Example usage


 void vOtherFunction( void )
 {
 TaskHandle_t xHandle = NULL;

     // Create the task, storing the handle.
     // 创建任务,存储句柄。
     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

     // Use the handle to delete the task.
     // 使用句柄删除任务。    
     if( xHandle != NULL )
     {
         vTaskDelete( xHandle );
     }
 }
   

函数代码

//tasks.c
#if ( INCLUDE_vTaskDelete == 1 )

    void vTaskDelete( TaskHandle_t xTaskToDelete )
    {
        TCB_t * pxTCB;

        taskENTER_CRITICAL();
        {
            /* If null is passed in here then it is the calling task that is
             * being deleted. */
            pxTCB = prvGetTCBFromHandle( xTaskToDelete );

            /* Remove task from the ready/delayed list. */
            if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
            {
                taskRESET_READY_PRIORITY( pxTCB->uxPriority );
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }

            /* Is the task waiting on an event also? */
            if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
            {
                ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }

            /* Increment the uxTaskNumber also so kernel aware debuggers can
             * detect that the task lists need re-generating.  This is done before
             * portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will
             * not return. */
            uxTaskNumber++;

            if( pxTCB == pxCurrentTCB )
            {
                /* A task is deleting itself.  This cannot complete within the
                 * task itself, as a context switch to another task is required.
                 * Place the task in the termination list.  The idle task will
                 * check the termination list and free up any memory allocated by
                 * the scheduler for the TCB and stack of the deleted task. */
                vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );

                /* 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. */
                ++uxDeletedTasksWaitingCleanUp;

                /* Call the delete hook before portPRE_TASK_DELETE_HOOK() as
                 * portPRE_TASK_DELETE_HOOK() does not return in the Win32 port. */
                traceTASK_DELETE( pxTCB );

                /* The pre-delete hook is primarily for the Windows simulator,
                 * in which Windows specific clean up operations are performed,
                 * after which it is not possible to yield away from this task -
                 * hence xYieldPending is used to latch that a context switch is
                 * required. */
                portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
            }
            else
            {
                --uxCurrentNumberOfTasks;
                traceTASK_DELETE( pxTCB );
                prvDeleteTCB( pxTCB );

                /* Reset the next expected unblock time in case it referred to
                 * the task that has just been deleted. */
                prvResetNextTaskUnblockTime();
            }
        }
        taskEXIT_CRITICAL();

        /* Force a reschedule if it is the currently running task that has just
         * been deleted. */
        if( xSchedulerRunning != pdFALSE )
        {
            if( pxTCB == pxCurrentTCB )
            {
                configASSERT( uxSchedulerSuspended == 0 );
                portYIELD_WITHIN_API();
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }
        }
    }

#endif /* INCLUDE_vTaskDelete */

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值