任务和调度程序 API

portSWITCH_TO_USER_MODE()

#include "FreeRTOS.h"
#include "task.h"

void portSWITCH_TO_USER_MODE( void );

清单1. portSWITCH_TO_USER_MODE() 声明原型

概述

此函数仅供高级用户使用,仅与 FreeRTOS MPU 移植(使用存储器保护单元的 FreeRTOS 移植)相关。

使用 xTaskCreateRestricted() 创建 MPU 受限任务。 提供给 xTaskCreateRestricted() 的参数指定正在创建的任务是应该是用户(非特权)模式任务还是超级用户(特权)模式任务。 超级用户模式任务可以调用 portSWITCH_TO_USER_MODE() 将自身从超级用户模式任务转换为用户模式任务。

参数

返回值

注意

portSWITCH_TO_USER_MODE() 没有允许任务将自己从用户模式转换为超级用户模式任务的对等函数。

vTaskAllocateMPURegions()

#include "FreeRTOS.h"
#include "task.h"
void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, 
                             const MemoryRegion_t* const xRegions );

清单2. vTaskAllocateMPURegions() 函数原型

概述

定义一组内存保护单元(MPU)区域供 MPU 限制任务使用。此功能仅供高级用户使用,仅与 FreeRTOS MPU 移植(使用内存保护单元的 FreeRTOS 移植)相关。 使用 xTaskCreateRestricted() 函数创建任务时,可以将内存区域分配给 MPU 受限任务。 然后可以使用 vTaskAllocateMPURegions() 函数在运行时重新定义(或重新分配)它们。

参数

参数

描述

xTaskToModify

正在修改受限任务的句柄(可以访问由 xRegions 参数定义的内存区域的任务)。

使用 xTaskCreateRestricted() API 函数的 pxCreatedTask 参数获取任务句柄。

任务可以通过传递 NULL 代替有效的任务句柄来修改自己的内存区域访问定义。

xRegions

MemoryRegion_t 结构的数组。 数组中的位置数由移植特定的 portNUM_CONFIGURABLE_REGIONS 常量定义。 在 Cortex-M3 上,NUM_CONFIGURABLE_REGIONS 定义为 3。

数组中的每个 MemoryRegion_t 结构定义单个 MPU 内存区域,供 xTaskToModify 参数引用的任务使用。

注意

MPU 内存区域使用清单 3 中所示的 MemoryRegion_t 结构定义。

typedef struct xMEMORY_REGION{
    void *pvBaseAddress;
    unsigned long ulLengthInBytes;
    unsigned long ulParameters;
} MemoryRegion_t;

清单3. xTaskCreateRestricted() 使用的数据结构

pvBaseAddressulLengthInBytes 成员分别作为内存区域的开始和内存区域的长度自解释。 这些必须符合 MPU 规定的尺寸和对齐限制。 特别地,每个区域的大小和对齐必须都等于两个值的相同幂次。

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

例子

/* Define an array that the task will both read from and write to.  Make sure the 
size and alignment are appropriate for an MPU region (note this uses GCCsyntax). */
static unsigned char ucOneKByte[ 1024 ] __attribute__((align( 1024 )));

/* Define an array of MemoryRegion_t structures that configures an MPU region
allowing 
read/write access for 1024 bytes starting at the beginning of the ucOneKByte array.  
The other two of the maximum three definable regions are unused,so set to zero. */
static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
{
    /* Base address    Length    Parameters */
    { ucOneKByte,      1024,     portMPU_REGION_READ_WRITE },
    { 0,               0,        0 },
    { 0,               0,        0 }
};

void vATask( void *pvParameters )
{
    /* This task was created using xTaskCreateRestricted() to have access to a 
    maximum of three MPU controlled memory regions. At some point it is required
    that these MPU regions are replaced with those defined in the xAltRegions const 
    structure defined above.  Use a call to vTaskAllocateMPURegions() for this 
    purpose.  NULL is used as the task handle to indicate that the change should be
    applied to the calling task.*/
    vTaskAllocateMPURegions( NULL, xAltRegions );
    
    /* Now the task can continue its function, but from this point on can only access
    its stack and the ucOneKByte array (unless any other statically defined or shared
    regions have been declared elsewhere). */
}

清单4. vTaskAllocateMPURegions() 的使用示例

xTaskAbortDelay()

#include "FreeRTOS.h"
#include "task.h"

BaseType_t xTaskAbortDelay( TaskHandle_t xTask );

清单5. xTaskAbortDelay() 函数原型

概述

调用包含超时参数的 API 函数可能导致调用任务进入阻塞状态。 处于阻塞状态的任务要么等待超时时间过去,要么等待事件发生超时,之后任务将自动离开阻塞状态并进入就绪状态。 这种行为有很多例子,其中两个是:

  • 如果任务调用 vTaskDelay(),它将进入阻塞状态,直到函数参数指定的超时时间结束,此时任务将自动离开阻塞状态并进入就绪状态。

  • 如果任务在其通知值为零时调用 ulTask​​NotifyTake(),它将进入阻塞状态,直到它收到通知或其中一个函数参数指定的超时已经过去,此时任务将自动离开阻塞状态并进入就绪状态。

即使任务正在等待的事件尚未发生,xTaskAbortDelay() 也会将任务从 “阻止” 状态移动到 “就绪” 状态,并且当任务进入 “阻止” 状态时指定的超时尚未过去。

当任务处于阻塞状态时,它不可用于调度程序,并且不会消耗任何处理时间。

参数

参数

描述

xTask

将被移出阻塞状态的任务句柄。

要获取任务的句柄,请使用 xTaskCreate() 创建任务并使用 pxCreatedTask 参数,或使用 xTaskCreateStatic() 创建任务并存储返回的值,或者在调用 xTaskGetHandle() 时使用任务的名称。

返回值

如果 xTask 引用的任务已从阻塞状态中删除,则返回 pdPASS。 如果 xTask 引用的任务未从阻塞状态中删除,因为它未处于阻塞状态,则返回 pdFAIL

注意

FreeRTOSConfig.h 中,INCLUDE_xTaskAbortDelay 必须设置为 1 才能使 xTaskAbortDelay() 可用。

例子

void vAFunction( TaskHandle_t xTask )
{
    /* The task referenced by xTask is blocked to wait for something that the task calling
    this function has determined will never happen.  Force the task referenced by xTask
    out of the Blocked state. */
    if( xTaskAbortDelay( xTask ) == pdFAIL)
    {
        /* The task referenced by xTask was not in the Blocked state anyway. */
    }
    else
    {
        /* The task referenced by xTask was in the Blocked state, but is not now. */
    }
}

清单6. xTaskAbortDelay() 的使用示例

xTaskCallApplicationTaskHook()

#include "FreeRTOS.h"
#include "task.h"

BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameters );

清单7. xTaskCallApplicationTaskHook() 函数原型

概述

此函数仅供高级用户使用。

vTaskSetApplicationTaskTag() 函数可用于为任务分配 “标记” 值。 标记值的含义和用法由应用程序编写者定义。 内核本身通常不会访问标记值。

作为特殊情况,标记值可用于将 “任务挂钩”(或回调)函数与任务相关联。 完成后,使用 xTaskCallApplicationTaskHook() 调用钩子函数。

任务钩子函数可用于任何目的。 本节中显示的示例演示了用于输出调试跟踪信息的任务挂钩。

任务挂钩函数必须具有清单 8 所示的原型。

BaseType_t xAnExampleTaskHookFunction( void *pvParameters );

清单 8. 所有任务钩子函数必须符合的原型

xTaskCallApplicationTaskHook() 仅在 FreeRTOSConfig.hconfigUSE_APPLICATION_TASK_TAG 设置为 1 时可用。

参数

参数

描述

xTask

正在调用其关联的钩子函数的任务的句柄。

要获取任务的句柄,请使用 xTaskCreate() 创建任务并使用 pxCreatedTask 参数,或使用 xTaskCreateStatic() 创建任务并存储返回的值,或者在调用 xTaskGetHandle()时使用任务的名称。

任务可以通过传递NULL代替有效的任务句柄来调用自己的钩子函数。

pvParameters

该值用作任务钩子函数本身的参数。此参数具有允许任务钩子函数 “指向 void 的指针” 类型,并通过转换间接地接收任何类型的参数。 例如,整数类型可以通过将整数转换为调用钩子函数的指向的 void 指针,然后通过将 void 指针参数转换回钩子函数本身内的整数来传递给钩子函数。

例子

/* Define a hook (callback) function – using the required prototype as 
demonstrated by Listing 8*/
static BaseType_t prvExampleTaskHook( void * pvParameter )
{
    /* Perform an action - this could be anything.  In this example the hook
    is used to output debug trace information.  pxCurrentTCB is the handle 
    of the currently executing task.  (vWriteTrace() is not an API function,
    its just used as an example.)*/
    vWriteTrace( pxCurrentTCB );
    
    /* This example does not make use of the hook return value so just returns
    0 in every case. */
    return 0;
}

/* Define an example task that makes use of its tag value. */
void vAnotherTask( void *pvParameters )
{
    /* vTaskSetApplicationTaskTag() sets the ‘tag’ value associated with a task.
    NULL is used in place of a valid task handle to indicate that it should be
    the tag value of the calling task that gets set.  In this example the ‘value’ 
    being set is the hook function. */
    vTaskSetApplicationTaskTag( NULL, prvExampleTaskHook );
    
    for( ;; )
    {
        /* The rest of the task code goes here. */
    }
}

/* Define the traceTASK_SWITCHED_OUT() macro to call the hook function of each
task that is switched out.  pxCurrentTCB points to the handle of the currently
running task. */
#define traceTASK_SWITCHED_OUT() xTaskCallApplicationTaskHook( pxCurrentTCB, 0 )

清单9. xTaskCallApplicationTaskHook() 使用示例

xTaskCheckForTimeOut()

#include "FreeRTOS.h"
#include "task.h"
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, 
                                 TickType_t * const pxTicksToWait );

清单10. xTaskCheckForTimeOut() 函数原型

概述

本函数仅供高级用户使用。

任务可以进入阻塞状态来等待一个事件。通常, 任务不会由于无限期的等待而处于阻塞状态,会指定超时期限。如果超时期限在任务等待事件发生之前到期,则任务将会从阻塞状态中移除。

如果任务在等待事件发生时不止一次的进入和退出阻塞状态,则每次进入阻塞状态时使用的超时必须进行调整,以确保在阻塞状态下花费的总时间不超过最初指定的超时时间。一般使用 xTaskCheckForTimeOut() 执行调整,考虑到偶然发生的事件,例如 Tick 计数器溢出,否则手动调整很容易出错。

参数

参数

描述

pxTimeOut

一个指向结构体的指针,该结构体包含确定是否发生超时所必须的信息。使用 vTaskSetTimeOutState() 初始化 pxTimeOut

pxTicksToWait

用于传递调整过后的阻塞时间,这是在考虑已经在阻塞状态下花费的时间之后剩余的阻塞时间。

返回值

若返回 pdTRUE ,则无剩余阻塞时间,并且发生超时。若返回 pdFALSE ,则还有剩余的阻塞时间,所以不发生超时。

例子

/* Driver library function used to receive uxWantedBytes from an Rx buffer that is filled 
by a UART interrupt.  If there are not enough bytes in the Rx buffer then the task enters 
the Blocked state until it is notified that more data has been placed into the buffer.  If 
there is still not enough data then the task re-enters the Blocked state, and 
xTaskCheckForTimeOut() is used to re-calculate the Block time to ensure the total amount 
of time spent in the Blocked state does not exceed MAX_TIME_TO_WAIT. This continues until 
either the buffer contains at least uxWantedBytes bytes, or the total amount of time spent 
in the Blocked state reaches MAX_TIME_TO_WAIT – at which point the task reads however many 
bytes are available up to a maximum of uxWantedBytes.*/
size_t xUART_Receive(uint8_t *pucBuffer, size_t uxWantedBytes )
{
    size_t uxReceived = 0;
    TickType_t xTicksToWait = MAX_TIME_TO_WAIT;
    TimeOut_t xTimeOut;
    
    /* Initialize xTimeOut.  This records the time at which this function was entered. */
    vTaskSetTimeOutState( &xTimeOut );
    
    /* Loop until the buffer contains the wanted number of bytes, or a timeout occurs. */
    while( UART_bytes_in_rx_buffer( pxUARTInstance ) < uxWantedBytes )
    {
        /* The buffer didn’t contain enough data so this task is going to enter the Blocked 
        state.  Adjusting xTicksToWait to account for any time that has been spent in the 
        Blocked state within this function so far to ensure the total amount of time spent 
        in the Blocked state does not exceed MAX_TIME_TO_WAIT. */
        if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) != pdFALSE )
        {
            /* Timed out before the wanted number of bytes were available, exit the loop. */
            break;
        }
        
        /* Wait for a maximum of xTicksToWait ticks to be notified that the receive 
        interrupt has placed more data intothe buffer. */
        ulTaskNotifyTake( pdTRUE, xTicksToWait );
    }
    
    /* Attempt to read uxWantedBytes from the receive buffer into pucBuffer.  The actual 
    number of bytes read (which might be less than uxWantedBytes) is returned. */
    uxReceived = UART_read_from_receive_buffer( pxUARTInstance, pucBuffer, uxWantedBytes );
    
    return uxReceived;
}

清单11. vTaskSetTimeOutState()xTaskCheckForTimeOut() 的使用示例

xTaskCreate()

#include "FreeRTOS.h"
#include "task.h"
BaseType_t xTaskCreate( TaskFunction_tpvTaskCode, 
                        const char* const pcName, 
                        unsigned shortusStackDepth, 
                        void *pvParameters, 
                        UBaseType_t uxPriority, 
                        TaskHandle_t *pxCreatedTask);

清单 12. xTaskCreate() 函数原型

概述

创建一个新的任务实例。

每个任务都与要用于保存任务状态的 RAM(任务控制块或 TCB),并被任务用作于堆。如果任务由 xTaskCreate() 创建,它所需的 RAM 从 FreeRTOS 栈中自动分配。如果任务由 xTaskCreateStatic() 创建,那么它所需的 RAM 应由应用编写者提供,这会产生两个额外的函数参数,但允许在编译时静态分配 RAM。

新创建的任务最初处于 “就绪” 状态,但如果没有能够运行的优先级较高的任务,则会立即成为 “运行状态” 任务。

可以在启动调度程序之前和之后创建任务。

参数

参数

描述

pvTaskCode

任务只是从不退出的 C 函数,所以通常实现为一个无限的循环。pvTaskCode 参数只是一个函数指针,指向实现任务的函数(实际上是个函数名)。

pcName

任务的描述性名称。这主要用于调试方便,但也可用来调用 xTaskGetHandle() 以获取任务的句柄。

应用程序定义的常量 configMAX_TASK_NAME_LEN 以字符定义名称的最大长度,包括 NULL 终止符。 提供长于此最大值的字符串将导致字符串被静默截断。

usStackDepth

每个任务都有自己唯一的堆,在创建任务时由内核分配给任务。 usStackDepth 值告诉内核堆栈的大小。

该值指定堆栈可以容纳的字数,而不是字节数。 例如,在具有 4 字节堆栈宽度的体系结构上,如果将 usStackDepth 作为 100 传入,则将分配 400 字节的堆栈空间(100 * 4 字节)。 堆栈深度乘以堆栈宽度不得超过 size_t 类型的变量中可包含的最大值。

空闲任务使用的堆栈大小由应用程序定义的常量 configMINIMAL_STACK_SIZE 定义。 为所选择的微控制器架构提供的演示应用程序中为此常量分配的值是该架构中任何任务的最低建议值。 如果您的任务使用大量堆栈空间,则必须分配更大的值。

pvParameters

任务函数接受 “指向void的指针”(void *)类型的参数。 分配给 pvParameters 的值将是传递给任务的值。

此参数具有 “指向void的指针” 类型,以允许任务参数有效地,并通过强制转换,间接接收任何类型的参数。 例如,通过在创建任务的点处将整数转换为 void 指针,然后通过将 void 指针参数转换回任务函数定义本身中的整数,可以将整数类型传递到任务函数。

uxPriority

定义任务将执行的优先级。 可以将优先级从 0(最低优先级)分配给(configMAX_PRIORITIES - 1),这是最高优先级。

configMAX_PRIORITIES 是用户定义的常量。 如果configUSE_PORT_OPTIMISED_TASK_SELECTION 设置为 0,那么可用的优先级数没有上限(除了使用的数据类型的限制和微控制器中可用的 RAM),但建议使用所需的最低优先级数 ,以避免浪费 RAM。

传递上面的 uxPriority 值(configMAX_PRIORITIES - 1)将导致分配给任务的优先级被限制为最大合法值。

pxCreatedTask

pxCreatedTask 可用于传递正在创建的任务的句柄。 然后,此句柄可用于引用 API 调用中的任务,例如,更改任务优先级或删除任务。如果您的应用程序没有使用任务句柄,那么 pxCreatedTask 可以设置为 NULL

返回值

返回值

描述

pdPASS

表示已成功创建任务。

errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY

表示无法创建任务,因为 FreeRTOS 没有足够的堆内存来分配任务数据结构和堆栈。

如果项目中包含 heap_1.cheap_2.cheap_4.c ,那么可用堆的总量由 FreeRTOSConfig.h 中的 configTOTAL_HEAP_SIZE 定义,并且使用可捕获内存分配失败的 vApplicationMallocFailedHook() 回调(或 hook)函数,可以使用 xPortGetFreeHeapSize() API 函数查询剩余的可用堆内存量。

如果 heap_3.c 包含在项目中,则总堆大小由链接器配置定义。

注意

FreeRTOSConfig.h 中,configSUPPORT_DYNAMIC_ALLOCATION 必须设置为 1,或者就设置成简单的未定义,以使此函数可用。

例子

/* Define a structure called xStruct and a variable of type xStruct.  These are just used to 
demonstrate a parameter being passed into a task function. */
typedef struct A_STRUCT
{
    char cStructMember1;
    char cStructMember2;
} xStruct;    

/* Define a variable of the type xStruct to pass as the task parameter. */
xStruct xParameter = { 1, 2 };

/* Define the task that will be created.  Note the name of the function that implements the task 
is used as the first parameter in the call to xTaskCreate() below. */
void vTaskCode( void * pvParameters )
{
    xStruct *pxParameters;
    
    /* Cast the void * parameter back to the required type. */
    pxParameters = ( xStruct * ) pvParameters;
    
    /* The parameter can now be accessed as expected. */
    if( pxParameters->cStructMember1 != 1 )
    {
        /* Etc. */
    }        
    
    /* Enter an infinite loop to perform the task processing. */
    for( ;; )
    {
        /* Task code goes here. */
    }
}    

/* Definea function that creates a task.  This could be called either before or after the 
scheduler has been started. */
void vAnotherFunction( void )
{
    TaskHandle_txHandle;
    
    /* Create the task. */
    if( xTaskCreate( 
        vTaskCode,            /* Pointer to the function that implements the task. */
        "Demo task",          /* Text name given to the task. */
        STACK_SIZE,           /* The size of the stack that should be created for the task.
                                 This is defined in words, not bytes. */
        (void*) &xParameter,  /* A reference to xParameters is used as the task parameter.
                                 This is cast to a void * to prevent compiler warnings. */
        TASK_PRIORITY,        /* The priority to assign to the newly created task.*/
        &xHandle              /* The handle to the task being created will be placed in
                                 xHandle. */
        ) != pdPASS )
    {
        /* The task could not be created as there was insufficient heap memory remaining. 
        If heap_1.c, heap_2.c or heap_4.c are included in the project then this situation can be 
        trapped using the vApplicationMallocFailedHook() callback (or ‘hook’) function,and the 
        amount of FreeRTOS heap memory that remains unallocated can be queried using the 
        xPortGetFreeHeapSize() API function.*/
    }
    else
    {
        /* The task was created successfully. The handle can now be used in other API functions,
        for example to change the priority of the task.*/
        vTaskPrioritySet( xHandle, 2 );
    }    
}

清单 13. xTaskCreate() 使用示例

xTaskCreateStatic()

#include "FreeRTOS.h"
#include "task.h"

TaskHandle_t xTaskCreateStatic( TaskFunction_t pvTaskCode,
                                const char * const pcName,
                                uint32_t ulStackDepth,
                                void *pvParameters,
                                UBaseType_t uxPriority,
                                StackType_t * const puxStackBuffer,
                                StaticTask_t * const pxTaskBuffer );

概述

创建一个任务的新实例。

每个任务都需要用于保存任务状态的 RAM(任务控制块,或叫 TCB), 并被任务用作其堆栈。 如果使用 xTaskCreate() 创建任务,则所需的 RAM 是从 FreeRTOS 堆自动分配的。 如果使用创建任务 xTaskCreateStatic() 然后 RAM 由应用程序编写者提供,这导致两个附加的函数参数,但在编译时允许静态分配 RAM。

新创建的任务最初处于就绪状态,但如果没有更高优先级的任务可以运行,则将立即成为运行状态任务。

可以在调度程序启动之前和之后创建任务。

参数

参数

描述

pvTaskCode

任务只是从不退出的 C 函数,因此,通常以无限循环的方式实现。 pvTaskCode 参数只是一个指向实现任务的函数(实际上只是函数名)的指针。

pcName

任务的描述性名称。 这主要用于方便调试,但也可用于调用 xTaskGetHandle() 以获取任务句柄。

应用程序定义的常量 configMAX_TASK_NAME_LEN 定义了名称的最大长度(以字符为单位)——包括 NULL 终止符。

提供比此最大值更长的字符串将导致该字符串被静默截断。

ulStackDepth

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

pvParameters

任务函数接受一个“指向 void 的指针”(void*)类型的参数。 分配给 pvParameters 的值将是传递给任务的值。

此参数具有“指向 void 的指针”类型,以允许任务参数有效地并通过强制转换间接接收任何类型的参数。 例如,整数类型可以通过在任务创建时将整数转换为空指针,然后通过将空指针参数转换回任务函数定义本身中的整数来传递给任务函数。

uxPriority

定义任务执行的优先级。 优先级可以从 0(最低优先级)分配到 (configMAX_PRIORITIES – 1),这是最高优先级。

configMAX_PRIORITIES 是用户定义的常量。 如果 configUSE_PORT_OPTIMISED_TASK_SELECTION 设置为 0,那么可用的优先级数量没有上限(除了使用的数据类型和微控制器中可用的 RAM 的限制),但建议使用最低数量的 需要的优先级,以避免浪费 RAM。

传递高于 (configMAX_PRIORITIES – 1)uxPriority 值将导致分配给任务的优先级被静默限制为最大的合法值。

puxStackBuffer

必须指向至少具有 ulStackDepth 索引的 StackType_t 变量数组(请参阅上面的 ulStackDepth 参数)。 该数组将用作创建的任务的堆栈,因此必须是持久的(不在由函数创建的堆栈帧中声明,或在应用程序执行时可以合法覆盖的任何其他内存中声明)。

pxTaskBuffer

必须指向 StaticTask_t 类型的变量。 该变量将用于保存创建的任务的数据结构 (TCB),因此它必须是持久的(不在由函数创建的堆栈帧中声明,或在应用程序执行时可以合法覆盖的任何其他内存中声明)。

返回值

返回值

描述

NULL

无法创建任务,因为 puxStackBufferpxTaskBuffer 是空。

任何其他值

如果返回非 NULL 值,则任务已创建,返回值是所创建任务的句柄。

注意

configSUPPORT_STATIC_ALLOCATION 必须在 FreeRTOSConfig.h 中设置为 1 才能使用此功能。

例子

/* Dimensions 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. */
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 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 parameter
    in the call to xTaskCreateStatic(). */
    configASSERT( ( uint32_t ) pvParameters == 1UL );
    for( ;; )
    {
        /* Task code goes here. */
    }
}

/* Function that creates a task. */
void vFunction( 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,      /* The 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. */
    vTaskSuspend( xHandle );
}

最后更新于