注意:
task.h中有FreeRTOS的MPU模式(Memory Protect Unit), 在使用前需要留意STM32芯片是否有MPU功能
xTASK_STATUS.ulRunTimeCounter: FreeRTOS可以选择性地收集每个任务使用的处理时间量的信息。然后,可以使用vTaskGetRunTimeStats()API函数以表格格式显示此信息,如右图所示。
/*
定义的宏
*/
/**
引用任务的类型。例如,调用xTaskCreate返回(通过指针参数)一个TaskHandle\t变量,然后用作vTaskDelete删除任务的参数。
*/
typedef void * TaskHandle_t;
/*
定义应用任务钩子函数必须遵从的模板
*/
typedef BaseType_t (*TaskHookFunction_t)( void * );
/* eTaskGetState返回的任务状态。 */
typedef enum
{
eRunning = 0, /* 任务查询自身运行的状态,因此必须运行*/
eReady, /* 正在查询的任务位于已读或挂起就绪列表中。 */
eBlocked, /* 正在查询的任务处于阻塞状态。 */
eSuspended, /* 正在查询的任务处于挂起状态,或处于无限超时的阻塞状态。 */
eDeleted, /* 正在查询的任务已被删除,但其TCB尚未释放。 */
eInvalid /* “无效状态”值。 */
} eTaskState;
/*调用vTaskNotify()时执行的操作。 */
typedef enum
{
eNoAction = 0, /* 通知任务而不更新其通知值。 */
eSetBits, /* 在任务的通知值中设置位。 */
eIncrement, /* 增加任务的通知值。 */
eSetValueWithOverwrite, /* 将任务的通知值设置为特定值,即使任务尚未读取上一个值。 */
eSetValueWithoutOverwrite /* 如果任务已读取上一个值,则设置任务的通知值。*/
} eNotifyAction;
/*
*仅供内部使用。
*/
typedef struct xTIME_OUT
{
BaseType_t xOverflowCount;
TickType_t xTimeOnEntering;
} TimeOut_t;
/*
* 定义使用MPU时分配给任务的内存范围,需要注意是否需要,MPU相关功能
*/
typedef struct xMEMORY_REGION
{
void *pvBaseAddress;
uint32_t ulLengthInBytes;
uint32_t ulParameters;
} MemoryRegion_t;
/*
* 创建受MPU保护的任务所需的参数。
*/
typedef struct xTASK_PARAMETERS
{
TaskFunction_t pvTaskCode;
const char * const pcName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
uint16_t usStackDepth;
void *pvParameters;
UBaseType_t uxPriority;
StackType_t *puxStackBuffer;
MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ];
} TaskParameters_t;
/* 与uxTaskGetSystemState()函数一起使用,返回系统中每个任务的状态。 */
typedef struct xTASK_STATUS
{
TaskHandle_t xHandle; /* 任务的句柄,结构体其余部分的信息与之关联 */
const char *pcTaskName; /* 指向任务名称的指针。如果在填充结构后删除了任务,则此值将无效! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
UBaseType_t xTaskNumber; /* 任务唯一的数字。 */
eTaskState eCurrentState; /* 结构增加时任务存在的状态。 */
UBaseType_t uxCurrentPriority; /* 结构增加时任务运行的优先级(可以继承)。 */
UBaseType_t uxBasePriority; /* 如果任务的当前优先级已被继承以避免在获取互斥锁时发生无限优先级反转,则任务将返回的优先级。仅当configUSE_互斥体在FreeRTOSConfig.h中定义为1时有效。*/
uint32_t ulRunTimeCounter; /* 迄今为止分配给任务的总运行时间,由运行时统计时钟定义。见http://www.freertos.org/rtos-run-time-stats.html。仅当configGENERATE_RUN_TIME_STATS在FreeRTOSConfig.h中定义为1时有效。 */
StackType_t *pxStackBase; /* 指向任务堆栈区域的最低地址。 */
uint16_t usStackHighWaterMark; /* 自任务创建以来为该任务保留的最小堆栈空间量。此值越接近于零,任务溢出堆栈的距离就越近。 */
} TaskStatus_t;
/* Possible return values for eTaskConfirmSleepModeStatus(). */
typedef enum
{
eAbortSleep = 0, /* 由于调用了portSUPPORESS_TICKS_AND_SLEEP(),任务已就绪或上下文开关挂起-中止进入睡眠模式。*/
eStandardSleep, /* 进入睡眠模式,其持续时间不会超过预期的空闲时间。 */
eNoTasksWaitingTimeout /* 没有任务在等待超时,因此进入一个只能由外部中断退出的休眠模式是安全的。 */
} eSleepModeStatus;
/**
*定义空闲任务使用的优先级。不能修改。
*/
#define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U )
/**
* task. h
*用于强制上下文切换的宏。
*/
#define taskYIELD() portYIELD()
/**
* task. h
*宏来标记关键代码区域的开始。抢占上下文
*处于关键区域时不能发生切换。
*注意:这可能会改变堆栈(取决于可移植实现)
*所以一定要小心使用!
*/
#define taskENTER_CRITICAL() portENTER_CRITICAL()
#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()
/**
* task. h
*
*标记关键代码区域结尾的宏。抢占上下文
*处于关键区域时不能发生切换。
*注意:这可能会改变堆栈(取决于可移植实现)
*所以一定要小心使用!
*/
#define taskEXIT_CRITICAL() portEXIT_CRITICAL()
#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x )
/**
* task. h
* 宏来禁用所有可屏蔽的中断。
*/
#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS()
/**
* task. h
* 启用微控制器中断的宏。
*/
#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS()
/* xTaskGetSchedulerState()返回的定义。当configASSERT()被定义为assert()语句中使用的常量时,taskSCHEDULER_SUSPENDED为0以生成更优化的代码。 */
#define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 )
#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 )
#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 )
/*
任务生成API
*/
/**
* task. h
*
BaseType_t xTaskCreate(
TaskFunction_t pvTaskCode,
const char * const pcName,
uint16_t usStackDepth,
void *pvParameters,
UBaseType_t uxPriority,
TaskHandle_t *pvCreatedTask
);
*
*创建新任务并将其添加到准备运行的任务列表中。
*
·*在内部,在FreeRTOS实现中,任务使用两个块内存。第一个块用于保存任务的数据结构。第二个块被使用作为其堆栈。
*如果任务是使用xTaskCreate()创建的,那么这两个内存块将在xTaskCreate()函数中自动动态分配。(见 *http://www.freertos.org/a00111.html)。如果使用xTaskCreateStatic()创建任务,则应用程序编写器必须提供所需的内存。因此, *xTaskCreateStatic()允许在不使用任何动态内存分配的情况下创建任务。
*
* 有关不使用任何动态内存分配的版本,请参见xTaskCreateStatic()。
*
*xTaskCreate()只能用于创建对整个微控制器内存映射具有无限制访问权限的任务。包含MPU支持的系统也可以使用xTaskCreateRestricted()创建MPU约束的任务。
*
*@param pvTaskCode指向任务项函数的指针。任务
*必须实现永不返回(即连续循环)。
*
*@param pcName任务的描述性名称。这主要是为了便于调试。configMAX_TASK_NAME_LEN定义的最大长度-默认值为16。
*
*@param usStackDepth任务堆栈的大小,指定为堆栈可以容纳的变量数,而不是字节数。例如,如果堆栈为16位宽,usStackDepth定义为100,则将为堆栈存储分配200字节。
*
*@param pvParameters指针,将用作正在创建的任务的参数。
*
*@param uxPriority任务运行的优先级。包括MPU支持的系统可以选择通过设置priority参数的bit portPRIVILEGE\u位以特权(系统)模式创建任务。例如,要创建优先级为2的特权任务,应将uxPriority参数设置为(2 | portPRIVILEGE_BIT)。
*
*@param pvCreatedTask用于传回一个句柄,通过该句柄可以引用创建的任务。
*
*@return pdPASS如果任务成功创建并添加到就绪列表中,则返回pdPASS,否则返回文件projdefs.h中定义的错误代码
*
* Example usage:
// Task to be created.
void vTaskCode( void * pvParameters )
{
for( ;; )
{
// Task code goes here.
}
}
// Function that creates a task.
void vOtherFunction( void )
{
static uint8_t ucParameterToPass;
TaskHandle_t xHandle = NULL;
// Create the task, storing the handle. Note that the passed parameter ucParameterToPass
// must exist for the lifetime of the task, so in this case is declared static. If it was just an
// an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
// the new task attempts to access it.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
configASSERT( xHandle );
// Use the handle to delete the task.
if( xHandle != NULL )
{
vTaskDelete( xHandle );
}
}
* \defgroup xTaskCreate xTaskCreate
* \ingroup Tasks
*/
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
#endif
/**
* task. h
*
TaskHandle_t xTaskCreateStatic( TaskFunction_t pvTaskCode,
const char * const pcName,
uint32_t ulStackDepth,
void *pvParameters,
UBaseType_t uxPriority,
StackType_t *pxStackBuffer,
StaticTask_t *pxTaskBuffer );
*
*创建新任务并将其添加到准备运行的任务列表中。
*
·*在内部,在FreeRTOS实现中,任务使用两个块内存。第一个块用于保存任务的数据结构。第二个块被使用作为其堆栈。
*如果任务是使用xTaskCreate()创建的,那么这两个内存块将在xTaskCreate()函数中自动动态分配。(见 *http://www.freertos.org/a00111.html)。如果使用xTaskCreateStatic()创建任务,则应用程序编写器必须提供所需的内存。因此, *xTaskCreateStatic()允许在不使用任何动态内存分配的情况下创建任务。
*
* @param pvTaskCode Pointer to the task entry function. Tasks
* must be implemented to never return (i.e. continuous loop).
*
* @param pcName A descriptive name for the task. This is mainly used to
* facilitate debugging. The maximum length of the string is defined by
* configMAX_TASK_NAME_LEN in FreeRTOSConfig.h.
*
* @param ulStackDepth The size of the task stack specified as the number of
* variables the stack can hold - not the number of bytes. For example, if
* the stack is 32-bits wide and ulStackDepth is defined as 100 then 400 bytes
* will be allocated for stack storage.
*
* @param pvParameters Pointer that will be used as the parameter for the task
* being created.
*
* @param uxPriority The priority at which the task will run.
*
* @param pxStackBuffer Must point to a StackType_t array that has at least
* ulStackDepth indexes - the array will then be used as the task's stack,
* removing the need for the stack to be allocated dynamically.
*
* @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will
* then be used to hold the task's data structures, removing the need for the
* memory to be allocated dynamically.
*
* @return If neither pxStackBuffer or pxTaskBuffer are NULL, then the task will
* be created and pdPASS is returned. If either pxStackBuffer or pxTaskBuffer
* are NULL then the task will not be created and
* errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY is returned.
*
* Example usage:
// 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 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, // Stack size in words, not bytes.
( 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 );
}
* \defgroup xTaskCreateStatic xTaskCreateStatic
* \ingroup Tasks
*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint32_t ulStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
StackType_t * const puxStackBuffer,
StaticTask_t * const pxTaskBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* task. h
*
BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
*
*xTaskCreateRestricted()只能在包含MPU实现的系统中使用。
*
*创建新任务并将其添加到准备运行的任务列表中。函数参数定义分配给任务的内存区域和相关访问权限。
*
*@param pxTaskDefinition指向一个结构的指针,该结构包含每个普通xTaskCreate()参数的成员(请参阅xTaskCreate()API文档)以及可选的堆栈缓冲区和内存区域定义。
*
*@param pxCreatedTask用于传回一个句柄,通过该句柄可以引用创建的任务。
*
*@return pdPASS如果任务成功创建并添加到就绪列表中,则返回pdPASS,否则返回文件projdefs.h中定义的错误代码
*
* Example usage:
//创建定义要创建的任务的TaskParameters结构。
static const TaskParameters_t xCheckTaskParameters =
{
vATask, // pvTaskCode-实现任务的函数。
"ATask", // pcName-只是任务的文本名称,以帮助调试。
100, // usStackDepth-以单词定义的堆栈大小。
NULL, // pvParameters-作为函数参数传递到任务函数中。
( 1UL | portPRIVILEGE_BIT ),// uxPriority-任务优先级,如果任务应在特权状态下运行,请设置portPRIVILEGE位。
cStackBuffer,// puxStackBuffer-用作任务堆栈的缓冲区。
// 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 }
}
};
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( ;; );
}
* \defgroup xTaskCreateRestricted xTaskCreateRestricted
* \ingroup Tasks
*/
#if( portUSING_MPU_WRAPPERS == 1 )
BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION;
#endif
/**
* task. h
*
void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
*
* 当通过调用xTaskCreateRestricted()创建任务时,内存区域被分配给受限制的任务。可以使用vTaskAllocateMPURegions()重新定义这些区域。
*
* @param xTask 正在更新的任务的句柄。
*
*@param xRegions指向包含新内存区域定义的MemoryRegion结构的指针。
*
* Example usage:
//定义一个MemoryRegion结构数组,该数组配置一个MPU区域,允许从ucOneKByte数组的开头开始对1024字节进行读/写访问。最大3个可定义区域的其他两个未被使用,因此设置为零。
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 )
{
//创建此任务时,它可以访问由MPU配置定义的某些内存区域。在某一点上,需要将这些MPU区域替换为上面xAltRegions const结构中定义的区域。为此,请使用对vTaskAllocateMPURegions()的调用。空用作任务句柄,指示此函数应修改调用任务的MPU区域。
vTaskAllocateMPURegions(空,xAltRegions);
//现在,任务可以继续其功能,但从现在起只能访问其堆栈和ucOneKByte数组(除非在其他地方声明了任何其他静态定义或共享区域)。
}
*/
void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION;
/**
* task. h
* void vTaskDelete( TaskHandle_t xTask );
*
*必须将INCLUDE-vTaskDelete定义为1才能使用此函数。有关更多信息,请参阅配置部分。
*
*从RTOS实时内核管理中删除一个任务。正在删除的任务将从所有就绪、阻止、挂起和事件列表中删除。
*
*注意:空闲任务负责从已删除的任务中释放内核分配的内存。因此,如果应用程序调用vTaskDelete(),那么空闲任务不缺少微控制器处理时间是很重要的。任务代码分配的内存不会自动释放,应该在删除任务之前释放。
*
*请参阅demo应用程序文件death.c以获取使用
* vTaskDelete ().
*
*@param xTask要删除的任务的句柄。传递NULL将导致删除调用任务。
*
* Example usage:
void vOtherFunction( void )
{
TaskHandle_t xHandle;
// Create the task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
// Use the handle to delete the task.
vTaskDelete( xHandle );
}
* \defgroup vTaskDelete vTaskDelete
* \ingroup Tasks
*/
void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION;
/*
任务控制API
*/
/**
*task.h
*void vTaskDelay(const tictype_t xTicksToDelay);
*
*在给定的时间间隔内延迟任务。任务保持阻塞的实际时间取决于刻度率。常数portTICK_PERIOD_MS可用于从刻度率实时计算-分辨率为一个刻度周期。
*
*INCLUDE_vTaskDelay必须定义为1才能使用此函数。有关更多信息,请参阅配置部分。
*
*vTaskDelay()指定相对于调用vTaskDelay()的时间,任务希望解除阻塞的时间。例如,在调用vTaskDelay()后,指定100个tick的块周期将导致任务解决阻塞100个ticks。因此,vTaskDelay()无法提供控制周期性任务频率的好方法,因为通过代码的路径以及其他任务和中断活动将影响调用vTaskDelay()的频率,从而影响任务下次执行的时间。请参见vTaskDelayUntil(),以获取用于促进固定频率执行的替代API函数。它通过指定调用任务应该解除阻止的绝对时间(而不是相对时间)来完成此操作。
*
*@param xTicksToDelay时间量,以计时周期为单位调用任务应被阻塞。
*
*示例用法:
void vtask函数(void*pvParameters)
{
阻塞500ms
const TickType_t xDelay=500/portTICK_PERIOD_MS;
用于(;;)
{
//只需每隔500毫秒切换一次LED,在每个切换之间切换。
vToggled();
vTaskDelay(xDelay);
}
}
* \defgroup vTaskDelay vTaskDelay
* \ingroup TaskCtrl
*/
void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION;
/**
*task.h
*void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement );
*必须将INCLUDE-vTaskDelayUntil定义为1才能使用此函数。
*有关更多信息,请参阅配置部分。
*
*将任务延迟到指定的时间。此函数可用于周期性任务,以确保恒定的执行频率。
*
*此函数与vTaskDelay()在一个重要方面不同:vTaskDelay()将导致任务在调用vTaskDelay()时阻塞指定数量的tick。因此,很难单独使用vTaskDelay()来生成固定的执行频率,因为任务开始执行与调用vTaskDelay()的任务之间的时间可能不固定[任务可能会通过调用之间的代码采用不同的路径,或者每次执行时可能会被中断或抢占不同的次数]。
*
*vTaskDelay()指定相对于调用函数的时间的唤醒时间,而vTaskDelayUntil()指定它希望解除阻止的绝对(准确)时间。
*
*常数portTICK_PERIOD_MS可用于从刻度率实时计算-分辨率为一个tick周期。
*
*@param pxPreviousWakeTime指向一个变量的指针,该变量保存上次解除阻止任务的时间。变量必须在首次使用前用当前时间初始化(见下面的示例)。此后,变量将在vTaskDelayUntil()中自动更新。
*
*@param xtime增加周期时间段。任务将在时间*pxPreviousWakeTime+xtTimeIncrement解除阻止。使用相同的xTimeIncrement参数值调用vTaskDelayUntil将导致任务以固定的接口周期执行。
*
*示例用法:
//每10个节拍执行一个动作。
void vTaskFunction( void * pvParameters )
{
TickType_t xLastWakeTime;
const TickType_t xFrequency=10;
//用当前时间初始化xlastwoketime变量。
xlastwoketime=xTaskGetTickCount();
for( ;; )
{
//等待下一个周期。
vTaskDelayUntil(&xlastwoketime,xFrequency);
//在此处执行操作。
}
}
*/
void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION;
BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
/**
* task. h
* UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );
*要使此函数可用,必须将INCLUDE-uxTaskPriorityGet定义为1。有关详细信息,请参阅配置部分。
*
* 获得任何任务的优先级。
*
* @param 要查询的任务的xTask句柄。传递空句柄将导致返回调用任务的优先级。
*
* @return xTas的优先权k.
*
* Example usage:
void vAFunction( void )
{
TaskHandle_t xHandle;
// Create a task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
// ...
// Use the handle to obtain the priority of the created task.
// It was created with tskIDLE_PRIORITY, but may have changed
// it itself.
if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
{
// The task has changed it's priority.
}
// ...
// Is our priority higher than the created task?
if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
{
// Our priority (obtained using NULL handle) is higher.
}
}
* \defgroup uxTaskPriorityGet uxTaskPriorityGet
* \ingroup TaskCtrl
*/
UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
/**
* task. h
* eTaskState eTaskGetState( TaskHandle_t xTask );
*
*要使此函数可用,必须将INCLUDE\u eTaskGetState定义为1。有关详细信息,请参阅配置部分。
*
*获取任何任务的状态。状态由eTaskState枚举类型编码。
*
* @param 要查询的任务的xTask句柄。
*
* @return 调用函数时xTask的状态。注意,任务的状态可能在被调用的函数和被调用任务测试的函数返回值之间发生变化。
*/
eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
/**
* task. h
* void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState );
*
* configUSE_TRACE_FACILITY 必须定义为1才能使用此函数。有关更多信息,请参阅配置部分。
*
* 使用有关任务的信息填充TaskStatus结构。
*
* @param 正在查询的任务的xTask句柄。如果xTask为空,那么将返回有关调用任务的信息。
*
* @param pxTaskStatus指向TaskStatus结构的指针,该结构将填充有关使用xTask参数传递的句柄所引用的任务的信息。
*
* @xGetFreeStackSpace TaskStatus结构包含一个成员,用于报告所查询任务的堆栈高水位线。计算堆栈高水位线需要相对较长的时间,并且会使系统暂时没有响应,因此提供了xGetFreeStackSpace参数以允许跳过高水位线检查。如果xGetFreeStackSpace未设置为pdFALSE,则高水印值将仅写入TaskStatus结构;
*
* @param eState eState TaskStatus结构包含一个成员,用于报告正在查询的任务的状态。获取任务状态的速度不如简单的赋值快,因此提供了state参数以允许从TaskStatus结构中省略状态信息。若要获取状态信息,请将state设置为eInvalid-否则,传递到state中的值将报告为TaskStatus结构中的任务状态。
*
* Example usage:
void vAFunction( void )
{
TaskHandle_t xHandle;
TaskStatus_t xTaskDetails;
// Obtain the handle of a task from its name.
xHandle = xTaskGetHandle( "Task_Name" );
// Check the handle is not NULL.
configASSERT( xHandle );
// Use the handle to obtain further information about the task.
vTaskGetInfo( xHandle,
&xTaskDetails,
pdTRUE, // Include the high water mark in xTaskDetails.
eInvalid ); // Include the task state in xTaskDetails.
}
* \defgroup vTaskGetInfo vTaskGetInfo
* \ingroup TaskCtrl
*/
void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ) PRIVILEGED_FUNCTION;
/**
* task. h
* void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
*
* 要使此函数可用,必须将INCLUDE vTaskPrioritySet定义为1。有关详细信息,请参阅配置部分。
*
* 设置任何任务的优先级。
*
* 如果设置的优先级高于当前执行的任务,则在函数返回之前将发生上下文切换。
*
* @param xTask正在为其设置优先级的任务的句柄。传递空句柄将导致设置调用任务的优先级。
*
* @param uxNewPriority任务的优先级。
*
* Example usage:
void vAFunction( void )
{
TaskHandle_t xHandle;
// Create a task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
// ...
// Use the handle to raise the priority of the created task.
vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );
// ...
// Use a NULL handle to raise our priority to the same value.
vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
}
* \defgroup vTaskPrioritySet vTaskPrioritySet
* \ingroup TaskCtrl
*/
void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION;
/**
* task. h
* void vTaskSuspend( TaskHandle_t xTaskToSuspend );
*
* 包含vTaskSuspend必须定义为1才能使用此函数。有关详细信息,请参阅配置部分。
*
* 暂停任何任务。当一个任务被挂起时,无论它的优先级如何,都不会得到任何微控制器的处理时间。
*
* 对vTaskSuspend的调用不是累积的,即在同一任务上调用vTaskSuspend()两次,仍然只需要调用vTaskResume()一次即可准备挂起的任务。
*
* @param xtasktosupread正在挂起的任务的句柄。传递空句柄将导致调用任务挂起。
*
* Example usage:
void vAFunction( void )
{
TaskHandle_t xHandle;
// Create a task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
// ...
// Use the handle to suspend the created task.
vTaskSuspend( xHandle );
// ...
// The created task will not run during this period, unless
// another task calls vTaskResume( xHandle ).
//...
// Suspend ourselves.
vTaskSuspend( NULL );
// We cannot get here unless another task calls vTaskResume
// with our handle as the parameter.
}
* \defgroup vTaskSuspend vTaskSuspend
* \ingroup TaskCtrl
*/
void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION;
/**
* task. h
* void vTaskResume( TaskHandle_t xTaskToResume );
*
* INCLUDE\u vTaskSuspend必须定义为1才能使用此函数。有关更多信息,请参阅配置部分。
*
* 继续执行挂起的任务。
*
* 对vTaskSuspend()的一个或多个调用已挂起的任务将可通过对vTaskResume()的单个调用再次运行。
*
* @param xTaskToResume Handle to the task being readied.
*
* Example usage:
void vAFunction( void )
{
TaskHandle_t xHandle;
// Create a task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
// ...
// Use the handle to suspend the created task.
vTaskSuspend( xHandle );
// ...
// The created task will not run during this period, unless
// another task calls vTaskResume( xHandle ).
//...
// Resume the suspended task ourselves.
vTaskResume( xHandle );
// The created task will once again get microcontroller processing
// time in accordance with its priority within the system.
}
* \defgroup vTaskResume vTaskResume
* \ingroup TaskCtrl
*/
void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
/**
* task. h
* void xTaskResumeFromISR( TaskHandle_t xTaskToResume );
*
* 必须将INCLUDE\xTaskResumeFromISR定义为1,此函数才能可用。有关更多信息,请参阅配置部分。
*
* vTaskResume()的一种实现,可以从ISR中调用。
*
* 对vTaskSuspend()的一个或多个调用挂起的任务将可通过对xTaskResumeFromISR()的单个调用再次运行。
*
* 如果中断可能在任务挂起之前到达,则不应使用xTaskResumeFromISR()将任务与中断同步,因为这可能会导致错过中断。使用信号量作为同步机制可以避免这种可能性。
*
* @param 正在准备的任务的xTaskToResume句柄。
*
* @return pdTRUE 如果继续执行任务会导致上下文切换,则为pdFALSE。ISR使用它来确定在ISR之后是否需要上下文切换。
*
* \defgroup vTaskResumeFromISR vTaskResumeFromISR
* \ingroup TaskCtrl
*/
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
/*
调度程序控制
*/
/**
* task. h
* void vTaskStartScheduler( void );
*
* 启动实时内核计时处理。调用之后,内核可以控制执行哪些任务以及何时执行。
*
* 有关创建任务和启动内核的示例,请参见演示应用程序文件main.c
*
* Example usage:
void vAFunction( void )
{
// Create at least one task before starting the kernel.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
// Start the real time kernel with preemption.
vTaskStartScheduler ();
// Will not get here unless a task calls vTaskEndScheduler ()
}
*
* \defgroup vTaskStartScheduler vTaskStartScheduler
* \ingroup SchedulerControl
*/
void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION;
/**
* task. h
* void vTaskEndScheduler( void );
*
* 注意:在编写本文时,只有x86实模式端口(它在PC上代替DOS运行)实现了这个功能。
*
* 停止实时内核计时。所有创建的任务将被自动删除,多任务(抢占或协作)将停止。然后从调用vTaskStartScheduler()的点开始执行,就像vTaskStartScheduler()刚刚返回一样。
*
* 请参阅演示应用程序文件main。以使用vTaskEndScheduler()的示例为例。
*
* VTaskEntPraceRever()要求在便携式层中定义一个退出函数(参见端口中的VPORTHORM调度程序)。c表示PC端口)。这将执行特定于硬件的操作,例如停止内核滴答。
*
* vTaskEndScheduler()将释放内核分配的所有资源,但不会释放应用程序任务分配的资源。
*
* Example usage:
void vTaskCode( void * pvParameters )
{
for( ;; )
{
// Task code goes here.
// At some point we want to end the real time kernel processing
// so call ...
vTaskEndScheduler ();
}
}
void vAFunction( void )
{
// Create at least one task before starting the kernel.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
// Start the real time kernel with preemption.
vTaskStartScheduler ();
// Will only get here when the vTaskCode () task has called
// vTaskEndScheduler (). When we get here we are back to single task
// execution.
}
*
* \defgroup vTaskEndScheduler vTaskEndScheduler
* \ingroup SchedulerControl
*/
void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION;
/**
* task. h
* void vTaskSuspendAll( void );
*
* 在不禁用中断的情况下挂起计划程序。调度程序挂起时不会发生上下文切换。
*
* 调用vTaskSuspendAll()之后,调用任务将继续执行,不会有被调出的风险,直到调用xTaskResumeAll()为止。
*
* 当调度程序挂起时,不能调用可能导致上下文切换的API函数(例如vTaskDelayUntil()、xQueueSend()等)。
*
* Example usage:
void vTask1( void * pvParameters )
{
for( ;; )
{
// Task code goes here.
// ...
//在某个时刻,任务希望执行一个长操作,在此期间它不希望被交换出去。它不能使用taskENTER_CRITICAL()/taskEXIT_CRITICAL(),因为操作的长度可能会导致错过中断(包括勾号)。
// 防止实时内核交换任务。
vTaskSuspendAll ();
// 在这里执行操作。没有必要使用关键部分,因为我们有所有的微控制器处理时间。
在这段时间内,中断仍将运行,并且内核计时计数将保持不变。
// ...
// 操作完成。重新启动内核。
xTaskResumeAll ();
}
}
* \defgroup vTaskSuspendAll vTaskSuspendAll
* \ingroup SchedulerControl
*/
void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION;
/**
* task. h
* BaseType_t xTaskResumeAll( void );
*
* 在调度程序活动被vTaskSuspendAll()调用挂起后恢复该活动。
*
* xTaskResumeAll()仅恢复计划程序。它不会取消挂起以前由调用vTaskSuspend()挂起的任务。
*
* @return 如果恢复调度程序导致上下文切换,则返回pdTRUE,否则返回pdFALSE。
*
* Example usage:
void vTask1( void * pvParameters )
{
for( ;; )
{
// Task code goes here.
// ...
//在某个时刻,任务希望执行一个长操作,在此期间它不希望被交换出去。它不能使用taskENTER_CRITICAL()/taskEXIT_CRITICAL(),因为操作的长度可能会导致错过中断(包括勾号)。
// 防止实时内核交换任务。
vTaskSuspendAll ();
// 在这里执行操作。没有必要使用关键部分,因为我们有所有的微控制器处理时间。
在这段时间内,中断仍将运行,并且内核计时计数将保持不变。
// ...
// The operation is complete. Restart the kernel. We want to force
// a context switch - but there is no point if resuming the scheduler
// caused a context switch already.
if( !xTaskResumeAll () )
{
taskYIELD ();
}
}
}
* \defgroup xTaskResumeAll xTaskResumeAll
* \ingroup SchedulerControl
*/
BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION;
/*
任务实用程序
*/
/**
* task. h
* TickType_t xTaskGetTickCount( void );
*
* @return return调用vTaskStartScheduler后的滴答数
*
* \defgroup xTaskGetTickCount xTaskGetTickCount
* \ingroup TaskUtils
*/
TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION;
/**
* task. h
* TickType_t xTaskGetTickCountFromISR( void );
*
* @return 调用vTaskStartScheduler之后的计时。
*
* 这是xTaskGetTickCount()的一个版本,可以安全地从ISR调用,前提是TickType_t是所用微控制器的自然字长,或者不支持或不使用中断嵌套。
*
* \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR
* \ingroup TaskUtils
*/
TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION;
/**
* task. h
* uint16_t uxTaskGetNumberOfTasks( void );
*
* *@返回实时内核当前管理的任务数。
* 这包括所有就绪、阻止和挂起的任务。已被删除但尚未被空闲任务释放的任务也将包含在计数中。
*
* \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks
* \ingroup TaskUtils
*/
UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION;
/**
* task. h
* char *pcTaskGetName( TaskHandle_t xTaskToQuery );
*
* @return 返回句柄xTaskToQuery引用的任务的文本(可读)名称。任务可以通过传入自己的句柄或将xTaskToQuery设置为空来查询自己的名称。
*
* \defgroup pcTaskGetName pcTaskGetName
* \ingroup TaskUtils
*/
char *pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/**
* task. h
* TaskHandle_t xTaskGetHandle( const char *pcNameToQuery );
*
* NOTE: 此功能需要相对较长的时间才能完成,应谨慎使用.
*
* @return 具有可读名称pcNameToQuery的任务的句柄。如果找不到匹配的名称,则返回NULL。要使pcTaskGetHandle()可用,必须在FreeRTOSConfig.h中将INCLUDE xTaskGetHandle设置为1。
*
* \defgroup pcTaskGetHandle pcTaskGetHandle
* \ingroup TaskUtils
*/
TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ) PRIVILEGED_FUNCTION;
/**
* task.h
* UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
*
* 要使此函数可用,必须在FreeRTOSConfig.h中将INCLUDE-uxTaskGetStackHighWaterMark设置为1。
*
* 返回与xTask关联的堆栈的高水位线。这是自任务启动以来的最小可用堆栈空间(换句话说,在32位计算机上,值为1表示4字节)。返回的数字越小,任务越接近溢出堆栈。
*
* @param 与要检查的堆栈关联的任务的xTask句柄。将xTask设置为NULL以检查调用任务的堆栈。
*
* @return 自xTask引用的任务创建以来,存在的最小可用堆栈空间量(即堆栈上的实际空间,而不是字节)。
*/
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
/*使用跟踪宏时,有时需要include FreeRTOS.h.完成此操作后,taskhook函数尚未定义,
所以下面的两个原型将导致编译错误。除非configUSE_APPLICATION_TASK_TAG configuration常量明确要求这两个原型,否则可以通过简单地防止它们包含来解决此问题。。*/
#ifdef configUSE_APPLICATION_TASK_TAG
#if configUSE_APPLICATION_TASK_TAG == 1
/**
* task.h
* void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction );
*
* 将pxHookFunction设置为任务xTask使用的任务挂钩函数。将xTask作为NULL传递具有设置调用任务钩子函数的效果。
*/
void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) PRIVILEGED_FUNCTION;
/**
* task.h
* void xTaskGetApplicationTaskTag( TaskHandle_t xTask );
*
* 返回分配给任务xTask的pxHookFunction值。
*/
TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
#endif /* configUSE_APPLICATION_TASK_TAG ==1 */
#endif /* ifdef configUSE_APPLICATION_TASK_TAG */
#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
/* 每个任务都包含一个指针数组,该数组由在FreeRTOSConfig.h中配置线程本地存储指针设置内核不使用指针本身,因此应用程序编写器可以使用任何他们想用的指针。以下两个功能是用于分别设置和查询指针 */
void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) PRIVILEGED_FUNCTION;
void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) PRIVILEGED_FUNCTION;
#endif
/**
* task.h
* BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter );
*
* 调用与xTask关联的hook函数。将xTask作为NULL传递具有调用正在运行的任务(调用任务)钩子函数的效果。
*
* pvParameter被传递给hook函数,以便任务按其需要进行解释。返回值是用户注册的任务挂钩函数返回的值。
*/
BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) PRIVILEGED_FUNCTION;
/**
* 只有在FreeRTOSConfig.h中将INCLUDE\uxtaskgetidletaskhandle设置为1时,xTaskGetIdleTaskHandle()才可用.
*
* 只需返回空闲任务的句柄。在启动计划程序之前调用xTaskGetIdleTaskHandle()无效。
*/
TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION;
/**
* configUSE_TRACE_FACILITY必须在FreeRTOSConfig.h中定义为1,才能使uxTaskGetSystemState()可用。
*
* uxTaskGetSystemState()为系统中的每个任务填充一个TaskStatus结构。TaskStatus结构包含任务句柄、任务名称、任务优先级、任务状态的成员,以及任务所消耗的运行时总数。有关完整的成员列表,请参阅此文件中的TaskStatus结构定义。
*
* 注意:此函数仅用于调试使用,因为其使用会导致调度程序在较长时间内保持挂起状态。
*
* @param pxTaskStatusArray指向TaskStatus结构数组的指针。数组必须至少包含一个由RTOS控制的任务的TaskStatus结构。可以使用uxTaskGetNumberOfTasks()API函数确定RTOS控制下的任务数。
*
* @param uxArraySize pxTaskStatusArray参数指向的数组大小。大小指定为数组中的索引数或数组中包含的TaskStatus结构数,而不是数组中的字节数。
*
* @param pulTotalRunTime如果configGENERATE_RUN_TIME_STATS设置为1 in
*FreeRTOSConfig.h然后*pulTotalRunTime由uxTaskGetSystemState()设置为自目标启动以来的总运行时间(由运行时统计时钟定义,请参阅http://www.freertos.org/rtos-run-time-stats.html)。pulTotalRunTime可以设置为空以忽略总运行时间信息。
*
*@return由uxTaskGetSystemState()填充的TaskStatus结构数。这应该等于uxTaskGetNumberOfTasks()API函数返回的数字,但如果在uxArraySize参数中传递的值太小,则该值将为零。
*
* Example usage:
//此示例演示如何从uxTaskGetSystemState()提供的原始数据生成易读的运行时统计信息表。易读的表被写入pcWriteBuffer
void vTaskGetRunTimeStats( char *pcWriteBuffer )
{
TaskStatus_t *pxTaskStatusArray;
volatile UBaseType_t uxArraySize, x;
uint32_t ulTotalRunTime, ulStatsAsPercentage;
// 确保写入缓冲区不包含字符串。
*pcWriteBuffer = 0x00;
//拍摄任务数量的快照,以防在执行此函数时任务数量发生更改。
uxArraySize = uxTaskGetNumberOfTasks();
//为每个任务分配任务状态结构。可以在编译时静态地分配数组。
pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) );
if( pxTaskStatusArray != NULL )
{
// 生成有关每个任务的原始状态信息。
uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime );
// 用于百分比计算。
ulTotalRunTime /= 100UL;
// 避免被零除错误。
if( ulTotalRunTime > 0 )
{
//对于pxTaskStatusArray数组中的每个填充位置,将原始数据格式化为人类可读的ASCII数据
for( x = 0; x < uxArraySize; x++ )
{
//任务使用的运行时间占总运行时间的百分比是多少?这将始终向下舍入到最接近的整数。ulTotalRunTimeDiv100已除以100。
ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime;
if( ulStatsAsPercentage > 0UL )
{
sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
}
else
{
//如果此处的百分比为零,则任务消耗的时间不到总运行时间的1%。
sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
}
pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
}
}
// The array is no longer needed, free the memory it consumes.
vPortFree( pxTaskStatusArray );
}
}
*/
UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) PRIVILEGED_FUNCTION;
/**
* task. h
* void vTaskList( char *pcWriteBuffer );
*
*configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_函数都必须定义为1,才能使用此函数。有关更多信息,请参阅FreeRTOS.org网站的配置部分。
*
*注1:此功能将在其持续时间内禁用中断。它不是用于正常的应用程序运行时,而是作为调试辅助。
*
*列出所有当前任务及其当前状态和堆栈使用高水位线。
*
* 任务报告为已阻止(“B”)、就绪(“R”)、已删除(“D”)或已挂起(“S”)。
*
* 请注意:
*
* 此功能仅为方便而提供,许多演示应用程序都使用此功能。不要认为它是调度程序的一部分。
*
*vTaskList()调用uxTaskGetSystemState(),然后将uxTaskGetSystemState()输出的一部分格式化为可读的表,该表显示任务名称、状态和堆栈使用情况。
*
*vTaskList()依赖于sprintf()C库函数,该函数可能会增大代码大小,使用大量堆栈,并在不同平台上提供不同的结果。sprintf()的另一种小型、第三方和有限功能的实现在名为printf stdarg.c的文件中的许多FreeRTOS/Demo子目录中提供(注意printf stdarg.c不提供完整的snprintf()实现!).
*
*建议生产系统直接调用uxTaskGetSystemState()来获取对原始统计数据的访问,而不是通过调用vTaskList()来间接访问。
*
*@param pcWriteBuffer以ASCII格式将上述详细信息写入其中的缓冲区。假定此缓冲区足够大,可以包含生成的报告。每个任务大约40字节应该足够了。
*
* \defgroup vTaskList vTaskList
* \ingroup TaskUtils
*/
void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/**
* task. h
* void vTaskGetRunTimeStats( char *pcWriteBuffer );
*
*configGENERATE_RUN_TIME_STATS和configUSE_STATS_FORMATTING_函数都必须定义为1才能使用此函数。应用程序还必须为portCONFIGURE_TIMER_for_RUN_TIME_STATS()和portGET_RUN_TIME_COUNTER_VALUE()提供定义,以分别配置外围计时器/计数器并返回计时器的当前计数值。计数器应至少为滴答计数频率的10倍。
*
*注1:此功能将在其持续时间内禁用中断。它不是用于正常的应用程序运行时,而是作为调试辅助。
*
*将configGENERATE_RUN_TIME_STATS设置为1将导致为每个任务存储总的累积执行时间。累积时间值的分辨率取决于portCONFIGURE_timer_FOR_RUN_time_STATS()宏配置的计时器的频率。调用vTaskGetRunTimeStats()将每个任务的总执行时间写入缓冲区中,既作为绝对计数值,也作为总系统执行时间的百分比。
*
* 注2:此功能仅为方便而提供,许多演示应用程序都使用此功能。不要认为它是调度程序的一部分。
*
* *vTaskGetRunTimeStats()调用uxTaskGetSystemState(),然后将uxTaskGetSystemState()输出的一部分格式化为可读表,该表以绝对值和百分比形式显示每个任务在运行状态中花费的时间量。
*
*vTaskGetRunTimeStats()依赖于sprintf()C库函数,该函数可能会增大代码大小,使用大量堆栈,并在不同平台上提供不同的结果。sprintf()的另一种小型、第三方和有限功能的实现在名为printf stdarg.c的文件中的许多FreeRTOS/Demo子目录中提供(注意printf stdarg.c不提供完整的snprintf()实现!).
*
*建议生产系统直接调用uxTaskGetSystemState()以获取对原始统计数据的访问,而不是通过调用vTaskGetRunTimeStats()间接访问。
*
*@param pcWriteBuffer以ASCII格式将执行时间写入的缓冲区。假定此缓冲区足够大,可以包含生成的报告。每个任务大约40字节应该足够了。
*
* \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats
* \ingroup TaskUtils
*/
void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/**
* task. h
* BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );
*
* configUSE_TASK_NOTIFICATIONS必须未定义或定义为1才能使用此函数.
*
* 当configUSE_TASK_NOTIFICATIONS设置为one时,每个任务都有自己的私有通知值“,该值是32位无符号整数(uint32_t)。
*
* 事件可以使用中间对象发送到任务。这些对象的例子包括队列、信号量、互斥量和事件组。任务通知是一种直接向任务发送事件而不需要此类中间对象的方法。
*
* 发送到任务的通知可以选择性地执行操作,例如更新、覆盖或增加任务的通知值。这样,任务通知可以用来向任务发送数据,或者用作轻量级和快速二进制或计数信号量。
*
* 发送到任务的通知将一直挂起,直到调用xTaskNotifyWait()或ulTaskNotifyTake()的任务清除它为止。如果任务已处于阻止状态,以便在通知到达时等待通知,则该任务将自动从阻止状态(未阻止)中删除,并清除通知。
*
* 任务可以使用xTaskNotifyWait()到[可选]块来等待通知挂起,或者使用ulTaskNotifyTake()到[可选]块来等待其通知值具有非零值。任务处于阻塞状态时不会占用任何CPU时间。
*
* 有关详细信息,请参见http://www.FreeRTOS.org/RTOS-task-notifications.html。
*
* @param xTaskToNotify被通知任务的句柄。任务的句柄可以从用于创建任务的xTaskCreate()API函数返回,而当前运行的任务的句柄可以通过调用xtaskgetcurrenttashandle()获得。
*
* @可随通知一起发送的参数ulValue数据。如何使用数据取决于eAction参数的值。
*
* @param eAction指定通知如何更新任务的通知值(如果有)。有效的反应值如下:
*
* eSetBits-任务的通知值用ulValue按位或。在这种情况下,xTaskNofify()始终返回pdPASS。
*
* e增加-任务的通知值增加。在这种情况下,不使用ulValue,xTaskNotify()始终返回pdPASS。
*
*eSetValueWithOverwrite-任务的通知值设置为ulValue的值,即使被通知的任务尚未处理上一个通知(该任务已挂起通知)。在这种情况下,xTaskNotify()始终返回pdPASS。
*
*eSetValueWithoutOverwrite-如果被通知的任务尚未挂起通知,则该任务的通知值设置为ulValue,xTaskNotify()将返回pdPASS。如果被通知的任务已经有一个通知挂起,则不执行任何操作,并返回pdFAIL。
*
*eNoAction-任务接收通知,但不更新其通知值。在这种情况下,不使用ulValue,xTaskNotify()始终返回pdPASS。
*
*pulperReviousNotificationValue-可用于在notify函数修改任何位之前传递主题任务的通知值。
*
* @return Dependent on the value of eAction. See the description of the
* eAction parameter.
*
* \defgroup xTaskNotify xTaskNotify
* \ingroup TaskNotifications
*/
BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) PRIVILEGED_FUNCTION;
#define xTaskNotify( xTaskToNotify, ulValue, eAction ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL )
#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) )
/**
* task. h
* BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );
*
* 配置使用任务通知必须未定义或定义为1才能使用此函数。
*
* 当configUSE_TASK_NOTIFICATIONS设置为one时,每个任务都有自己的私有“通知值”,它是一个32位无符号整数(uint32)。
*
* *xTaskNotify()的一个版本,可从中断服务例程(ISR)中使用
*
* 事件可以使用中间对象发送到任务。这些对象的例子包括队列、信号量、互斥量和事件组。任务通知是一种直接向任务发送事件而不需要此类中间对象的方法。
*
* 发送到任务的通知可以选择性地执行操作,例如更新、覆盖或增加任务的通知值。这样,任务通知可以用来向任务发送数据,或者用作轻量级和快速二进制或计数信号量。
*
*发送到任务的通知将一直挂起,直到调用xTaskNotifyWait()或ulTaskNotifyTake()的任务清除它为止。如果任务已处于阻止状态,以便在通知到达时等待通知,则该任务将自动从阻止状态(未阻止)中删除,并清除通知。
*
*任务可以使用xTaskNotifyWait()到[可选]块来等待通知挂起,或者使用ulTaskNotifyTake()到[可选]块来等待其通知值具有非零值。任务处于阻塞状态时不会占用任何CPU时间。
*
* See http://www.FreeRTOS.org/RTOS-task-notifications.html for details.
*
*@param xTaskToNotify被通知任务的句柄。任务的句柄可以从用于创建任务的xTaskCreate()API函数返回,而当前运行的任务的句柄可以通过调用xtaskgetcurrenttashandle()获得。
*
*@param ulValue可随通知一起发送的数据。如何使用数据取决于eAction参数的值。
*
*@param eAction指定通知如何更新任务的通知值(如果有)。有效的反应值如下:
*
*eSetBits-任务的通知值用ulValue按位或。在这种情况下,xTaskNofify()始终返回pdPASS。
*
*e增加-任务的通知值增加。在这种情况下,不使用ulValue,xTaskNotify()始终返回pdPASS。
*
*eSetValueWithOverwrite-任务的通知值设置为ulValue的值,即使被通知的任务尚未处理上一个通知(该任务已挂起通知)。在这种情况下,xTaskNotify()始终返回pdPASS。
*
*eSetValueWithoutOverwrite-如果被通知的任务尚未挂起通知,则该任务的通知值设置为ulValue,xTaskNotify()将返回pdPASS。如果被通知的任务已经有一个通知挂起,则不执行任何操作,并返回pdFAIL。
*
*eNoAction-任务接收通知,但不更新其通知值。在这种情况下,不使用ulValue,xTaskNotify()始终返回pdPASS。
*
*@param pxHigherPriorityTaskWoken xTaskNotifyFromISR()将pxHigherPriorityTaskWoken设置为pdTRUE,如果发送通知导致向其发送通知的任务离开阻止状态,并且未阻止的任务的优先级高于当前正在运行的任务。如果XTaskBooTyFyFISMISH()将此值设置为PDTALL,则在中断退出之前应请求上下文切换。如何从ISR请求上下文切换取决于端口-请参阅正在使用的端口的文档页。
*
*@return取决于eAction的值。请参阅eAction参数的说明。
*
* \defgroup xTaskNotify xTaskNotify
* \ingroup TaskNotifications
*/
BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) )
#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) )
/**
* task. h
* BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
*
* 配置使用任务通知必须未定义或定义为1才能使用此函数。
*
* 当configUSE_TASK_NOTIFICATIONS设置为one时,每个任务都有自己的私有“通知值”,即32位无符号整数(uint32_t)。
*
* 事件可以使用中间对象发送到任务。这些对象的例子包括队列、信号量、互斥量和事件组。任务通知是一种直接向任务发送事件而不需要此类中间对象 的方法。
*
* 发送到任务的通知可以选择性地执行操作,例如更新、覆盖或增加任务的通知值。这样,任务通知可以用来向任务发送数据,或者用作轻量级和快速二进制或计数信号量。
*
*发送到任务的通知将一直挂起,直到调用xTaskNotifyWait()或ulTaskNotifyTake()的任务清除它为止。如果任务已处于阻止状态,以便在通知到达 时等待通知,则该任务将自动从阻止状态(未阻止)中删除,并清除通知。
*
*任务可以使用xTaskNotifyWait()到[可选]块来等待通知挂起,或者使用ulTaskNotifyTake()到[可选]块来等待其通知值具有非零值。任务处于阻塞状态时不会占用任何CPU时间。
*
* See http://www.FreeRTOS.org/RTOS-task-notifications.html for details.
*
*@param ulbitstoclearonetry位在ulbitstoclearonetry值中设置,在任务检查是否有任何通知挂起之前,将在调用任务的通知值中清除,如果没有通知挂起,则可以选择阻塞。将ulbitstoclearonetry设置为ULONG_MAX(如果包含limits.h)或0xfffffful(如果不包含limits.h)将具有将任务的通知值重置为0的效果。将ulbitstoclearonetry设置为0将使任务的通知值保持不变。
*
*@ PARAM ULTBSTORLLIONEXECUT,如果在调用任务退出XTASKNOTIFYWAITE()函数之前挂起或收到通知,那么任务的通知值(见XTaskNoTyYy()API函数)将使用PulnTimeCtItValk参数传递出去。然后,在任务的通知值中清除任何在ObjStLogExalEnExchange中设置的位(Note PulnTimeCtItValk值是在清除任何位之前设置的)。设置ULTBSTORLYONEXECUTE到ULUNYOXMAX(如果包含限制H)或0xFFFFFFFULL(如果不包括H限制)将在任务退出之前将任务的通知值重置为0。当函数退出时,将ULTBSTOLLYNEXONEXIT设置为0将使任务的通知值不变(在这种情况下,PulnTimeCtItValue中传递的值将与任务的通知值匹配)。
*
*@param pulNotificationValue用于从函数中传递任务的通知值。注意:通过ULBSTEXLILLION退出非零造成的任何位的清除不会影响所传递的值。
*
*@ PARAM XTICKSTOWAIT,在调用XTaskNoTyYeWAITE()时,如果通知尚未被挂起,任务将在阻塞状态中等待接收的通知的最大时间量。任务处于阻止状态时不会占用任何处理时间。这是在kernel ticks中指定的,宏pdMS-TO-TICSK(value-in-ms)可用于将以毫秒为单位指定的时间转换为以ticks为单位指定的时间。
*
*@return如果收到通知(包括调用xTaskNotifyWait时已挂起的通知),则返回pdPASS。否则返回pdFAIL。
*
* \defgroup xTaskNotifyWait xTaskNotifyWait
* \ingroup TaskNotifications
*/
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
* task. h
* BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
*
* 配置使用任务通知必须未定义或定义为1,此宏才能使用。
*
* 当configUSE_TASK_NOTIFICATIONS设置为one时,每个任务都有自己的私有“通知值”,即32位无符号整数(uint32_t)
*
*事件可以使用中间对象发送到任务。这些对象的例子包括队列、信号量、互斥量和事件组。任务通知是一种直接向任务发送事件而不需要此类中间对象的方法。
*
*发送到任务的通知可以选择性地执行操作,例如更新、覆盖或增加任务的通知值。这样,任务通知可以用来向任务发送数据,或者用作轻量级和快速二进制或计数信号量。
*
* xTaskNotifyGive()是一个助手宏,当任务通知用作轻量级、更快的二进制或计数信号量等价物时使用。实际的FreeRTOS信号量是使用xSemaphoreGive()API函数给出的,而使用任务通知的等效操作是xTaskNotifyGive()。
*
* 当任务通知被用作二进制或计数信号量等价物时,被通知的任务应该使用ulTaskNotificationTake()API函数而不是xTaskNotifyWait()API函数等待通知。
*
* See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details.
*
* @param xTaskToNotify被通知任务的句柄。任务的句柄可以从用于创建任务的xTaskCreate()API函数返回,而当前运行的任务的句柄可以通过调用xtaskgetcurrenttashandle()获得。
*
*@return xTaskNotifyGive()是一个宏,它调用xTaskNotify(),并将eAction参数设置为eIncrement,因此总是返回pdPASS。
*
* \defgroup xTaskNotifyGive xTaskNotifyGive
* \ingroup TaskNotifications
*/
#define xTaskNotifyGive( xTaskToNotify ) xTaskGenericNotify( ( xTaskToNotify ), ( 0 ), eIncrement, NULL )
/**
* task. h
* void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
*
* 配置使用任务通知必须未定义或定义为1,此宏才能使用
*
* 当configUSE_TASK_NOTIFICATIONS设置为one时,每个任务都有自己的私有“通知值”,即32位无符号整数(uint32_t)。
*
* 可以从中断服务调用的xTaskNotifyGive()版本例行程序(ISR)。
*
*事件可以使用中间对象发送到任务。这些对象的例子包括队列、信号量、互斥量和事件组。任务通知是一种直接向任务发送事件而不需要此类中间对象的方法。
*
* 发送到任务的通知可以选择性地执行操作,例如更新、覆盖或增加任务的通知值。这样,任务通知可以用来向任务发送数据,或者用作轻量级和快速二进制或计数信号量。
*
* vTaskNotifyGiveFromISR()用于将任务通知用作轻量级、更快的二进制或计数信号量等价物时。实际的FreeRTOS信号量是使用xSemaphoreGiveFromISR()API函数从ISR发出的,而使用任务通知的等效操作是vTaskNotifyGiveFromISR()。
*
* 当任务通知被用作二进制或计数信号量等价物时,被通知的任务应该使用ulTaskNotificationTake()API函数而不是xTaskNotifyWait()API函数等待通知。
*
* See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details.
*
* @param xTaskToNotify被通知任务的句柄。任务的句柄可以从用于创建任务的xTaskCreate()API函数返回,而当前运行的任务的句柄可以通过调用xtaskgetcurrenttashandle()获得。
*
* @param pxHigherPriorityTaskWoken vtasknotifygivefromsir()将*pxHigherPriorityTaskWoken设置为pdTRUE,如果发送通知导致向其发送通知的任务离开阻止状态,并且未阻止的任务的优先级高于当前正在运行的任务。如果vtaskNoTyfyGiFrEuffRISE()将此值设置为PDTUTE,则在中断退出之前应请求上下文切换。如何从ISR请求上下文切换取决于端口-请参阅正在使用的端口的文档页。
*
* \defgroup xTaskNotifyWait xTaskNotifyWait
* \ingroup TaskNotifications
*/
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;