不同的嵌入式系统具有不同的内存配置和时间要求。所以单一的内存分配算法只可能适合部分应用程序。
FreeRTOS 将内存分配作为可移植层面(相对于基本的内核代码部分而言)。这使得不同的应用程序可以提供适合自身的具体实现。
本章期望让读者了解以下事情:
(1)当内核请求内存时,其调用pvPortMalloc()而不是直接调用malloc();当释放内存时,调用vPortFree()而不是直接调用free()。
pvPortMalloc()具有与malloc()相同的函数原型;vPortFree()也具有与free()相同的函数原型。
(2)FreeRTOS 自带有三种pvPortMalloc()与vPortFree()实现范例.FreeRTOS 的用户可以选用其中一种,也可以采用自己的内存管理方式
这三个范例对应三个源文件:heap_1.c,heap_2.c,heap_3.c——这三个文件都放在目录FreeRTOS\Source\Portable\MemMang 中
(3)早期版本的FreeRTOS 所采用的原始内存池和内存块分配方案已经被移除了,因为定义内存块和内存池的大小需要较深入的努力和理解。
(4)选择内存分配方案时不必考虑一些复杂的因素,比如确定性与内存碎片等,而只需要从性能上考虑,比如代码大小和简易性
在小型嵌入式系统中,通常是在启动调度器之前创建任务,队列和信号量。
这种情况表明,动态分配内存只会出现在应用程序真正开始执行实时功能之前,而且内存一旦分配就不会再释放
(1)Heap_1.c 实现了一个非常基本的pvPortMalloc()版本,而且没有实现vPortFree()
如果应用程序不需要删除任务,队列或者信号量,则具有使用heap_1 的潜质
(2)这种分配方案是将FreeRTOS 的内存堆空间看作一个简单的数组。
当调用pvPortMalloc()时,则将数组又简单地细分为更小的内存块。
(3)数组的总大小(字节为单位)在FreeRTOSConfig.h 中由configTOTAL_HEAP_SIZE定义。
以这种方式定义一个巨型数组会让整个应用程序看起来耗费了许多内存——即使是在数组没有进行任何实际分配之前。
(4)需要为每个创建的任务在堆空间上分配一个任务控制块(TCB)和一个栈空间
(1)A 表示数组在没有任何任务创建时的情形,这里整个数据是空的。
(2)B 表示数组在创建了一个任务后的情形。
(3)C 表示数组在创建了三个任务后的情形。
(1)Heap_2.c 也是使用了一个由configTOTAL_HEAP_SIZE 定义大小的简单数组
(2)不同于heap_1 的是,heap_2 采用了一个最佳匹配算法来分配内存,并且支持内存释放
(3)由于声明了一个静态数组,所以会让整个应用程序看起来耗费了许多内存——即使是在数组没有进行任何实际分配之前
(4)最佳匹配算法保证pvPortMalloc()会使用最接近请求大小的空闲内存块
举例:堆空间中包含了三个空闲内存块,分别为5 字节,25 字节和100 字节大小。pvPortMalloc()被调用以请求分配20 字节大小的内存空间。
匹配请求字节数的最小空闲内存块是具有25字节大小的内存块——所以pvPortMalloc()会将这个25 字节块再分为一个20 字节块和一个5 字节块3,然后返回一个指向20 字节块的指针。
剩下的5 字节块则保留下来,留待以后调用pvPortMalloc()时使用
(5)Heap_2.c 并不会把相邻的空闲块合并成一个更大的内存块,所以会产生内存碎片——如果分配和释放的总是相同大小的内存块,则内存碎片就不会成为一个问题
(6)Heap_2.c 适合用于那些重复创建与删除具有相同栈空间任务的应用程序
上图展示了当任务创建,删除以及再创建过程中,最佳匹配算法是如何工作的
(1)A 表示数组在创建了三个任务后的情形。数组的顶部还剩余一个大空闲块。
(2) B 表示数组在删除了一个任务后的情形。顶部的大空闲块保持不变,并多出了两个小的空闲块,分别是被删除任务的TCB 和任务栈。
(3) C 表示数组在又创建了一个任务后的情形。创建一个任务会产生两次调用pvPortMalloc(),一次是分配TCB,一次是分配任务栈
注:(1)调用pvPortMalloc()发生在xTaskCreate() API 函数内部
(2)每个TCB 都具有相同大小,所以最佳匹配算法可以确保之前被删除的任务占用的TCB 空间被重新分配用作新任务的TCB 空间。
(3)新建任务的栈空间与之前被删除任务的栈空间大小相同,所以最佳匹配算法会保证之前被删除任务占用的栈空间会被重新分配用作新任务的栈空间。数组顶部的大空闲块依然保持不变。
(4)Heap_2.c 虽然不具备确定性,但是比大多数标准库实现的malloc()与free()更有效率
(1)Heap_3.c 简单地调用了标准库函数malloc()和free(),但是通过暂时挂起调度器使得函数调用具备线程安全特性
(2)内存堆空间大小不受configTOTAL_HEAP_SIZE 影响,而是由链接器配置
乐高42177奔驰G500套装共有2891个零件,套装分为20个步骤,拼装时间大约需要6个小时。
Emo 是一款个人伴侣机器人,集时尚与创新于一身。他的诞生离不开最新的树莓派 4 技术和先进的设计。他不仅仅是一款机器人,更是一个活生生的存在。
青少年等级考试,英文名称(Youth Level Test)以下简称等级考试。等级考试是中国电子学会服务于国家教育改革和全民科学素质提升的需要, 以提升我国 青少年整体信息素养和创新能力为目标,于2011年起面向全国青少年开展的信息技术能力素质 的评价项目。
这是积木悬浮术??乐高现在已经不归地球管了吗? NO!这是物理,是【张力】! 果然,学好数理化,走遍天下都不怕~
ESP-BOX 是乐鑫科技推出的面向 AIoT、边缘 AI 和 IIoT 应用的开发平台。
使用servo库控制舵机与通过9,10引脚对直流电机PWM调速时冲突问题的解决办法。
新课标在秋季即将开始执行,其中信息科技课程与STEM教育是紧密相关的,如何更好的展开STEM学习,以培养孩子们的STEM思维呢?本文总结了一个STEM课程的学习路径,供家长参考。
用于Arduino的Adafruit_GFX库为我们所有的LCD和OLED显示器提供了通用语法和图形功能集。这使Arduino程序可以轻松地在显示类型之间进行调整,而不必花太多精力……
本文讲解如何在Micropython环境下使用ESP32的ESPNow功能进行数据传输。