FREERTOS学习笔记十-内存管理

FREERTOS学习笔记十-内存管理

1.FreeRTOS内存管理方式

1.1 heap_1.c中的内存分配

​ 动态内存分配需要一个内存堆,FreeRTOS中的内存堆为ucHeap[],大小为configTOTAL_HEAP_SIZE。不管是哪种内存分配方法,它们的内存堆都为ucHeap[],而且大小都是configTOTAL_HEAP_SIZE。

特点:
①适用于那些一旦创建好任务、信号量和队列就再也不会删除的应用,实际上大多数的FreeRTOS应用都是这样的。
②具有可确定性(执行所花费的时间大多数都是一样的),而且不会导致内存碎片。
③代码实现和内存分配过程都非常简单,内存是从一个静态数组中分配到的,也就是适合于那些不需要动态内存分配的应用。

1.2 heap_2.c中的内存分配

​ heap_2.c提供了一个更好的配算法,不像heap_1.c那样,heap_2.c提供了内存释放函数**。**heap_2.c不会把释放调的内存块合并成一个大块,这样有一个缺点,随着你不断的申请内存,内存堆就会被分为很多个大小不一的内存(块),也就是会导致内存碎片!

特点:
①可以使用在那些可能会重复的删除任务、队列、信号量等的应用中,要注意有内存碎片产生!
②如果分配和释放的内存大小是随机的,那么就要慎重使用了。
③如果应用中的任务、队列、信号量和互斥信号量具有不可预料性(如所需的内存大小不能确定,每次所需的内存都不相同,或者说大多数情况下所需的内存都是不同的)的话可能会导致内存碎片。
④具有不可确定性,但是也远比标准C中的mallo()和free()效率高!

1.3 heap_3.c中的内存分配

​ 这个分配方法是对标准C中的函数malloc()和free()的简单封装,FreeRTOS对这两个函数做了线程保护。

特点:

①需要编译器提供一个内存堆,编译器库要提供malloc()和free()函数。比如STM32的话可以通过修改启动文件中的Heap_Size来修改内存堆的大小。
②具有不确定性。
③可能会增加代码量。
注意:在heap_3.c中configTOTAL_HEAP_SIZE是没用的!

1.4 heap_4.c中的内存分配

​ heap_4.c提供了一个最优的匹配算法,不像heap_2.c,heap_4.c会将内存碎片合并成一个大的可用内存块,它提供了合并算法。内存堆为ucHeap[],大小为configTOTAL_HEAP_SIZE。可以通过函数xPortGetFreeHeapSize()来获取剩余的内存大小。

特点:

①可是用在那些需要重复创建和删除任务、队列、信号量和互斥信号量等的应用中。
②不会像heap_2.c那样产生严重的内存碎片,即使分配的内存大小是随机的。
③具有不确定性,但是远比C标准库中的malloc()和free()效率高。heap_4.c非常适合于那些需要直接调用函数pvPortMalloc()和vPortFree()来申请和释放内存的应用。

1.5 heap_5.c中的内存分配

​ heap_5.c使用了和heap_4.c相同的合并算法,内存管理实现起来基本相同,但是heap_5.c允许内存堆跨越多个不连续的内存段。比如STM32的内部RAM可以作为内存堆,但是STM32内部RAM比较小,遇到那些需要大容量RAM的应用就不行了,如音视频处理。

1.6 总结

​ FreeRTOS官方提供的5种内存分配方法已经介绍完,heap_1.c最简单,但是只能申请内存,不能释放。heap_2.c提供了内存释放函数,用户代码也可以直接调用函数pvPortMalloc()和vPortFree()来申请和释放内存,但是heap_2.c会导致内存碎片的产生!heap_3.c是对标准C库中的函数malloc()和free()的简单封装,并且提供了线程保护。heap_4.c相对与heap_2.c提供了内存合并功能,可以降低内存碎片的产生,我们移植FreeRTOS的时候就选择了heap_4.c。heap_5.c基本上和heap_4.c一样,只是heap_5.c支持内存堆使用不连续的内存块。
————————————————

以上原文链接:https://blog.csdn.net/weixin_44502943/article/details/121017944

2.CubeMX查看内存管理方式

请添加图片描述

3.程序测试1——查看剩余内存

3.1程序代码

/* USER CODE END Header_StartKEY_Task */
void StartKEY_Task(void const * argument)
{
  /* USER CODE BEGIN StartKEY_Task */
  /* Infinite loop */
	uint16_t ProducerValue = 1;
  for(;;)
  {
		if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == 0)
		{
			osDelay(10);//消抖
			if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == 0)
			{
				osThreadSuspendAll();
				printf("使用RAM:%d/100 \r\n",100 - xPortGetFreeHeapSize()*100/configTOTAL_HEAP_SIZE);
				osThreadResumeAll();
			}
		}
		while(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == 0)
		{
			osDelay(10);
		}
    osDelay(1);
  }
  /* USER CODE END StartKEY_Task */
}

3.2运行结果

请添加图片描述

4.程序测试2——申请与释放内存

4.1程序源码

/* USER CODE END Header_StartKEY_Task */
void StartKEY_Task(void const * argument)
{
  /* USER CODE BEGIN StartKEY_Task */
  /* Infinite loop */
	void *home;
  for(;;)
  {
		if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == 0)
		{
			osDelay(10);//消抖
			if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == 0)
			{
				osThreadSuspendAll();
				printf("当前RAM:%d/100 \r\n",100 - xPortGetFreeHeapSize()*100/configTOTAL_HEAP_SIZE);
				osThreadResumeAll();
				home = pvPortMalloc(configTOTAL_HEAP_SIZE*4/100);
				osThreadSuspendAll();
				printf("申请之后RAM:%d/100 \r\n",100 - xPortGetFreeHeapSize()*100/configTOTAL_HEAP_SIZE);
				osThreadResumeAll();
				vPortFree(home);
				osThreadSuspendAll();
				printf("释放之后RAM:%d/100 \r\n",100 - xPortGetFreeHeapSize()*100/configTOTAL_HEAP_SIZE);
				osThreadResumeAll();
			}
		}
		while(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == 0)
		{
			osDelay(10);
		}
    osDelay(1);
  }
  /* USER CODE END StartKEY_Task */
}

4.2运行结果

请添加图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值