FreeRTOS中的堆栈计算

面膜仪
FreeRTOS中的堆栈计算
夹网布1.栈的重要性
其实不管是普通的程序还是Freertos程序,分配的栈的⼤⼩是很重要的,要不然带不动程序,就容易造成程序的崩溃。
机读答题卡函数调⽤时的现场保护和返回地址,函数的形参,进⼊中断函数前和中断嵌套等都需要栈空间。
2.检测堆⼤⼩
xPortGetFreeHeapSize()
可以获取调⽤时堆中空闲内存的⼤⼩,以字节为单位。使⽤它可以优化堆的⼤⼩。需要注意,当使⽤heap_3时是不能调⽤这个函数的。
xPortGetMinimumEverFreeHeapSize()
此函数返回FreeRTOS应⽤程序开始运⾏之后,曾经存在的最⼩的未被分配的存储空间的字节数。
需要注意xPortGetMinimumEverFreeHeapSize()只在使⽤heap_4或者heap_5时⽣效。
printf(“xPortGetFreeHeapSize =%d\r\n”,xPortGetFreeHeapSize());
printf(“xPortGetMinimumEverFreeHeapSize =%d\r\n”,xPortGetMinimumEverFreeHeapSize());
例如:两个函数的返回值打印出来,⽐如分别为2200和2000。2200代表⽬前还有2200可以⽤,2000:代表程序的堆分配了最多后还剩下2000bytes可以⽤,我们就可以适当的减⼩这个数值,但是⼜不能全部减掉,适当的留⼀些,以备不时之需。⽽我们⼀开始分配时,也要先从⼤往⼩的⽅向适当调整堆的⼤⼩。
3.检测栈⼤⼩变压器油箱
uxTaskGetStackHighWaterMark()
垂直风道机箱printf(" 最⼩的栈空间⼤⼩: %d \r\n",
(int32_t)uxTaskGetStackHighWaterMark(NULL));
可以得出该任务⾃启动起来最⼩剩余栈空间⼤⼩。然后我们就可以计算出最⼤使⽤的⼤⼩,⼀般可以再乘以1.5-2倍左右作为最终分配的值。注意:返回的以字为单位,真实的bytes需要乘以4。
4.程序⾥的堆栈⼤⼩
这⾥的栈空间⼜叫做系统栈空间:中断函数和中断嵌套才⽤的到这些栈。
瓶花木
任务栈使⽤这⾥分配的栈空间。
5.计算堆栈⼤⼩
对于Cortex-M3内核和未使⽤FPU(浮点运算单元)功能的Cortex-M4内核在发⽣中断时需要将16个通⽤寄存器全部⼊栈,每个寄存器占⽤4个字节,也就是16*4 = 64字节的空间。 可能发⽣⼏次中断嵌套就是要64乘以⼏即可。当然,这种是最坏执⾏情况,也就是所有的寄存器都⼊栈。
(注:任务执⾏的过程中发⽣中断的话,有8个寄存器是⾃动⼊栈的,这个栈是任务栈,进⼊中断以后其余寄存器⼊栈以及发⽣中断嵌套都是⽤的系统栈)
对于具有FPU(浮点运算单元)功能的Cortex-M4内核,如果在任务中进⾏了浮点运算,那么在发⽣中断的时候除了16个通⽤寄存器需要⼊栈,还有34个浮点寄存器也是要⼊栈的,也就是(16+34)*4 = 200字节的空间。当然,这种是最坏执⾏情况,也就是所有的寄存器都⼊栈。
(注:任务执⾏的过程中发送中断的话,有8个通⽤寄存器和18个浮点寄存器是⾃动⼊栈的,这个栈是任务栈,进⼊中断以后其余通⽤寄存器和浮点寄存器⼊栈以及发⽣中断嵌套都是⽤的系统栈)。
6.堆栈溢出检测
设置堆栈溢出检测,每个任务都有⼀个任务堆栈,如果使⽤函数xTaskCreate()创建⼀个任务的话那么这个任务的堆栈是⾃动从FreeRTOS的堆(ucHeap)中分配的,堆栈的⼤⼩是由函数xTaskCreate()的参数usStackDepth
来决定的。如果使⽤函数xTaskCreateStatic()创建任务的话任务堆栈是由⽤户设置的,参数pxStackBuffer为任务堆栈,⼀般是⼀个数组。
堆栈溢出是导致应⽤程序不稳定的主要因素,FreeRTOS
提供了两种可选的机制来帮助检测和调试堆栈溢出,不管使⽤哪种机制都要设置宏configCHECK_FOR_STACK_OVERFLOW。如果使能了堆栈检测功能的话,即宏configCHECK_FOR_STACK_OVERFLOW不为0,那么⽤户必须提供⼀个钩⼦函数(回调函数),当内核检测到堆栈溢出以后就会调⽤这个钩⼦函数,此钩⼦函数原型如下:
void vApplicationStackOverflowHook( TaskHandle_t  xTask,
char*pcTaskName );
参数xTask是任务句柄,pcTaskName是任务名字,要注意的是堆栈溢出太严重的话可能会损毁这两个参数,如果发⽣这种情况的话可以直接查看变量 pxCurrentTCB来确定哪个任务发⽣了堆栈溢出。
有些处理器可能在堆栈溢出的时候⽣成⼀个fault中断来提⽰这种错误,另外,堆栈溢出检测会增加上下⽂切换的开销,建议在调试的时候使⽤。
6.1 堆栈溢出检测⽅法1
configCHECK_FOR_STACK_OVERFLOW==1,使⽤堆栈溢出检测⽅法1。
上下⽂切换的时候需要保存现场,现场是保存在堆栈中的,这个时候任务堆栈使⽤率很可能达到最⼤值,⽅法⼀就是不断的检测任务堆栈指针是否指向有效空间,如果指向了⽆效空间的话就会调⽤钩⼦函数。⽅法⼀的优点就是快!但是缺点就是不能检测所有的堆栈溢出。
6.2 堆栈溢出检测⽅法2
configCHECK_FOR_STACK_OVERFLOW==2,使⽤堆栈溢出检测⽅法2。
使⽤⽅法⼆的话在创建任务的时候会向任务堆栈填充⼀个已知的标记值,⽅法⼆会⼀直检测堆栈后⾯的⼏个bytes(标记值)是否被改写,如果被改写的话就会调⽤堆栈溢出钩⼦函数,⽅法⼆也会使⽤⽅法⼀中的机制!⽅法⼆⽐⽅法⼀要慢⼀些,但是对⽤户⽽⾔还是很快的!⽅法⼆能检测到⼏乎所有的堆栈溢出,但是也有⼀些情况检测不到,⽐如溢出值和标记值相同的时候。
总结
欢迎指正

本文发布于:2024-09-22 16:50:00,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/2/309981.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:堆栈   任务   检测   溢出   函数
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议