stm32单片机与FreeRTOS、LwIP内存堆栈使用情况分析

stm32单片机与FreeRTOS、LwIP堆栈内存使用分析

作为一个工业通信产品研发工程师,经常会遇到需要在单片机上使用中间件FreeRTOS、LwIP的情况。本篇文章主要是梳理各中间件内存使用方式,以及在结合使用时需要注意的内存管理问题。
首先说结论,单片机和中间件FreeRTOS、LwIP的堆栈是互相独立的。具体如图。
各中间件(FreeRTOS、LwIP)内存使用图单片机总内存(以下称为RAM)包括已使用的内存和未使用的RAM。

红色区域代表已使用内存,由RW和ZI-Data(包括FreeRTOS堆栈、LwIP堆栈以及其他程序占用的RAM)还有单片机堆栈(HEAP、STACK)组成。白色区域是未使用的RAM。

如上信息,可以通过编译生成的.map文件得到证实。
请添加图片描述

单片机堆栈内存使用分析

在单片机中,堆和栈都是内存区域,它们都具有存储数据的作用。下面分别介绍一下它们的作用:

堆(HEAP):在单片机中,堆的作用与在计算机上运行的程序的堆类似,用于动态分配内存。当程序需要在运行时创建一个新的变量或对象时,会从堆中申请一块内存空间,并返回该内存空间的地址。

栈(STACK):在单片机中,栈的作用与在计算机上运行的程序的栈类似,用于存储函数调用的局部变量、参数和返回地址等信息。当程序执行函数调用时,会从栈中分配一段内存空间,用于存储函数的参数和局部变量等信息。当函数返回时,栈中的这些信息会被弹出,并恢复函数调用前的状态。

堆内存的使用仅与以下函数关联。

malloc();
free();

也就是说,堆内存的大小只需要满足程序中使用上述函数分配的内存空间就可以了。

栈内存的使用则较为简单。经测试在使用FreeRTOS的情况下,栈内存空间基本用不到(后面会分析原因)。

已keil5为例,单片机堆栈大小的设置方法通常是编辑工程文件夹下的MDK-ARM/{单片机型号}.s文件。如图:
请添加图片描述

FreeRTOS堆栈内存使用分析

FreeRTOSConfig.h 中有定义如下。

#if defined(__GNUC__)
 #define configTOTAL_HEAP_SIZE			( ( size_t ) ( 25 * 1024 ) )
#else
 #define configTOTAL_HEAP_SIZE			( ( size_t ) ( 50 * 1024 ) )
#endif

FreeRTOS 创建任务、消息队列及FreeRTOS的API函数都是从configTOTAL_HEAP_SIZE中申请内存。

FreeRTOS 的堆空间使用情况如图。
请添加图片描述
由图可见,任务、队列、用户使用 pvPortMalloc() 分配的空间都从heap堆上面划分。

此外,由于任务使用的栈内存实际上是在FreeRTOS 的堆空间的。所以不需要其他的栈空间来存放。

此外,函数xPortGetFreeHeapSize() 可以获取调用堆中空闲内存的大小,以Byte为单位。函数xPortGetMinimumEverFreeHeapSize() 可以返回FreeRTOS应用程序开始运行之后曾经存在的最小的未被分配的存储空间的字节数(只有heap_4和heap_5有效)。运用这两个函数可以有效的减少内存浪费。

LwIP堆栈内存使用分析

LWIP默认的内存策略包括内存池(POOL)和内存堆(HEAP)两种。

内存池是指为了满足特定内存分配的需要以及优化内存占用,制定了各种尺寸大小的内存池(每种内存池管理的内存块大小固定)。内存堆本质上是一大块连续内存(可以理解为数组),当需要内存时就从这个数组中按照特定算法切分一块所需大小的内存块,将这块内存的地址提供出去;剩余内存仍然存放在内存堆中以便继续分配。

关于内存池(POOL)和内存堆(HEAP)的详细讲解可以参考LwIP系列–内存管理(内存池)详解LwIP系列–内存管理(堆内存)详解

在内存池模式下,memp_std.h头文件中的定义了各种内存池。

/*
 * A list of internal pools used by LWIP.
 *
 * LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description)
 *     creates a pool name MEMP_pool_name. description is used in stats.c
 */
#if LWIP_RAW
LWIP_MEMPOOL(RAW_PCB,        MEMP_NUM_RAW_PCB,         sizeof(struct raw_pcb),        "RAW_PCB")
#endif /* LWIP_RAW */

#if LWIP_UDP
LWIP_MEMPOOL(UDP_PCB,        MEMP_NUM_UDP_PCB,         sizeof(struct udp_pcb),        "UDP_PCB")
#endif /* LWIP_UDP */

#if LWIP_TCP
LWIP_MEMPOOL(TCP_PCB,        MEMP_NUM_TCP_PCB,         sizeof(struct tcp_pcb),        "TCP_PCB")
LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN,  sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN")
LWIP_MEMPOOL(TCP_SEG,        MEMP_NUM_TCP_SEG,         sizeof(struct tcp_seg),        "TCP_SEG")
#endif /* LWIP_TCP */

#if LWIP_ALTCP && LWIP_TCP
LWIP_MEMPOOL(ALTCP_PCB,      MEMP_NUM_ALTCP_PCB,       sizeof(struct altcp_pcb),      "ALTCP_PCB")
#endif /* LWIP_ALTCP && LWIP_TCP */

#if LWIP_IPV4 && IP_REASSEMBLY
LWIP_MEMPOOL(REASSDATA,      MEMP_NUM_REASSDATA,       sizeof(struct ip_reassdata),   "REASSDATA")
#endif /* LWIP_IPV4 && IP_REASSEMBLY */
#if (IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG)
LWIP_MEMPOOL(FRAG_PBUF,      MEMP_NUM_FRAG_PBUF,       sizeof(struct pbuf_custom_ref),"FRAG_PBUF")
#endif /* IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF || (LWIP_IPV6 && LWIP_IPV6_FRAG) */

#if LWIP_NETCONN || LWIP_SOCKET
LWIP_MEMPOOL(NETBUF,         MEMP_NUM_NETBUF,          sizeof(struct netbuf),         "NETBUF")
LWIP_MEMPOOL(NETCONN,        MEMP_NUM_NETCONN,         sizeof(struct netconn),        "NETCONN")
#endif /* LWIP_NETCONN || LWIP_SOCKET */

可以通过修改宏定义来实现内存池内容的增减。

内存堆的实现同理,两者可以并存。他们所需要的内存(统称LwIP堆栈)空间是独立的,参考编译生成的.map文件如下。

请添加图片描述

此外,LwIP也给我们提供了其他可选的内存策略。

  1. 当定义宏MEM_LIBC_MALLOC为1,那么与内存堆相关的代码就不会被编译的,内存堆中的mem_malloc()和mem_free()就会被ANSI
    C编译器自带的malloc()和free()替代。(相当于把mem.o占用的空间放到了单片机HEAP中)
  2. 当定义宏MEMP_MEM_MALLOC为1,那么内存池文件memp.c就不会被编译。(相当于把memp.o占用的空间放到了单片机HEAP中)
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
STM32F407是一款由STMicroelectronics公司生产的32位ARM Cortex-M4系列的单片机,它具有丰富的外设和高性能。FreeRTOS是一个流行的开源实时操作系统,它提供了任务管理、内存管理、时间管理、消息传递等功能,可以帮助开发者进行多任务处理。LwIP是一种轻量级的协议栈,适用于嵌入式系统,它提供了TCP/IP协议栈的功能,使设备能够通过网络进行通信。 在STM32F407上使用FreeRTOSLwIP可以实现多任务处理和网络通信。通过FreeRTOS,可以将整个系统划分为多个任务,每个任务负责一个特定的功能模块,例如任务A负责处理传感器数据,任务B负责绘制图形界面,任务C负责网络通信等。FreeRTOS提供了任务管理功能,可以根据任务的优先级和时间片轮转算法来进行任务调度。同时,FreeRTOS还提供了同步机制,如信号量、互斥锁等,使得任务之间能够安全地共享资源。 而LwIP提供了TCP/IP协议栈的功能,它可以实现设备之间的网络通信。使用LwIP可以通过以太网接口连接到网络,实现TCP、UDP等协议的通信。LwIP还支持多个连接,可以在同一个系统中同时处理多个网络连接。 在使用STM32F407、FreeRTOSLwIP时,需要根据实际需求进行配置和编程。首先,需要在STM32F407上配置和初始化相应的外设和引脚,使其能够正常工作。然后,需要在FreeRTOS中创建任务,并根据任务的优先级设置任务的调度顺序。在任务中,可以使用LwIP提供的API进行网络通信的编程。最后,还需要处理中断和异常,确保系统能够正常运行。 总之,STM32F407、FreeRTOSLwIP的组合可以实现单片机上的多任务处理和网络通信。这个组合适用于需要同时处理多个任务和进行网络通信的应用场景,如物联网设备、智能家居等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

andre_ww

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值