1.函数介绍
创建方法有三种,删除一种
函数描述xTaskCreate()动态的创建一个任务xTaskCreateStatic()使用静态的方法创建一个任务xTaskCreateRestricted()创建一个使用MPU进行限制的任务,相关内存使用动态内存分配xTaskDelete()删除一个任务- xTaskCreate() 学这个,看源码是很有必要的,我们来瞅一瞅源码的函数定义 函数返回值:pdPass 任务创建成功 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY: 任务创建失败,堆栈内存不足
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) //这是一个宏定义,意思是支持动态内存,可以参考一下第一节的内容
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, //任务的函数
const char * const pcName, //任务的名称
const uint16_t usStackDepth,//堆栈的大小,把这个数值乘上四然后单位写成B,这就是真实的大小
void * const pvParameters, //任务参数
UBaseType_t uxPriority, //优先级
TaskHandle_t * const pxCreatedTask //任务句柄,任务创建成功以后会返回此任务的任务句柄,这个句柄其实就是任务的任务堆栈。此参数就用来保存这个任务句柄。其他API函数可能会使用这个句柄。
) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
#endif
- xTaskCreateStatic() 静态创建任务,需要我们来提供相应的内存空间。返回值如下: NULL:任务创建失败,puxStackBuffer 或者 pxTaskBuffer为NULL的时候会发生这个错误 其他值:任务创建成功,这个返回值就是任务句柄,动态创建任务的时候要提供返回值,静态的方法创建任务会自动返回任务句柄
#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,//任务堆栈,一般是数组,数组类型要为StackType_t
StaticTask_t * const pxTaskBuffer //任务控制块TCB task_controllor_block
) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
#endif /* configSUPPORT_STATIC_ALLOCATION */
- xTaskDelete() 任务删除函数 可以删除上面两个方法创建出来的函数,删除的任务就真的没了,句柄也没了,如果任务是动态方法创建的,任务删除后必须要给空闲任务一定的运行时间,为什么呢?因为被删除的动态任务所申请的堆栈和控制内存在空闲任务中才会被释放掉。 只有内核创建的任务内存才会被自动释放,用户调用pvPortMalloc()自行分配的内存不会被释放,必须用户调用pvPortFree()才行,否则就会内存泄漏。 删除时候传入的是TaskHandle_t xTaskToDelete ,是不是很熟悉,就是我们的句柄
#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 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;
/* 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;
prvDeleteTCB( pxTCB );
/* Reset the next expected unblock time in case it referred to
the task that has just been deleted. */
prvResetNextTaskUnblockTime();
}
traceTASK_DELETE( pxTCB );
}
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 */
2.动态创建删除实例
第一步定义一些需要的宏、变量和函数:
#define TASK1_PRIORITY 3 //任务优先级
#define TASK1_STACK_SIZE 120 //任务堆栈大小
TaskHandle_t task1TaskHandle; //任务处理
void task1( void * pvParameters ); //任务函数声明
第二步声明并定义一个任务:
void task1(void * pvParamter){
int i = 0;
while(1){
LED1=~LED1; //灯闪一闪
vTaskDelay(1000); //再延时一下下
}
}
第三步使用任务创建函数创建任务:
/创建任务
xTaskCreate((TaskFunction_t) task1,
(char *) "task1",
(uint16_t ) TASK1_STACK_SIZE, //堆栈大小
(void * ) NULL,
(UBaseType_t) TASK1_PRIORITY, //优先级,这里的数值不能是最小的0,因为零是空闲函数的优先级,咱是好孩子,不强人家的优先级,空闲任务呢也做了一些伟大的事情,它可以回收内存空间
(TaskHandle_t * )&task1TaskHandle); //任务处理句柄,这个是需要的,创建完成后,可以通过句柄对这个任务进行一些操作,比如进行删除任务
第四步开启任务的调度: 第一次使用的时候就忘记这个了,任务完全不会动,一定记得开启哦~
vTaskStartScheduler();
第五步进行任务删除: 如果我们希望LED灯闪烁一下后以后再也不闪该怎么办,看代码:
void task1(void * pvParamter){
int i = 0;
while(i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?