打印
[PIC®/AVR®/dsPIC®产品]

(三)FreeRTOS创建和删除任务

[复制链接]
1631|28
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 奔波儿熊 于 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 );





使用特权

评论回复
沙发
捉虫天师| | 2019-6-27 23:57 | 只看该作者
点赞,多谢分享教程。

使用特权

评论回复
板凳
zljiu| | 2019-7-25 15:09 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
地板
mintspring| | 2019-7-26 00:51 | 只看该作者
终于看完了,多谢分享。

使用特权

评论回复
5
天灵灵地灵灵| | 2019-7-31 23:28 | 只看该作者
任务里面怎么使用中断呢?

使用特权

评论回复
6
wanduzi| | 2019-7-31 23:36 | 只看该作者
不太懂,单片机用RTOS的作用是什么。

使用特权

评论回复
7
598330983| | 2019-7-31 23:51 | 只看该作者
学RTOS要先学什么呢。

使用特权

评论回复
8
51xlf| | 2019-8-5 11:25 | 只看该作者
RTOS 系统的核心就是任务管理   

使用特权

评论回复
9
i1mcu| | 2019-8-5 11:25 | 只看该作者
FreeRTOS和PIC32MX的相关资料有吗     

使用特权

评论回复
10
pmp| | 2019-8-5 11:26 | 只看该作者
为什么要选用FreeRTOS?         

使用特权

评论回复
11
mmbs| | 2019-8-5 11:26 | 只看该作者
解和学习一下FREERTOS  

使用特权

评论回复
12
1988020566| | 2019-8-5 11:27 | 只看该作者
适用于微控制器的开源操作系统  

使用特权

评论回复
13
lzbf| | 2019-8-5 11:27 | 只看该作者
创建和删除任务同时吗?   

使用特权

评论回复
14
houjiakai| | 2019-8-5 11:27 | 只看该作者
freeRTOS比uCOS II优胜的地方?     

使用特权

评论回复
15
youtome| | 2019-8-5 11:28 | 只看该作者
rtos 有没有类似shell的功能  

使用特权

评论回复
16
cemaj| | 2019-8-5 11:28 | 只看该作者
能够分享一下相关的源代码吗

使用特权

评论回复
17
sanfuzi| | 2019-8-5 11:28 | 只看该作者
FreeRTOS性能还是不错的。     

使用特权

评论回复
18
sanfuzi| | 2019-8-5 11:29 | 只看该作者
FreeRTOS性能还是不错的。     

使用特权

评论回复
19
houjiakai| | 2019-8-5 11:29 | 只看该作者
移植freeRTOS到stm32开发板有教程吗

使用特权

评论回复
20
51xlf| | 2019-8-5 11:29 | 只看该作者
使用RTOS 的多任务处理功能  

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

22

主题

503

帖子

2

粉丝