创建新的任务并添加到任务队列中,准备运行
-
Parameters:
-
pvTaskCode |
指向任务的入口函数. 任务必须执行并且永不返回 (即:无限循环). |
pcName |
描述任务的名字。主要便于调试。最大长度由configMAX_TASK_NAME_LEN.定义 |
usStackDepth |
指定任务堆栈的大小 ,堆栈能保护变量的数目- 不是字节数. 例如,如果堆栈为16位宽度,usStackDepth定义为 100, 200 字节,这些将分配给堆栈。堆栈嵌套深度(堆栈宽度)不能超多最大值——包含了size_t类型的变量 |
pvParameters |
指针用于作为一个参数传向创建的任务 |
uxPriority |
任务运行时的优先级( 0 : 优先级最低) |
pvCreatedTask |
用于传递一个处理——引用创建的任务 |
-
返回:
-
pdPASS 是如果任务成功创建并且添加到就绪列中,另外错误代码在projdefs. H文件定义
使用例子:
// 使用句柄来删除任务 vTaskDelete( xHandle ); }
// 创建任务,存储处理。注意传递的参数为ucParameterToPass //它在任务中不能始终存在, 所以定义为静态变量. 如果它是动态堆栈的变量,可能存在 // 没有那么长,或者至少随着时间毁灭, // 新的时间, 尝试存储它 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
// 函数来创建一个任务 void vOtherFunction( void ) { static unsigned char ucParameterToPass; xTaskHandle xHandle;
// 创建任务 void vTaskCode( void * pvParameters ) { for( ;; ) { // 任务代码 } }
portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode, const portCHAR * const pcName, unsigned portSHORT usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pvCreatedTask );
[注
:以下为FreeRTOS_v4
.5
.0在at91sam7s64处理器上的task任务创建函数
(gliethtp
)
]
signed portBASE_TYPE xTaskCreate
( pdTASK_CODE pvTaskCode
,
const
signed portCHAR
*
const pcName
,
unsigned portSHORT usStackDepth
,
void
*pvParameters
,
unsigned portBASE_TYPE uxPriority
, xTaskHandle
*pxCreatedTask
)
{
signed portBASE_TYPE xReturn
; tskTCB
* pxNewTCB
;
#
if
( configUSE_TRACE_FACILITY
=
= 1
)
//uxTaskNumber为任务id号,一般用来调试,每个任务会唯一对应一个处于[0,0xffffffff]范围之间的数值
//因为优先级并不能唯一表示一个task,所以为了能够唯一标识一个task,
//可以使用TCB或者TCB->uxTCBNumber
static
unsigned portBASE_TYPE uxTaskNumber
= 0
;
#
endif
//动态申请tskTCB存储区和usStackDepth堆栈存储区
//FreeRTOS提供3中动态内存分配机制,具体可参见《浅析FreeRTOS_v4.5.0内存分配与回收及其改进方案》
//文章地址:http://blog.chinaunix.net/u1/38994/showart_392500.html pxNewTCB
= prvAllocateTCBAndStack
( usStackDepth
)
;
if
( pxNewTCB
!
=
NULL
)
{ portSTACK_TYPE
*pxTopOfStack
;
//对task的
//pxTCB->pcTaskName
//pxTCB->uxBasePriority
//pxTCB->xGenericListItem
//pxTCB->xEventListItem进行初始化,
//将xEventListItem->xItemValue值置为configMAX_PRIORITIES - ( portTickType ) uxPriority
//所以xEventListItem->xItemValue的最小值为1.(注:非0[gliethttp]) prvInitialiseTCBVariables
( pxNewTCB
, pcName
, uxPriority
)
;
#
if portSTACK_GROWTH
< 0
{
//堆栈是向下生长的,at91sam7s64就是以这种方式来生长堆栈 pxTopOfStack
= pxNewTCB
-
>pxStack
+
( usStackDepth
- 1
)
;
}
#
else
{ pxTopOfStack
= pxNewTCB
-
>pxStack
;
}
#
endif
//初始化该task对应的堆栈空间
//具体可参见《浅析FreeRTOS_v4.5.0的任务切换原理和栈结构》
//文章地址:http://blog.chinaunix.net/u1/38994/showart_391270.html
//需要注意的是pvTaskCode应该+4,即lr-4,这样来模拟IRQ,
//pxNewTCB->pxTopOfStack存放了当前task使用到的sp栈顶值 pxNewTCB
-
>pxTopOfStack
= pxPortInitialiseStack
( pxTopOfStack
, pvTaskCode
, pvParameters
)
; portENTER_CRITICAL
(
)
;
//原子操作
{ uxCurrentNumberOfTasks
+
+
;
if
( uxCurrentNumberOfTasks
=
=
(
unsigned portBASE_TYPE
) 1
)
{
//这是FreeRTOS系统创建的第1个任务,那么初始化FreeRTOS的一些基础量:
//1.pxReadyTasksLists队列链表
//2.xDelayedTaskList1队列链表
//3.xDelayedTaskList2队列链表
//4.xPendingReadyList队列链表
//5.xTasksWaitingTermination队列链表
//6.xSuspendedTaskList队列链表
//7.pxDelayedTaskList = &xDelayedTaskList1;暂时的前台时间队列链表
//8.pxOverflowDelayedTaskList = &xDelayedTaskList2;暂时的后台时间队列链表 pxCurrentTCB
= pxNewTCB
; prvInitialiseTaskLists
(
)
;
}
else
{
if
( xSchedulerRunning
=
= pdFALSE
)
{
//当前FreeRTOS还没有启动调度器,
//那么当前pxCurrentTCB需要是指向最高优先级任务
if
( pxCurrentTCB
-
>uxPriority
<
= uxPriority
)
{
//比它高,所以pxNewTCB应该做当前任务 pxCurrentTCB
= pxNewTCB
;
}
}
}
if
( pxNewTCB
-
>uxPriority
> uxTopUsedPriority
)
{ uxTopUsedPriority
= pxNewTCB
-
>uxPriority
;
//在vTaskList()中使用到了
}
#
if
( configUSE_TRACE_FACILITY
=
= 1
)
{ pxNewTCB
-
>uxTCBNumber
= uxTaskNumber
;
//存储新创建的task的id号 uxTaskNumber
+
+
;
//id号+1,以便供下一个创建的task使用
}
#
endif
//#define prvAddTaskToReadyQueue( pxTCB ) \
//{ \
// if( pxTCB->uxPriority > uxTopReadyPriority ) \
// { \
// uxTopReadyPriority = pxTCB->uxPriority; \
// } \
// vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) );\
//}
//把新创建的task添加到就绪运行队列链表中,
//本task会被插入到pxReadyTasksLists中自己优先级所对应的数组下
//这时本task对应优先级的数组可能已经有同优先级的任务在上边了,
//没关系,只需要将本task添加到轮转调度的最后位置即可,对于FreeRTOS轮转调度的理解,
//可以参见《浅析FreeRTOS_v4.5.0的任务切换原理和栈结构》
//文章地址:http://blog.chinaunix.net/u1/38994/showart_391270.html prvAddTaskToReadyQueue
( pxNewTCB
)
; xReturn
= pdPASS
;
//标示成功创建
} portEXIT_CRITICAL
(
)
;
//原子操作结束
}
else
{ xReturn
= errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY
;
}
if
( xReturn
=
= pdPASS
)
{
if
(
(
void
*
) pxCreatedTask
!
=
NULL
)
{
*pxCreatedTask
=
( xTaskHandle
) pxNewTCB
;
//把创建的TCB,传递到外界参数pxCreatedTask中
}
if
( xSchedulerRunning
!
= pdFALSE
)
{
//os已经正常启动
if
( pxCurrentTCB
-
>uxPriority
< uxPriority
)
{
//新创建的task-B的优先级比调用创建函数xTaskCreate()的task-A的优先级高
//那么task-B立即抢占task-A,取得cpu的使用权
//可以参见《浅析FreeRTOS_v4.5.0的任务切换原理和栈结构》
//文章地址:http://blog.chinaunix.net/u1/38994/showart_391270.html taskYIELD
(
)
;
}
}
}
return xReturn
;
//返回xTaskCreate()函数的执行结果
}