搜索
bottom↓
回复: 34

关于 uCOS 堆栈大小定义的问题请教

[复制链接]

出0入0汤圆

发表于 2009-9-15 14:28:34 | 显示全部楼层 |阅读模式
在任哲的书第 22 页

问题1、#define TASK_STK_SIZE   512    //定义堆栈的长度(1024个字节) //为什么是 1024个字节???

问题2、怎么知道一个任务的堆栈大小,而不越界???

出0入0汤圆

发表于 2009-9-15 14:46:51 | 显示全部楼层
能否将《任哲的书》上传上来呢?

出0入0汤圆

发表于 2009-9-17 23:07:08 | 显示全部楼层
看你是几位机啦 32位机 512 就是2Kb 16位机就是1024啦~~看你os_cpu.h里OS_STK是怎么定义的啦~~

出0入0汤圆

发表于 2009-9-18 15:40:57 | 显示全部楼层
#define TASK_STK_SIZE   512//这个只是数组长度,每个数组元素的长度没告诉你撒,char就是512字节,int就是1024了,long就是2K了
堆栈大小是你定的,用多少是系统自己定的,不同的断点保护占用的堆栈不一样了,所以你只需要定义足够的大小,稍微估算下,不浪费太多最好。(浪费是必须的)

出0入0汤圆

发表于 2009-9-19 09:33:30 | 显示全部楼层
ucos太吃堆栈了。

出0入0汤圆

发表于 2010-7-14 20:46:06 | 显示全部楼层
问题2、怎么知道一个任务的堆栈大小,而不越界???

Re:主要与MCU的类型及OSTaskStkInit()函数有关,一般估计方法为OSTaskStkInit()函数所开辟的空间 + 当前任务所需要变量空间 + 一点点富余空间即可,详细的解释如下引用参考.
**************************************************************************************************************************************************************
  堆栈作用的就是用来保存局部变量,从本质上讲也就是将CPU寄存器的值保存到RAM中。在uCOS中,每一个任务都有一个独立的任务堆栈。为了深入理解任务堆栈的作用,不妨分析任务从“出生”到“消亡”的整个过程,具体就是分析任务的建立,运行,挂起几种状态中任务堆栈的变化情况。

  现在假设系统运行着一个由用户创建的用以完成打印工作的任务TPrint。TPrint最初通过OSTaskCreate()函数创建,在该函数中与任务堆栈有关的第一段代码是大家比较熟悉的函数OSTaskStkInit(),这个函数是在uCOS移植过程中必须实现的,其作用是“初始化堆栈”,其实就是预先在RAM中的一块区域中把任务将来运行开始时CPU寄存器应处的状态(正确值)准备好,之后,任务第一次被内核调度器调度运行时,将这些准备好的数据(寄存器的值)推到CPU的寄存器中,如果数据设计的合理,CPU便会按照我们预先设计好的思路运行。所以,“初始化堆栈”实际上是做了一个“未雨绸缪”的工作。这个过程中有两点是必须慎重考虑的,一是PC该如何定位,二是CPU的其它寄存器(除PC之外)该怎么处理。先说第一点,因为任务是第一次运行,而任务从本质上将就是一段代码,所以PC指针应该定位到这段代码的第一行处,即所谓的入口地址(Entry Point)处,这个地址由任务指针保存着,所以把该指针值赋给PC即可。第二,这段代码还未被执行过,所以代码中的变量与CPU的其它寄存器一点关系也没有,因此R0-R12,R14可随便给值(引用者注释:这里所说的R0~R12及R14只是针对原作者所用MCU而言,不同的MCU是不一样的),或者不赋值也可,让这些寄存器保持原来的值,显然后者更为简单。最后再给CPSR赋值,用户可以根据实际需要使系统运行于系统模式或管理模式。经过入栈和出栈,此时SP指向任务堆栈的最底端(就是已经定义好的任务堆栈数组的最后一个元素)。

  之后任务代码开始正式运行,因为CPU的寄存器是有限的,所以在运行时不可避免地要把一些临时变量暂时保存到堆栈中。具体应保存到哪个地址呢,不用担心,SP知道(任务第一次运行时,这个地址就是任务堆栈数组的最后一个元素的地址)。任务堆栈的大小和任务代码中临时变量的数目有关,如果这段代码临变量特别多,堆栈就应设计的大一些。

  然后,TPrint任务由于某种原因将要被挂起,所以应把任务的运行现场放到堆栈里保护起来,TPrint任务再次运行时再把这个现场还原,任务就能从上次断点处紧接着运行。那么,这个现场是什么呢?从本质上讲,TPrint任务的运行过程就是CPU在执行一段特定的代码,所以这个现场就是CPU的现场,也就是寄存器的值。这些寄存器的值包含了代码执行时的所有信息,包括当前运行到了这段代码的哪个位置处(由PC值指明)。因此,把CPU的寄存器的值推入堆栈,然后记住栈顶指针的位置(SP由OSTCBCur->OSTCBStkPtr保存),当任务再次将要运行前,从SP指向的地址处依次把先前保存的CPU寄存器的值放到CPU的寄存器中,任务就可以从上次中断的地方准确无误地执行。这个过程就像突然把任务冻结了,与任务有关的任何东西都不能动了,一段时间之后又把任务解冻,与它有关的东西又变得可用,于是任务又可以活蹦乱跳地跑起来了。

  从以上分析可以看出,任务堆栈至始至终伴随着任务,与之生死与共,它的作用可以概括为两点:第一,当任务运行时,它用来保存一些局部变量;第二,当任务挂起时,它负责保存任务的运行现场,也就是CPU寄存器的值。有些朋友正是忽视了第一点,产生了“任务堆栈大小应是固定值的疑问”。我感觉,这可能与对函数OSTaskStkInit()的理解有关,我们都称之为堆栈初始化函数,但此处的“初始化”与我们理解的初始化不太一样,平时讲的(变量的)初始化似乎指的是将变量的所有成员都一一初始化。而此处的堆栈的初始化仅仅是初始化了很大一个堆栈的一小部分,因为当前只有这部分是有用的,而剩余的大部分用不到,所以不用初始化,就像有些变量不用初始化一样(有默认值或随机值)。更深入一点考虑,当任务挂起时,任务堆栈中保存任务挂起前CPU寄存器的这一连续的区域肯定在整个堆栈的最上面;当任务重新开始运行时,SP弹出寄存器的值,这段区域变成空白的区域。而且,任务每次挂起前用来保存当前CPU寄存器这一连续区域在整个任务堆栈空间中是浮动的。

出0入0汤圆

发表于 2010-8-14 18:03:23 | 显示全部楼层
学习

出0入0汤圆

发表于 2010-8-15 16:59:46 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-26 19:33:44 | 显示全部楼层
好东东,赞一个。

出0入0汤圆

发表于 2011-6-29 09:38:47 | 显示全部楼层
回复【3楼】xm042041
#define task_stk_size   512//这个只是数组长度,每个数组元素的长度没告诉你撒,char就是512字节,int就是1024了,long就是2k了
堆栈大小是你定的,用多少是系统自己定的,不同的断点保护占用的堆栈不一样了,所以你只需要定义足够的大小,稍微估算下,不浪费太多最好。(浪费是必须的)
-----------------------------------------------------------------------

mark

出0入0汤圆

发表于 2011-10-20 13:09:44 | 显示全部楼层
楼主的应该是16位定义的512(半字/双字节),所以512是1024个字节。

出0入0汤圆

发表于 2011-10-25 22:19:19 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-26 08:39:59 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-18 23:00:00 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-3 19:30:06 | 显示全部楼层
学习了,谢谢分享!!

出0入0汤圆

发表于 2012-2-3 19:32:24 | 显示全部楼层
ucos有个函数可以检查当前进程堆栈最大使用量,先调试后改堆栈代码就可以了。

出0入0汤圆

发表于 2012-2-5 10:30:35 | 显示全部楼层
如果是IAR,可以看到堆栈的使用。

出0入0汤圆

发表于 2012-2-5 18:52:32 | 显示全部楼层
回复【16楼】schwarz  
-----------------------------------------------------------------------

这个iar看到的堆栈应该是整个芯片的堆栈使用情况吧.而ucos申请的堆栈是全局变量,不在堆栈里面的,是ucos抽象出来的堆栈.

出0入0汤圆

发表于 2012-2-6 17:51:59 | 显示全部楼层
回复【17楼】myHXH
回复【16楼】schwarz   
-----------------------------------------------------------------------
这个iar看到的堆栈应该是整个芯片的堆栈使用情况吧.而ucos申请的堆栈是全局变量,不在堆栈里面的,是ucos抽象出来的堆栈.
-----------------------------------------------------------------------

错!IAR可以看到任何任务栈状态,MDK看不到,解决方案如下:
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=5388328

出0入0汤圆

发表于 2012-8-7 23:09:06 | 显示全部楼层
楼主讲得很正确,要获取每个任务最大堆栈使用量其实很简单,第次任务切换时任务私有的SP由OSTCBCur->OSTCBStkPtr保存,这个值是堆栈顶(stack top),而每个任务堆栈又有一个堆栈bottom 这个值是OSTaskCreate()建立任务时的参数 *ptos。 在每次任务切换时将bottom值和top值作差,就得出堆栈使用量,递推取最大值即可。

不知我说的对不对,自己理解的。举代码作证。

出0入0汤圆

发表于 2012-8-8 00:15:42 来自手机 | 显示全部楼层
mark         

出0入0汤圆

发表于 2012-8-13 22:39:43 | 显示全部楼层
6楼分析的透彻啊

出0入0汤圆

发表于 2013-3-21 17:34:03 | 显示全部楼层
向六楼学习……!

出0入0汤圆

发表于 2013-4-9 15:27:47 | 显示全部楼层
六樓好樣的 ,學習中

出0入0汤圆

发表于 2013-7-24 10:53:48 | 显示全部楼层
                                                mark

出0入0汤圆

发表于 2013-7-24 11:02:17 | 显示全部楼层
直接调用对堆栈检查函数OSTaskStkChk(OS_PRIO_SELF,&stk_data),即可检查当前堆栈的使用情况,不过一般堆栈容量建议留有10%的容余。掉用这个函数的任务需要用OSTaskCreateExt来创建

出0入8汤圆

发表于 2013-8-1 18:49:37 | 显示全部楼层
20L:
楼主讲得很正确,要获取每个任务最大堆栈使用量其实很简单,第次任务切换时任务私有的SP由OSTCBCur->OSTCBStkPtr保存,这个值是堆栈顶(stack top),而每个任务堆栈又有一个堆栈bottom 这个值是OSTaskCreate()建立任务时的参数 *ptos。 在每次任务切换时将bottom值和top值作差,就得出堆栈使用量,递推取最大值即可。

不知我说的对不对,自己理解的。举代码作证。

////////
这种方式不是很全面,只是只能CHECK上下文时候堆栈的使用状态,其他嵌套中断使用的堆栈状态检测不出来,我一般这样处理,在任务堆栈的最后8个位置写入一个固定的数据,比如:

只要堆栈最后的8个位置的值不会被修改,系统一定是安全的!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入8汤圆

发表于 2013-8-1 19:00:33 | 显示全部楼层
或者看这里就知道堆栈是已溢出了:


象下面这样就要小心了:


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-8-1 19:11:28 | 显示全部楼层
Ding 楼上

出0入0汤圆

发表于 2013-9-14 09:39:06 | 显示全部楼层
skype 发表于 2013-8-1 18:49
20L:
楼主讲得很正确,要获取每个任务最大堆栈使用量其实很简单,第次任务切换时任务私有的SP由OSTCBCur->O ...

简单实用的好方法。

出0入0汤圆

发表于 2013-9-14 10:01:31 | 显示全部楼层
还在讨论这个无聊的问题,前面那么多高手让你们换IAR,还在用MDK的小盆友们继续抓瞎吧。IAR解决这个问题太简单了,max%,cur%是各个任务栈历史最大使用量和当前使用量,根据max%调整你的任务栈大小就可以了。用MDK别继续思路广欢乐多了,小白们也别捧臭脚了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-10-16 22:36:03 | 显示全部楼层
coolhe 发表于 2010-7-14 20:46
问题2、怎么知道一个任务的堆栈大小,而不越界???

Re:主要与MCU的类型及OSTaskStkInit()函数有关,一般 ...

牛逼···········

出0入0汤圆

发表于 2014-10-17 10:58:52 | 显示全部楼层

出0入0汤圆

发表于 2014-10-17 19:39:01 来自手机 | 显示全部楼层
学习一下

出0入0汤圆

发表于 2014-11-11 10:40:33 | 显示全部楼层
学习
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-9 03:20

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表