- BaseType_t xTaskCreate(
- TaskFunction_t pxTaskCode,
- const char *const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
- const configSTACK_DEPTH_TYPE usStackDepth, void *const pvParameters, UBaseType_t uxPriority,
- TaskHandle_t *const pxCreatedTask)
- {
- TCB_t * pxNewTCB;
- BaseType_t xReturn;
- /* If the stack grows down then allocate the stack then the TCB so the stack
- does not grow into the TCB. Likewise if the stack grows up then allocate
- the TCB then the stack. */
- #if (portSTACK_GROWTH > 0)
- {
- /* Allocate space for the TCB. Where the memory comes from depends on
- the implementation of the port malloc function and whether or not static
- allocation is being used. */
- pxNewTCB = (TCB_t *)pvPortMalloc(sizeof(TCB_t));
- if (pxNewTCB != NULL) {
- /* Allocate space for the stack used by the task being created.
- The base of the stack memory stored in the TCB so the task can
- be deleted later if required. */
- pxNewTCB->pxStack = (StackType_t *)pvPortMalloc((
- ((size_t)usStackDepth)
- * sizeof(StackType_t))); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
- if (pxNewTCB->pxStack == NULL) {
- /* Could not allocate the stack. Delete the allocated TCB. */
- vPortFree(pxNewTCB);
- pxNewTCB = NULL;
- }
- }
- }
- #else /* portSTACK_GROWTH */
- {
- StackType_t *pxStack;
- /* Allocate space for the stack used by the task being created. */
- pxStack = (StackType_t *)pvPortMalloc(
- (((size_t)usStackDepth)
- * sizeof(StackType_t))); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
- if (pxStack != NULL) {
- /* Allocate space for the TCB. */
- pxNewTCB = (TCB_t *)pvPortMalloc(
- sizeof(TCB_t)); /*lint !e961 MISRA exception as the casts are only redundant for some paths. */
- if (pxNewTCB != NULL) {
- /* Store the stack location in the TCB. */
- pxNewTCB->pxStack = pxStack;
- } else {
- /* The stack cannot be used as the TCB was not created. Free
- it again. */
- vPortFree(pxStack);
- }
- } else {
- pxNewTCB = NULL;
- }
- }
- #endif /* portSTACK_GROWTH */
- if (pxNewTCB != NULL) {
- #if (tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE \
- != 0) /*lint !e731 Macro has been consolidated for readability reasons. */
- {
- /* Tasks can be created statically or dynamically, so note this
- task was created dynamically in case it is later deleted. */
- pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
- }
- #endif /* configSUPPORT_STATIC_ALLOCATION */
- prvInitialiseNewTask(
- pxTaskCode, pcName, (uint32_t)usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL);
- prvAddNewTaskToReadyList(pxNewTCB);
- xReturn = pdPASS;
- } else {
- xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
- }
- return xReturn;
- }
xTaskCreate()函数的参数:
TaskFunction_t pxTaskCode: 任务函数的名字, 任务函数不能返回,要么是一个无限循环,要么在函数退出之前执行vTaskDelete( NULL );
const char *const pcName: 用于描述作用的任务名字,是一个字符串,要求可读性好,FreeRTOS不会使用这个名字, configMAX_TASK_NAME_LEN宏定义了任务名字的最大长度,包括字符串末尾的'\0'
const configSTACK_DEPTH_TYPE usStackDepth:任务堆栈深度,该值应该大于MINIMAL_STACK_SIZE,但FreeRTOS并不会检测该值是否大于MINIMAL_STACK_SIZE, MINIMAL_STACK_SIZE的值是空闲任务的堆栈深度,空闲任务理应是需要堆栈最小的任务;实际的堆栈的字节数=usStackDepth*堆栈的宽度, AVR的堆栈宽度就是1, ARM的堆栈宽度是4.
void *const pvParameters:传递给任务函数的参数
UBaseType_t uxPriority:任务的优先级,可以为0~(configMAX_PRIORITIES-1)范围内的任何一个值. 数字越小,优先级越低,0是最低优先级;数字越大,优先级越高,configMAX_PRIORITIES-1是最高优先级.空闲任务的优先级为0.
TaskHandle_t *const pxCreatedTask:任务句柄,如果不需要可以设为NULL.
3.任务创建完成后要调用vTaskStartScheduler()开始执行任务.
4.一个最简单的创建任务的例子:
- void vTaskFunction( void *pvParameters )
- {
- char *pcTaskName;
- volatile unsigned long ul;
- /* The string to print out is passed in via the parameter. Cast this to a
- character pointer. */
- pcTaskName = ( char * ) pvParameters;
- /* As per most tasks, this task is implemented in an infinite loop. */
- for( ;; )
- {
- /* Print out the name of this task. */
- vPrintString( pcTaskName );
- /* Delay for a period. */
- for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
- {
- /* This loop is just a very crude delay implementation. There is
- nothing to do in here. Later exercises will replace this crude
- loop with a proper delay/sleep function. */
- }
- }
- }
- /* Define the strings that will be passed in as the task parameters. These are
- defined const and not on the stack to ensure they remain valid when the tasks are
- executing. */
- static const char *pcTextForTask1 = “Task 1 is running\r\n”;
- static const char *pcTextForTask2 = “Task 2 is running\t\n”;
- int main( void )
- {
- /* Create one of the two tasks. */
- xTaskCreate( vTaskFunction, /* Pointer to the function that implements
- the task. */
- "Task 1", /* Text name for the task. This is to
- facilitate debugging only. */
- 1000, /* Stack depth - most small microcontrollers
- will use much less stack than this. */
- (void*)pcTextForTask1, /* Pass the text to be printed into the task
- using the task parameter. */
- 1, /* This task will run at priority 1. */
- NULL ); /* We are not using the task handle. */
- /* Create the other task in exactly the same way. Note this time that multiple
- tasks are being created from the SAME task implementation (vTaskFunction). Only
- the value passed in the parameter is different. Two instances of the same
- task are being created. */
- xTaskCreate( vTaskFunction, "Task 2", 1000, (void*)pcTextForTask2, 1, NULL );
- /* Start the scheduler so our tasks start executing. */
- vTaskStartScheduler();
- /* If all is well then main() will never reach here as the scheduler will
- now be running the tasks. If main() does reach here then it is likely that
- there was insufficient heap memory available for the idle task to be created.
- CHAPTER 5 provides more information on memory management. */
- for( ;; );
- }
以上代码中任务的执行时序:
5.任务删除函数原型如下,使用比较简单,只需要传入某个任务的句柄就可以删除该任务. 如果传入NULL的话,会删除当前正在运行的任务,一般在某个任务函数内调用vTaskDelete( NULL )用于删除某个任务自己.
- void vTaskDelete( xTaskHandle pxTaskToDelete );