crazydtone 发表于 2013-12-24 11:39:21

avr stack 浅析 (欢迎拍砖)

本帖最后由 crazydtone 于 2013-12-24 11:45 编辑

用ATmega128时,程序运行出现了很奇怪的现象,经查找不是程序本身的问题,最后是由于stack overflow所造成的。看了一下ICC AVR的help文档关于 data area的部分,特此将其贴出来。如果那里有不妥的话,请拍砖。。。

数据空间用于存储全局变量、the stack frames和用于动态内存分配的heap。一般来说,它们出现在输出文件中(当程序运行时,其被使用)。一个程序所使用的数据空间如下:


Hardware Stack / HW Stack:the hardware stack starts at the end of the SRAM.
Software Stack / SW Stack:software stack which grows downward is below the HW Stack

为了确保HW Stack不会grow past SW Stack并且SW Stack不会grow into heap,这些是由你决定的,否则不可预期的事情将会发生!!!

HW Stack :HW Stack 用于子程序调用和中断处理
SW Stack:SW Stack用于给parameters,局部变量分配Stack



由于HW Stack主要用于存储函数返回地址,一般情况下其比SW Stack小。一般情况下,如果你的程序不是call-intensive(调用密集)并且没有使用调用密集的库函数,比如使用 %f格式的printf函数,默认的16Bytes Return Stack Size能够正常的工作。在绝大多数情况下,
Return Stack Size最大值 40 Bytes 是足够的,除非你的程序有很深的递归调用。


Stack Checking

任意程序失败的常见来源是由于stack溢出到其他数据空间区域。HW / SW Stack都有可能溢出,当一个堆栈溢出时, Bad things可能发生。通过使用Stack Checking 函数可以检测溢出的情况。

Stack checking function

几个库函数用于stack overflow checking。考虑以下Memory Map,如果HW Stack grows into SW Stack,SW Stack的内容将会改变(在SW Stack中局部变量和其他的stacked items将改变)。
由于HW Stack用于保存函数的返回地址,如果你的函数 call tree太深的话,这种情况将会发生。


同样的,SW Stack 溢出到 data areas将会改变全局变量(global variable)或者静态分配的内存(或者Heap items,如果你使用动态内存分配的话)。如果你声明了太多的局部变量或者一个局部的聚合(aggregate)变量太大,此种情况将会发生!!!
如果你在程序中使用了非常多的printf函数,格式字符串将会占用许多data area。
这个通常也会导致stack溢出。
总结:

1、        使用stack checking function 要在你的*.c 文件中加入 #include<macros.h>

2、在你的程序代码中插入 “_StackCheck();”,此处你想检查stack是否overflow。
此函数可以在你程序中的任何位置,比如:插入到你的WDT函数中。

2、        当¬_StackCheck()检测到stack overflow,其将调用_StackOverflowed()(有一个integer参数,1表示HW Stack 溢出,0表示SW Stack溢出)。

3、        默认的_StackOverflowed()库函数跳到地址0并且复位运行的程序。为了改变这个默认的behavior,在你的代码中可以设计你自己的_StackOverflowed() function。所设计的函数将会覆盖默认的。为了程序调试,你的_StackOverflowed() function应该做些提示表明一个catastrophic condition,也许闪烁一个LED。如果你使用调试器的话,你可以在 StackOverflowed()中设置一个断点。
Tips:StackCheck() 和StackOverflowed()的函数原型在macros.h中!!!

Sentinels

Startup code在data area和SW stack之上的地址处写入了一个sentinel 字节,如果sentinel 字节改变的话,此时 stack overflow已经发生。

Notes:如果你使用动态内存分配,必须跳过sentinel字节。

wxty 发表于 2013-12-24 13:48:24

马克,有用!

imjacob 发表于 2013-12-24 16:20:25

第一次听说还有 软件栈 ,硬件栈。是不是AVR 独有的啊

funnynypd 发表于 2014-12-7 11:40:37

This is unique to IAR AVR, GCC AVR doesn't have this limit.

crazydtone 发表于 2014-12-10 13:50:27

funnynypd 发表于 2014-12-7 11:40
This is unique to IAR AVR, GCC AVR doesn't have this limit.

这个确实和编译器有关系,之前用的ICCAVR,现在改用IAR啦。

GCC编译出来的程序也要考虑实际的RAM大小以及加载程序时的地址。

funnynypd 发表于 2014-12-12 00:37:38

本帖最后由 funnynypd 于 2014-12-12 00:39 编辑

>之前用的ICCAVR,现在改用IAR啦。

I am on the opposite direction. IAR uses too much RAM with Less Flash. This is a pain of the neck if you using Attiny26, which has very limited RAM.
So Far, the GCC AVR doesn't let me down yet. So disappointing for IAR AVR.

For IAR AVR, when program size is growing, the following error shows up, and you are dead:
"Error: Segment RSTACK (size: 0x8 align: 0) is too long for segment definition. At
least 0x6 more bytes needed. The problem occurred while processing the segment placement
command "-Z(DATA)RSTACK+_..X_RSTACK_SIZE=_..X_RSTACK_BASE-_..X_RSTACK_END", where at the
moment of placement the available memory ranges were "DATA:de-df"
   Reserved ranges relevant to this placement:
   DATA:60-8f         TINY_I
   DATA:90-aa         TINY_Z
   DATA:ab-bd         TINY_N
   DATA:be-dd         CSTACK
   DATA:de-df         RSTACK
"

The Error is so typical and cannot be resolved.

zzsczz 发表于 2015-9-13 07:39:07

这个楼可以铲一铲学51的时候,芯片裸奔,没什么system stack 和user stack之分,只有一个硬的stak。按照 http://www.keil.com/support/man/docs/c166/c166_ap_stack.htm 的说法,system stack 用来存放函数返回地址,user stack保存调用参数和局部变量。还有一种分类法,即内核的stack和task的stack分开。分开存放的好处是提高稳定性,比如西门子基于c166 以及pxros的s7-300产品,还有基于6809的os—9       https://en.m.wikipedia.org/wiki/OS-9       。弱点是需要软硬件支持,并培训使用者。就软件方面,有2个极端: forth语言,内置的基础设施区分了return stack 和data stack;万金油c语言,可以在os上跑,也可以裸奔,至于两种stack的实现,交给编译器处理,如楼主所述,gcc和iar在avr上对stack的实现不同。还有如ucosii之类的,在数据结构设计上支持多个stack(分为os stack 和task stack),底层硬件无特殊限制。btw,学校的数据结构 编译原理 教学太失败了

freeboyxd 发表于 2015-9-14 21:28:02

学习了,谢谢楼主
页: [1]
查看完整版本: avr stack 浅析 (欢迎拍砖)