DMOZ中文网站分类目录-免费收录各类优秀网站的中文网站目录.
  • DmozDir.org
DMOZ目录快速登录入口-免费收录各类优秀网站的中文网站目录.由人工编辑,并提供网站分类目录检索及地区分类目录检索,是站长免费推广网站的有力平台!

STM32内存结构介绍和FreeRTOS内存分配技巧

  • STM32内存结构介绍和FreeRTOS内存分配技巧

  • 已被浏览: 60 次2021年04月06日    来源:  https://www.cnblogs.com/puyu9495/p/14610674.html
  • 这是我第一次使用FreeRTOS构建STM32的项目,踩了好些坑,又发现了我缺乏对于操作系统的内存及其空间的分配的知识,故写下文档记录学习成果。文章最后要解决的问题是,如何恰当地分配FreeRTOS中的堆、任务栈的空间。但是在概念的理解上,

    这是我第一次使用FreeRTOS构建STM32的项目,踩了好些坑,又发现了我缺乏对于操作系统的内存及其空间的分配的知识,故写下文档记录学习成果。

    文章最后要解决的问题是,如何恰当地分配FreeRTOS中的堆、任务栈的空间。但是在概念的理解上,也需要知道STM32内存的相关知识。所以首先大致介绍一下STM32的内存结构。

    STM32内存结构

    STM32的数据在物理上分别储存在RAM和Flash中。RAM可读可写,掉电清零。Flash可读不可写,但能掉电储存,并且一般空间比RAM大很多。

    在关于如何使用RAM和Flash的问题上,STM32的内存又有了6个储存数据段和3种储存属性区的概念。

    6个储存数据段

    data

    数据段,储存已初始化的,且初始化不为0的全局变量和静态变量。

    bss

    Block Started by Symbol。储存未初始化的,或初始化为0的全局变量和静态变量。

    text

    代码段,储存程序代码。

    constdata

    储存只读常量。

    heap

    堆,存放进程运行中被动态分配的内存段。其可用大小定义在启动文件startup_stm32fxx.s中,由程序员使用malloc()free()函数进行分配和释放。

    stack

    栈,其大小定义在启动文件startup_stm32fxx.s中,由系统自动分配和释放。可存放局部变量、函数的参数和返回值,中断发生时能保存现场。但是static声明的局部静态变量不储存在栈中,而是放在data数据段。

    3种储存属性区

    RO(Read Only)

    烧写到Flash中,可以长久保存。text代码段和constdata都属于RO。由于需要掉电储存,RO里也保存了一份data的数据。

    RW(Read Write)

    储存在RAM中。data属于此区。上电时单片机会将Flash中保存的data类型数据复制到RAM中,以供读写使用。

    ZI(Zero Init)

    零初始化区,同样储存在RAM里。系统上电时会把此区域的数据进行0初始化。bss,heap,stack均属于这个区域。

    小结

    STM32的RAM上有RW和ZI两个属性区,里边包含了data,bss,堆(heap),栈(stack)这几个数据段。这里是程序运行的所在。

    Flash中有RO区,包含了text、constdata和data三个段,这里则是程序本体所在。

    FreeRTOS中的堆

    FreeRTOS中的堆也属于ZI区,但是它与STM32内存结构中的堆并不占用相同的空间,两个堆同时存在。以下出现的堆(heap)表示FreeRTOS堆,另外在STM32启动文件中定义大小的堆称为系统堆。

    FreeRTOS内核主要使用的内存管理函数为:

    void *pvPortMalloc( size_t xSize );	//申请内存
    void vPortFree( void *pv );	        //释放内存
    

    以上函数控制的是FreeRTOS堆;系统堆则应使用malloc()free()来分配和释放。

    FreeRTOS有5种heap的实现方式,在STM32CubeMX中默认为heap_4.c。这种方式可以满足大部分使用需求,暂时不用关注其实现细节。

    这一个堆的大小定义在FreeRTOSConfig.c中:

    #define configTOTAL_HEAP_SIZE ((size_t)3072)
    

    FreeRTOS创建任务时默认的任务栈大小为128字,在32位系统中即为128*4=512Byte,再加上TCB块占用84Byte,一共596Byte。而大小为3072Byte的堆允许创建3个这样的任务,占用约1800Byte。堆中剩余的部分则存放了系统内核、信号量、队列、任务通知等数据。

    需要创建更多任务时,堆的大小可自行修改。用RAM的空间减去已分配的空间,即为能给堆分配的最大空间:

    \[Space = RAM - bss - data - SysHeap - Stack \]

    FreeRTOS堆和任务空间分配技巧

    FreeRTOS堆和任务栈在运行中具有很强的动态性,其大小很难估计。

    我们在实际使用中,可以先把空间调整得大一些。程序正常运行后,再通过一些API查看堆栈剩余的空间大小,估算程序运行中需求内存空间的最大值。最后将这个最大值乘一个安全系数,得到最终应该分配的空间大小。安全系数推荐1.3到1.5。

    查看堆(heap)剩余空间的API有:

    size_t xPortGetFreeHeapSize( void );	         //获取当前未分配的内存堆大小
    size_t xPortGetMinimumEverFreeHeapSize( void );	 //获取未分配的内存堆历史最小值
    

    它们返回值的单位都是字节。

    需要注意的是,xPortGetFreeHeapSize() 在使用heap_3.c时不能被调用;xPortGetMinimumEverFreeHeapSize()则只能在使用heap_4.cheap_5.c时生效。

    FreeRTOS中也有查看任务栈剩余空间的API:

    UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
    

    这个函数可以获取一个任务从创建好到调用此函数时,任务栈空间的历史最小剩余值(HighWaterMark)。使用这个函数时需注意,它的返回值的单位是字(STM32里1个字长为4个字节)。

    这个API默认是关闭状态,需要手动在Cubemx(或配置文件中)将宏INCLUDE_uxTaskGetStackHighWaterMark置为1。

    我在使用过这些API后发现,他们本身也会占用相当的内存空间,尤其是uxTaskGetStackHighWaterMark(),会拖慢任务运行速度。所以在程序的正式版中,应该将他们删除。


    以上信息来源于网络,如有侵权,请联系站长删除。

    TAG:内存 分配 结构 技巧 FreeRTOS

  • 上一篇:go的令牌桶实现库 go-rate
  • 与“STM32内存结构介绍和FreeRTOS内存分配技巧”相关的资讯
  • 封装Vue竖直纵向表头左右结构的table表格
  • Java 树结构实际应用 二(哈夫曼树和哈夫曼编码)
  • PriorityQueue 是线性结构吗?90%的人都搞错了!
  • 检测随机图中的种植结构
  • 计算机网络的七层结构、五层结构和四层结构