freertos与STM32分析栈、堆、全局区、常量区、代码区、RAM、ROM,及如何分配堆栈空间

基于STM32分析栈、堆、全局区、常量区、代码区、RAM、ROM
FreeRTOS任务栈大小确定及其溢出检测(下
FreeRTOS ------ 栈、堆、任务栈
KEIL工具之堆栈2
FreeRTOS高级篇7—FreeRTOS内存管理分析
FreeRTOS中的堆栈设置”与“系统启动文件中堆栈”的关系
使用freertos如何确定分配堆栈空间大小
整理了一下,不知道是不是没有FreeRTOS时的裸机STM32????:
在这里插入图片描述
j结合资料:
Code, RO-data,RW-data,ZI-data

Code为程序代码部分
RO-data 表示 程序定义的常量const temp;
RW-data 表示 已初始化的全局变量
ZI-data 表示 未初始化的全局变量

Program Size: Code=“18248” RO-data=320 RW-data=260 ZI-data=3952

Code, RO-data,RW-data …flash
RW-data, ZIdata…RAM

在这里插入图片描述在这里插入图片描述

猜测:
#define configTOTAL_HEAP_SIZE ((size_t)(6*1024)) //系统所有总的堆大小在这里插入图片描述
12480+1024=13504,只有ZI_Data改变了

#define configTOTAL_HEAP_SIZE ((size_t)(7*1024)) //系统所有总的堆大小
在这里插入图片描述
**-===========================================================**
13504+1024=14528,也只有ZI_Data改变了

FreeRTOS系统堆:设置为 8 1024*
#define configTOTAL_HEAP_SIZE ((size_t)(8*1024)) //系统所有总的堆大小
在这里插入图片描述
系统堆栈:
在这里插入图片描述

FreeRTOS系统堆:设置为 8 1024,不变*
ZI_Data是不是就是上图的还未使用的heap空间,因为程序其他地方都没变,申请的堆再变大一个字节,也还是多余的,,,
当#define configTOTAL_HEAP_SIZE ((size_t)(8*1024)) //系统所有总的堆大小
在这里插入图片描述
系统堆栈,堆增加0x1000,其他增加一点点;
在这里插入图片描述
18624-14528=4096=0x1000,刚好增加这个数

任务栈空间设置:
在这里插入图片描述
为什么叫做系统所有堆的大小?不是叫堆栈或栈?
个人理解:这个系统堆指的是操作系统FreeRTOS使用的一段内存堆(在RAM中划过来的),每个任务有自己发任务堆栈,任务创建可以采用动态创建和静态创建,我使用的一般是动态创建任务的方式,如果静态创建,就和我们自己开辟的空间有关,通常静态创建任务用数组作为容器,但是通常静态创建的方式不使用,不管了。简称任务栈

系统栈空间设置:
在这里插入图片描述
系统栈空间, 任务栈不使用这里的栈空间,哪里使用这里的栈空间呢?
答案就在中断函数和中断嵌套。

由于 Cortex-M3 和 M4 内核具有双堆栈指针,MSP 主堆栈指针和 PSP 进程堆栈指针,或者叫 PSP
任务堆栈指针也是可以的。在 FreeRTOS 操作系统中,主堆栈指针 MSP 是给系统栈空间使用的
程堆栈指针 PSP 是给任务栈使用
的。 也就是说,在 FreeRTOS 任务中,所有栈空间的使用都是通过
PSP 指针进行指向的
一旦进入了中断函数以及可能发生的中断嵌套都是用的 MSP 指针

实际应用中系统栈空间分配多大,主要是看可能发生的中断嵌套层数,下面我们就按照最坏执行情况
进行考虑,所有的寄存器都需要入栈,此时分为两种情况:
1:64 字节
对于 Cortex-M3 内核和未使用 FPU(浮点运算单元)功能的 Cortex-M4 内核在发生中断时需
要将 16 个通用寄存器全部入栈,每个寄存器占用 4 个字节,也就是 16*4 = 64 字节的空间。
可能发生几次中断嵌套就是要 64 乘以几即可。 当然,这种是最坏执行情况,也就是所有的寄存
器都入栈。
(注:任务执行的过程中发生中断的话,有 8 个寄存器是自动入栈的,这个栈是任务栈,进入中
断以后其余寄存器入栈以及发生中断嵌套都是用的系统栈)
2:200 字节
对于具有 FPU(浮点运算单元)功能的 Cortex-M4 内核,如果在任务中进行了浮点运算,那么
在发生中断的时候除了 16 个通用寄存器需要入栈,还有 34 个浮点寄存器也是要入栈的,也就是
(16+34)*4 = 200 字节的空间。当然,这种是最坏执行情况,也就是所有的寄存器都入栈。
(注:任务执行的过程中发送中断的话,有 8 个通用寄存器和 18 个浮点寄存器是自动入栈的,
这个栈是任务栈,进入中断以后其余通用寄存器和浮点寄存器入栈以及发生中断嵌套都是用的系
统栈)

使用如下函数即可启动 FreeRTOS:
vTaskStartScheduler();
函数原型:
void vTaskStartScheduler( void );
函数描述:
函数 vTaskStartScheduler 用于启动 FreeRTOS 调度器,即启动 FreeRTOS 的多任务执行。
使用这个函数要注意以下几个问题:

  1. 空闲任务和可选的定时器任务是在调用这个函数后自动创建的。
  2. 正常情况下这个函数是不会返回的,运行到这里极有可能是用于定时器任务或者空闲任务的 heap 空
    间不足造成创建失败,此时需要加大 FreeRTOSConfig.h 文件中定义的 heap 大小:
    #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) )
    在这里插入图片描述

任务栈大小的确定

每个任务都需要自己的栈空间,应用不同,每个任务需要的栈大小不同的。
将如下的几个选项简单的累加就可以得到一个粗略的栈大小
1, 函数的嵌套调用,针对每一级函数用到栈空间的有如下四项:
2,函数局部变量。
3,函数形参,一般情况下函数的形参是直接使用的 CPU 寄存器,不需要使用栈空间,但是这个函数中如果还嵌套了一个函数的话,这个存储了函数形参的 CPU 寄存器内容是要入栈的。 所以建议大家也把这部分算在栈大小中。
4, 函数返回地址,针对 M3 和 M4 内核的 MCU,一般函数的返回地址是专门保存到 LR(LinkRegister)寄存器里面的,如果这个函数里面还调用了一个函数的话,这个存储了函数返回地址的 LR 寄存器内容是要入栈的。 所以建议大家也把这部分算在栈大小中。
5, 函数内部的状态保存操作也需要额外的栈空间。
6, 任务切换,任务切换时所有的寄存器都需要入栈,对于带 FPU 浮点处理单元的 M4 内核 MCU 来说,FPU 寄存器也是需要入栈的。
7,针对 M3 内核和 M4 内核的 MCU 来说,在任务执行过程中,如果发生中断:
M3 内核的 MCU 有 8 个寄存器是自动入栈的,这个栈是任务栈,进入中断以后其余寄存器入栈以及发生中断嵌套都是用的系统栈。
M4 内核的 MCU 有 8 个通用寄存器和 18 个浮点寄存器是自动入栈的,这个栈是任务栈,进入中断以后其余通用寄存器和浮点寄存器入栈以及发生中断嵌套都是用的系统栈。
8, 进入中断以后使用的局部变量以及可能发生的中断嵌套都是用的系统栈,这点要注意。
实际应用中将这些都加起来是一件非常麻烦的工作,上面这些栈空间加起来的总和只是栈的最小需求
实际分配的栈大小可以在最小栈需求的基础上乘以一个安全系数,一般取 1.5-2。上面的计算是我们用户可以确定的栈大小,项目应用中还存在无法确定的栈大小,比如调用printf函数就很难确定实际的栈消耗。又比如通过函数指针实现函数的间接调用,因为函数指针不是固定的指向一个函数进行调用,而是根据不同的程序设计可以指向不同的函数,使得栈大小的计算变得比较麻烦。
另外还要注意一点,建议不要编写递归代码,因为我们不知道递归的层数,栈的大小也是不好确定的。
一般来说,用户可以事先给任务分配一个大的栈空间,再采用的调试方法打印任务栈的
使用情况,运行一段时间就会有个大概的范围了,适当减小。这种方法比较简单且实用些。

函数栈大小确定
关于 MDK 生成的 map 和 htm 文件的使用,安富莱电子有出过一期视频教程,可以在这里查看:
http://bbs.armfly.com/read.php?tid=15408

看到其中一个人的结论:
FreeRTOS中的堆栈,并没有占用系统启动文件中的堆栈空间大小。两者在空间分配上互不影响,需要单独设置。并且FreeRTOS有自己的内存申请函数pvPortMalloc()以及一系列的内存管理函数。

还有点不太明白,有FreeRTOS后,是不是stm32芯片的RAM=系统堆栈+FreeRTOS堆+其他?其中FreeRTOS堆里面创建任务划分了若干任务栈
在这里插入图片描述
要想正常成功并充分利用资源执行,任务栈和FreeRTOS堆空间要申请合适,创建任务的函数里面的值是以字为单位,需要乘以4变成字节,uxTaskGetStackHighWaterMark()返回值也是以字为单位

  • 13
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值