跟着野火从零开始手搓FreeRTOS(6)多优先级的配置

        在 FreeRTOS 中,数字优先级越小,逻辑优先级也越小。

        之前提过,就绪列表其实就是一个数组, 里面存的是就绪任务的TCB(准确来说是 TCB 里面的 xStateListItem 节点),数组的下标对应任务的优先级,优先级越低对应的数组下标越小。空闲任务的优先级最低,对应的下标为 0 。

        任务在创建的时候,会根据任务的优先级将任务插入到就绪列表不同的位置。相同优先级的任务插入到就绪列表里面的同一条链表中,按照时间片轮转的方式交替运行。

        pxCurrenTCB 是一个全局的 TCB 指针,用于当前正在运行的 TCB 。所以想要实现优先级,只要在任务切换的时候让 pxCurrenTCB 指向最高优先级的就绪任务的 TCB 即可。

        FreeRTOS 提供了两种方法,一套是通用的,一套是根据特定的处理器优化过的。

前期变量定义

        首先需要定义空闲任务的优先级,还要定义一个表示创建任务的最高优先级的静态变量uxTopReadyPriority,默认这个变量的值为0,即空闲任务的优先级。

/* 空闲任务的优先级,task.h定义 */
#define tskIDLE_PRIORITY			       ( ( UBaseType_t ) 0U )
/* uxTopReadyPriority,定义task.c定义 */
static volatile UBaseType_t uxTopReadyPriority 		= tskIDLE_PRIORITY;

    通用方法

        寻找优先级的实现在 task.c 中实现。

        寻找最高优先级的方法通过宏configUSE_PORT_OPTIMISED_TASK_SELECTION来控制,为0是通用方法,1是优化方法。这个宏在 portmacro.h 中定义为1。 

获取最高优先级函数taskRECORD_READY_PRIORITY()

        调用taskRECORD_READY_PRIORITY()来更新uxTopReadyPriority的值,获得最高优先级。之后将通过uxTopReadyPriority的值,来确定就绪任务。

/* 查找最高优先级的就绪任务:通用方法 */                                    
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )#define taskRECORD_READY_PRIORITY( uxPriority )														\{																									\if( ( uxPriority ) > uxTopReadyPriority )														\{																								\uxTopReadyPriority = ( uxPriority );														\}																								\} #define taskSELECT_HIGHEST_PRIORITY_TASK()															\{																									\UBaseType_t uxTopPriority = uxTopReadyPriority;														\\/* 寻找包含就绪任务的最高优先级的队列 */                                                          \while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) )							\{																								\--uxTopPriority;																			\}																								\\/* 获取优先级最高的就绪任务的TCB,然后更新到pxCurrentTCB */							            \listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );			\/* 更新uxTopReadyPriority */                                                                    \uxTopReadyPriority = uxTopPriority;																\} /* taskSELECT_HIGHEST_PRIORITY_TASK */

 寻找最高优先级就绪任务taskSELECT_HIGHEST_PRIORITY_TASK()

         taskSELECT_HIGHEST_PRIORITY_TASK()实现寻找最高优先级任务的功能,将uxTopReadyPriority和pxCurrentTCB 的值更新为优先级最高的就绪任务对应的值。

        这个函数首先将上一步获取的最大优先级取出来,通过while循环判断当前优先级对应的链表里有没有任务。因为FreeRTOS的优先级越小,对应的数字越小,所以如果检测不到当前链表下的任务,那么就让优先级减一再去进行判断。循环往复,直到检测到链表中的任务为止,跳出循环。

        之后获取这个任务的TCB,更新uxTopReadyPriority和pxCurrentTCB的值,至此确定好了优先级。

优化方法

        这里还是借用野火的图和例子:

        Cortex-M内核有一个计算前导零的指令CLZ,所谓前导零就是计算一个变量从高位开始第一次出现 1 的位的前面的零的个数。 比如: 一个 32 位的变量 uxTopReadyPriority, 其位 0、位 24 和 位 25 均 置 1 , 其 余 位 为 0 。 那 么 使 用 前 导 零 指 令 __CLZ (uxTopReadyPriority)可以很快的计算出 uxTopReadyPriority 的前导零的个数为 6。

        如果 uxTopReadyPriority 的每个位号对应的是任务的优先级,任务就绪时,则将对应的位置 1,反之则清零。那么上述例子中优先级 0、优先级 24 和优先级 25 这三个任务中优先级为 25 的任务优先级最高。利用前导零计算指令可以很快计算出就绪任务中的最高优先级为:

( 31UL  -  ( uint32_t ) __clz( ( uxReadyPriorities ) ) ) = ( 31UL - ( uint32_t ) 6 ) = 25。

        概括来讲,优化方法就是用位数-1来减去前导零的个数来得到最高优先级。

        首先在portmacro.h中定义需要的两个函数并根据优先级修改相应的位。

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

优先级修改函数taskRECORD_READY_PRIORITY()与taskRESET_READY_PRIORITY()

        taskRECORD_READY_PRIORITY()可以根据传入的形参(一般就是任务的优先级)将uxTopReadyPriority的某个位置1,通过上述例子提到的方法,通过计算前导零的个数来得到最高优先级。taskRESET_READY_PRIORITY()则与之相反,它会将某个位清0。

        需要注意的是,taskRESET_READY_PRIORITY()清0前要先保证就绪列表中对应优先级下的链表中没有任务。

        之后使用taskSELECT_HIGHEST_PRIORITY_TASK()寻找最高优先级就绪任务。这个函数实现的功能和通用方法的基本一致,只不过这里是将最高优先级存到局部变量uxTopPriority中。

/* 这两个宏定义只有在选择优化方法时才用,这里定义为空 */#define taskRESET_READY_PRIORITY( uxPriority )#define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )/* 查找最高优先级的就绪任务:根据处理器架构优化后的方法 */
#else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */#define taskRECORD_READY_PRIORITY( uxPriority )	portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )/*-----------------------------------------------------------*/#define taskSELECT_HIGHEST_PRIORITY_TASK()														    \{																								    \UBaseType_t uxTopPriority;																		    \\/* 寻找最高优先级 */								                            \portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );								    \/* 获取优先级最高的就绪任务的TCB,然后更新到pxCurrentTCB */                                       \listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );		    \} /* taskSELECT_HIGHEST_PRIORITY_TASK() *//*-----------------------------------------------------------*/
#if 0#define taskRESET_READY_PRIORITY( uxPriority )														\{																									\if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 )	\{																								\portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) );							\}																								\}
#else#define taskRESET_READY_PRIORITY( uxPriority )											            \{																							        \portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) );					        \}
#endif#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2979256.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

GUI简述

GUI概述 swing概述 swing是java设计的GUI包&#xff0c;该包包括了GUI中各种组件支持 swing中的组件包括两大类&#xff0c;容器&#xff08;例如窗口&#xff0c;对话框&#xff0c;面板&#xff09;和功能组件&#xff08;如按钮&#xff0c;输入框&#xff0c;菜单等&…

【RSGIS数据资源】2018年北京森林站东灵山样地无人机遥感生态数据集

文章目录 一、数据集基本信息二、数据结构和内容三、 数据集质量控制&#xff08;一&#xff09; 产生方式&#xff08;二&#xff09; 数据源说明&#xff08;三&#xff09; 数据采集、加工处理方法 四、 数据使用 一、数据集基本信息 说明数据集基本描述信息&#xff0c;包…

Linux安装部署Tomcat

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ Linux安装部署Tomcat //将tomcat压缩包解压到对…

电脑上如何将png图片改为jpg?这几个方法一定用的上

在我们的日常工作、学习中&#xff0c;经常需要用到不同的图片格式类型&#xff0c;比如jpg、png、gif、tiff等等&#xff0c;这些图片之间有着非常大的区别&#xff0c;静态图片jpg格式&#xff0c;设计工作者常接触到的png&#xff0c;还有我们平时发的动态表情包是gif格式&a…

微服务架构中10个常用的设计模式,建议收藏!

从软件开发早期&#xff08;1960 年代&#xff09;开始&#xff0c;应对大型软件系统中的复杂性一直是一项令人生畏的任务。多年来为了应对软件系统的复杂性&#xff0c;软件工程师和架构师们做了许多尝试&#xff1a;David Parnas 的模块化和封装 &#xff08;1972&#xff09…

上门废品回收小程序,互联网回收拥有哪些特点?

随着社会的进步&#xff0c;人们的生活水平不断提高&#xff0c;产生的可回收物也在不断上升&#xff0c;每年垃圾站都能产生大量的可回收物&#xff0c;这也造成了资源的浪费。 目前&#xff0c;加快发展回收模式&#xff0c;提高我国回收效率成为了当下回收市场发展的重要方…

鬼手剪辑如何导入剪映草稿箱?含工程文件

鬼手剪辑导入剪映功能介绍 功能概述 鬼手剪辑导入剪映功能可以让您将鬼手剪辑翻译、克隆和一键解说等作品的工程文件导入到剪映草稿&#xff0c;以便通过剪映进行精细化调整。 推荐使用场景 视频二创 视频语音翻译 短剧解说等作品的微调 导出的工程文件包含以下元素 视频…

java学习笔记1

java基础入门 1 初识java 1.1 jdk安装 1.1.1 下载jdk https://www.oracle.com/java/technologies/downloads/#java8-windows1.1.2 安装jdk jdk-8u361-windows-x64.exe安装到D:\Program Files\Java\jdk1.8.0_361安装jre,修改地址到D:\Program Files\Java\jre1.8.0_361jdk安装…

供应链拉动与推动生产方式(供应链维度)

一、推式供应链与拉式供应链的定义 1、推动式供应链 推动式供应链是以制造商为核心企业&#xff0c;根据产品的生产和库存情况&#xff0c;有计划地把商品推销给客户&#xff0c;其驱动力源于供应链上游制造商的生产。在这种运作方式下&#xff0c;供应链上各节点比较松散&am…

刷课必备!用Python实现网上自动做题

前言 开学少不了老师会布置一些 软件上面的作业&#xff0c;今天教大家用python制作自动答题脚本&#xff0c;100%准确率哦喜欢的同学记得关注、收藏哦 环境使用 Python3.8Pycharm 模块使用 import requests —> 数据请求模块 pip install requestsimport parsel —>…

基于DEAP数据集的四种机器学习方法的情绪分类

在机器学习领域&#xff0c;KNN&#xff08;K-Nearest Neighbors&#xff09;、SVM&#xff08;Support Vector Machine&#xff09;、决策树&#xff08;Decision Tree&#xff09;和随机森林&#xff08;Random Forest&#xff09;是常见且广泛应用的算法。 介绍 1. KNN&am…

【YOLOv8改进[Head检测头]】YOLOv8换个RT-DETR head助力模型更优秀

一RT-DETR 官方论文地址&#xff1a;https://arxiv.org/pdf/2304.08069.pdf 因为YOLO的合理速度和准确性之间的权衡, 这一系列已成为最流行的实时目标检测框架。然而&#xff0c;观察到nms对yolo的速度和准确性产生了负面影响。最近&#xff0c;基于端到端变换器的检测器(DETR…

谁说快是转瞬即逝,PUMA说快是永恒

巴黎奥运会、欧洲杯、美洲杯......2024年可以说是名副其实的体育大年。在各种全球体育盛事营造的浓厚体育氛围当中&#xff0c;各大体育品牌纷纷开始发力。 4月10日&#xff0c;全球领先运动品牌PUMA率先发布了其为本届奥运会准备的17套奥运装配&#xff0c;包括瑞士、瑞典等国…

PMP新版考试也要复习49个过程?如何复习更高效?

PMP中有五大过程组、十大知识领域&#xff0c;共计49个子过程&#xff0c;那么如何才能快速的记住这49个子过程&#xff0c;可以参考这篇文章理解加深记忆。 记忆需要花费时间&#xff1a;30分钟 记忆持续时间&#xff1a;永久 接下来按照思路进行 场景&#xff1a;大家都熟…

炉管设备的内部构造详解

知识星球&#xff08;星球名&#xff1a;芯片制造与封测社区&#xff09;里的学员问&#xff1a;炉管设备&#xff08;立式&#xff09;的内部构造是怎样的&#xff1f; 如上图&#xff0c;是一个典型的&#xff1a; 上半部&#xff1a; Heating Element&#xff08;加热线圈…

【Python-装饰器】

Python-装饰器 ■ 简介■ 装饰器的一般写法&#xff08;闭包写法&#xff09;■ 装饰器的语法 (outer写法) ■ 简介 装饰器其实是一种闭包&#xff0c; 功能就是在不破坏目标函数原有的代码和功能的前提下为目标函数增加新功能。 ■ 装饰器的一般写法&#xff08;闭包写法&am…

JWT原理解析

一、概述 虽然现在很多的开发框架会支持JWT的使用&#xff0c;但是对JWT还是没有一个详细的了解&#xff0c;有很多疑惑&#xff1a; JWT比之前的session或者token有什么好处&#xff1f;JWT的构成元素是什么&#xff1f;JWT从生成到使用的详细流程&#xff1f; 二、 JWT 2…

机器学习基础:绪论

1. 概念 机器学习是从人工智能中产生的一个重要学科分支&#xff0c;是实现智能化的关键。 机器学习是一类算法的总称&#xff0c;这些算法企图从大量历史数据中挖掘出其中隐含的规律&#xff0c;并用于预测或者分类&#xff0c;更具体的说&#xff0c;机器学习可以看作是寻找…

南京邮电大学数学实验A 作业3 编程与作图 答案 | 《MATLAB数学实验》第三版 第二章 课后习题答案

若要获得更好的阅读体验&#xff0c;请前往 链接。 1(课本习题2) 求满足 ∑ n 0 m ln ⁡ ( 1 n ) > 100 \sum_{n 0}^{m}{\ln{(1 n)}} > 100 ∑n0m​ln(1n)>100的m最小值. 代码: slog(1);n0; while s<100nn1;sslog(1n); end fprintf("最小m值是%d"…