FreeRTOS使用 — 合理使用内存 “ 任务中创建任务 ”

news2024/11/28 6:32:35

前言

在我们学习 RTOS 的过程中,很多朋友都不会遇到内存不够的问题,因为大部分的开发板使用的芯片对学习来说,内存 “足够大” 。所以基本上很多人学会了基本功能,到了实际工作中使用,往往会遇到内存不够的问题,因为公司产品是需要控制成本的,一般来说,内存越大成本越高,工作中有时候使用的芯片内存可能会比较小,很多朋友就会遇到学习的时候遇不到的问题,一下子不知如何处理了。

本文的说明以 FreeRTOS 为例,其实在博主的 FreeRTOS 系列博文当中说得最多的就是内存问题:

【导航】FreeRTOS学习专栏目录 【快速跳转】

即便当时写 FreeRTOS 专栏的时候整个系列流程好像不是那么合理,适合有一定基础的小伙伴,但是对于内存的节约 问题上有详细的说明。

最近在一些项目的 FreeRTOS 使用上,其实博主自己也经历思考了一些问题,所以又来对 FreeRTOS 的专栏进行一些补充,那么本文就来测试一下 使用 FreeRTOS 的时候如何应用 “ 在任务中创建任务的方式 ” 合理的分配任务以节约内存 。

我是矜辰所致,全网同名,尽量用心写好每一系列文章,不浮夸,不将就,认真对待学知识的我们,矜辰所致,金石为开!

目录

  • 前言
  • 一、目的说明(为什么要在任务中创建任务)
  • 二、实验验证
    • 2.1 测试环境
    • 2.2 FreeRTOS 任务 API 复习
    • 2.3 实际操作
    • 2.4 问题测试
    • 2.5 最终测试
  • 结语

一、目的说明(为什么要在任务中创建任务)

在写文章之间,首先说明一下本文要解决的是什么问题,我们使用一个例子来说明:

你使用的 CPU 的内存只有 5K RAM 空间可以提供给你的 FreeRTOS 任务,
而你需要用到4个任务:
周期任务A:1.5K
周期任务B:1.5K
周期任务C: 1.5K
一次性任务D: 1.5K(开机后接收到某个任务通知/消息的一次性任务)

这时候,如果一开始全部任务都创建,显然不可行,那么我们可以开始只创建必要的任务,等到一次性任务完成后,然后在这个任务中创建其他的周期任务,再删除这个一次性任务即可。

说明!!! 对于本文所提出的问题,其实实际中有更多更好的解决方式,比如把一次性任务加在初始化阶段中完成,或者直接在某个周期任务循环前面(while(1) 前面)走一遍一次性的任务过程。

但是本着研究的态度,还挺想看看在 STM32CubeMX 的 FreeRTOS 环境下面,是否能够正常的使用上面这个不太聪明的方法实现效果,或许以后有用得着的地方!所以我还是计划简单的测试下。

二、实验验证

上面分析完成,我们来进行实际的使用测试,先说明下本文使用的测试环境。

2.1 测试环境

测试环境:

硬件平台: STM32L051C8T6 RAM大小: 8K
软件环境: STM32CubeMX
FreeRTOS分配空间: 3K
在这里插入图片描述

先看一下下面的图片,对应上面我们说过的最后其实我们想要长期周期运行的任务只有前面3个,最后一个是需要开机初始化时候运行一次的任务(设计的时候因为用到了 FreeRTOS 的任务通信机制,所以不太好直接在初始化还没开始调度前面进行完成)。

在这里插入图片描述

由上图可知,我们是无法直接创建全部的任务的,即便你想先创建,然后运行完了删除来节约内存,是行不通的。

先说明,上面的任务去掉 64 大小的 myTask04 是可以的,就是256 + 192 +128 的任务组合是我们最终需要保留的周期任务。

那么我们来使用上面提到的思路进行,在允许的范围内,先建立一个初始化的任务(其中 KeyTask 任务我写了一些程序,所以此次就保留在这里,这个保留这个任务不影响本次测试):

在这里插入图片描述

上面的 InitTask 就对应一次性任务 Task04,因为会删除,我们可以创建得大一点,但是也得注意大小。

在 STM32CubeMX 的设置到这里就完成了,其他的地方都需要我们在代码中直接修改。

在 KeyTask 任务中,我们还是加入了任务状态查看功能:

在这里插入图片描述

这里额外说明一下,相比我以前的系列文章,这里多加了一个剩余空间的打印:

printf("free space is %d\n",xPortGetFreeHeapSize());

刚开始,在我们的 InitTask 中,我们什么都不做,初始状态如下图:

在这里插入图片描述

在这里插入图片描述

接下来我们要考虑的就是在当前程序中,我们该如何创建新的任务,而不是依靠 STM32CubeMX 初始化创建。

2.2 FreeRTOS 任务 API 复习

我们先来复习一下 FreeRTOS 的创建任务函数原型(示例以动态创建函数来说明),如下图:

在这里插入图片描述

而在 CMSIS 接口下面通过封装后统一使用的是 osThreadCreate , 我们也来复习一下:

在这里插入图片描述
详细的任务 API 解析请参考以前的博文:FreeRTOS记录(二、FreeRTOS任务API认识和源码简析)

我们再来参考一下系统自动的任务创建操作:

在这里插入图片描述

2.3 实际操作

我们参考这种方式,手动的在 Init 任务中创建新的任务,首先手动定义任务句柄以及声明任务函数,如下图:

在这里插入图片描述

然后我们直接在 InitTask 任务中进行任务创建,当然为了更好的查看结果,我还加入了任务状态打印,如下图:

在这里插入图片描述

最后不要忘了实现一下 myTask02 任务函数:

在这里插入图片描述

测试一下看看效果:

在这里插入图片描述

上面可以看到,出问题了,并没有创建新的任务,奇了怪了!

我以为是创建函数出问题了,把下面的创建函数语句:

osThreadDef(myTask02, StartmyTask02Task, osPriorityNormal, 0, 192);
myTask02Handle = osThreadCreate(osThread(myTask02), NULL);

改成了

xTaskCreate( StartmyTask02Task, "myTask02", 192, NULL, osPriorityHigh, &myTask02Handle );

还是不行。

其中还以为是前后要加点延时,测试过也不行,难道是不能创建,没有道理啊!

于是我在原本的另外一个 KeyTask 任务中,加上了一个按键操作,按下按键新建一个 myTask02 ,语句是和在 InitTask 中语句一样的,如下图:

在这里插入图片描述

IninTask 中的代码保持不变,再次测试看看:

在这里插入图片描述

这样可以说明,在任务中创建任务是没问题的,使用的程序语句也是没有问题的,但是开始为什么会创建失败呢?

2.4 问题测试

我进行了一些测试排除了一些问题:

测试记录:
和任务优先级无关(把新创建的任务的优先级设置成比自己高,比自己低,和自己相等)
和延时无关(前后加上足够的延时)
和本任务的栈大小无关(怕自己任务栈不够,去掉了打印,还是创建失败,对比 KeyTask 的栈空间一样还是可以成功)

(中间写了一大堆,最后全部删除了,这都怪自己犯二了 !)

前面刚刚用图片说明了,任务大小 256 + 192 + 128 + 64 都已经内存不够了:

在这里插入图片描述

在上面测试中我初始的任务为 256 + 256 ,还想在没删除任务的时候创建一个大小为 192 的任务……

在这里插入图片描述

好吧! 我是傻子!

2.5 最终测试

这次冷静下来发现了这么二的问题,唉 ~

文章开头说过,我们最终需要的任务是 256 + 192 +128 的组合,然后还有一些操作需要在 InitTask 中实现的,实际上我开始把 InitTask 放成 256 当时是为了打印一些数据方便测试,脑子一下子没反应过来……

我们这里把思路理清楚,我们首先创建一个 256 的 KeyTask 和 192 的 InitTask, 然后在 192 的InitTask 中做初始化的工作,然后创建一个 128 的 myTask03 ,然后 InitTask 自己删除,删除完成以后在 myTask03 中循环前面创建一个 192 的 myTask02 ,结束(确实有点绕,但是前面说了只是为了测试)。

那么我们调整一下,IninTask 改成 192 大小,如下图:

在这里插入图片描述

然后我们 Task02 和 Task03 的定义我们这里就直接一起测试了,首先是任务2 和任务 3 句柄定义和函数声明:

在这里插入图片描述

InitTask 还是打印一下状态,新建任务3 ,这次的空间是足够的:

在这里插入图片描述

实现任务2 和任务 3 函数,在任务3 中创建任务 2 ,如下图:

在这里插入图片描述

我们直接上一下最后测试的结果:

在这里插入图片描述

整理来说最后结果是正常的!

虽然上图中有一个疑问,我加了延时测试了一下无果,暂时也不想折腾了,因为在 FreeRTOS 中使用 printf 函数打印调试是很占用任务内存大小的,尤其是在我们这种小内存的 CPU 上是很痛苦的一件事情。

最终发现 任务 3 的剩余栈基本没了,这也可能是一个问题,是因为在任务中使用任务创建的操作也会占用很大的内存吗?有必要测试一下。

因为过程都正常了,所以我也不需要 printf 操作,所以我把所有的 printf 去掉后,看看任务剩余栈的情况,这里直接上一下结果:

在这里插入图片描述

至此,本文的测试也算是圆满结束!!

结语

本来是一次简单的实验测试,但是因为自己一下子翻了糊涂,导致中途出现了莫民奇妙的问题,这种问题总是无法避免啊,但是好在最后我们成功实现了自己想要的结果,也算是实验成功了!

在文章开头我们就说过,在实际中遇到此类问题,或许会有更好的方法。但是通过本次的实验,可以让我们更好的应用操作系统的任务创建与删除操作,而不是只会在程序开始时候创建到现成的一直用到底 。

好了,本文就到这里,谢谢大家!

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

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

相关文章

pikachu靶场-10 XXE漏洞

XXE漏洞 概述 XXE -“xml external entity injection” 既"xml外部实体注入漏洞"。 概括一下就是"攻击者通过向服务器注入指定的xml实体内容,从而让服务器按照指定的配置进行执行,导致问题" 也就是说服务端接收和解析了来自用户端的xml数据,而又没有做严…

shell语法总结一(持续补充)

文章目录一、变量1、变量的命名规则2、查看变量3、删除命令4、变量的作用域4.1、局部变量4.2、全局变量4.3、环境变量5、自定义变量6、只读变量二、字符串1、单引号2、双引号(用的多)3、拼接字符串4、获取字符串的长度5、提取子字符串三、shell数组1、定…

必须掌握的数据库面试问题

一、为什么用自增列作为主键 1、如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引。 如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引。 如果也没有这样的唯一索引,则InnoDB会选择内置…

1990-2021年全国各省产业高级化 数据

1990-2021年全国各省产业高级化数据 1、来源为:统计NJ、各省NJ 2、包括:全国31个省份 3、时间:1990-2021年 4、指标包括: 各地区经纬度、第三产业增加值、第二产业增加值、高级化水平 高级化水平第三产业增加值(亿元) / 第二…

HTTP协议【报文格式】

文章目录HTTP协议什么是HTTP协议HTTP协议格式抓包工具的使用HTTP请求URLURL的组成URL encodeHTTP请求的报文格式HTTP响应的报文格式HTTP方法GET方法POST方法POST方法与GET方法的区别请求报头HTTP响应状态码状态码的组成状态码的类别HTTP协议 什么是HTTP协议 HTTP协议即Hyper T…

m基于GA遗传优化的多因素加权竞价博弈频谱分配算法matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 假设有M个用户均为MIMO Full Duplex&#xff0c;N个频率&#xff0c;1<N<M&#xff0c;设计算法实现M个用户与N个频率的匹配。 由于在一个MIMO系统中&#xff0c;用户数量M大于可用的频谱个…

web自动化测试入门篇04——selenium+python基础方法封装

&#x1f60f;作者简介&#xff1a;博主是一位测试管理者&#xff0c;同时也是一名对外企业兼职讲师。 &#x1f4e1;主页地址&#xff1a;【Austin_zhai】 &#x1f646;目的与景愿&#xff1a;旨在于能帮助更多的测试行业人员提升软硬技能&#xff0c;分享行业相关最新信息。…

记录一次解决centos不定时触发oom的经历

前言 前一段时间&#xff0c;业务部门的系统不定时的反馈&#xff0c;系统打开不了&#xff0c;提示&#xff1a; 等技术开发同学反应过来去查看业务状态时&#xff0c;服务又恢复了&#xff0c;由于不是核心的业务&#xff0c;并且出问题差不多1分钟左右&#xff0c;没太在意…

【Vue 快速入门系列】todoList案例小总结

文章目录一、案例效果二、项目介绍三、版本更新迭代末、项目素材1.css样式2.html一、案例效果 如下图所示&#xff0c;制作一个这样的记事本&#xff0c;可以使用这个记事本进行数据的存储以及管理&#xff0c;样式是天禹老师写好的我们直接使用就好了&#xff0c;主要在这个小…

[UE][UE5]零基础学习-学习记录1-UE5安装与基本使用方法

[UE5]学习1-UE5安装与基本使用方法写在前面01.作者碎碎念2.UE5安装方法01.UE5需要的电脑配置02.UE5安装方法001.Epic下载002.下载安装UE503.基本使用方法001.创建项目打开现有的项目&#xff1a;002.文件目录结构003.用户界面介绍1).3D画面视窗2).菜单栏3).内容浏览器4).属性面…

关于CM3/CM4位带操作的总结

1.位带操作定义 STM32的存储器映射中的内存区域和外设区域有一段地址空间&#xff08;都是最低1MB&#xff09;是位带区域&#xff0c;跟这个区域相对应的有一段位带别名区域&#xff0c;位带别名区的大小是位带区的32倍&#xff0c;位带别名区的每一个地址都对应位带区域的一个…

C. Hamiltonian Wall edu139 div2

Problem - C - Codeforces 题意是给你一个2*n的网格&#xff0c;让你一笔把所有的B涂满&#xff0c;并且只能涂一次&#xff0c;问你是否可行 分析&#xff1a; 其实分析的时候我想到了转移。每一次的结果是由上一次转移而来&#xff0c;所以如果前后矛盾的话&#xff0c;即…

人工智能:智能语音技术应用场景介绍

❤️作者主页&#xff1a;IT技术分享社区 ❤️作者简介&#xff1a;大家好,我是IT技术分享社区的博主&#xff0c;从事C#、Java开发九年&#xff0c;对数据库、C#、Java、前端、运维、电脑技巧等经验丰富。 ❤️个人荣誉&#xff1a; 数据库领域优质创作者&#x1f3c6;&#x…

虹科QA | SWCF2022 12月6日演讲笔记:C波段卫星与5G之间的干扰排查及解决方案

虹科2022年度SWCF卫星通信与仿真测试研讨会正在进行中。昨日精彩演讲&#xff1a;C波段卫星与5G之间的干扰排查及解决方案&#xff0c;感谢大家的观看与支持&#xff01; 昨晚的直播间收到一些粉丝的技术问题&#xff0c;虹小科汇总了热点问题并请讲师详细解答&#xff0c;在此…

目前UI设计薪资待遇怎么样?工作好找吗?

UI设计的火爆&#xff0c;导致有很多年轻人都愿意投身于这个行业。有很多年轻的朋友都在问&#xff0c;UI设计的薪资待遇怎么样&#xff1f;工作难找吗&#xff1f;本文统一解答一下。 1、UI设计的薪资水平 UI设计的薪资待遇一直很好&#xff0c;学习UI设计之前没有任何相关基础…

PMP每日一练 | 考试不迷路-12.13(包含敏捷+多选)

被延期考试的宝子 一定要坚持刷题 每日5道PMP习题助大家上岸PMP&#xff01; ​题目1-2&#xff1a; ​1.一位主要相关方要求将每日站立会议的持续时间人15分钟增加到1小时。Scrum主管应该做什么? ( ) A.接受建议并建议团队更改会议时间表 B.安排与产品负责人和团队开…

窗口销毁消息 WM_DESTROY 的正确处理方式

上次&#xff0c;我提到了可能导致正常的消息循环被破坏的怪异之处。 有一位读者 Adrian 指出&#xff0c;WM_GETMINMAXINFO 消息在顶级窗口 WM_NCCREATE 之前到达。这确实很不幸&#xff0c;但&#xff08;无论是否错误&#xff09;十多年来一直如此&#xff0c;现在修改它会…

【实时数仓】实现用户行为日志相关功能(源码)

文章目录一 准备用户行为日志-DWD层1 代码实现&#xff08;1&#xff09;识别新老访客&#xff08;2&#xff09;利用侧输出流实现数据拆分&#xff08;3&#xff09;将不同流的数据推送到下游kafka的不同Topic&#xff08;分流&#xff09;a 封装方法b 程序中调用kafka工具类获…

数据链路层

文章目录数据链路层的功能ARP协议DNS-------域名解析&#xff08;浅浅的了解一下&#xff09;在浏览器中输入URL后&#xff0c;发生的事情&#xff08;经典面试题&#xff09;ICMP协议NAT技术代理服务器网络核心知识大总结数据链路层的功能 对比理解网络层。 网络层 &#xff…

飞控学习随记

常见指令 编译Arduplane程序 cd ardupilot/ ./waf plane 进入 Tools/autotest 文件夹中&#xff0c;启动3D flightgear ./fg_quad_view.sh 进入ArduPLane文件夹中&#xff0c;启动仿真 sim_vehicle.py --map --console -L KSFO&#xff08;-L 选择起飞位置&#xff09; 解锁…