STM32CubeMX学习笔记30---FreeRTOS内存管理

news2025/1/12 13:32:01

一、简介

1 基本概念

        FreeRTOS 操作系统将内核与内存管理分开实现,操作系统内核仅规定了必要的内存管理函数原型,而不关心这些内存管理函数是如何实现的,所以在 FreeRTOS 中提供了多种内存分配算法(分配策略),但是上层接口(API)却是统一的。这样做可以增加系统的灵活性:用户可以选择对自己更有利的内存管理策略,在不同的应用场合使用不同的内存分配策略。

        在嵌入式程序设计中内存分配应该是根据所设计系统的特点来决定选择使用动态内存分配还是静态内存分配算法,一些可靠性要求非常高的系统应选择使用静态的,而普通的业务系统可以使用动态来提高内存使用效率。静态可以保证设备的可靠性但是需要考虑内存上限,内存使用效率低,而动态则是相反。

        每当任务,队列或是信号量被创建时,内核需要进行动态内存分配。虽然可以调用标准的 malloc()与 free()库函数,但必须承担以下若干问题:

  1. 这两个函数在小型嵌入式系统中可能不可用,小型嵌入式设备中的 RAM 不足。
  2. 这两个函数的具体实现可能会相对较大,会占用较多宝贵的代码空间。
  3. 这两个函数通常不具备线程安全特性。
  4. 这两个函数具有不确定性。每次调用时的时间开销都可能不同。
  5. 这两个函数会产生内存碎片。
  6. 这两个函数会使得链接器配置得复杂。

FreeRTOS 对内存管理做了很多事情,FreeRTOS 的 V9.0.0 版本为我们提供了 5 种内存管理算法,分别是 heap_1.c、heap_2.c、heap_3.c、heap_4.c、heap_5.c,源文件存放于 FreeRTOS\Source\portable\MemMang 路径下,在使用的时候选择其中一个添加到我们的工程中去即可。

FreeRTOS 的内存管理模块通过对内存的申请、释放操作,来管理用户和系统对内存的使用,使内存的利用率和使用效率达到最优,同时最大限度地解决系统可能产生的内存碎片问题。

2 、内存管理方案

 2.1 heap_1.c

heap_1.c 管理方案是 FreeRTOS 提供所有内存管理方案中最简单的一个,它只能申请内存而不能进行内存释放,并且申请内存的时间是一个常量,这样子对于要求安全的嵌入式设备来说是最好的,因为不允许内存释放,就不会产生内存碎片而导致系统崩溃,但是也有缺点,那就是内存利用率不高,某段内存只能用于内存申请的地方,即使该内存只使用一次,也无法让系统回收重新利用。

实际上,大多数的嵌入式系统并不会经常动态申请与释放内存,一般都是在系统完成的时候,就一直使用下去,永不删除,所以这个内存管理方案实现简洁、安全可靠,使用的非常广泛。

内 存 分 配 时 需 要 的 总 的 堆 空 间 由 文 件 FreeRTOSConfig.h 中 的 宏 ·configTOTAL_HEAP_SIZE 配置,单位为字。通过调用函数 xPortGetFreeHeapSize() 我们可以知道还剩下多少内存没有使用,但是并不包括内存碎片。这样一来我们可以实时的调整和优化 configTOTAL_HEAP_SIZE 的大小。

heap_1.c 实现了一个非常基本的 pvPortMalloc() 版本,而且没有实现 vPortFree()。

 heap1.c 方案具有以下特点:

  • 用于从不删除任务、队列、信号量、互斥量等的应用程序(实际上大多数使用 FreeRTOS 的应用程序都符合这个条件)。
  • 函数的执行时间是确定的并且不会产生内存碎片。
2.2 heap_2.c

heap_2.c 方案与 heap_1.c 方案采用的内存管理算法不一样,它采用一种最佳匹配算法(best fit algorithm),比如我们申请 100 字节的内存,而可申请内存中有三块对应大小 200 字节, 500 字节和 1000 字节大小的内存块,按照算法的最佳匹配,这时候系统会把 200 字节大小的内存块进行分割并返回申请内存的起始地址,剩余的内存则插回链表留待下次申请。heap_2.c 方案支持释放申请的内存,但是它不能把相邻的两个小的内存块合成一个大的内存块,对于每次申请内存大小都比较固定的,这个方式是没有问题的,而对于每次申请并不是固定内存大小的则会造成内存碎片,后面要讲解的 heap_4.c 方案采用的内存管理算法能解决内存碎片的问题,可以把这些释放的相邻的小的内存块合并成一个大的内存块。

同样的,内存分配时需要的总的内存堆空间由文件 FreeRTOSConfig.h 中的宏 configTOTAL_HEAP_SIZE 配置,单位为字。通过调用函数 xPortGetFreeHeapSize() 我们可以知道还剩下多少内存没有使用,但是并不包括内存碎片,这样一来我们可以实时的调整和优化 configTOTAL_HEAP_SIZE 的大小。

heap_2.c 方案具有以下特点:

  • 可以用在那些反复的删除任务、队列、信号量、等内核对象且不担心内存碎片的应用程序。
  • 如果我们的应用程序中的队列、任务、信号量、等工作在一个不可预料的顺序,这样子也有可能会导致内存碎片。
  • 具有不确定性,但是效率比标准 C 库中的 malloc 函数高得多。
  • 不能用于那些内存分配和释放是随机大小的应用程序。
 2.3 heap_3.c

heap_3.c 方案只是简单的封装了标准 C 库中的 malloc()和 free()函数,并且能满足常用的编译器。重新封装后的 malloc()和 free()函数具有保护功能,采用的封装方式是操作内存前挂起调度器、完成后再恢复调度器。

heap_3.c 方案具有以下特点:

  • 需要链接器设置一个堆,malloc()和 free()函数由编译器提供。
  • 具有不确定性。
  • 很可能增大 RTOS 内核的代码大小。

要注意的是在 使 用 heap_3.c 方 案 时 , FreeRTOSConfig.h 文件中的configTOTAL_HEAP_SIZE 宏定义不起作用。在 STM32 系列的工程中,这个由编译器定义的堆都在启动文件里面设置,单位为字节,我们具体以 STM32F10x 系列为例

2.4 heap_4.c

heap_4.c 方案与 heap_2.c 方案一样都采用最佳匹配算法来实现动态的内存分配,但是不一样的是 heap_4.c 方案还包含了一种合并算法,能把相邻的空闲的内存块合并成一个更大的块,这样可以减少内存碎片。heap_4.c 方案特别适用于移植层中可以直接使用 pvPortMalloc()和 vPortFree()函数来分配和释放内存的代码。

内 存 分 配 时 需 要 的 总 的 堆 空 间 由 文 件 FreeRTOSConfig.h 中 的 宏 ·configTOTAL_HEAP_SIZE 配置,单位为字。通过调用函数 xPortGetFreeHeapSize() 我们可以知道还剩下多少内存没有使用,但是并不包括内存碎片。这样一来我们可以实时的调整和优化 configTOTAL_HEAP_SIZE 的大小。

heap_4.c 方案的空闲内存块也是以单链表的形式连接起来的,BlockLink_t 类型的局部静态变量 xStart 表示链表头,但 heap_4.c 内存管理方案的链表尾部则保存在内存堆空间最后位置,并使用 BlockLink_t 指针类型局部静态变量 pxEnd 指向这个区域(而 heap_2.c 内存管理方案则使用 BlockLink_t 类型的静态变量 xEnd 表示链表尾)

heap_4.c 内存管理方案的空闲块链表不是以内存块大小进行排序的,而是以内存块起始地址大小排序,内存地址小的在前,地址大的在后,因为 heap_4.c 方案还有一个内存合并算法,在释放内存的时候,假如相邻的两个空闲内存块在地址上是连续的,那么就可以合并为一个内存块,这也是为了适应合并算法而作的改变。

heap_4.c 方案具有以下特点:

  • 可用于重复删除任务、队列、信号量、互斥量等的应用程序。
  • 可用于分配和释放随机字节内存的应用程序,但并不像 heap2.c 那样产生严重的内存碎片。
  • 具有不确定性,但是效率比标准 C 库中的 malloc 函数高得多。
2.5 heap_5.c

heap_5.c 方案在实现动态内存分配时与 heap4.c 方案一样,采用最佳匹配算法和合并算法,并且允许内存堆跨越多个非连续的内存区,也就是允许在不连续的内存堆中实现内存分配,比如用户在片内 RAM 中定义一个内存堆,还可以在外部 SDRAM 再定义一个或多个内存堆,这些内存都归系统管理。

heap_5.c 方案通过调用 vPortDefineHeapRegions()函数来实现系统管理的内存初始化,在内存初始化未完成前不允许使用内存分配和释放函数。如创建 FreeRTOS 对象(任务、队列、信号量等)时会隐式的调用 pvPortMalloc()函数,因此必须注意:使用 heap_5.c 内存管理方案创建任何对象前,要先调用 vPortDefineHeapRegions()函数将内存初始化。

heap_5.c 方案具有以下特点:

  • 可用于重复删除任务、队列、信号量、互斥量等的应用程序。
  • 可用于分配和释放随机字节内存的应用程序,但并不像 heap2.c 那样产生严重的内存碎片。
  • 具有不确定性,但是效率比标准 C 库中的 malloc 函数高得多。
  • 允许内存堆跨越多个非连续的内存区,也就是允许在不连续的内存堆中实现内存分配。

二、STM32CubeMX设置

1、配置RCC、USART1、时钟72M
2、配置SYS,将Timebase Source修改为除滴答定时器外的其他定时器。
3、初始化LED的两个引脚
4、开启FreeRTOS,v1与v2版本不同,一般选用v1即可
5、创建两个线程LED1,LED2。

以上步骤可参考:STM32CubeMX学习笔记22---FreeRTOS(任务创建和删除)-CSDN博客

6、内存管理策略

在 Config parameters 的 Memory management settings 中默认内存管理策略为 heap_4

7、生成代码

三、相关API函数

1、 创建内存池:osPoolCreate

函数osPoolId osPoolCreate (const osPoolDef_t *pool_def)
参数pool_def: 引用由osThreadDef定义的任务
返回值成功返回内存池ID,失败返回0

2 、通过内存池开辟空间:osPoolAlloc

函数void *osPoolAlloc (osPoolId pool_id)
参数pool_id: 内存池ID
返回值成功返回分配的内存块地址,失败返回0

3、 通过内存池开辟空间,并初始化为0:osPoolCAlloc

函数void *osPoolCAlloc (osPoolId pool_id)
参数pool_id: 内存池ID
返回值成功返回分配的内存块地址,失败返回0

4 、释放开辟的空间:osPoolFree

函数osStatus osPoolFree (osPoolId pool_id, void *block)
参数pool_id: 内存池ID

block :要返回内存池的内存块地址
返回值错误码

四、程序编程

Memory Handler定义

/* USER CODE BEGIN PV */
osPoolId poolHandle;
/* USER CODE END PV */

Memory分配

void StartTask3(void const * argument)
{
  /* USER CODE BEGIN StartTask3 */
  /* Infinite loop */
	char i=0;
	
  osPoolDef(Memory, 10, uint8_t);	            //定义了10个大小为uint8_t的内存池
  poolHandle = osPoolCreate(osPool(Memory));	//创建内存池
  uint8_t *pBuffer = osPoolAlloc(poolHandle);   //申请1个内存地址
	*pBuffer=12;
  for(;;)
  { 
		
		printf("task3 run %d\r\n",(*pBuffer)++);
		osDelay(500);
  }
  /* USER CODE END StartTask3 */
}

下载验证:

五、参考文献

STM32CubeMX学习笔记(35)——FreeRTOS实时操作系统使用(内存管理)_freertos 内存管理切换-CSDN博客

韦东山freeRTOS系列教程之【第二章】内存管理_第二章 内存管理-CSDN博客

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

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

相关文章

亚马逊云科技产品测评:玩转云服务器(EC2)

文章目录 📑引言一、亚马逊发展历史介绍二、云服务器资源地域分布三、云服务器实例规格四、EC2计费模式五、亚马逊免费EC2领取 📑引言 亚马逊:世界上最大的云服务器提供商 亚马逊云科技 是由亚马逊公司提供的一系列云计算服务。它提供了弹性计…

AI绘画:Stable Diffusion 拒绝一眼塑料味的AI质感,超写实人物图片如何制作?简单几步教会你!

今天给大家介绍一款能够对生成的人像进行皮肤调节的 lora。 上面两幅图片的生成参数一样,尺寸也一样,但右边一幅图片相较于左面图片的画面质感,特别是人像皮肤的质感上有很大的提升,看上去更加细腻有层感。 这就是我们今天要介绍…

并行执行的概念—— 《OceanBase 并行执行》系列 一

From 产品经理: 这是一份姗姗来迟的关于OceanBase并行执行的系统化产品文档。 自2019年起,并行执行功能已被许多客户应用于多种场景之中,其重要性日益凸显。然而,遗憾的是,我们始终未能提供一份详尽的用户使用文档&…

高防护皮带机巡检机器人:适应恶劣环境的智能助手

在众多工业领域中,皮带机作为一种重要的物料输送设备,广泛应用于发电厂、煤栈等场所。然而,长期以来,皮带机的巡检工作一直依赖人工,存在着劳动强度大、检测效率低、安全性差等问题。为了解决这些痛点,皮带…

进程与线程(进程)

进程: 概念:进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位 PID:当进程被创建时,操作系统会为该进程分配一个唯一的、不重复的“身份证号” 组成: PCB(进程控制块)&#…

【SpringMVC 】什么是SpringMVC(一)?如何创建一个简单的springMvc应用?

文章目录 SpringMVC第一章1、什么是SpringMVC2、创建第一个SpringMVC的应用1-3步第4步第5步第6步7-8步3、基本语法1、进入控制器类的方式方式1:方式2:方式3:方式4:方式5:2、在控制器类中取值的方式方式1:方式2:方式3:方式4:方式5:方式6:超链接方式7:日期方式8:aja…

Unity | Shader基础知识(第十三集:编写内置着色器阶段总结和表面着色器的补充介绍)

目录 前言 一、表面着色器的补充介绍 二、案例viewDir详解 1.viewDir是什么 2.viewDir的作用 3.使用viewDir写shader 前言 注意观察的小伙伴会发现,这组教程前半部分我们在编写着色器的时候,用的是顶点着色器和片元着色器的组合。 SubShader{CGPRO…

什么是DDoS攻击?DDoS攻击的原理是什么?

一、DDoS攻击概念 DDoS攻击又叫“分布式拒绝服务”(Distributed DenialofService)攻击,它是一种通过控制大量计算机、物联网终端或网络僵尸(Zombie)来向目标网站发送大量请求,从而耗尽其服务器资源,导致正常用户无法访…

ESCI3罗德与施瓦茨ESCI3测试接收机

181/2461/8938产品概述: R&S ESCI接收机的特点包括: 出色表现 多达10个子范围的可编程扫描表自动或交互式预览和最终EMI测量的内部测试程序预扫描、数据缩减(峰列表)和最终测量的评估功能光谱分析仪快速ACP测量时域分析(记…

【计算机毕业设计】基于SpringBoot+Vue智能停车计费系统设计与实现

目录 一、项目介绍 二、项目主要技术 三、系统功能结构设计 四、系统详细功能的实现 4.1 前台功能实现 4.2 管理员模块实现 4.3 用户后台模块实现 五、实现代码 一、项目介绍 该系统采用了java技术、SpringBoot 框架,连接MySQL数据库,具有较高…

【STM32嵌入式系统设计与开发】——18StaticNixite(静态数码管应用)

这里写目录标题 STM32资料包: 百度网盘下载链接:链接:https://pan.baidu.com/s/1mWx9Asaipk-2z9HY17wYXQ?pwd8888 提取码:88881、函数编辑(1)主函数编辑(2)主函数头文件函数&#x…

Linux USB转串口设备路径的查找方法

1、USB转串口设备 USB转串口设备是在嵌入式软件开发过程中经常要使用的,常常用于对接各种各样的串口设备。如果一台linux主机上使用多个usb转串口设备时,应用程序中就需要知道自己操作的是哪个串口设备。串口设备在系统上电时,由于驱动加载的…

如何利用工具实现文件批量移动并自动编号重命名文件夹

在处理大量文件和文件夹时,我们经常需要对其进行批量移动和重命名。掌握一些实用的工具和方法,可以大大提高我们的工作效率。本文将介绍如何用云炫文件管理器实现文件批量移动并自动编号重命名文件夹。 云炫文件管理器:这是一款功能强大的文…

如何将视频转换成gif表情包?超简单的方法分享

把视频中的片段截取制作成gif动画表情包是现在网络中常见的制作图片的一种方法。Gif表情包能够调节聊天中的氛围,快速有趣的传递信息。也因为gif动图兼容性高、体积小便于分享所以在现在的网络中非常的收欢迎。接下来,小编就给大家分享一下怎么把视频转g…

8、基本数据类型转换(自动转换和强制转换)

基本类型转换 1、自动类型转换2、强制类型转换 1、自动类型转换 定义:当Java程序在进行赋值或者运算时,精度小的类型会自动转换成精度大的数据类型,这个就是自动类型转换。(自动小转大) 背多芬: 这里要明…

Windows环境下VSCode C环境配置

前言: 本文记录了自己在配置 Windows环境下 VSCode C开发环境的遇到的问题和解决方法。 参考: vscode c语言没有代码提示_clangd提示不生效-CSDN博客 VSCODE无法跳转_vscode 不能跳转-CSDN博客 vscode c/c环境配置(MinGW)调用第三官方库…

工业网关是做什么的?-天拓四方

随着信息技术的迅猛发展,物联网技术正日益融入我们生活的方方面面。而在工业领域,物联网技术的应用更是为传统制造业带来了翻天覆地的变化。其中,工业网关作为物联网的重要组成部分,正发挥着越来越重要的作用。那么,工…

纯血鸿蒙APP实战开发——短视频切换实现案例

短视频切换实现案例 介绍 短视频切换在应用开发中是一种常见场景,上下滑动可以切换视频,十分方便。本模块基于Swiper组件和Video组件实现短视频切换功能。 效果图预览 使用说明 上下滑动可以切换视频。点击屏幕暂停视频,再次点击继续播放…

excel中数据筛选技巧

1、筛选excel中破折号前后都为空的数据 在Excel中查找破折号前后为空的数据,你可以结合使用Excel的查找和筛选功能,或者利用一些公式来判断。以下是两种常用的方法: 方法一:使用筛选功能选中数据范围:首先&#xff0c…

[开发|鸿蒙] 鸿蒙OS开发环境搭建(笔记,持续更新)

搭建开发环境流程: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/installation_process-0000001071425528-V2 鸿蒙DevEco Studio 3.1.1 Release仅支持windows和mac系统 运行环境要求 为保证DevEco Studio正常运行,建议电脑配置…