FreeRTOS–堆内存管理

坐品种要,最近启幕修FreeRTOS,一开始小紧张,因为少单星期天前对FreeRTOS的熟悉度几乎也零星,经过对FreeRTOS官网的例证程序的索,和档次蒙问题的化解,遇到了无数熟识的人影,以前以Linux平台编程的阅历为了自家有些坏实惠之更,后悔当初不曾会在第一小企业要下,浪费了大好时光。好吧,现在还是奔下中心来施行抓FreeRTOS吧。

继承还是同多元FreeRTOS相关的随笔,先管FreeRTOS“圣经”Mastering the FreeRTOS Real Time kernel -- A Hands On Tutorial Guide 20161204好好研读,接连的几只随笔都是自自从马上按照“圣经”中翻下的。翻译难免有着疏漏、词不达意,大家聚在圈吧。

起FreeRTOS
V9.0.0从头FreeRTOS应用程序可以了用静态分配内存,而尚未必要引入堆内存管理。

章引言和限量

前提

FreeRTOS是坐C源文件之款型提供的,因此变成同叫做合格的C语言编程人员是使用FreeRTOS的必要条件,因而这个节假定读者熟悉以下概念:

  • C语言项目是哪构建的,包含不同之编译和链接过程
  • 堆放和货栈分别是呀
  • 标准C库的malloc()free()函数

动态内存分配和它和FreeRTOS的关联

由FreeRTOS
V9.0.0初始根本对象既可以以编译的时光静态分配,也堪在运行时动态分配。
本书随后的回用会介绍以下基本对象:tasks,
queues, semaphoresevent
groups
。为了尽量让FreeRTOS易于使,这些基础对象并无是在编译时静态分配的,而是于运行时动态分配的。内核对象创建时FreeRTOS分配RAM而以基础对象删除时放内存。这样的政策减少了规划与计划及之全力,简化了API,并且减少了RAM的占据。

动态内存分配是C语言编程的定义,而休是指向FreeRTOS或者基本上任务编程的定义。它和FreeRTOS是相关的,因为基本对象是动态分配的,并且通用编译器提供的动态内存分配方案于实时应用程序并无连续称的。

内存可以行使正式C库的malloc()free()函数来分配,但产生或无合乎,或者当,因为生几乎触及由:

  • 在小型嵌入式系统面临连无连续可用之
  • 它的实现可能非常之非常,占据了一对一深之等同块代码空间
  • 他们几乎都不是线程安全之
  • 其并无是确定的,每次调用这些函数执行的日或许还不雷同
  • 她发出或来碎片
  • 其有或于乱链接器的布局
  • 要允许堆空间的生方向覆盖任何变量占据的内存,它们会化为debug的灾难

动态内存分配的可选项

从今FreeRTOS
V9.0.0开根本对象既可当编译时静态分配为可以以运行时动态分配
。如今FreeRTOS把内存分配放在可移植层。这是认识及不同的嵌入式操作有差之动态内存管理办法与时空要求,因此单个的动态内存分配算法将只有称为应用程序的一个子集。同样,从基本代码库中移除动态内存分配使得应用程序编写者提供温馨的特定的贯彻,如果符合之口舌。

当FreeRTOS需要RAM的时候,并无是调用malloc(),而是调用pvPortMalloc()。当得自由RAM的早晚,并无是调用free(),而是调用vPortFree()pvPortMalloc()和标准C库的malloc()产生同的函数原型,vPortFree()和标准C库的free()发出雷同的函数原型。

pvPortMalloc()vPortFree()还是公函数,因此会给采取代码调用。

FreeRTOS对于pvPortMalloc()vPortFree()供了5栽实现,后续章节会讲到。FreeRTOS应用程序可以使中的等同种,或者应用好的贯彻。5栽实现各自以heap_1.c,
heap_2.c, heap_3.c, heap_4.cheap_5.c文件被,都在叫文件夹
FreeRTOS/Source/portable/MemMang 下。

范围

本章节转业为为读者深入明:

  • FreeRTOS何时分配RAM
  • FreeRTOS 提供的5种内存分配方案
  • 选用哪一样种植内存分配方案

内存分配方案示例

Heap_4 (其他几栽小无失探听)

heap_1, heap_2
一样,heap_4啊是拿数组切割成重小的丘。和前一样,数组是静态声明的,由宏configTOTAL_HEAP_SIZE点名大小,所以马上就使即便数组中的内存还未曾被分配出去就让应用程序显得消耗了大量的RAM。

Heap_4应用了首届适应算法来分配内存。和heap_2不同,heap_4将近的空的存储空间拼凑成一个重怪之外存块,这就算减少了内存碎片化的高风险。

头适应算法确保了pvPortMalloc()以第一块空闲的够用深的内存来满足要提请之字节数。考虑下的景:

  • 堆放里发3片空闲内存块,它们的尺寸分别是5只字节,200只字节,100独字节
  • 调用pvPortMalloc()来报名20个字节的RAM
    满足字节数要求的率先块空闲RAM块是200只字节的RAM块,因此pvPortMalloc()把大小为200只字节的RAM块分割成稀块,一片是20独字节,一片是180个字节,然会返回一个针对20单字节的指针。新的180只字节大小的RAM块将于继续的pvPortMalloc()调用中可用。

Figure 7 演示了 heap_4
最先适应算法如何拼接内存,同样也演示了内存的分红和自由:

图片 1

  1. A示范了创建3单任务之后的数组的规范,一生块空的丘有被数组的上面。
  2. B示范了去除1独任务之后的高频组,一杀块空的丘有被数组的顶端。被去除的挺任务占据的TCB和储藏室存储空间现在凡是拖欠的,并且它拼接成一个特别的拖欠的块。
  3. C示范了FreeRTOS创建了一个Queue。队列是透过xQueueCreate() API
    创建的,它是调用pvPortMalloc()
    来分配存储空间的。由于heap_4使长适应算法,pvportMalloc()用会见使用第一片老的足容纳队排的RAM块来分配,在Figure
    7中即动用前剔除任务的那无异块。然而队列并无净消耗大空闲的章,所以特别RAM块会分成两单部分,未采取的局部以会见由于持续之pvPortMalloc()占用。
  4. D以身作则了应用程序直接调用pvPortMalloc()假设非是间接地由FreeRTOS
    API调用之后的事态。用户分配的段足够小,能够在第一单空闲的章节中,这个节就是班占用的回和后的TCB占用的章之间的那无异块。
    去任务释放的内存,现在受剪切成3个章节,第一单章是行,第二只章节是用户分配的,第三独章节还是拖欠的。
  5. E
    演示了排删除后,存储空间为自行释放了。现在用户分配的节两限还是空闲区块。
  6. F
    演示了用户分配的囤积空间释放的动静。这个节现在与少数止的空闲区块拼接成了一个重特别的空闲区块。

Heap_4并无是众所周知的,但是一旦于标准库函数实现之malloc()free()运作的再次快。

设定Heap_4一再组的起首地址

此章节带有重复高阶的音,仅仅为用Heap_4是尚未必要看与掌握是节的。

好几时候应用程序开发者需要指定heap_4数组的原初地址在有特定的内存。例如,FreeRTOS
任务的栈是从堆积如山着分配的,就发或出必要保证堆是分配在快的内存中,而未是慢速的外存。

默认情况下,heap_4数组是以heap_4.c来文件被宣示的,它的开场地址是由于链接器自动确定的。然而,如果当文书FreeRTOSConfig.h屡遭拿编译时布置选configAPPLICATION_ALLOCATED_HEAP倘为常量1,那么数组必须由使用FreeRTOS的使用声明。如果将数组声明也运用的同样有的,那么用编写者可以指定数组的起首地址。

苟将公文FreeRTOSConfig.h中的configAPPLICATION_ALLOCATED_HEAP设定为1,那么应用程序源文件被务必声明一个名啊ucHeapuint8_t类的数组,它的尺寸来configTOTAL_HEAP_SIZE设定。

拿变量放在有内存地址的语法取决于使用了哪种编译器,下面演示了少数栽编译器的用法:

  1. Listing
    2演示的凡GCC编译器声明数组并将数组放在名字啊.my_heap的段中。
  2. Listing 3演示的凡IAR编译器把数组放在内存绝对地址0x20000000上。

uint8_t ucHeap [configTOTAL_HEAP_SIZE] attribute ((
section(“.my_heap”) ));

Listing 2

uint8_t ucHeap [configTOTAL_HEAP_SIZE] @ 0x20000000;

Listing 3

以及堆积相关的实用函数

xPortGetFreeHeapSize() API

以此函数可以获调用时堆中空闲内存的分寸,以字节为单位。使用她好优化堆的深浅。例如,当内核对象都创了后调用xPortGetFreeHeapSize()返回2000,那么得将configTOTAL_HEAP_SIZE减小2000.

用留意,当使用heap_3时是不克调用这个函数的。

xPortGetMinimumEverFreeHeapSize() API

这个函数返回FreeRTOS应用程序开始运行之后都有的无比小之不受分配的囤积空间的字节数。它的返回值指示了应用程序离将要耗尽堆空间的接近程度。例如xPortGetMinimunEverFreeHeapSize()回200单字节,那么自从应用程序开始运行之后的某个时间,在运用200独字节就会见拿堆空间用完。

亟需注意,xPortGetMinimumEverFreeHeapSize()单纯于运heap_4或者heap_5时生效。

Malloc 失败钩子函数

应用程序可以一直调用pvPortMalloc()。当然在FreeRTOS源文件中于内核对象创建时为会见调用这个函数。此类的根本对象包括任务,队列,信号量和事件组。

暨业内库函数malloc()一样,如果pvPortMalloc()因为申请RAM的轻重缓急非克满足没能回来一块RAM上空就会回来NULL。如果编程人员调用pvPortMalloc()来创造基础对象,但是返NULL就是认证内核对象没开创成功。

事例中之享有堆分配方案还足以给pvPortMalloc()部署一个钩子函数(也称作回调函数),当pvPortMalloc()返回NULL时常调用这个钩子函数。

假若文件FreeRTOSConfig.h中的configUSE_MALLOC_FAILED_HOOK设置为1,那么应用程序必须提供一个内存分配失败时的钩函数,它的讳以及原型参见如下。只要针对斯动用来说是适当的,这个钩子函数可以为此任何方式来促成。

void vApplicationMallocFailedHook( void );

声明

接转载,请注明出处和作者,同时保留声明。
作者:LinTeX9527
出处:http://www.cnblogs.com/LinTeX9527/p/8007541.html
本博客的文章一经随便特别说明,均为原创,转载请注明出处。如未经作者同意要保留这个段子声明,且以文章页面明显位置给起原文连接,否则保留追究法律责任的权利。