本帖最后由 奔波儿熊 于 2019-6-28 11:22 编辑
1.FreeRTOS有三个任务创建函数和一个任务删除函数: 函数 | 说明 | xTaskCreate() | 使用动态内存分配创建一个任务. | xTaskCreateStatic() | 使用静态内存分配创建一个任务. | xTaskCreateRestricted() | 使用动态内存分配创建一个受MPU保护的任务. | vTaskDelete() | 删除一个任务. |
2.这里只着重介绍一下经常使用的xTaskCreate()函数.
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 );
|
共2人点赞
|