当前位置: 首页 > news >正文

freertos 源码分析四 任务创建的简单分析

任务创建xTaskCreate
为TCB和TCB栈分配空间, 初始化,加入就绪任务链表

#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,const char * const pcName,const configSTACK_DEPTH_TYPE usStackDepth,void * const pvParameters,UBaseType_t uxPriority,TaskHandle_t * const pxCreatedTask ){    TCB_t * pxNewTCB;BaseType_t xReturn;#if ( portSTACK_GROWTH > 0 ){pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); if( pxNewTCB != NULL ){memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) ); pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); if( pxNewTCB->pxStack == NULL ){vPortFree( pxNewTCB );pxNewTCB = NULL;}}}#else{StackType_t * pxStack;pxStack = pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) );if( pxStack != NULL ){pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );                                                                            if( pxNewTCB != NULL ){memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );pxNewTCB->pxStack = pxStack;}else{vPortFreeStack( pxStack );}}else{pxNewTCB = NULL;}}#endifif( pxNewTCB != NULL ){#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ){pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;}#endifprvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );prvAddNewTaskToReadyList( pxNewTCB );xReturn = pdPASS;}else{xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;}return xReturn;}
#endif

TCB初始化
设置栈顶栈底,任务名,优先级,初始化及填充状态消息表项。

static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,const char * const pcName,const uint32_t ulStackDepth,                                                                                     void * const pvParameters,UBaseType_t uxPriority,TaskHandle_t * const pxCreatedTask,TCB_t * pxNewTCB,const MemoryRegion_t * const xRegions )
{StackType_t * pxTopOfStack;UBaseType_t x;#if ( portSTACK_GROWTH < 0 ){pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] );pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );                                                                                                                                                 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );#if ( configRECORD_STACK_HIGH_ADDRESS == 1 ){pxNewTCB->pxEndOfStack = pxTopOfStack;}#endif}#else{pxTopOfStack = pxNewTCB->pxStack;configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );}#endifif( pcName != NULL ){for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ){pxNewTCB->pcTaskName[ x ] = pcName[ x ];if( pcName[ x ] == ( char ) 0x00 ){break;}}pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';}configASSERT( uxPriority < configMAX_PRIORITIES );if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )                                                                                       {uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;}pxNewTCB->uxPriority = uxPriority;#if ( configUSE_MUTEXES == 1 ){pxNewTCB->uxBasePriority = uxPriority;}#endifvListInitialiseItem( &( pxNewTCB->xStateListItem ) );vListInitialiseItem( &( pxNewTCB->xEventListItem ) );listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority );listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );if( pxCreatedTask != NULL ){*pxCreatedTask = ( TaskHandle_t ) pxNewTCB;}}

加入就绪态链表 禁中断 任务数加一,设为当前,开中断

static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )                                                                                           
{taskENTER_CRITICAL();  {uxCurrentNumberOfTasks++;if( pxCurrentTCB == NULL ){pxCurrentTCB = pxNewTCB;if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ){prvInitialiseTaskLists();}}else{if( xSchedulerRunning == pdFALSE ){if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority ){pxCurrentTCB = pxNewTCB;}}}uxTaskNumber++;prvAddTaskToReadyList( pxNewTCB );}taskEXIT_CRITICAL();if( xSchedulerRunning != pdFALSE ){if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority ){taskYIELD_IF_USING_PREEMPTION();}}
}

若是uxCurrentNumberOfTasks 为1,即第一个任务,初始化各链表

static void prvInitialiseTaskLists( void )
{UBaseType_t uxPriority;for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ ){vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );}vListInitialise( &xDelayedTaskList1 );vListInitialise( &xDelayedTaskList2 );vListInitialise( &xPendingReadyList );#if ( INCLUDE_vTaskDelete == 1 ){vListInitialise( &xTasksWaitingTermination );}#endif#if ( INCLUDE_vTaskSuspend == 1 ){vListInitialise( &xSuspendedTaskList );}#endifpxDelayedTaskList = &xDelayedTaskList1;pxOverflowDelayedTaskList = &xDelayedTaskList2;
}  

prvAddTaskToReadyList宏定义

#define prvAddTaskToReadyList( pxTCB )                                                                 \traceMOVED_TASK_TO_READY_STATE( pxTCB );                                                           \taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );                                                \listINSERT_END( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )

记录最高优先级

#define taskRECORD_READY_PRIORITY( uxPriority ) \
{                                               \if( ( uxPriority ) > uxTopReadyPriority )   \{                                           \uxTopReadyPriority = ( uxPriority );    \}                                           \
}

listINSERT_END 加入链表

taskYIELD_IF_USING_PREEMPTION 定义 
#if ( configUSE_PREEMPTION == 0 )#define taskYIELD_IF_USING_PREEMPTION()
#else#define taskYIELD_IF_USING_PREEMPTION()    portYIELD_WITHIN_API()                                                                              
#endif#ifndef portYIELD_WITHIN_API#define portYIELD_WITHIN_API    portYIELD                                                                                                      
#endif
stm32对应portYIELD 定义 适配不同定义不同
#define portYIELD()||   |   |   |   __asm volatile ( "SWI 0" )
http://www.lryc.cn/news/295278.html

相关文章:

  • 二叉树的锯齿形遍历,力扣
  • 避免Arrays.asList陷阱:优雅处理结构性修改的方法
  • 微信小程序(三十六)事件传参
  • 编译原理与技术(三)——语法分析(二)自顶向下-递归下降
  • okhttp 的 拦截器
  • Android:多线程下载网络图片
  • 跟着GPT学设计模式之原型模式
  • 博客|基于Springboot的个人博客系统设计与实现(源码+数据库+文档)
  • 【gcc】webrtc发送侧计算 丢包率
  • elementui上传文件不允许重名
  • 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Video媒体组件
  • Linux操作系统运维-Docker的基础知识梳理总结
  • PMP考试成绩如何查询?
  • 【Scala】 2. 函数
  • 14.0 Zookeeper环球锁实现原理
  • 课时16:本地变量_普通变量
  • 阿里云服务器centos_7_9_x64位,3台,搭建k8s集群
  • 代码随想录第二十八天
  • 【python】绘制爱心图案
  • 在 Elastic Agent 中为 Logstash 输出配置 SSL/TLS
  • Vue中对虚拟DOM的理解
  • golang通用后台管理项目——Go+Vue通用后台管理项目实战
  • 推动海外云手机发展的几个因素
  • python coding with ChatGPT 打卡第17天| 二叉树:找树左下角的值、路径总和
  • 2020年通信工程师初级 综合能力 真题
  • 12.0 Zookeeper 数据同步流程
  • 作业2.6
  • Qt应用软件【协议篇】TCP示例
  • C# CAD交互界面-自定义面板集(四)
  • 物流自动化移动机器人|HEGERLS三维智能四向穿梭车助力优化企业供应链