IAR的CSTACK和RSTACK的设置.docx

上传人:b****5 文档编号:29307016 上传时间:2023-07-22 格式:DOCX 页数:25 大小:22.06KB
下载 相关 举报
IAR的CSTACK和RSTACK的设置.docx_第1页
第1页 / 共25页
IAR的CSTACK和RSTACK的设置.docx_第2页
第2页 / 共25页
IAR的CSTACK和RSTACK的设置.docx_第3页
第3页 / 共25页
IAR的CSTACK和RSTACK的设置.docx_第4页
第4页 / 共25页
IAR的CSTACK和RSTACK的设置.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

IAR的CSTACK和RSTACK的设置.docx

《IAR的CSTACK和RSTACK的设置.docx》由会员分享,可在线阅读,更多相关《IAR的CSTACK和RSTACK的设置.docx(25页珍藏版)》请在冰豆网上搜索。

IAR的CSTACK和RSTACK的设置.docx

IAR的CSTACK和RSTACK的设置

IAR的CSTACK和RSTACK的设置

RSTACK程序返回用的,保存的是程序调用函数的返回地址,你填写的数值X2才是占用的字节数,例如,你填写10,那么RSTACK尺寸是20字节,可以函数嵌套10层左右

CSTACK函数局部变量用的区域,所有的功能函数使用的局部变量都是从这个堆栈申请使用的,用完了再还回去。

子函数里面用到的局部变量都是在这里面取来用的.

例如:

voidFn(void)

{

unsignedcharTT[64];

}

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

 

当出现CSTACK和RSTACK溢出的时候,一般有2种情况:

1.CSTACK和RSTACK真的不够用

2.中断反复重入,例如:

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

 

CSTACK设大点,200也不算大。

RSTACK一般设置到32就够了。

32层函数,中断嵌套,一般应该够了。

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

 

这个问题也困扰过我,现在整理了拿出来。

在中断的时候,RAM溢出了,一般在中断里,堆栈最深,中断里出问题一般是RSTACK的问题,这个是存函数调用返回地址的,也就是说,函数嵌套调用太多了。

而C编译器编译的代码操作堆栈的次数远比我们想的多,当然这也是一个优秀C编译器的高级之处。

我一般碰到的问题是CSTACK设置问题,CSTACK是用来存数据的,这些数据主要用于函数间传递参数、全局变量同步等等。

这个你要看E文版的IAR说明书。

这两个参数具体要设置多少,要看MAP文件。

IAR不会自动告诉你的,而是需要由用户设定好。

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

WedApr0812:

53:

082009:

Thestack'CStack'isfilledto100%(16bytesusedoutof16).Thewarningthresholdissetto90%.

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

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

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

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

 

没遇见过,一般来说函数嵌套调用的层数不会太多,RSTACK我一般设为32都够用了,CSTACK看单片机RAM大小,除了全局变量占用的之外我都全部分配给CSTACK,

也就是说CSTACK=RAM大小-全局变量总数-RSTACK

 

AVR的堆栈分为2种,一种是硬件堆栈,另一种是软件堆栈。

硬件堆栈存放调用函数的返回地址,其大小跟函数的调用层数相关。

如果打开C/C++编译选项中优化选项的交叉调用的值为“unlimited”时,要特别小心。

一般设为32应该没什么。

其类型为RStack,界面设置值为调用深度,字节数是其2倍。

软件堆栈存放所以局部变量(部分局部变量可能是寄存器变量),如果函数的局部变量中有数组,则其大小要设置大一些。

如果不想出错,就跟上楼所说的一样。

硬件堆栈和软件堆栈都是向下增长的(编译器默认),至于是硬件堆栈在低地址,还是软件堆栈在低地址,默认情况下由编译器决定,其地址应该在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定义的数值,其变量名是可以自己定的。

 

在编译开关里面加入--string_literals_in_flash就可以把(C/C++Compile-->ExtraOptions-->Usecommandlineoptions-->--string_literals_in_flash

fun("str")的"str"放到FLASH里。

--string_literals_in_flash

如果直接定义constunsignedcharstr的话在flash里面,但初始化拷贝到RAM中,如果定义__flashconstunsignedcharstr的话就不会拷贝到RAM中了

------------------------------------------------------------------------------------------------------------------------

需要设置Generaloptions->LibraryOption->printfformatter设置成Medium或full

然后需要设置CSTACK大小,Generaloptions->System默认的是0x80,更改为0x100或者更大

 

CTRL+T格式化代码

CTRL+BMatchBrackets

CTRL+TAutoIndent

CTRL+KBlockComment

CTRL+SHIFT+KBlockUncomment

 

编译器清零只是把.bss段(GCC),NEAR_Z(IAR,或者TINY_Z,FAR_Z)清零。

其他段并没有清零

 

1、__no_init对RAM里的变量修饰结果为:

启动代码内不会操作这个变量。

2、__no_init对EEP里的变量修饰结果为:

生成EEP文件的时候不向文件内对应地址写0,和启动代码无关。

 

CONST定义的变量会放在FLASH和ram中。

使用下面这个加FLASH,就可以编译过去。

/*

********************************************************************************************

头部文件名:

MCU_C_Macro_Data_Define.h

头部文件名称:

嵌入式微处理器

C程序的数据类型和常用指令宏定义的头部文件

适用器件芯片类型:

嵌入式微处理器

文件版本:

  1.0

文件功能:

    本文件是对嵌入式微处理器C程序的数据类型、在编程中一些常用操作和指令及位操作进行

  宏定义的头部文件。

文件说明:

    在使用本文件前,必须首先使用全局预定义字符来对C编译系统进行定义!

对各种C编译系统规定使用的全局预定义字符如下(中括号里面的字符):

①.IAREmbeddedWorkbenchforAtmelAVR------[_IAR_EW_AVR_]

②.ICCAVR------------------------------------[_ICC_AVR_]

③.CodeVisionAVR----------------------------[_CodeVision_AVR_]

编译工具软件:

链接文件:

编作者:

编作者E-Mail:

PTZSW@163.COM

编制日期:

2005年8月18日

----------------------------------------------------------------------------------------

头部文件版本历史:

2005年8月18日--------版本1.0:

发行版本

********************************************************************************************

*/

/*==========================================================================================

下面两条指令是本头部文件条件编译的预处理指令,用于防止本头部文件被其他文件重复引用。

==========================================================================================*/

#ifndefMCU_C_MACRO_DATA_DEFINE_H//"MCU_C_MACRO_DATA_DEFINE_H"条件编译开始

#defineMCU_C_MACRO_DATA_DEFINE_H

/*==========================================================================================

下面这三条指令是用于区分编译系统为C++或C的预处理指令。

"__cplusplus"为C++预处理器名字,这三条指令表明接在其下面的那些指令为C程序特征。

==========================================================================================*/

#ifdef__cplusplus

extern"C"{

#endif

 

/*==========================================================================================

定义系统处理的数据位字长度大小:

==========================================================================================*/

#defineSYSDATA_BITNUM8//定义系统数据位的字长数

 

/*==========================================================================================

为了做到较好的软件可移植性,推荐用户在编程时使用下面定义的数据类型大小

==========================================================================================*/

typedefunsignedcharBOOLEAN;//定义【布尔(逻辑)】数据类型

typedefcharchar8;//char8代表【有符号字符】数据类型

typedefunsignedcharUc

har8;//Uchar8代表【无符号字符】数据类型

typedefintint16;//int16代表【有符号整数】数据类型

typedefunsignedintUint16;//Uint16代表【无符号整数】数据类型

typedeflongintint32;//int32代表【有符号长整数】数据类型

typedefunsignedlongintUint32;//Uint32代表【无符号长整数】数据类型

typedeffloatfloat32;//float32代表【单精度浮点数】数据类型

/*==========================================================================================

位操作定义(用于变量中某一位的直接置位/清除位),推荐置位/清除位的语句为:

①.变量名称|=BITn;置位操作(将变量与下面的位定义值进行按位或运算)

②.变量名称&=~BITn;清除位操作(将变量与下面的位定义值的非值进行按位与运算)

==========================================================================================*/

#defineBIT00x01//BIT0=(1<<1)=0b00000001

#defineBIT10x02//BIT1=(1<<2)=0b00000010

#defineBIT20x04//BIT2=(1<<3)=0b00000100

#defineBIT30x08//BIT3=(1<<4)=0b00001000

#defineBIT40x10//BIT4=(1<<5)=0b00010000

#defineBIT50x20//BIT5=(1<<6)=0b00100000

#defineBIT60x40//BIT6=(1<<7)=0b01000000

#defineBIT70x80//BIT7=(1<<8)=0b10000000

#defineBIT_HIGHBIT7//BIT7=(1<<8)=0b10000000

#defineBIT_LOWBIT0//BIT0=(1<<1)=0b00000001

 

/*

********************************************************************************************

AVR单片机常用操作和指令宏的定义

********************************************************************************************

*/

/*--------------------------------------------------------------------------------------

位操作指令的宏定义:

①.对存储在地址中的数据变量执行置位操作指令:

SET_BIT(ADDRESS,BIT)

②.对存储在地址中的数据变量执行清位操作指令:

CLEAR_BIT(ADDRESS,BIT)

③.测试存储在地址中的数据变量某一位数值的指令:

TEST_BIT(ADDRESS,BIT)

其中:

ADDRESS-----变量存储地址

BIT---------位数(阿拉伯数字)

--------------------------------------------------------------------------------------*/

#ifdefined(_IAR_EW_AVR_)||defined(_ICC_AVR_)||defined(_CodeVision_AVR_)

#defineSET_BIT(ADDRESS,BIT)((ADDRESS)|=(1<<(BIT)))

#defineCLEAR_BIT(ADDRESS,BIT)((ADDRESS)&=~(1<<(BIT))

#defineTEST_BIT(ADDRESS,BIT)((ADDRESS)&(1<<(BIT)))

#endif

/*--------------------------------------------------------------------------------------

IAREmbeddedWorkbenchforAVR编译器对16位的寄存器进行读写操作指令的宏定义:

①.对16位的寄存器进行写入的操作指令:

OUT_WORD(ADDRESS,VAL)

②.读取16位的寄存器中内容的操作指令:

IN_WORD(ADDRESS,VAL)

其中:

ADDRESS-----寄存器的存储地址

VAL---------位数(阿拉伯数字)

--------------------------------------------------------------------------------------*/

#ifdefined(_IAR_EW_AVR_)//"IAREmbeddedWorkbenchAVR"条件编译开始

#defineOUT_WORD(ADDRESS,VAL)\

{\

__disable_interrupt();\

(ADDRESS)=(VAL);\

__enable_interrupt();\

}

#defineIN_WORD(ADDRESS,VAL)\

{\

__disable_interrupt();\

(VAL)=(ADDRESS);\

__enable_interrupt();\

}

#endif//"defined(_IAR_EW_AVR_)"条件编译结束

 

/*--------------------------------------------------------------------------------------

在编程中一些常用操作和指令宏的定义:

①.WDR()--------看门狗定时器复位指令

②.SEI()--------使能全局中断指令

③.CLI()--------禁止全局中断指令

④.SLEEP()------MCU进入休眠状态指令

⑤.NOP()--------空操作指令

--------------------------------------------------------------------------------------*/

#ifdefined(_IAR_EW_AVR_)||defined(_ICC_AVR_)||defined(_CodeVision_AVR_)

#defineWDR()asm("wdr")//看门狗定时器复位

#defineSEI()asm("sei")//使能全局中断

#defineCLI()asm("cli")//禁止全局中断

#defineSLEEP()asm("sleep")//MCU进入休眠状态

#defineNOP()asm("nop")//空操作

#endif

 

/*--------------------------------------------------------------------------------------

EEPROM存储器扩展的操作和指令宏的定义:

①.eeprom-----------------------------指向EEPROM存储器的关键字

②.EEPROM_WRITE(ADDRESS,DATA)--------写入数据到EEPROM存储器中某一个具体地址的指令

③.EEPROM_READ(DATA,ADDRESS)---------从EEPROM存储器中某一个具体地址读取数据的指令

其中:

ADDRESS---------访问EEPROM存储器的具体地址

DATA------------对EEPROM存储器执行操作的数据

--------------------------------------------------------------------------------------*/

#ifdefined(_IAR_EW_AVR_)//"IAREmbeddedWorkbenchAVR"条件编译开始

#defineeeprom__eeprom//定义指向EEPROM存储器的关键字

#ifndefEEPROM_WRITE

#defineEEPROM_WRITE(ADDRESS,DATA)__EEPUT(ADDRESS,DATA)

#end

if

#ifndefEEPROM_READ

#defineEEPROM_READ(DATA,ADDRESS)__EEGET(DATA,ADDRESS)

#endif

#ifndef_EEPUT

#define_EEPUT(V,A)__EEPUT(V,A)

#endif

#ifndef_EEGET

#define_EEGET(V,A)__EEGET(V,A)

#endif

#ifdef__HAS_EEPROM__//"__HAS_EEPROM__"条件编译开始

#define__EEPUT(ADDRESS,DATA)(*((unsignedchar__eeprom*)ADDRESS)=DATA)

#define__EEGET(DATA,ADDRESS)(DATA=*((unsignedchar__eeprom*)ADDRESS))

#else

#define__EEPUT(ADDRESS,DATA){\

while(EECR&0x02);\

EEAR=(ADDRESS);\

EEDR=(DATA);\

EECR=0x04;\

EECR=0x02;\

}

#define_

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 职业教育 > 其它

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1