当前位置:网站首页>【FreeRTOS】13 动态内存管理

【FreeRTOS】13 动态内存管理

2022-08-10 15:36:00 xiaobaibai_2021

本节我们来学习FreeRTOS的动态内存管理功能。

在FreeRTOS中,动态内存管理是非常重要的功能,之前讲过的任务创建、信号量创建、消息队列的创建等等,都有动态创建和静态创建两种方式。静态创建时,需要用户先定义一块内存区;而动态创建时,不需要指定内存区,系统会自动在堆(heap)中申请一块内存区;这里动态创建时,就用到了动态内存管理的功能;此外,用户的应用程序也可以动态申请内存区使用。

1)FreeRTOS动态内存管理

说到动态内存管理,我们最容易想到的就是C语言中的动态内存分配函数malloc(),这个函数可以申请一块指定大小的内存区,以指针形式返回内存的地址。用户可以使用这片内存,用完之后要用free()函数来释放,否则会造成内存泄漏。

在嵌入式系统中,为了提高代码的运行效率,一般不使用标准C的malloc和free函数,通常会用相对简单的方法去实现内存的分配,再封装成与malloc和free相同的函数接口。

FreeRTOS中,申请内存的函数原型如下:

void *pvPortMalloc( size_t xWantedSize );//参数为需申请的字节数,返回地址指针;

释放内存的函数原型如下:

void vPortFree( void *pv ); //参数为指向内存的指针;

虽然FreeRTOS提供了统一的函数接口对应于标准C语言中的malloc和free,但是它们内部的具体实现却有多种方式。FreeRTOS实际上有5种实现动态内存分配的方式,可以由用户选择使用哪一种。下面分别来介绍它们的异同。

Heap_1方式:

它是5种方法中最简单的,运行效率最高;只支持申请内存,不允许释放;具有时间确定性,不会产生内存碎片;虽然它不支持释放,但是在嵌入式系统下编程一般情况下也够用,因为无论是任务创建、信号量创建等等,在创建之后一般很少需要删除,也就不用释放内存了。

Heap_2方式:

支持内存申请、内存释放;但不支持内存碎片整理(也就是释放后的空闲小内存块不会被合并成大内存块)。

Heap_2方式比较适用于动态分配的内存块大小都是一样的情况,比如每次创建队列时,长度一样,这样不会产生内存碎片。使用时先用pvPortMalloc函数申请内存,得到内存块指针后,再用静态方式创建资源,使用完之后用vPortFree函数释放内存。

Heap_3方式:

对编译器提供的malloc和free进行了封装,需要编译器提供malloc和free的实现。

Heap_4方式:

支持内存申请、内存释放;并且支持内存碎片整理。

Heap_5方式:

这种方式是在heap_4的基础上,增加了对不连续的内存区的支持,也就是堆空间可以是不连续的空间;比如我们单片机内部有SRAM,外部也可以挂载SRAM或SDRAM,如果想把这样两片不连续的地址空间都管理起来,可以用heap_5方式来进行动态内存管理。

使用heap_5方式进行动态内存管理时,需调用vPortDefineHeapRegions函数进行初始化,之后才能调用申请内存、动态创建任务、动态创建信号量之类的申请内存操作。

FreeRTOS的堆空间大小由configTOTAL_HEAP_SIZE宏来确定;除了heap_3方式,其他的几种内存分配方式,都是在这个堆空间里分配的。

使用FreeRTOS的堆空间作为动态内存时(也就是除heap_3之外),可以用xPortGetFreeHeapSize()函数来获取剩余可用堆空间的大小。使用heap_4或heap_5时,可以用xPortGetMinimumEverFreeHeapSize()函数来获取历史剩余可用空间的最小值。

2)编程试验

下面我们来编写一个程序试验freeRTOS的动态内存分配功能。

首先创建工程,默认情况下,cubemx中freeRTOS的堆大小定义为3072字节,使用heap_4方式,我们不修改它,生成keil工程:

生成keil工程后,可以看到源文件中有heap_4.c文件;而且FreeRTOSConfig.h文件中的configTOTAL_HEAP_SIZE宏定义为3072:

在任务中编写如下代码,申请、释放内存,并打印剩余内存空间大小:

程序运行的结果如下图所示:

初始时,内存堆中有1216字节的可用空间;

执行申请10字节空间后,减小到了1192字节;这里不是减小10字节,一方面是因为freeRTOS中申请内存时要8字节对齐,另一方面是因为管理已申请的内存块也需要一定的空间;

执行动态创建一个信号量后,减小到了1112字节;

释放申请的空间后,可用空间回到了1216字节;

最后打印历史可用空间的最小值,1112字节。

可以看到,动态申请内存空间时,堆中的可用空间也是相应变化的。

好了,本节的内容就到这里了。

如果觉得有用可以关注作者微信号“小白白学电子”,在公众号可以找到代码和资料下载地址

原网站

版权声明
本文为[xiaobaibai_2021]所创,转载请带上原文链接,感谢
https://blog.csdn.net/little_grapes/article/details/126168638