嗨,你为什么那么努力?因为我想去的地方很远,想买的东西很贵,喜欢的人很优秀!
– 来自网络热句,出处未知
概述
首先说明的是,在 RT-Thread
中,将本文提及的 任务
称之为 线程
。
在使用 RTOS
开发项目时,一个任务会拥有自己独立的线程栈,用来在任务调度时保存该任务的当前上下文内容,比如当前 CPU 寄存器的值、函数的局部变量等。不同的任务复杂程度不同,需要的栈大小也不同,给多了浪费(毕竟单片机中的 RAM
贵的一匹),给少了更严重,栈溢出造成的后果会让整个系统崩溃。
所以,一个合适的栈大小便十分重要,本文就来聊聊这个栈大小如何配置的问题。
方法论
理论上来说,你是可以计算出任务所需要的大概的值,但是要考虑的因素比较多,比如寄存器的数量的不同等,不同类型的单片机亦有差别,所以这种方式比较费脑,对底层知识的理解也要比较深刻,可能比较适合大佬吧(我不是大佬也不知道大佬们怎么做)。
比较普适的做法是,可以先设置较大的任务栈,比如 1KB
或 2KB
的大小,确保不会出现栈溢出的情况,然后让系统运行一段比较长的时间,同时要尽量触发各种可能的工况,通过查看任务栈的被使用的最大深度值,一般将最终的任务栈大小设定为该值的 1.5~2
倍为比较合适的值。
不断地修改和检查栈大小是否配置合适这个过程,是动态调节的过程,最终会找到一个比较好的方案。
不同的 RTOS
,如何检测任务栈的使用情况呢?
RT-Thread
在 FinSH
中用 list_thread
命令查看线程运行过程中线程所使用的栈的大小,这里的大小指的是从线程启动运行时到当前时刻点,线程使用的最大栈深度,
FreeRTOS
使用 uxTaskGetStackHighWaterMark()
API
函数来查看实际使用了多少栈,如果分配的栈比需要的多,则可以减少栈大小,并且可以使用栈溢出检测特性来确定栈是否太小。
比如,在一个任务中使用如下调用:
printf(" the min free stack size is %d \r\n",(int32_t)uxTaskGetStackHighWaterMark(NULL));
ucos
ucos 提供了一个系统任务:STATISTICS
任务,可以统计各任务的CPU使用率,也就是任务栈使用情况,可以借用该统计任务的函数来统计各任务的栈使用情况。
参考资料
- 《FreeRTOS 常见问题——栈应该有多大?》:https://blog.csdn.net/weixin_44567318/article/details/119549227
- 《FreeRTOS 的任务栈设置》:https://www.cnblogs.com/yangguang-it/p/7123727.html
- 《使用freertos如何确定分配堆栈空间大小》:https://blog.csdn.net/aningxiaoxixi/article/details/103144501
- 《ucos任务栈大小计算,如何高效定义栈空间大小!》:https://blog.csdn.net/dongtuoc/article/details/79361042
- 《RT-Thread 官方文档:线程栈》:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/thread/thread?id=线程栈
更多精彩内容,更多惊喜,请关注公众号《嵌入式小散修》。