首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

[求助]关于cw编译的问题,请高手们多多指教

[求助]关于cw编译的问题,请高手们多多指教

硬件使用jl8,将prm文件中ram和为一个,堆栈设为0x50。
1 在使用中定义了一个全局数组变量(7个成员),最后发现这个数组在ram中的位置直接影响到运行结果,即将这个数组定义在其他全局变量的前面运行的结果就不对,只有将此数组放在最后才能够正确运行。开始怀疑到是否堆栈不够(因为程序里使用了读写eeprom的程序),加大了堆栈到0x80,也还是不行。百思不得其解,于是只好将数组放在最后,暂时没有发现问题,但不知是为什么。
2 另外在调试的时候还有一个奇怪的现象。有一段程序都已能够正常运行,后来对这段程序进行了精简处理,去掉了程序中不用的变量及无用的代码,结果编译后的程序出现与前者不一样的结果。我的程序是用来测试485从节点通讯可靠性的,在使用不精简的程序时,与从机进行1000通讯没有发现任何问题,当使用精简程序后发现对从机进行1000通讯时,会有30多次从机未应答的现象,用示波器观察,从机还是给了回应,不知两次编译结果到底发生了什么变化。
以上我遇到的两个问题让我很困扰,请各位高手指教
1。函数中的局部变量占用的是堆栈的空间,全局变量并不是占用的堆栈的空间。
从你的叙述看,可能是有重叠了,你可以用这两个指令,把堆栈推到RAM的最后去。
ldhx        #($15F+1)
txs

2。可能是精简的时候疏忽了什么,再仔细检查一下程序。
首先谢谢你的回复。
1 从编译后生成的P&E_pcs.map文件中可以看到我申明数组的位置,堆栈的摆放是按照编译器默认的,放在所有声明全局变量的后边,从0xc1至0x110共0x50,看不出哪里会产生重叠呀。另外早先我也试过将堆栈放到最后,好像也是不行。
2 程序我仔细检查过了,没有发现精简时删除出错的地方,在删减时删除了一些全局变量,这个问题似乎又与上一个问题相似,全局变量定义的数量与位置影响了最终运行结果。[em16]
我有同样问题出现,也曾挂相关贴子,但一直未得到答案.顶一下.
后来发现在精简程序的时候,为了减少全局变量的个数,将联合中定义的1位(此联合只用到此1位),转至其他联合中空余的位,程序运行时便会出现2中描述的现象。好郁闷呐,大家给点建议吧[em16]
一定是全局数组变量与其他全局变量出现地址冲突了。你可以去编译完成后生成的MAP文件里面确定下。不过强烈建议将RAM分为2块:前一块用来放堆栈及自动编译的全局变量,后一块用来放自己指定位置的全局变量、常数等。
感谢aressos的回复
我目前的prm中定义如下:
NAMES END /* CodeWarrior will pass all the needed files to the linker by command line. But here you may add your own files too. */

SEGMENTS /* here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */
//  Z_RAM  = READ_WRITE 0x0060 TO 0x00FF;
//  RAM    = READ_WRITE 0x0100 TO 0x015F;
  RAM    = READ_WRITE 0x0060 TO 0x015F;
  ROM    = READ_ONLY  0xDC00 TO 0xFBFF;
END

PLACEMENT /* here all predefined and user segments are placed into the SEGMENTS defined above. */
  DEFAULT_ROM                   INTO ROM;
  DEFAULT_RAM                   INTO RAM;
//  _DATA_ZEROPAGE, MY_ZEROPAGE   INTO Z_RAM;
  //SSTACK                        INTO RAM ;
END

STACKSIZE 0x50

VECTOR 0 _Startup /* reset vector: this is the default entry point for a C/C++ application. */

仅仅改变一个全局变量数组定义的位置,编译后执行的结果完全不一样。
下面我只列出好用和不好用时生产map文件中不一致的地方。
程序好用的:
- VARIABLES:
BackLightTime             B5       1       1       6   .common     
     cfg_use               B6       3       3      41   .common     
     mnum                  B9       7       7      56   .common   

SECTION USE IN OBJECT-ALLOCATION SECTION
SECTION: ".common"
LcdFlash refresh relay WorkStatus TempChange SleepTime FlashTime
BackLightTime cfg_use mnum

OBJECT LIST SORTED BY ADDRESS
BackLightTime        B5       1       1       6   .common     
     cfg_use         B6       3       3      41   .common     
     mnum            B9       7       7      56   .common   

程序不好用的:
- VARIABLES:
     mnum                  B5       7       7      56   .common     
BackLightTime             BC       1       1       6   .common     
     cfg_use               BD       3       3      41   .common
SECTION USE IN OBJECT-ALLOCATION SECTION
SECTION: ".common"
LcdFlash refresh relay WorkStatus TempChange SleepTime FlashTime mnum
BackLightTime cfg_use

OBJECT LIST SORTED BY ADDRESS
     mnum               B5       7       7      56   .common     
     BackLightTime      BC       1       1       6   .common     
     cfg_use            BD       3       3      41   .common   
另外我也尝试了aressor所说的将堆栈放在0x60~0xff当中,使用#pragma将部分变量也放在这个空间,但是还是不行,请大家帮助再分析分析,谢了。
楼主试下PRM文件里改成这样行不
RAM = READ_WRITE 0x0060 TO 0x0013F;
Z_RAM = READ_WRITE 0x0140 TO 0x015F;
//RAM = READ_WRITE 0x0060 TO 0x015F;
ROM = READ_ONLY 0xDC00 TO 0xFBFF;
END

PLACEMENT /* here all predefined and user segments are placed into the SEGMENTS defined above. */
DEFAULT_ROM INTO ROM;
DEFAULT_RAM INTO RAM;
// _DATA_ZEROPAGE, MY_ZEROPAGE INTO Z_RAM;
//SSTACK INTO RAM ;
程序里面用累似
uint  Uab           @ 0x140;
的方法指定数组的位置在Z_RAM里。
你还可以更改Z_RAM和RAM的大小,以达到不浪费RAM空间的目的。

我用12的单片机可能与你有点不一样。你可参照更改。以下是我的一个PRM文件
NAMES
END

SEGMENTS
    RAM  = READ_WRITE 0x0400 TO 0xFFF;
    RAM2 = READ_WRITE 0x1000 TO 0x1FFF;
    /* unbanked FLASH ROM */
    ROM_4000 = READ_ONLY  0x4000 TO 0x7FFF;
    ROM_8000 = READ_ONLY  0x8000 TO 0xBFFF;
    ROM_C000 = READ_ONLY  0xC000 TO 0xFEFF;
    /* banked FLASH ROM */
    PAGE_38 = READ_ONLY  0x388000 TO 0x38BFFF;
    PAGE_39 = READ_ONLY  0x398000 TO 0x39BFFF;
    PAGE_3A = READ_ONLY  0x3A8000 TO 0x3ABFFF;
    PAGE_3B = READ_ONLY  0x3B8000 TO 0x3BBFFF;
    PAGE_3C = READ_ONLY  0x3C8000 TO 0x3CBFFF;
    PAGE_3D = READ_ONLY  0x3D8000 TO 0x3DBFFF;
/*    PAGE_3E = READ_ONLY  0x3E8000 TO 0x3EBFFF; not used: equivalent to ROM_4000 */
/*    PAGE_3F = READ_ONLY  0x3F8000 TO 0x3FBFFF; not used: equivalent to ROM_C000 */
END

PLACEMENT
    _PRESTART,                   /* Used in HIWARE format: jump to _Startup at the code start */
    STARTUP,                     /* startup data structures */
    ROM_VAR,                     /* constant variables */
    STRINGS,                     /* string literals */
    VIRTUAL_TABLE_SEGMENT,       /* C++ virtual table segment */
    NON_BANKED,                  /* runtime routines which must not be banked */
    COPY,                         /* copy down information: how to initialize variables */
                                  /* in case you want to use ROM_4000 here as well, make sure
                                    that all files (incl. library files) are compiled with the
                                    option: -OnB=b */
                                 INTO  /*ROM_C000*/ ROM_4000;
    DEFAULT_ROM,
    MyConstSeg                   INTO  PAGE_38,PAGE_39,PAGE_3A,PAGE_3B,PAGE_3C,PAGE_3D;
    DEFAULT_RAM                  INTO  RAM;
    MyConstSeg1                  INTO  ROM_8000;
    MyVarSeg                     INTO  RAM2;
END

STACKSIZE 0x500

VECTOR 0 _Startup /* reset vector: this is the default entry point for a C/C++ application. */
//VECTOR 0 Entry  /* reset vector: this is the default entry point for a Assembly application. */
//INIT Entry      /* for assembly applications: that this is as well the initialisation entry point */
在定义变量时有2种情况
第一种(自己指定):uint  Uab           @ 0x1001;          //这样Uab就在1001地址也就是RAM2里面
第二种(系统编译):#pragma DATA_SEG DEFAULT
int i,k,m,n;//这样是放在RAM里面,系统自动400+500开始编译。

MAP文件里面:
- VARIABLES:
     AD1COUNT                                  1000       2       2       4   MyVarSeg   
     AD2COUNT                                  1002       2       2       4   MyVarSeg   
     In                                        1004       4       4       4   MyVarSeg   
     _Ia                                       1008       4       4       5   MyVarSeg   
这段是在RAM2里面
Device_Code                                902       2       2       0   .abs_section_902
     Uab                                        904       2       2       1   .abs_section_904
     Ubc                                        906       2       2       1   .abs_section_906
//这段是在RAM里面(400+堆栈的500所以从900开始)

希望对你能有帮助
返回列表