最近整合各位工程师写的PICCOLO评估版驱动包时发现:当增加的C文件包多了几个后,就不能在RAM内调试了,其会输出信息
>> error: can't allocate .text, size 0000104a (page 0) in PRAML0 (avail:
00000900)
显然是CMD文件中没有为程序申请足够的空间,但是实际上MAIN函数内除了调用初始化中断和时钟外,没有其他函数了。因此一定是编译器没有及时清除掉那些没有用的函数。通过查看MAP文件我们可以查到如下信息:
.text 0 00000000 0000104a
00000000 00000021 main.obj (.text)
00000021 00000065 ZLG2802x_DRV_Adc.obj (.text)
00000086 000000f9 ZLG2802x_DRV_CLK.obj (.text)
0000017f 00000495 ZLG2802x_DRV_GPIO.obj (.text)
00000614 0000014a ZLG2802x_DRV_I2C.obj (.text)
0000075e 000000f0 ZLG2802x_DRV_INT.obj (.text)
0000084e 000000ff ZLG2802x_DRV_INTService.obj (.text)
0000094d 00000451 ZLG2802x_DRV_Pwm.obj (.text)
00000d9e 000000fc ZLG2802x_DRV_SCI.obj (.text)
00000e9a 000000e4 ZLG2802x_DRV_Spi.obj (.text)
00000f7e 00000015 ZLG2802x_DRV_tag_c.obj (.text)
00000f93 00000044 rts2800_ml.lib : boot.obj (.text)
00000fd7 00000019 : exit.obj (.text)
00000ff0 00000018 : ll_aox.obj (.text)
00001008 0000001e : ll_cmp.obj (.text)
00001026 00000009 : _lock.obj (.text)
0000102f 0000001b : args_main.obj (.text)
显然,事实上确实这样,那些压根没用到的函数都被安置了地址空间,而实际上此时需要运行的的主程序可能一辈子也不需要它们帮忙。
因此,肯定是关于优化的问题了,编译器和链接器貌似不是那么聪明,至少从编译和链接“战术”上讲,默认策略是非常保守嘀。
翻了下TI的资料库,找到优化手册,然后试着做如下优化:打开Build Option对话框,其中Complier页 Opt Level选File (-o3), Program Level Opt 选 Program Mode Compilation) (-pm).
然后编译,仍旧因内存空间不够而出现错误。
这时,我们再查看下MAP文件中的.text段:
.text 0 00000000 0000104a
00000000 00000f93 main.obj (.text)
00000f93 00000044 rts2800_ml.lib : boot.obj (.text)
00000fd7 00000019 : exit.obj (.text)
00000ff0 00000018 : ll_aox.obj (.text)
00001008 0000001e : ll_cmp.obj (.text)
00001026 00000009 : _lock.obj (.text)
0000102f 0000001b : args_main.obj (.text)
这一看,很兴奋啊,因为很多乱七八糟的OBJ文件总算聪明的自动开溜了(其实是被迫,哪有那么自觉啊),可仔细瞧瞧,不对啊,main.obj怎么这么大?而且大的惊人!难不成那些自动开溜的obj全部“变身”藏到main.obj内了?为了找到线索,我们把MAP文件往下翻,这些乱跑的obj再怎么藏也总会在MAP文件留下蛛丝马迹嘀,因为说白了,函数、变量啊这些乱七八糟的东东具体怎么在存储空间找到自己的座位还是得听MAP文件嘀,而MAP文件在大局(输入输出段地址空间分派)的决策上又得听CMD文件嘀。好,不罗嗦了,看下我们接着查到了什么:
00000021 _adcClkInit
00000040 _adcSocInit
00000079 _adcSocStart
000001cc _aioDisable
000001b9 _aioEnable
00000f93 _c_int00
0000016b _clkPeripheralDisable
00000158 _clkPeripheralEnable
…………
00000f53 _spiTxIntARegister
00000efb _spififoConfing
…………
其实一大堆,为阅读方便就不全贴出来了,这里可以看出具体的地址分派表中,出现好多压根没调用到的函数,而这些都是在驱动文件内的,也就是那些本该在“开溜”的obj文件内的,这些家伙居然还好意思蹲在这地方!不得不令人“发指”啊!看来我们的优化强度还不够,城管的力度还不够大……
得,加足马力,来个猛的!再次打开Build Option对话框,把其中Complier页Complier页 Opt Level选File (-o3), Program Level Opt 选 No Ext Func/Var Refs (-pm -op2);
编译下,果然老虎一发威,东东全吓跑!
Build Complete,
0 Errors, 0 Warnings, 0 Remarks.
不过,先哲曾经告诉过我们——万事都不能太过头!严重注意:TI的这种优化方式是有前提嘀!具体可以查看TMS320C28x Optimizing C_C++ Compiler User's Guide (Rev. C).pdf,这个手册中会对优化选项有较详细的讲解,比如对-O0、-O1、-O2、-O3的不同优化级别的使用需要注意场合,说白了就是提醒你在使用先进武器的时候别把自己给搭上了^_^(有些函数啊啥的是不能被编译器优化掉嘀,否则后果不堪……)。这方面的东西我们以后专门讲下。
最后不得不再提下MAP文件,这个文件真是好啊,我总习惯编写程序时把它拉到CCS内,编译后就可以查下它这个大管家是如何帮我具体分派函数地址的,比如有时写了个文件,需要查看下它编译后若全部存到DSC内需要多少空间,则可以关闭全部优化选项,然后编译,此时虽然可能因为存储器空间不够而提示错误,但还是可以从MAP文件看到这个文件中的元素在存储器中需要占用的空间大小。一言以蔽之,MAP文件可以提供解决调试中出现的问题的很多线索,的确是个好东东! |