任务和调度程序 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() 函数在运行时重新定义(或重新分配)它们。

参数

注意

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() 也会将任务从 “阻止” 状态移动到 “就绪” 状态,并且当任务进入 “阻止” 状态时指定的超时尚未过去。

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

参数

注意

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 时可用。

参数

例子

/* 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 计数器溢出,否则手动调整很容易出错。

参数

例子

/* 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。

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

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

参数

返回值

注意

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。

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

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

参数

返回值

注意

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 );
}

最后更新于