搜索
bottom↓
回复: 41

令人疑惑的 CSTACK 和 RSTACK (IAR for AVR )崩溃中......

[复制链接]

出0入0汤圆

发表于 2009-4-8 11:35:09 | 显示全部楼层 |阅读模式
最近在搞一个小项目的测试工作,用M128做了一个测试架,但是出了奇怪的问题:变量经常被莫名奇妙的改变,设置的条件语句根本不起作用,开始以为是选择了优化的原因,后来将优化完全关闭,程序还是乱七八糟的,用 IAR debug的时候一到中断的地方就提示 CSTACK 使用100% 或者 RSTACK 使用100% 后来将 这两个数据设置为100(开始是60)也不行,再设置为200的时候屏蔽了部分代码后,程序能正常运行,现在问题是这两个数据究竟要设为多大才算合适?依据是什么?

PS:本人的这个程序调用flash字符串比较多,因为是通过串口直接发送到计算机显示的,计算机上只有一个串口调试助手。

请各位大侠赐教!

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2009-4-8 11:40:03 | 显示全部楼层
在网上搜索了一下,关于 CSTACK RSTACK 的介绍也是只言片语 甚至iar的帮助都简单的很。

出0入0汤圆

发表于 2009-4-8 11:52:35 | 显示全部楼层
如果设置这么大还不行,就要考虑是否代码的问题了,而不仅仅是把STACK放大

出0入0汤圆

发表于 2009-4-8 11:57:09 | 显示全部楼层
RSTACK 程序返回用的,保存的是程序调用函数的返回地址  , 你填写的数值 X 2才是占用的字节数,例如,你填写10,那么RSTACK尺寸是20字节,可以函数嵌套10层左右

CSTACK 函数局部变量用的区域,所有的功能函数使用的局部变量都是从这个堆栈申请使用的,用完了再还回去。子函数里面用到的局部变量都是在这里面取来用的.
例如:
void Fn(void)
{
     unsigned char TT[64];
}

TT[64] 就会从CSTACK取出来用,用完后TT没用了,就可以还给CSTACK了,当子函数使用局部变量太多的时候,要注意CSTACK尺寸

出0入0汤圆

发表于 2009-4-8 12:07:26 | 显示全部楼层
当出现CSTACK和RSTACK溢出的时候,一般有2种情况:

1. CSTACK和RSTACK真的不够用

2. 中断反复重入,例如:当进去一个中断,你直接开启总中断,如果这个中断信号还在,那么中断函数会重入,这样你不管设置CSTACK和RSTACK多大,溢出是必然的, 一般情况是,如果你系统想执行所为的中断嵌套,你进去中断后,首先要关闭自身中断,然后再开总中断,退出时再重新开启自身中断

出0入0汤圆

 楼主| 发表于 2009-4-8 12:28:17 | 显示全部楼层
多谢楼上赐教,你所说的第2中情况我觉得不太可能,因为我没有在中断中打开总中断,另外AVR不是在执行一个中断的时候会将全局中断自动关闭,执行完毕再打开吗?
至于第一种情况我试试看看,我在函数中是声明了部分局部数组变量,但都没有超过100.

另外楼上的兄弟可以QQ聊吗?我的QQ是38845216

万般无奈刚才咨询了一下北京麦克泰公司,他们公司是代理iar编程器的,对于软件方面也不是太明白,只是说,增大一些看看再说。我晕啊

出0入0汤圆

发表于 2009-4-8 12:43:39 | 显示全部楼层
CSTACK设大点,200也不算大。

RSTACK一般设置到32就够了。
32层函数,中断嵌套,一般应该够了。

如果代码空间不是很紧张,最高优化建议用speed优化。

楼主使用了printf??

出0入0汤圆

 楼主| 发表于 2009-4-8 12:51:03 | 显示全部楼层
但是我这个程序大概只有5K左右啊,难道CSTACK要设为256?
我只在一个函数中声明了一个80个字节的数组,其他的函数中的局部变量不会超过4个。
难道CSTACK的尺寸是所有的局部变量的总和?
这个跟flash变量有关系吗?我这个程序中的Flash变量到时很多,但是全部都是指针传递的。

比如这个函数:
/*********************************
函数名称:SendConstToUart1()
函数功能:发送Const数据到串口1
入口参数:Const数据
出口参数:返回值为1时表示发送成功,0表示长度出错
********************************/
uint8 SendConstToUart1(uint8 __flash  *str)
{
        if('\0' == *str) return 0;
        while('\0' != *str)
        {
                if(0xff == *str) break;
                while(0 == (UCSR1A & (1<<UDRE1)))__delay_cycles(1);
                           UDR1 = *str++;
        }
        return 1;
}

出0入0汤圆

 楼主| 发表于 2009-4-8 12:57:18 | 显示全部楼层
六楼上官兄,我没有使用Printf函数,发送数据函数是采用自己编写的,在楼上一样贴出来了

出0入0汤圆

发表于 2009-4-8 13:29:20 | 显示全部楼层
这个问题也困扰过我,现在整理了拿出来。。。。

在中断的时候,RAM溢出了,一般在中断里,堆栈最深,中断里出问题一般是RSTACK 的问题,这个是存函数调用返回地址的,也就是说,函数嵌套调用太多了。而C编译器编译的代码操作堆栈的次数远比我们想的多,当然这也是一个优秀C编译器的高级之处。

我一般碰到的问题是CSTACK设置问题,CSTACK是用来存数据的,这些数据主要用于函数间传递参数、全局变量同步等等。这个你要看E文版的IAR说明书。

这两个参数具体要设置多少,要看MAP文件。IAR不会自动告诉你的,而是需要由用户设定好。

我把我的一个程序改了,在中断里出现下面的提示:

Wed Apr 08 12:53:08 2009: The stack 'CStack' is filled to 100% (16 bytes used out of 16). The warning threshold is set to 90%.

说明我的0X10小了,实际用到的大于16了,而到底这个大于16的数是多少,要看MAP文件里的相关数据。

在你工程目录的Debug\List下,找到你的MAP文件,里面记载着编译器编译你的工程时,资源的使用情况。

打开.MAP文件,搜索 CALL GRAPH ,你会发现你写的每个的函数都在这里,而每个函数用了多少资源,也都列在此。

找到最大的数,设置一下,试试吧。

出0入0汤圆

发表于 2009-4-8 14:25:52 | 显示全部楼层
感谢楼主各位大虾的整理说明,回头也试一试,感觉个地方就是IAR里面最难懂的。

出0入0汤圆

发表于 2009-4-8 16:14:13 | 显示全部楼层
多谢楼上的各位 前阵子也遇上了这类问题

出0入0汤圆

 楼主| 发表于 2009-4-8 16:22:12 | 显示全部楼层
laoma 我要到日本去放烟火
void_c void *c
lmserver

将以上这三位大侠所说的结合起来看一下基本上有些眉目了。
请各位高手踊跃发言,不吝赐教。

出0入0汤圆

发表于 2009-4-8 17:38:41 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-4-8 17:53:42 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-4-8 19:55:07 | 显示全部楼层
也曾经遇到同样的困惑,但是仿真调试的时候它好像会自动给出警告,告诉你已经超出90%了,我一般都是加大它们的数值完事。

出0入0汤圆

发表于 2009-4-10 10:30:38 | 显示全部楼层
没遇见过,一般来说函数嵌套调用的层数不会太多,RSTACK我一般设为32都够用了,CSTACK看单片机RAM大小,除了全局变量占用的之外我都全部分配给CSTACK,也就是说CSTACK = RAM大小 - 全局变量总数 - RSTACK

出0入0汤圆

发表于 2009-5-11 19:56:31 | 显示全部楼层

出0入0汤圆

发表于 2009-7-1 10:04:16 | 显示全部楼层
今天使用ek-stm32板调试程序很奇怪,一开始程序运行好好,什么都没有改,重新烧录一下,就提示cstack溢出,再重新烧录一下就好了,奇怪啊!

出0入0汤圆

发表于 2009-7-1 13:42:43 | 显示全部楼层
CSTACK软
RSTACK硬

出0入0汤圆

发表于 2009-8-29 00:37:00 | 显示全部楼层
函数中定义了大数组,CRC校验的表是不是就在函数里边,定义成全局变量就ok了。

出0入0汤圆

发表于 2009-11-5 17:32:18 | 显示全部楼层
mark。

出0入0汤圆

发表于 2009-11-5 17:39:56 | 显示全部楼层
IAR里常量字符串好像也是放在RAM里的,很耗RAM,不知道什么方法可以解决

比如
if(0 == flag)
{
    PutString("Something is wrong.");
}

其中PutString是一个通过串口发送字符串的函数。我试的时候发现Something is wrong这个字符串是占用RAM的,要是能放到FLASH中就好了。

__flagh char  output[] = "XXXXXXx";
这种定义方式是指定在FLASH里的,不过要是每次都写PutString(output)就麻烦了(调试信息通常很多的)

出0入0汤圆

发表于 2009-11-6 11:48:57 | 显示全部楼层
mark一下,堆栈,CSTACK,RSTACK。

出0入0汤圆

发表于 2009-11-6 13:05:06 | 显示全部楼层
【22楼】 billowtust

         --string_literals_in_flash

出0入0汤圆

发表于 2009-12-10 14:17:37 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-12 13:36:31 | 显示全部楼层
AVR的堆栈分为2种,一种是硬件堆栈,另一种是软件堆栈。
    硬件堆栈存放调用函数的返回地址,其大小跟函数的调用层数相关。如果打开C/C++编译选项中优化选项的交叉调用的值为“unlimited”时,要特别小心。一般设为32应该没什么。其类型为RStack,界面设置值为调用深度,字节数是其2倍。
    软件堆栈存放所以局部变量(部分局部变量可能是寄存器变量),如果函数的局部变量中有数组,则其大小要设置大一些。如果不想出错,就跟16楼所说的一样。
    硬件堆栈和软件堆栈都是向下增长的(编译器默认),至于是硬件堆栈在低地址,还是软件堆栈在低地址,默认情况下由编译器决定,其地址应该在RAM的相对低的地址,但也可以通过.xcl配置文件进行更改。如:
-D_..X_RSTACK_SIZE=16                        // 硬件堆栈的大小
-D_..X_CSTACK_SIZE=20                        // 软件堆栈的大小

-Z(DATA)RSTACK+_..X_RSTACK_SIZE=(_..X_SRAM_END-_..X_RSTACK_SIZE)-_..X_SRAM_END         
-Z(DATA)CSTACK+_..X_CSTACK_SIZE=(_..X_SRAM_END-_..X_RSTACK_SIZE-_..X_CSTACK_SIZE)-(_..X_SRAM_END-_..X_RSTACK_SIZE)

上述例子就硬性确定了硬件堆栈和软件堆栈的大小与位置。
另:以-D定义的数值,其变量名是可以自己定的。

出0入0汤圆

发表于 2010-4-22 14:43:18 | 显示全部楼层
记号

出0入0汤圆

发表于 2010-11-6 14:28:19 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-7 20:33:19 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-1 16:55:27 | 显示全部楼层
学习了

出0入0汤圆

发表于 2011-7-5 16:52:55 | 显示全部楼层
mark一下,堆栈,CSTACK,RSTACK。

出0入0汤圆

发表于 2011-7-6 13:19:00 | 显示全部楼层
大家有没碰到过连接代码是出界的问题啊

出0入0汤圆

发表于 2012-3-28 12:26:40 | 显示全部楼层
Si_Bin 发表于 2009-11-6 13:05
【22楼】 billowtust

         --string_literals_in_flash

这个是在哪里设置的啊

出0入0汤圆

发表于 2012-3-28 13:08:47 | 显示全部楼层
进来了就顶。     

出0入296汤圆

发表于 2012-3-28 13:10:09 | 显示全部楼层
wuzhujian 发表于 2009-12-12 13:36
AVR的堆栈分为2种,一种是硬件堆栈,另一种是软件堆栈。
    硬件堆栈存放调用函数的返回地址,其大小跟函 ...

如果你能补充一个图片,介绍CSTACK和RSTACK的在地址空间中的位置,生长方向,
同时标注好静态分配的变量(全局,静态局部,HEAP)所处的位置以及生长方向,
就完美了。

替大家谢谢先

出0入0汤圆

发表于 2012-3-28 15:45:08 | 显示全部楼层
搞定了
   

出0入0汤圆

发表于 2012-3-28 15:45:57 | 显示全部楼层
IAR for AVR中操作put("abcd")比gcc要方便

出0入0汤圆

发表于 2013-5-27 12:32:07 | 显示全部楼层
lzh7735 发表于 2009-4-10 10:30
没遇见过,一般来说函数嵌套调用的层数不会太多,RSTACK我一般设为32都够用了,CSTACK看单片机RAM大小,除 ...

请问全局变量总数在map文件中怎么看呢

出0入0汤圆

发表于 2014-2-25 16:44:48 | 显示全部楼层
本帖最后由 crazydtone 于 2014-2-25 16:58 编辑
Gorgon_Meducer 发表于 2012-3-28 13:10
如果你能补充一个图片,介绍CSTACK和RSTACK的在地址空间中的位置,生长方向,
同时标注好静态分配的变量 ...


ICCAVR编译出来的文件在RAM中的分配

之前发过一个帖子,连接如下:
http://www.amobbs.com/thread-5564164-1-1.html

搭个顺风车,嘿嘿...
现在有个问题,目前的使用M128单片机,其有4KB Ram 。目前使用情况如下:

- variables       = 3302 (0xCE6) bytes from 0x0100 to 0x0DE5        //
- heap, s/w stack = 762 (0x2FA) bytes from 0x0DE6 to 0x10DF     //
- h/w stack       = 32 (0x20) bytes from 0x10E0 to 0x10FF           //

全局变量(数组)稍微多点,使用“_StackCheck();”函数检查,会出现复位现象,目前这种情况有什么好的解决办法呢(可能以后的程序还要变大)?

麻烦 Gorgon_Meducer 回复一下呢,谢谢...

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2015-5-19 13:27:48 | 显示全部楼层
我看不懂!!

出0入0汤圆

发表于 2016-10-29 14:56:33 | 显示全部楼层
laoma 发表于 2009-4-8 12:07
当出现CSTACK和RSTACK溢出的时候,一般有2种情况:

1. CSTACK和RSTACK真的不够用

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

本版积分规则

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

GMT+8, 2024-5-17 06:13

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

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