FreeRTOS内核全局变量

2023-05-16

想要分析FreeRTOS源码,想要理解FreeRTOS源码的整个宏观架构,有一个前提就是必须知道FreeRTOS内核中那些全局变量的意义,每个全局变量都是用来干什么的。只有了解了这些全局变量我们才能从宏观上看清FreeRTOS的真面目,学习其金华,领略其巧妙。

PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;					//指向当前运行任务的任务控制块
PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];//优先级就绪列表数组,每个优先级下都有一条列表 

pxReadyTasksLists 是一个列表类型的数组,每个元素都是一条列表,所以最大优先级不要设置的太大,越大越耗费内存。FreeRTOS 中每个优先级下都有一条就绪列表,同优先级的任务都挂到此列表上。

PRIVILEGED_DATA static List_t xDelayedTaskList1;						//延时列表1
PRIVILEGED_DATA static List_t xDelayedTaskList2;						//延时列表2
PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;				//指向延时列表的指针
PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList;		//指向延时溢出列表的指针

需要阻塞的任务都挂载到延时列表上。
FreeRTOS内核时钟节拍xTickCountTickType_t 类型的变量,xTickCount存在溢出的情况,溢出怎么办呢?用两条列表交替使用,巧妙的解决了时钟节拍溢出的问题,实现原理在下一篇文章详细解析。

PRIVILEGED_DATA static List_t xPendingReadyList;						//调度器挂起期间,就绪的任务暂时挂载到此列表上

调度器挂起期间,就绪的任务暂时挂载到此列表上。因为调度器挂起期间不允许任务切换,不允许任务切换就不能挂载到就绪列表上(如果挂载到就绪列表上会造成任务切换),所以需要暂时将就绪的任务挂载到此列表上,待任务调度器恢复以后,将此列表中的任务移到就绪列表中。

#if( INCLUDE_vTaskDelete == 1 )
	PRIVILEGED_DATA static List_t xTasksWaitingTermination;				//任务删除自己以后将自己挂在此列表上,在空闲任务中释放内存
	PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;//任务删除自己的个数
#endif
#if ( INCLUDE_vTaskSuspend == 1 )
	PRIVILEGED_DATA static List_t xSuspendedTaskList;					//任务挂起列表
#endif
PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks 	= ( UBaseType_t ) 0U;//系统中当前任务的数量
PRIVILEGED_DATA static volatile TickType_t xTickCount 				= ( TickType_t ) 0U; //时钟节拍数
PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority 		= tskIDLE_PRIORITY;  
PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning 		= pdFALSE;			 //任务调度器挂起还是运行  pdTRUE表示运行  pdFALSE表示挂起 
PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks 			= ( UBaseType_t ) 0U;//任务调度器在挂起期间时钟节拍的个数
PRIVILEGED_DATA static volatile BaseType_t xYieldPending 			= pdFALSE;			 //是否需要进行一次任务切换标志位
PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows 			= ( BaseType_t ) 0;	 //记录时钟节拍计数器溢出了多少次
PRIVILEGED_DATA static UBaseType_t uxTaskNumber 					= ( UBaseType_t ) 0U;
PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime		= ( TickType_t ) 0U; //保存距离最近一个解锁任务的解锁时间
PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle					= NULL;				 //空闲任务句柄

PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY; 特别说明一下uxTopReadyPriority
CPU在查找最高优先级时有两种方法,一种是硬件方法,一种是软件方法。
硬件方法:依赖CPU,CPU必须支持CLZ指令。uxTopReadyPriority的每个bit都代表一个优先级,如果某个bit为1表示对应优先级下有就绪任务。
软件方法:不依赖CPU,任何CPU都可以使用。uxTopReadyPriority代表的是就绪任务中的最高优先级。

既然说到最高优先级查找的问题了,我们干脆详细的剖析一下吧。
我们都知道任务的切换是在PendSV中进行的,PendSV中断服务函数中调用了vTaskSwitchContextvTaskSwitchContext又调用了taskSELECT_HIGHEST_PRIORITY_TASKtaskSELECT_HIGHEST_PRIORITY_TASK的作用是找到就绪任务中优先级最高的任务,让pxCurrentTCB指向该任务的任务控制块。

硬件方法:
taskSELECT_HIGHEST_PRIORITY_TASK是一个宏,源码如下

#define taskSELECT_HIGHEST_PRIORITY_TASK()														\
{																								\
UBaseType_t uxTopPriority;																		\
	portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );								\
	configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 );		\
	listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );		\
} /* taskSELECT_HIGHEST_PRIORITY_TASK() */

portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );的功能是从uxTopReadyPriority中找到最高优先级,将优先级赋值给uxTopPriority
实现方法如下:

#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __clz( ( uxReadyPriorities ) ) )

举个例子:现在只有优先级2和优先级5下有任务就绪,那么变量uxTopReadyPriority的二进制是这样的
uxTopReadyPriority = 00000000 00000000 00000000 00100100
CLZ指令是计算前导0指令。返回第一个1前边有多少个0 。
__clz( ( uxReadyPriorities ) ) 的结果就是26, 31 - 26 = 5。uxTopPriority 就是5了。这样就算出了最高优先级是5。

再来看listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );的作用是从就绪列表中找到最高优先级任务的TCB,将其赋值给pxCurrentTCB
实现方法如下:

#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )										\
{																							\
List_t * const pxConstList = ( pxList );													\
	/* Increment the index to the next item and return the item, ensuring */				\
	/* we don't return the marker used at the end of the list.  */							\
	/*列表指针向后遍历一个节点 */																								\
	( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;							\
	/*如果列表指针指向了列表的迷你列表项,就再向后遍历一个节点  (别忘记列表是双向环形的)*/\
	if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) )	\
	{																						\
		( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;						\
	}																						\
	/*pvOwner成员中保存的是TCB的地址*/			\
	( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;											\
}

到此硬件实现方法讲完了,可能有的大兄弟有个疑问uxTopReadyPriority 变量是如何维护的。
如果有任务就绪调用的是下面这个宏来 置位优先级bit

#define taskRECORD_READY_PRIORITY( uxPriority )	portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )

如果某个优先级下没有就绪任务调用的是下面这个宏复位优先级bit

#define taskRESET_READY_PRIORITY( uxPriority )														\
{																									\
	if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 )	\
	{																								\
		portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) );							\
	}																								\
}

对应优先级的就绪列表中没有就绪任务就复位优先级,宏portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); 的内部实现如下:

#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )

最后:FreeRTOS是一个很优秀的RTOS,源码中有很多写法很巧妙,值得我们去学习。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS内核全局变量 的相关文章

  • Ubuntu下Jlink驱动安装使用

    Ubuntu下Jlink驱动安装使用 1 Jlink驱动下载安装2 Jlink驱动配置 想自己开发Nuttx系统 xff0c 很重要的一步就是将自己的代码下载到相应的硬件上 xff0c 对于STM家族处理器而言 xff0c 我们很多时候会使
  • PX4旋翼位置控制

    PX4旋翼位置控制 1 概括2 符号和函数说明2 1 符号说明2 2 函数说明 3 代码解析3 1 外环位置控制 positionController 3 2 内环速度控制 velocityController const float am
  • 数值分析(1)误差及误差分析

    数值分析1 误差及误差分析 第一章有效数有效数字和相对误差误差的数值运算条件数 第一章 有效数 定义 xff1a 某个数字 x x x 可以写成下面的形式
  • PX4 模块代码启动流程

    PX4模块代码启动流程 由于经常纠结程序代码启动流程 xff0c 以EKF2为例总结一下 版本 V1 9 0 源码路径 xff1a src modules ekf2 ekf2 main cpp 第一步 xff1a 启动时会进入和文件名相同的
  • PX4中的卡尔曼滤波——代码公式对照解释

    PX4中位置速度卡尔曼滤波解释 1 变量解释2 代码和公式对应2 1卡尔曼滤波公式 2 2 对应代码2 2 状态更新公式说明 3 总结 这篇博客以PX4中速度和位置估计来分析卡尔曼滤波过程 xff0c 将枯燥的公式和鲜活的代码联系起来 版本
  • PX4多传感器优先级判断

    PX4多传感器优先级判断 1 简介2 代码分析2 1 主体思路2 2 代码探究 这篇博客讨论了PX4在很多传感器下如何自动选择最优传感器 版本 xff1a v1 9 0 源码位置 xff1a src lib ecl sensors sens
  • PX4垂直起降过程研究总结

    这篇博客只要对垂直起降过程和控制逻辑进行分析 版本 xff1a V1 10 2 源码位置 xff1a src modules vtol att control vtol att control main cpp src modules vt
  • PX4 四元数旋翼姿态控制修正

    PX4 四元数旋翼姿态控制修正 1 四元数介绍2 旋翼四元数角度控制逻辑3 最终控制实现逻辑4 仿真验证 版本 xff1a V1 10 2 xff1b 源码位置 xff1a src modules ma att control ma att
  • PX4实践中遇到的问题总结(持续更新中!!!!)

    PX4实践中遇到的问题总结 xff08 持续更新中 xff01 xff01 xff09 1 解锁的时候各种传感器报错2 舵机莫名抖动3 起落架没法转向4 遥控器无法校准5 遥控器校准好之后操纵出现问题 1 解锁的时候各种传感器报错 如果是处
  • PX4 添加自定义参数

    PX4 添加自定义参数 PX4添加参数1 以添加参数 VT TILT MC 2 为例2 验证 PX4添加参数 1 以添加参数 VT TILT MC 2 为例 tiltrotor cpp 在构造函数里面初始化参数映射 params handl
  • Ubuntu系统中文乱码的解决办法

    Ubuntu系统中文乱码的解决办法 文章目录 Ubuntu系统中文乱码的解决办法1 安装中文语言2 安装语言设置的命令locale3 安装中文的相关字体4 修改语言的环境变量4 1 环境变量一4 2 设置二 5 正式配置语言后记 最近在do
  • Laf Assistant:云开发从未如此爽快!

    原文链接 xff1a https forum laf run d 67 工欲善其事 xff0c 必先利其器 在编写代码时 xff0c IDE 也是我们不可或缺的 它可以让我们更高效地完成代码编写 xff0c 提高开发效率 因此 xff0c
  • PX4垂起(Tiltrotor)偏航控制研究

    PX4垂起 xff08 Tiltrotor xff09 偏航控制研究 PX4垂起 xff08 Tiltrotor xff09 偏航控制研究1 问题描述2 过渡过程中为什么没有偏航角度控制问题1 xff1a 为什么在过渡阶段固定翼位置控制没有
  • PX4卡尔曼滤波分析

    PX4卡尔曼滤波分析 本文主要介绍了PX4中EKF相关的代码
  • 飞行器参数辨识-极大似然估计

    飞行器参数辨识 极大似然估计 1 理论1 1 极大似然估计一般理论1 2 极大似然估计应用在飞行器参数估计1 3 拟线性化求解带估计参数 2 程序实现2 1 飞行器运动的状态方程 1 理论 1 1 极大似然估计一般理论 n n n 个随机观
  • 使用opencv进行车牌提取及识别

    https blog csdn net u011808673 article details 78510692
  • ​天天干着打杂的活,你做好突破自我的觉悟了吗?

    天天干着打杂的活 xff0c 你做好突破自我的觉悟了吗 xff1f 本文为草核儿创作 xff0c 经授权在本公众号原创首发 关于作者 xff1a 草核儿 xff0c 互联网行业沉思者 xff01 希望传播的是正能量 xff0c 但偶尔会被误
  • 数据仓库系列:如何优雅地规划数仓体系

    0x00 前言 数仓规划是数仓建设的蓝图 xff0c 涵盖从需求分析开始到最终的数仓评估验收整个环境 xff1b 数仓规划之所以重要 xff0c 是因为它是描述了数据流动的概念性框架 xff0c 为元数据管理奠定了基础 xff0c 对数据加
  • 【实践案例分享】有赞数据仓库实践之路

    作者 xff1a 叶瑞典 团队 xff1a 数据中台 一 大数据环境下的有赞数仓 关于数据仓库 xff0c 在维基百科中将它定义为用于报表和数据分析的系统 xff0c 是商务智能 Business Intelligence 的核心部分 在数
  • 3分钟看懂用户标签体系怎么做

    随着越来越多的企业开始追求对用户的精细化运营 用各种手段延长用户的生命周期 xff0c 促进用户的活跃与转化 xff0c 并尽一切可能产生商业价值 xff0c 已经是运营的核心 而要做好精准化运营的第一步 xff0c 便是更好的认识我们的用

随机推荐

  • 数据运营系列(三):熵权法如何确定指标权重构建评价体系

    1 熵权法 信息论基本原理解释信息是系统有序性的度量单位 xff0c 而熵可以度量系统的无序程度 xff1b 如果某个指标的信息熵越小 xff0c 该指标提供的信息量越大 xff0c 指标变异程度 方差 高 xff0c 因此在综合评价中所起
  • 漫谈数据团队协作之各岗位间的相互尊重

    最近和几位资深的团队管理者聊团队协作 xff0c 受益匪浅 xff0c 其中有一个观点令居士印象深刻 xff1a 想让团队成员之间能够默契地协作 xff0c 有非常多的方法 xff0c 但是 xff0c 有一个很重要且很基本的要求是 xff
  • 【Proteus仿真】【STM32单片机】智能窗帘控制系统设计

    文章目录 一 功能简介二 软件设计三 实验现象联系作者 一 功能简介 本项目使用Proteus8仿真STM32单片机控制器 xff0c 使用LCD1602显示模块 按键模块 HC05蓝牙 DHT11温湿度 PCF8591 ADC模块 光线传
  • 直播PPT分享-如何体现数据同学的业务敏感度

    今天即兴给大家直播分享了一次 xff0c 反馈还比较不错 xff0c 不少童鞋私信我要ppt xff0c 这里就统一发出来给大家参考了 xff0c 其实内容很少 xff0c 6句话搞定 以后 xff0c 居士会不定期地直播分享 xff0c
  • 无题

    今天在思考一个问题 xff0c 关于互联网行业的 xff0c 其他行业还不太清楚不敢妄加评论 互联网行业在当前社会中其实面临着很多社会问题需要解决和探索 xff0c 比如职业发展的不确定性 35岁的职业危机 职业社交关系的难处理 xff0c
  • Markdown学习笔记:如何画流程图

    如何使用markdown画流程图 话说网上关于使用markdown画流程图的相关的教程真是一堆堆的坑 xff0c 我丝毫不怀疑这些博文作者确实是知道如何使用markdown画流程图了 xff0c 但是写出来的文章却丝毫没有明白具体的使用方法
  • Gradle打jar包,包含所有依赖

    前言 最近被gradle折腾的欲仙欲死 gradle想把所有依赖打进jar包主要有两种方式 xff1a 一种是重写jar动作 xff0c 一种是用第三方插件 为了装x xff0c 我一直都是用的第一种方式 xff0c 结果出了问题解决不了
  • Spring Data Rest如何暴露ID字段

    前言 为了懒省事 xff0c 使用Spring Data Rest来直接提供rest接口 xff0c 重点遇到点小坑 xff0c 记录一下 记录 问题 entity xff1a span class hljs annotation 64 E
  • hadoop清空回收站

    直接删除目录 xff08 不放入回收站 xff09 hdfs dfs span class hljs attribute rm span span class hljs attribute skipTrash span path span
  • 漫谈数据仓库之拉链表(原理、设计以及在Hive中的实现)

    0x00 前言 本文将会谈一谈在数据仓库中拉链表相关的内容 xff0c 包括它的原理 设计 以及在我们大数据场景下的实现方式 最新文章已经迁入公众 xff1a 木东居士 全文由下面几个部分组成 xff1a 先分享一下拉链表的用途 什么是拉链
  • 《数据仓库实践》

    序言 2017 年初 xff0c 我开始在简书上写关于数据仓库的系列博客 xff0c 博客主题围绕大数据场景下数据仓库的理论和实践来展开 xff0c 截止现在已有十篇左右 最初写作的时候主要是抱着学习和总结的态度 xff0c 导致很多地方略
  • 一种计算用户留存的方法

    0x00 概述 用户留存分析是互联网时代常用的一种数据分析方法 而很多快速发展的公司并没有相应的方法论沉淀 xff0c 这就导致了在计算用户留存的时候会出现下面的一些问题 xff1a 1 xff09 用户留存的定义不明确 xff0c 不同的
  • MAVLink--结构

    MAVLink源文件结构 MAVLink是为微型飞行器MAV xff08 Micro Air Vehicle xff09 设计的 xff08 LGPL xff09 开源的通讯协议 是无人飞行器和地面站 xff08 Ground Contro
  • 关于函数strtok和strtok_r的使用要点和实现原理(二)

    xff08 一 xff09 中已经介绍了使用strtok函数的一些注意事项 xff0c 本篇将介绍strtok的一个应用并引出strtok r函数 1 一个应用实例 网络上一个比较经典的例子是将字符串切分 xff0c 存入结构体中 如 xf
  • TX2 ubuntu CPU占用率、占用物理内存、占用虚拟内存、进程ID、系统温度

    文件解释 在实际工作中有时需要程序打印出某个进程的内存占用情况以作参考 下面介绍一种通过Linux下的伪文件系统 proc计算某进程内存占用的程序实现方法 首先 为什么会有所谓的 伪文件 呢 Linux系统的文件类型大致可分为三类 普通文件
  • 【Fast RTPS】入门--------Ubuntu系统下

    RTPS协议的简单介绍 在RTPS的顶层 xff0c Domain域定义了不同的通信层 几个域可以同时独立地共存 域包含任意数量的参与者Participants xff0c 即发送和接收数据的元素 参与者使用端Endpoints xff1a
  • Linux 内核配置选项(转)

    Linux 内核配置选项 from http www mitbbs com mitbbs article t php board 61 Linux amp gid 61 10715608 amp ftype 61 0 第一部分 01 Cod
  • Cortex-M3双堆栈MSP和PSP

    什么是栈 xff1f 在谈M3堆栈之前我们先回忆一下数据结构中的栈 栈是一种先进后出的数据结构 类似于枪支的弹夹 xff0c 先放入的子弹最后打出 xff0c 后放入的子弹先打出 M3内核的堆栈也不例外 xff0c 也是先进后出的 栈的作用
  • 烧毁DC/DC电路问题

    使用芯龙半导体的XL7005A DC DC芯片 已经很多年了 xff0c 用的也很稳定 这次在做一个设备的时候 xff0c 系统上电就会烧DC DC芯片以及系统电路中的LDO和MCU等 试了很多次终于发现规律了 xff0c DC DC电路就
  • FreeRTOS内核全局变量

    想要分析FreeRTOS源码 xff0c 想要理解FreeRTOS源码的整个宏观架构 xff0c 有一个前提就是必须知道FreeRTOS内核中那些全局变量的意义 xff0c 每个全局变量都是用来干什么的 只有了解了这些全局变量我们才能从宏观