前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >FreeRTOS静态和动态创建任务

FreeRTOS静态和动态创建任务

作者头像
心跳包
发布2020-08-31 11:06:33
1.4K0
发布2020-08-31 11:06:33
举报
文章被收录于专栏:嵌入式智能硬件

静态创建任务 源代码 xTaskCreateStatic 静态的方式创建任务,需要用户先申请任务控制模块和任务栈需要的内存(一般使用静态内存),然后把内存地址传递给函数,函数负责其他初始化。 函数按顺序完成: * 根据用户传递内存,初始化任务 TCB * 初始化任务堆栈 * 将新建任务加入到就绪链表中 * 如果调度器运行,新任务优先级更高,触发系统切换

代码语言:javascript
复制
TaskHandle_t xTaskCreateStatic( 
     TaskFunction_t pxTaskCode,
     const char * const pcName,
     const uint32_t ulStackDepth,
     void * const pvParameters,
     UBaseType_t uxPriority,
     StackType_t * const puxStackBuffer,
     StaticTask_t * const pxTaskBuffer )
 {
     TCB_t *pxNewTCB;
     TaskHandle_t xReturn;
     configASSERT( puxStackBuffer != NULL );
     configASSERT( pxTaskBuffer != NULL );
    if ((pxTaskBuffer != NULL) && (puxStackBuffer != NULL)) 
     {
         // 设置用户传递进来的任务控制块和栈的内存地址到对应指针变量
         pxNewTCB = (TCB_t *)pxTaskBuffer; 
         pxNewTCB->pxStack = (StackType_t *)puxStackBuffer;
        #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
         {
             // 标识这个任务控制块和栈内存时静态的
             // 删除任务的时候, 系统不会做内存回收处理
             pxNewTCB->ucStaticallyAllocated = 
                 tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
         }
         #endif
         // 初始化任务控制块 下文介绍
         prvInitialiseNewTask( pxTaskCode, pcName,
             ulStackDepth, pvParameters, uxPriority, 
             &xReturn, pxNewTCB, NULL );
        // 把新任务插入就绪链表 下文介绍
         prvAddNewTaskToReadyList( pxNewTCB );
     }
     else 
     {
         xReturn = NULL;
     }
     return xReturn;
 }

动态创建任务 源代码 xTaskCreate 动态创建任务, 调用函数内部向系统申请创建新任务所需的内存,包括任务控制块和栈。 所以调用这个函数,在内存堆空间不足或者碎片话的情况下,可能创建新任务失败,需要判断函数执行后是否成功返回。 其源码解析如下所示。

代码语言:javascript
复制
BaseType_t xTaskCreate( 
     TaskFunction_t pxTaskCode,
     const char * const pcName,
     const uint16_t usStackDepth,
     void * const pvParameters,
     UBaseType_t uxPriority,
     TaskHandle_t * const pxCreatedTask )    
 {
     TCB_t *pxNewTCB;
     BaseType_t xReturn;
    // 如果是向下增长的栈, 先申请栈内存再申请任务控制块内存
     // 可以避免栈溢出覆盖了自己任务控制块
     // 对应向上增长的则相反
    // 在旧版本 V8.0.0 中没有这么处理,统一先 TCB 后 Stack
     // 项目上碰到平台栈向下增长, 栈溢出错时候覆盖了自己的 TCB 
     // 导致调试的时候无法获取出错任务信息(比如任务名)
     #if( portSTACK_GROWTH > 0 )
     {
         // 申请任务控制块内存
         pxNewTCB = (TCB_t *)pvPortMalloc(sizeof(TCB_t));
         if( pxNewTCB != NULL )
         {
             // 申请栈内存, 返回地址设置任务中的栈指针
             pxNewTCB->pxStack = (StackType_t *)pvPortMalloc(
                 (((size_t)usStackDepth) * sizeof(StackType_t)));
            if( pxNewTCB->pxStack == NULL )
             {
                 // 栈内存申请失败, 释放前面申请的任务控制块内存
                 vPortFree( pxNewTCB );
                 pxNewTCB = NULL;
             }
         }
     }
     #else /*栈向下增长*/
     {
         StackType_t *pxStack;
         pxStack = (StackType_t *)pvPortMalloc(
             (((size_t)usStackDepth) * sizeof(StackType_t)));
        if( pxStack != NULL )
         {
             pxNewTCB = (TCB_t *)pvPortMalloc(sizeof(TCB_t));
             if( pxNewTCB != NULL )
             {
                 pxNewTCB->pxStack = pxStack;
             }
             else
             {
                 vPortFree( pxStack );
             }
         }
         else
         {
             pxNewTCB = NULL;
         }
     }
     #endif

     if( pxNewTCB != NULL )
     {
         // 成功申请所需内存 执行任务初始化操作
        #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
         {
             // 标志任务控制块和栈是动态申请
             // 删除任务系统会自动回收内存
             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;
 }
 
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/10/14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档