当前位置: 首页 > 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" )

相关文章:

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

任务创建xTaskCreate 为TCB和TCB栈分配空间&#xff0c; 初始化&#xff0c;加入就绪任务链表 #if ( configSUPPORT_DYNAMIC_ALLOCATION 1 )BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,const char * const pcName,const configSTACK_DEPTH_TYPE usStackDepth,void *…...

二叉树的锯齿形遍历,力扣

目录 题目&#xff1a; 我们直接看题解吧&#xff1a; 快速理解解题思路小建议&#xff1a; 解题方法&#xff1a; 相似题目对比分析&#xff1a; 解题分析&#xff1a; 解题思路&#xff1a; 补充说明&#xff1a; 思路优化&#xff1a; 代码实现(层序遍历倒序)&#xff1a; 题…...

避免Arrays.asList陷阱:优雅处理结构性修改的方法

临近年终&#xff0c;项目交付排期比较紧张&#xff0c;导致很多时候&#xff0c;Code Review 往往是走马观花&#xff0c;没有严格执行。最近&#xff0c;一个实习生就产生了一个十分低级的代码BUG。笔者感觉这个问题&#xff0c;对于实习生&#xff0c;尤其是刚入职的 应届 J…...

微信小程序(三十六)事件传参

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.传参步骤 2.传参接收解构步骤 源码&#xff1a; index.wxml <button type"primary" bind:tap"onclick" mark:index"{{0}}" mark:remb"{{1}}" class"But&quo…...

编译原理与技术(三)——语法分析(二)自顶向下-递归下降

一、语法分析的两种方法 自顶向下&#xff08;Top-down&#xff09;&#xff1a; 针对输入串&#xff0c;从文法的开始符号出发&#xff0c;尝试根据产生式规则推导&#xff08;derive&#xff09;出该输入串。 从根部开始构造语法树。 自底向上&#xff08;Bottom-up&#…...

okhttp 的 拦截器

拦截器有很多作用&#xff0c;实现就是责任链模式&#xff0c;细节&#xff0c;等我有时间补上。 后面有时间更新一下。 OkHttp最核心的工作是在 getResponseWithInterceptorChain() 中进行&#xff0c;在进入这个方法分析之前&#xff0c;我们先来了 解什么是责任链模式&…...

Android:多线程下载网络图片

3.12 网络图片操作 1、通过URL请求获取网络图片 示例: 创建t_picture.xml,页面layout布局文件,一个Button按钮和一个ImageView容器显示图片。 <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.a…...

跟着GPT学设计模式之原型模式

如果对象的创建成本比较大&#xff0c;而同一个类的不同对象之间差别不大&#xff08;大部分字段都相同&#xff09;&#xff0c;在这种情况下&#xff0c;我们可以利用对已有对象&#xff08;原型&#xff09;进行复制&#xff08;或者叫拷贝&#xff09;的方式来创建新对象&a…...

博客|基于Springboot的个人博客系统设计与实现(源码+数据库+文档)

个人博客系统目录 目录 基于Springboot的个人博客系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员功能实现 &#xff08;1&#xff09;用户管理 &#xff08;2&#xff09;文章分类管理 &#xff08;3&#xff09;公告信息管理 &#xff08;4&#…...

【gcc】webrtc发送侧计算 丢包率

大神的分析 : 提到: 每当收到cc-feedback或者收到RR-report的时候就能统计出丢包率,在cc-controller中就会调用SendSideBandwidthEstimation::UpdatePacketsLost()去更新丢包率,同时进行码率预估 G:\CDN\rtcCli\m98\src\modules\congestion_controller\goog_cc\send_side_b…...

elementui上传文件不允许重名

需求&#xff1a; 用户可以多文件上传 &#xff0c;在上传到服务器之前需要检查服务器中有无重名的文件&#xff0c;如果有会返回重名文件的名称数组&#xff0c;这些文件需要一个一个的向用户确认是否要覆盖重传。确认完毕后再上传到服务器。 检查文件重名&#xff1a; //上传…...

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Video媒体组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Video媒体组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Video媒体组件 用于播放视频文件并控制其播放状态的组件。 子组件 无 接口…...

Linux操作系统运维-Docker的基础知识梳理总结

Linux操作系统运维-Docker的基础知识梳理总结 docker用来解决不同开发人员软件调试时环境不统一的问题&#xff0c;保证了程序调试时运行环境的一致性。docker的设计理念便是一处镜像&#xff0c;处处运行&#xff0c;即通过产生用户软件&#xff0c;运行环境及其运行配置的统一…...

PMP考试成绩如何查询?

PMP考试成绩已经陆续出来了&#xff0c;出成绩时间大概一周左右&#xff0c;没收到的别着急&#xff0c;先把如何查询成绩路径弄清楚。 【如何查询成绩】 1、输入网址&#xff08;PMI官网&#xff0c;不知道网址的私戳&#xff09;&#xff0c;点击 Log In 如果忘记 PMI 的账…...

【Scala】 2. 函数

2. 函数 scala运算符、if … else …两部分和C语言类型&#xff0c;这里不再赘述&#xff0c;这里从for循环开始讲讲scala和c/c的不同之处。 2.1 for循环 scala中主要包含to和until两个关键字&#xff0c;下面分别看看两者的用法&#xff0c;看例子就行了。 (1) to的用法 …...

14.0 Zookeeper环球锁实现原理

全局锁是控制全局系统之间同步访问共享资源的一种方式。 下面介绍zookeeper如何实现全民锁&#xff0c;讲解他锁和共享锁两类全民锁。 排他锁 排他锁&#xff08;Exclusive Locks&#xff09;&#xff0c;又被称为写锁或独占锁&#xff0c;如果事务T1对数据对象O1加上排他锁…...

课时16:本地变量_普通变量

2.2.2 普通变量 学习目标 这一节&#xff0c;我们从 基础知识、简单实践、小结 三个方面来学习。 基础知识 变量分类 所谓的本地变量就是&#xff1a;在当前系统的某个环境下才能生效的变量&#xff0c;作用范围小。本地变量按照变量值的生成方式包含两种&#xff1a;普通…...

阿里云服务器centos_7_9_x64位,3台,搭建k8s集群

目录 1.环境信息 2.搭建过程 2.1 安装Docker源 2.2 安装Docker 2.3 安装kubeadm&#xff0c;kubelet和kubectl 2.4 部署Kubernetes Master(node1) 2.5 安装Pod网络插件&#xff08;CNI&#xff09; 2.6 加入Kubernetes Node 2.7 测试kubernetes集群 3.部署 Dashboard…...

代码随想录第二十八天

第七章 回溯算法part04 ​ ● 93.复原IP地址 ​ ● 78.子集 ​ ● 90.子集II 详细布置 93.复原IP地址 本期本来是很有难度的&#xff0c;不过 大家做完 分割回文串 之后&#xff0c;本题就容易很多了 题目链接/文章讲解&#xff1a;https://programmercarl.com/0093.%E5…...

【python】绘制爱心图案

以下是一个简单的Python代码示例&#xff0c;它使用turtle模块绘制一个代表爱和情人节的心形图案。 首先&#xff0c;请确保计算机上安装了Python和turtle模块。然后&#xff0c;将以下代码保存到一个.py文件中&#xff0c;运行它就可以看到爱心图案的绘制过程。 import turt…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

深入理解Optional:处理空指针异常

1. 使用Optional处理可能为空的集合 在Java开发中&#xff0c;集合判空是一个常见但容易出错的场景。传统方式虽然可行&#xff0c;但存在一些潜在问题&#xff1a; // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...

Oracle11g安装包

Oracle 11g安装包 适用于windows系统&#xff0c;64位 下载路径 oracle 11g 安装包...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...

【堆垛策略】设计方法

堆垛策略的设计是积木堆叠系统的核心&#xff0c;直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法&#xff0c;涵盖基础规则、优化算法和容错机制&#xff1a; 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则&#xff1a; 大尺寸/重量积木在下&#xf…...