Embedded 如何更改FreeRTOS中任务的最大可用堆大小?

Embedded 如何更改FreeRTOS中任务的最大可用堆大小?,embedded,malloc,heap,keil,freertos,Embedded,Malloc,Heap,Keil,Freertos,我正在以以下方式创建任务中的元素列表: l = (dllist*)pvPortMalloc(sizeof(dllist)); dllist是32字节大。 我的嵌入式系统有60kB的SRAM,所以我希望我的200个元素列表可以被系统轻松处理。我发现在为8个元素分配空间后,系统在第9次malloc函数调用256byte+时崩溃 如果可能的话,我可以在哪里更改freeRTOS中的堆大小? 我可以请求堆大小的当前状态吗? 我在文档中找不到这方面的信息,所以我希望有人能对此提供一些见解。

我正在以以下方式创建任务中的元素列表:

        l = (dllist*)pvPortMalloc(sizeof(dllist));
dllist是32字节大。 我的嵌入式系统有60kB的SRAM,所以我希望我的200个元素列表可以被系统轻松处理。我发现在为8个元素分配空间后,系统在第9次malloc函数调用256byte+时崩溃

如果可能的话,我可以在哪里更改freeRTOS中的堆大小? 我可以请求堆大小的当前状态吗? 我在文档中找不到这方面的信息,所以我希望有人能对此提供一些见解。
提前谢谢

对于标准分配器,您可以在FreeRTOSConfig.h中找到一个配置选项

然而: 很可能您已经用完了内存,这取决于所使用的分配器。IIRC有一个不释放任何块的,释放的只是一个虚拟块。因此,返回的任何块都将丢失。如果您只在启动时分配内存,然后使用现有的内存,那么这仍然很有用

其他分配器可能只是在返回后不合并相邻的块,从而比完全成熟的分配器更快地增加碎片

此外,您可能会将内存释放到碎片中。根据您的alloc/free模式,您很快可能会得到一个看起来像瑞士奶酪的堆:分配的块之间有许多洞。因此,尽管仍有足够的可用内存,但没有一个块足够大,满足所需的大小

如果您只在那里分配大小相同的块,那么最好使用您自己的分配器或固定大小的池块。Thaqt将静态分配,例如数组,并在启动期间链接为链表。Alloc/free则只是堆栈上的push/pop或队列上的put/get。如果写得好的话,这也会非常快,并且具有复杂的O1中断安全性

注意,正常的malloc/free不是中断安全的


最后:不要铸造void*。实际上,这就是标准malloc返回的结果,我希望FreeRTOS variant也会这样做。

对于标准分配器,您可以在FreeRTOSConfig.h中找到一个配置选项

然而: 很可能您已经用完了内存,这取决于所使用的分配器。IIRC有一个不释放任何块的,释放的只是一个虚拟块。因此,返回的任何块都将丢失。如果您只在启动时分配内存,然后使用现有的内存,那么这仍然很有用

其他分配器可能只是在返回后不合并相邻的块,从而比完全成熟的分配器更快地增加碎片

此外,您可能会将内存释放到碎片中。根据您的alloc/free模式,您很快可能会得到一个看起来像瑞士奶酪的堆:分配的块之间有许多洞。因此,尽管仍有足够的可用内存,但没有一个块足够大,满足所需的大小

如果您只在那里分配大小相同的块,那么最好使用您自己的分配器或固定大小的池块。Thaqt将静态分配,例如数组,并在启动期间链接为链表。Alloc/free则只是堆栈上的push/pop或队列上的put/get。如果写得好的话,这也会非常快,并且具有复杂的O1中断安全性

注意,正常的malloc/free不是中断安全的


最后:不要铸造void*。好的,这实际上是标准malloc返回的结果,我希望FreeRTOS变体也会这样做。

是-FreeRTOS pvPortMalloc返回void*

如果您有60K的SRAM,并且configTOTAL_HEAP_的大小很大,那么在分配256个字节后,您不太可能用完堆,除非您手头几乎没有剩余的堆。许多FreeRTOS演示将一直创建对象,直到所有堆都被使用为止,因此,如果您的应用程序基于其中一个,那么在代码执行之前,您的堆将很低。您可能还通过创建具有巨大堆栈的任务来消耗大量堆空间

heap_4和heap_5将组合相邻的块,这将尽可能减少碎片,但我认为这不会是您的问题-尤其是您没有提到在任何地方释放任何内容

除非您使用的是heap_3.c,它使标准c库malloc和free thread安全,否则您可以调用xPortGetFreeHeapSize查看您有多少可用堆。您还可以使用xPortGetMinimumEverFreeHeapSize来查询您曾经有多接近耗尽堆。更多信息:


您还可以定义malloc failed hook来获取pvPortMalloc返回NULL的即时通知。

是-FreeRTOS pvPortMalloc返回void*

如果您有60K的SRAM,并且configTOTAL_HEAP_的大小很大,那么在分配256个字节后,您不太可能用完堆,除非您手头几乎没有剩余的堆。许多FreeRTOS演示将继续创建对象,直到所有堆都被使用,所以如果 您的应用程序基于其中一个,那么在执行代码之前,您的堆将很低。您可能还通过创建具有巨大堆栈的任务来消耗大量堆空间

heap_4和heap_5将组合相邻的块,这将尽可能减少碎片,但我认为这不会是您的问题-尤其是您没有提到在任何地方释放任何内容

除非您使用的是heap_3.c,它使标准c库malloc和free thread安全,否则您可以调用xPortGetFreeHeapSize查看您有多少可用堆。您还可以使用xPortGetMinimumEverFreeHeapSize来查询您曾经有多接近耗尽堆。更多信息:


您还可以定义malloc failed hook来获取pvPortMalloc返回NULL的即时通知。

可用堆空间的总量由configTOTAL\u heap\u SIZE设置,该值在FreeRTOSConfig.h中定义。内存管理。@WeatherVane:这取决于他使用的内存分配器。上次我看了这些,有4种不同的类型,没有一种符合项目的要求。@Weather Vane:谢谢你,Richard提到的设置和功能使我找到了解决方案,我将堆大小增加到25 kB,现在它运行得很顺利。我观察到的一件有趣的事情是,增加任务的堆栈大小也会增加可用的堆大小。我想知道这是什么原因。可用堆空间的总量是由configTOTAL\u heap\u SIZE设置的,它在FreeRTOSConfig.h中定义。内存管理。@WeatherVane:这取决于他使用的内存分配器。上次我看了这些,有4种不同的类型,没有一种符合项目的要求。@Weather Vane:谢谢你,Richard提到的设置和功能使我找到了解决方案,我将堆大小增加到25 kB,现在它运行得很顺利。我观察到的一件有趣的事情是,增加任务的堆栈大小也会增加可用的堆大小。我想知道为什么会这样。我没有使用演示代码,也没有进行其他分配,我的代码使用的是heap_4,它也释放了内存,但我认为在4x32字节的mallocs之后,碎片化不会成为问题。我将使用xPortGetFreeHeapSize并在完成后报告,谢谢:谢谢使用函数我可以找出真正的问题请看我在下面的评论我的问题如果你想知道:我没有使用演示代码,也没有使用ant其他分配,我的代码使用的是heap_4,它还可以释放内存,但我认为在4x32字节mallocs之后,碎片化不会成为问题。我将使用xPortGetFreeHeapSize并在完成后报告,谢谢:谢谢使用这些函数,我可以找出真正的问题。如果您想知道:我使用的是heap4中的alloc函数,它应该可以防止碎片,特别是当系统崩溃前只分配了几块内存时。事实上,我正在使用一个链表作为内存块。一个普通的分配器实际上不能防止碎片,只能减少碎片,除非你不释放或不使用单个块大小。对于后者,游泳池将更容易、更快。然而,我只是查看了一下可用的分配器,并编写了自己的分配器。主要是因为我使用Cortex-M中的MPU,需要自然对齐的块和单词对齐的块。我使用heap4中的alloc函数,它应该可以防止碎片,特别是当系统崩溃前只分配了几个内存块时。事实上,我正在使用一个链表作为内存块。一个普通的分配器实际上不能防止碎片,只能减少碎片,除非你不释放或不使用单个块大小。对于后者,游泳池将更容易、更快。然而,我只是查看了一下可用的分配器,并编写了自己的分配器。主要是因为我使用Cortex-M中的MPU,需要自然对齐的块和单词对齐的块。