DSP常见编译错误.docx_第1页
DSP常见编译错误.docx_第2页
DSP常见编译错误.docx_第3页
DSP常见编译错误.docx_第4页
DSP常见编译错误.docx_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1.DSP编程技巧到底有什么好资料?话说专门深入讲解这个的资料并不是太多,因为大部分DSP书籍都是讲解算法或者寄存器是怎么使用的,那尽量罗列一下(如有遗漏请在评论区补充),有:(1)DSP C2000程序员高手进阶这本书是当年笔者学习DSP的时候看了好几遍的,讲的非常深入、透彻,可惜早就卖光了并且没有再版。需要的网友可以考虑去图书馆看看,图书馆里最不缺少的就是老版本的书籍了。(2)EEPW牛人业话我们EEPW首页的牛人业话里,已经有大量这方面的总结了,链接太多就不一一列举了,请到/news/articlelist/type/39中阅读。(3)官方资料最权威的当然还是官方资料,特别是TMS320C28x Optimizing C/C+ Compiler Users Guide和TMS320C28x Assembly Language Tools Users Guide。不足之处就在于,它们都像教科书,严谨有余,活泼不足,特别是初入门的人看起来会比较累。(4)参加一些培训好的培训一般都是要付费的,这个要根据自己的实际情况进行取舍了。2. 答疑解惑哪家强?经验的积累,除了自己努力的自学之外,有时候一些难关还是得有别人的帮助才行,可能你花3天搞不定的问题,他一看就想起来是什么原因了。如果是企业客户,那直接联系官方技术支持,很容易就搞定了。或者也可以去官方论坛提问,然后等待解答。对于广大网友来说,直接获得技术支持可能有一定的难度。我们EEPW的论坛的人气充足,对问题的响应速度也是迅雷不及掩耳的,所以有关DSP的问题尽可以到/forum/29/1下提问。前面这两个无关具体技术,但是能起到 “源头”的作用。接下来就是具体的技术问题了,有几十个,我们慢慢来看吧。3. 作为入门者,创建一个最基本的工程需要做哪些事情?最简单的入门方法是从现有的例子上入手,比如购买开发板的话,一般都会附送十几到几十个上手用的例子工程,把它们研究一遍,基本上入门这关就过了。对于C2000 DSP的学习来说,先到TI网站上搜索ControlSUITE软件下载安装,里面的入门视频、工程例子和所有的文档资料都是一应俱全的。如果你买书籍来入门的话,和教编程的书籍一样,大部分都还是以“Hello world”作为第一个程序入手,然后运行程序显示在调试窗口中的。4. 一个定点的C28x起始工程最少需要哪些文件和选项?1) 编译器选项:-v28 -ml -mt -g -pdr w2) 包含main()函数的一个.c或者.cpp程序3) 实时运行支持库文件rts2800_ml.lib4) 链接文件(.cmd)和头文件:一个小的入门工程,一般从别的工程里把它们复制过来就好了,比如可以从ControlSUITE软件的目录下找到对应器件的。5. 一个浮点的C28x起始工程最少需要哪些文件和选项(启用浮点支持)?1) 编译器选项:-v28 -float_support=fpu32 -ml -mt -g -pdr -w2) 包含main()函数的一个.c或者.cpp程序3) 实时运行支持库文件rts2800_fpu32.lib4) 链接文件(.cmd)和头文件:一个小的入门工程,一般从别的工程里把它们复制过来就好了,比如可以从ControlSUITE软件的目录下找到对应器件的。6. 包含CLA和VCU的器件,其入门工程需要哪些额外选项?新器件层次不穷,短短几年时间,包含控制律加速器(CLA)和VCU加速器(用来执行高效 Viterbi、复杂算术运算,16 位快速傅里叶变换 (FFT) 和 CRC 算法)的器件已经有几十种了,而且像CLA、VCU这些技术还在快速地升级中,如果要在代码中用到这些特性,就需要添加-cla_support=cla0和-vcu_support=vcu0这样的选项。7. 编译器选项有那么多中,典型的配置有哪些?C28x编译器的选项非常多,我们用了很长的篇幅来讲解它们。作为典型配置的话,对于C28x的CPU来说(通常我们把DSP的架构划分为CPU+外设,更复杂的则还有FPU、CLA、VCU等额外单元),常用的选项如表1所示。注:如果一个选项没有别名,则代表在使用它的时候直接使用全名,如表1的第二列那样的形式。8. 含有CLA加速器的CPU必备的编译器选项?除了问答4、5、7提到的选项之外,CLACPU对编译器也有一定的要求,如表2所示。表2 CLACPU必备的编译器选项9. “大内存模型”和“小内存模型”的区别是什么?C28x一般使用大内存模型,假设数据可以存放在存储单元的任何可用空间中。小内存模型的提出其实针对的是基于C27x模式CPU的代码,它默认数据是存放在低64k存储空间范围内的,除非使用far关键字进行特别指明。现在的DSP器件片上存储空间普遍比较大,显然使用大内存模型更为合理。10. 什么是“统一内存模型”?统一内存模型“-unified_memory”指在“统一的内存模式”下产生代码。顾名思义,就是把所有的存储空间定义为一个整体,不管它是片上的SRAM、ROM、OTP还是使用XINTF接口的外部的存储单元,通常把外设的寄存器也映射到数据存储空间中。这样编译器在编译时就可以使用PREAD/PWRITE/MAC等指令来处理大部分的内存复制memcpy调用和结构体的分配。11. 实时运行库RTS的作用是什么?在计算机程序设计领域,运行时库是一种被编译器用来实现编程语言内置函数,以提供该语言程序运行时(执行)支持的一种特殊的计算机程序库。这种库一般包括基本的输入输出或是内存管理等支持。在DSP的编程中,它们的作用是用来建立C/C+代码运行的环境,主要包括以下几个方面:1) ANSI/ISO C/C+标准库。2) C的输入输出I/O库。3) 为主机的操作系统提供底层的I/O支持。4)DSP的启动程序_c_int00(可参考/article/262926.htm)。12. RTS中函数的描述从哪里可以找到?在问答11中,RTS包含了四大类内容。前面两者因为是标准C/C+的内容,并没有在TI的文档中给出额外的说明;此外,C+ STL库和它们的API的使用也没有TI官方文档。此时我们可以参考标准C/C+的书籍、资料、网页等。如果希望最权威的参考,可以查阅TI提供的参考链接:1) The Standard C+ Library: A Tutorial and Reference, Nicolai M. Josuttis, Addison-Wesley, ISBN 0-201-37926-02) The C+ Programming Language (Third or Special Editions), Bjarne Stroustrup, Addison-Wesley, ISBN 0-201-88954-4 or 0-201-70073-5.3) C+ online reference at /4) C代码的静态检查工具/当然,作为DSP的开发人员,高效保质地完成代码工作才是最重要,上面那些书籍、链接,请慢慢研究吧。14. 从哪里可以找到RTS库文件?通常情况下,随CCS软件安装而提供的RTS库文件都位于CCS安装目录中,编译器Codegen对应的子目录中。例如,在新版本的CCS6.x中,C28x的编译器位于CCS安装目录下面的toolscompilerc2000_6.2.5lib中(根据编译器版本的不同,倒数第二个目录名字会有相应的变化)。在老版本的CCS中,RTS库文件被默认安装到操作系统的程序目录中,例如C:Program FilesTexas InstrumentsC2000 Code Generation Tools 5.2.4。对于其它一些特殊的库,例如FPU快速运行支持库FastRTS,则在下载安装了FastRTS安装包之后,位于其安装目录之下的lib文件夹中,例如FPUfastRTSV100librts2800_fpu32_fast_supplement.lib。如果安装了controlSuite软件,则可以通过它内置的说明或者搜索功能找到对应的库文件。15. RTS库那么多,我们应该使用哪一个?随着器件类型、特性的不断发展,现在在CCS安装目录下叫RTSxxx.lib的文件已经非常非常多了,那么到底哪些是适合我们使用的呢?对于C28x器件,总结如表3所示。表3 C28x DSP使用的实时运行支持库16. 已经启用了rts2800_fpu32_eh.lib ,为什么还要用rts2800_fpu32_fast_supplement.lib?在含有FPU的器件上,如果在不启用-float_support=fpu32编译器选项的情况下使用浮点数编程,那么它的运算还是CPU来执行的,执行效率就和从定点CPU上直接使用浮点运行进行编程一样低;启用了-float_support=fpu32编译器选项之后,浮点数的加法、减法、乘法等操作则有FPU来完成,执行效率自然要高出很多。使用rts2800_fpu32_fast_supplement.lib库的目的,则是为了调用DSP的ROM中的数学表快速计算一些数学函数,包括atan、atan2、cos、division、isqrt、sin、sincos、sqrt等。如果不使用rts2800_fpu32_fast_supplement.lib库来完成这些数学运算,则编译器默认情况下是使用标准C/C+数学库里的函数来完成这些运算的,效率自然不能和查找ROM中的数学表一样迅速。那么CCS为什么不附带安装FastRTS库呢?这可能和在定点DSP的使用中,IQmath库也不是附带安装是通用的道理吧,其它相类似的,一些信号处理函数库,例如FFT、IFFT等也不是CCS安装的时候附带的,需要自己去下载安装支持程序。17. 如何把RTS库添加到工程文件中?如果使用命令行脚本的方式添加库文件,则使用-l 来添加即可。在图形化界面下,填加RTS库文件的选项在不同版本的CCS中是不一样的,在此把它们一一列出。在CCS6.x和5.x版本下:在工程管理器中的工程名上点击右键,选择properties,然后切换到如下视图。在CCS4.x版本下:在CCS3.3版本以及更低的版本下:针对比CCS3.3更古老的版本:如果不习惯使用Eclipse样式的开发环境,或者某些仿真器不兼容CCS4.x以及以上版本,或者你还在使用最古老的TMS320VC33这样的芯片,否则至少应该升级到CCS3.3这样的版本了。18. 在对库文件进行修改,或者使用不同版本的编译器时,如何重新编译库文件?在编译器版本不低于6.0.2的情况下,我们可以直接使用编译器提供的工具来重新编译RTS库文件,即Mklib程序。如需使用此工具,请参考它的帮助说明文档。在编译器版本低于6.0.2的情况下,我们需要进入编译器codegen的库文件目录中,找到rtssrc.zip这个文件并解压,然后根据其中rtssrc_zip_README.txt里面描述的步骤进行库文件的重新编译。22. 除了使用编译器的优化选项之外,还可以使用什么方法提高程序的性能?编译器的优化选项,只能在代码满足众多选项的要求时,才能得到较好的优化效果。在我们编程的时候,首先要做到心里有数,尽可能使用一些高效的编程方式,例如使用右移操作代替除以2的倍数的操作,可以大幅度地减少代码运行时间等。这些技巧很多是与C/C+的熟练使用所相关的。此外,根据器件的特点,例如是否包含FPU、CLA等,把特定的代码放在不同的区域执行,也能起到提高程序性能的效果;根据代码对性能的要求,把它们运行在不同的位置,例如RAM快于Flash,Flash又快于XINTF等;在器件包含数学表的情况下,使用内建的数序函数库,而不是标准的C数学库等。在此我们可以给出一些提示:1) 代码运行在Flash中一定要使能预读缓冲区,并配置适当的等待状态。一般在各个器件的头文件与外设示例包里都有对应的例子。2) 把时间关键的代码和/常数数组等从Flash复制到RAM中运行在RAM中运行时,最大的指令周期比Flash中运行时要高,其执行速度也要快出不少,所以可以根据需要把实时性能要求较高的程序复制到RAM中运行,具体的方法和实例可以参考/general/docs/litabsmultiplefilelist.tsp?literatureNumber=spra958l下面的Running an Application from Internal Flash Memory on the TMS320F28xxxDSP。3) 评估代码和数据的存储地址的划分,并根据需要修改链接文件i. 如果某段代码和它所读取的数据位于同一个物理内存区间中,则因为它们使用相同的地址总线等资源,无法同时访问,造成了资源的冲突,这会降低程序的性能,所以最好把代码和数据保存在不同的内存区间中。ii. 等待状态(wait)会降低系统性能,因为CPU会执行过多的无用状态且在此期间无法处理别的任务:当CPU读取或者访问存储单元或者外设的时候,该存储器或者外设有可能在CPU默认分配的时间内无法完成数据的传输,此时就需要在CPU的ready信号中插入等待状态,直到数据传输完成才能让CPU继续执行别的任务。C28x器件上,大部分的SARAM都是零等待的,但是在C2833x器件中,有一些模块却不是,例如某些Flash/OTP的访问等。iii. 如果在代码中大量使用两个数据缓冲区,则把两个数据缓冲区存放在不同的RAM模块中有可能会提高代码的性能,因为大量读写同一块RAM区间会产生更多的流水线停滞,造成性能的降低。4) 使用编译器中的统一内存模式-unified_memory此模式把所有的存储空间定义为一个整体,这样编译器在编译时就可以使用RPT与PREAD指令来处理大部分的内存复制调用和结构体的分配。5) 使用Flash和外部存储器如果代码需要在Flash或外部存储器中运行,则在编译时开启-me选项。它将禁止编译器使用快速分支指令(SBF/BF),转而使用普通的跳转指令(SB/B)。BF指令在默认情况下是被启用的,它能够将跳转分支使用的指令周期从7个降低到4个,在零等待状态的SAM中执行时,快速分支指令的预读特性使得它较为高效,但是在非零等待的存储器中执行时,SBF/BF的预读反而造成了性能的下降,此时需要人为地对预读和等待进行规划。6) 使用内联函数在编译时开启内联函数功能,则编译器会自动把多次调用的函数进行内联,大大减少函数调用和返回操作所带来的开销。当然,根据“空间换时间”的原则,开启内联会增加一定的代码尺寸。23. 为什么一个char类型的数组中,每个元素都占用了16bit的地址?这是因为在C28x上,字节(byte)和字(word)是等价的:也就是说它们都是16位或者说16比特(bit)宽的,即sizeof(int) = sizeof(char) = 1。24. sizeof(int) = sizeof(char) = 1貌似与ANSI标准是相违背的?在ANSI/ISO的C定义中,sizeof操作符以字节形式给出了其操作数的存储大小。ANSI/ISO还规定,sizeof操作符取char的值时,返回值为1。因为TMS320C28x中的字节是16位的,char也是16位的,所以sizeof的结果符合ANSI标准的。作为补充,选16位,而不是8位或者别的什么位数作为char的宽度,主要是为了统一寻址的便利,虽然在某种程度上说这增加了一定的存储器空间占用,或者说浪费了一些空间,因为它们在存储空间中制造了一些空洞。25. 如果char是16位的,那么如何高效地访问8位的值?可以使用_byte()和_mov_byte()这样的编译器内联函数。请参考/article/265102.htm。26. 编译结果提示undefined symbols,名字中包含$符号,怎么破?名字中带美元符号的函数,例如FS$MPY, FS$TOL等,都是RTS库里的内置函数,编译器提示我们这些函数未定义,表明我们没有把对应的RTS库给加入到工程中,例如MPY是数学函数,需要添加相关的数学库,例如FPU数学库等。27. 链接器提示“_c_int00 is not defined”,怎么破?在/article/262926.htm这篇文章中,已经分析了_c_int00的含义。找不到_c_int00的话,说明我们遗漏了包含它的RTS库,例如 rts2800_ml.lib、rts2800_fpu32.lib等待,这些RTS库的具体区别在答疑解惑的第15条中已经有对比了(/article/265108.htm)。28. 新版本的编译器中,printf()/sprintf()函数貌似要使用更多的栈?这是因为printf()函数被重新修改了,以支持多个级别的printf格式说明符支持和修正,以减少代码大小和总内存大小(包括bss)。printf由sprintf()间接调用,它使用一个400个元素的大小的局部数组。为了保存一致性,printf()一直都在使用这么大的内存空间,而编译器也在尽量避免使用malloc()进行内存分配。与老版本所不同的的是,此数组以前是静态的,而现在它被保存在.bss,而不是栈中;这样做的目的是,如果用户使用C I/O,则他们往往会在使用合适尺寸的栈的同时尽量减小.bss的使用。29. 如果不需要printf()/sprintf()的全部特性,怎么样才能减小代码体积?初学者往往使用printf打印“Hello World”这样的方式来完成第一个DSP编程的程序,这种方法虽然是非常直观明了的,感觉起来功能也是非常简单的,但是一编译结果发现提示栈的空间不够,或者有“program will not fit into available memory”之类的错误。这是因为标准的printf()/sprintf()提供了非常多的特性支持,造成了在DSP上实现时,产生的代码尺寸非常大。此时我们可以根据需要调整不同级别的格式格式限定符,例如通过链接器的选项,我们可以指定-printf_support=full, minimal或者nofloat, full为默认参数,表示支持所有的格式;nofloat不支持对浮点类型的数据的输入/打印,包括%a,%A, %f, %F,%g,%G,%e和%E,支持其它的字符、定点格式等;minimal:对数据格式的最小支持,只包含了不指定数据宽度和精度标志的整形、字符型或者字符串,即只支持%,%d,%o,%c,%s和%x格式。其详细含义可参考/article/236048.htm。需要注意的是,如果-printf_support使用了不支持的格式,链接器并不能给出特定的实时运行库的错误提示,在使用时要仔细检查。此外,如果不去指定链接器选项,我们也可以修改printf函数默认对应的源程序_printfi.c来实现类似的效果,它的路径一般在编译器的库函数目录下,例如ticcsv6toolscompilerc2000_6.2.5libsrc。在此路径下,有3个printf函数对应的c程序,它们与链接器选项的对应关系如下表所示。由此我们也可以看出,支持全部格式的printf的源程序的大小,达到了最小格式支持下源程序大小的23倍还要多。30. CCS编译器是否支持任何工业标准?1) 所有的TIDSP支持的C语言标准:C89 (ISO/IEC 9899:1990,或者叫NSI X3.159-1989)C99 (ISO/IEC 9899:1999). 不完全支持。2) 不支持的C语言标准:C11 (ISO/IEC 9899:2011)3) 支持的C+标准:C+98 (ISO/IEC 14882:1998)C+03 (本质是C+98的bug修复)4) 不支持的C+标准:C+ TR1C+11 (ISO/IEC 14882:2011)5) IEEE-754 (ISO/IEC/IEEE 60559)标准:TI的ARM和DSP的C/C+编译器支持32位和64位的二进制浮点数运算,能够支持IEEE754标准中大部分特性。6) MISRA-CMISRA C是由汽车产业软件可靠性协会(MISRA,motor industry software reliability association)提出的C语言开发标准,在控制有关的代码中是非常有用的标准,具体使用方法可参考/article/247057.htm。7) 其它标准在工业领域中,safety安全特性在一些应用场合中已经是要求必须具备的功能了,相关的标准包括IEC61508、TV认证等。目前已经有一部分包含硬件safety特性的DSP器件了;如果使用软件来实现这些特性,则目前还需要我们自己来编写代码以支持这样的特征。31. CCS编译器对GCC扩展的支持如何?GNU编译器结合GCC支持许多标准ANSI/ISO C/C+所不支持的特性。在开源应用和Linux等开发中,GCC的编译器gcc和g+等都被广泛使用。所以为了保证对GCC工具所开发的代码的兼容性,TI的编译器也支持某些GCC的扩展特性。目前支持的一些特性基本都包含在GCC4.3中,可查看:/onlinedocs/gcc-4.3.6/gcc/C-Extensions.html。32. 如何了解有关编译/代码产生工具的已知问题,并获得最新进展?老外喜欢用IBM的ClearQuest系统来报告bug并分享解决方案,我们可以使用TI提供的开放链接/cqweb/#/SDo-Web/SDOWP&format=HTML&version=cqwj来报告bug、查看/分享解决方案等,其界面如下图所示:避开老旧的“传统”bug的最好办法当然是定期升级编译器和开发环境了。通过配置,新版本的CCS在启动后会自动检测升级并自动升级,这也简化了我们对开发环境的维护工作。33. 链接文件中包含那么多个段,有什么快速识别的方法?把下面这个例子记牢就好了:/ Global variables x & y = .ebss/ Initial values 2 & 7 = .cinit/int x = 2;int y = 7;void main()long z; / Local variable = .stackz = x + y; / Code = .text34. 为什么我们需要链接文件.cmd?为何编译器不能自动分配存储空间并进行内存管理?在操作系统存在的情况下,这些工作确实不需要我们花费太多的心思。但是在嵌入式的DSP处理中,这样做的主要原因是处理能力和存储空间是十分有限的,必须要我们进行一定的介入,例如我们需要考虑的因素包括:1) 运行速度:在RAM中比在Flash中快,在Flash中又比在外部存储器(使用XINTF)中快。2) 代码是否需要存储在非易失的存储器中(例如Flash)?3) 任务是否是时间关键的?例如需要把某个时间关键的ISR被保存在Flash中,然后运行时复制到RAM里。4) 一些RAM可被DMA模块所访问,而另一些则不行。5) 使用单独的物理RAM模块来避免资源的冲突。例如,在C2000 DSP中,RAM模块都是在单个机器周期内只能访问一次的SARAM(Single-access RAM)。6) 资源是否位于外部存储器中?7) 代码是否需要保存在包含缓存或者预读的存储器中以提高性能?在C2000DSP中,我们几乎见不到缓存或者预读的概念,它们一般出现在包括ARM处理器的器件中。8) 存储器在程序空间、数据空间中是否具有等待状态?9) 是否有需要被代码安全模块CSM所保护的代码?CSM并不能保护所有的代码空间。以上这些因素,在我们编程时也是需要特别关注,甚至是较为头疼的事情,显然让编辑器去自动实现它们,在目前阶段是不可能的(除非编译器的算法有一天能实现一定程度的人工智能)。所以在现阶段,我们需要使用链接器命令文件cmd去描述每个段所需要使用的内存情况。如果我们没有把某一个特殊的或者自定义的段给指定到特定的存储空间中,则此时链接器会自动把它给分配到一个可用的存储空间里,这有可能会影响到程序的执行效果。所以我们要开启编译器的-w选项,这样在在未定义的输出段被创建时,开发环境的控制台窗口中会产生相关的警告信息。35. 虽然可用的存储空间看起来比section的长度要大,但是链接器为何提示“placement fails for object”?这种情况一般是因为段的空间的分配是并不是我们想象中的连续的一个紧挨一个,而是被编译器给“分块”管理了。在内存地址分配时,一个段需要完全适配到页(page)中,或者从页的边界开始连续分配;为了满足这个要求,段在分配到页中时,可能无法完全利用某些页,导致内存地址中产生了间隙(hole),使得实际所需要的内存空间超过了根据变量大小计算出来的理论值。编译器这样做的目的是为了优化数据页(DP)寄存器的加载,达到减小代码尺寸和优化程序性能的目的。例如,针对一个数组,如果数组的长度小于64字(words),则编译器仅需安全地加载DP一次就可以访问数组的全部元素;如果数组长度大于64字,则在访问每64字的数组元素时,编译器仅需加载一次DP,当然如果访问多个64字的数组元素则仍需要多次加载DP。举例说明:在cmd里定义:RAMM1 : origin = 0x000400, length = 0x000400 /* on-chip RAM block M1 */commbuf : RAMM1 PAGE = 1在main.c里定义以下几个变量#pragma DATA_SECTION(sendT, commbuf)Uint16 sendT260;#pragma DATA_SECTION(receT, commbuf)Uint16 receT260;#pragma DATA_SECTION(CntPPR, commbuf)Uint32 CntPPR250;表面上共需260+260+250*2=1020,commbuf正好放得下.但ccs提示空间不够:(run placement fails for object commbuf, size 0x474 (page 1).Available ranges: RAMM1 size: 0x400 unused: 0x400 max hole: 0x400)产生错误的原因是根据DP加载的原则,page被划分为64word的小单元,而数组被存储在连续的、整块的单元上,未使用到的空间不会再分配给其它数组或者变量使用。所以16位260长度的数组实际占用了64*5=320 (64*4=256 FLASHA | FLASHC | FLASHD, PAGE = 0方法三:完整分割法这个名字有点古怪,它本质仍然是把.text分割,目标区域也可以有多个,但是当第一个区域就满足要求时,则只把它分配到第一个区域中,剩余的目前区域实际上未被使用到。在实际编程实现时,这些方法仍然存在一定的限制,包括:1. 在包含控制律加速器CLA 的Piccolo器件中,只有特定的内存区域可被CLA所使用。2. 在含有DMA的器件中,并不是所有的内存都可被DMA所访问。3. 一般情况下,SRAM都是单个机器周期内只能访问一次,但是0等待状态的。但在一些器件中,程序内存控制是包含等待状态的,例如在某些2833x器件中,DMA可访问的数据空间是0等待状态的,但是程序控制是1等待状态的。这些SRAM空间更适合纯数据访问类型的使用。37. 在cmd文件中,可以把连续的Flash模块组合为一个整体的区间吗?答案是可以的。在Flash的烧写中,可以在同一时间被烧写的Flash的最小长度被称为扇区(sector),所以通过把我们的代码进行分区烧写,就可以把它们对齐到扇区。Flash模块结合的方法一:直接合并法以把两个Flash扇区组和为一个段为例:合并前,两个扇区的定义是:MEMORY/ Individual sectors E and F called out in the MEMORY description/.FLASHF : origin = 0x310000, length = 0x008000 /* on-chip FLASH */FLASHE : origin = 0x318000, length = 0x008000 /* on-chip FLASH */.合并之后的Flash区间为:MEMORY/ Sectors E and F merged into one in the MEMORY description/.FLASH : origin = 0x310000, length = 0x010000 /* on-chip FLASH F & FLASH E */.方法二:反其道行之,把段分配到多个Flash模块中,与问答36的方法二是一致的,例如:SECTIONS.text: *(.text) FLASHE| FLASHH38. 在cmd文件中,可以把相邻的SARAM模块组合为一个整体的区间吗?答案是可以的,方法与Flash组合的方法一样。虽然这样做是完全没有问题的,但需要牢记SARAM模块都是单个机器周期内只能访问一次的,所以为了优化程序的性能,最好把代码给分区到不同的物理SARAM模块中,这样可以减少大量读/写操作中的资源冲突。39. 对于DSP/BIOS的工程,如何了解链接的信息?DSP/BIOS 的配置工具生成一个cmd文件,规定如何连接所有DSP/BIOS 生成的程序段,并且默认链接至所有 C/C+ 语言编译程序生成的程序段。 当从 RAM 运行程序时,可能只需要这一个cmd文件就够了。但在当从Flash中执行时,很有可能需要生成且连接一个或多个自定义的程序段。此外,任何配置片载Flash控制寄存器(例如,Flash等待状态)的代码不能从Flash执行。我们也许需要从 RAM(而非Flash)中运行特定时间关键函数来大幅提升性能。 必须创建一个自定义cmd来处理这些我们定义的程序段。可以参考Running an Application from Internal Flash Memory on the TMS320F28xx DSP这个文档,其示例代码在/general/docs/lit/getliterature.tsp?baseLiteratureNumber=spra958&fileType=zip。需要注意的是,这些文档和程序与新版本的CCS中所包含SYS/BIOS并不是完全兼容的。此外,如果我们想使用第三方的操作系统,例如VxWorks、us/OS、INTEGRITY等,则要根据这些RTOS的特点进行内存的分配与管理。43. Error: option -include_path is missing its parameter dir,如何解决?本文引用地址:/article/267640.htm这个错误的发生往往是编译器没有能够正确地解析包含变量或者宏的头文件的路径。解决方法可以利用上图中的Variables选项卡,点击Add,把自定义的变量添加进去,此时CCS会检查该编译器变量是否符合标准。44. Error: unresolved symbols remain,如何解决?出现这个错误说明链接器在符号表中找不到相关的符号定义。在这个例子中,源程序example中使用了函数myfunc,但是在编译生成的所有目标文件(.obj)或者所有的库文件(.lib)中都找不到这个函数。解决的方法自然是找到这个函数从哪里来的?然后把它的源添加到工程中。在使用Stellarisware或者ControlSuite套件中的例子来创建我们自己的工程时,如果忘了使用library选项把库文件添加到链接器的路径里,则经常会出现此错误。这些库文件包括:Stellarisware/Tivaware中的driverlib, grlib, usblib,ControlSuite中的driverlib, IQMath等等。那么接下来的步骤就是添加对应的库文件了。最直接的方法是在工程属性里选择,如下图所示:此外,如果在C+代码中引用C代码的头文件,如果这个头文件是自定义的(而不是系统提供的),则最好在头文件中添加extern C .以方便在C+代码中方便使用#include来引用该头文件。那么问题又来了:C编译器不认识extern C怎么办?此时要使用#ifdef这样的宏来在C中屏蔽它们,即:#ifdef _cplusplusextern C #endif45. Error: placement fails for section xxx,如何解决?这个错误说明我们定义的段超过了指定存储器区间的大小。可以从以下几个方面来解决此问题:1. 检查栈和堆的长度,看看是不是给它们配置了过大的值,导致了在RAM中保存不下去?然后尝试减小它们的长度。2. 尝试使能或者增加编译器的优化级别,未经优化的代码往往需要更多的存储空间。3. 如果使用了I/O代码,则它们会显著增加代码尺寸,例如在很多小容量的器件上,一个printf()函数就能超过存储容量了,此时可以使用printf()的最小格式,请参考/article/266820.htm。4. 可以考虑修改cmd文件,以增加某个段所使用的存储空间的长度;代价是别的存储空间的长度会相应减小,有可能导致新的placement fails 这样的错误产生。具体可参考/article/256732.htm。5. 尝试精简/优化代码,在不影响功能的情况下,使用一些编程技巧来减小代码尺寸。例如,我们可以使用“空间换时间”,或者“时间换空间”的方法,在代码尺寸和执行速度上做一些折衷。比如对于一个滑动傅立叶变换(sDFT),我们既可以使用很大的数组来保存滑动值, 从而实现很高的运算速度;也可以减少运算速度,每个周期只使用几个点来完成计算,这样可以极大地减小存储空间的占用。6. 不到万不得已,不要去考虑更换芯片。但是如果在产品开发的评估阶段,存储空间就已经捉襟见肘了,则还是要提早考虑升级芯片的,不然以后再增加新的功能,或者哪怕是仅仅修正了一个小的bug,有可能就彻底放不进去了。46. Tag_Memory_Model attribute value of 1 that is different than one previously seen (2); combining incompatible files,是神马意思?这个错误表明链接器所链接的目标文件中存在不同的内存模式,比如说有的目标文件使用了大内存模式,而有的使用的是小内存模式。修改的方法则是让所有的文件在链接时都使用相同的内存模式。事实上这种错误出现的场合并不算太多,主要出现在工程中引用了别人提供的某些obj文件或者库文件的时候。在C2000上,新建工程的时候推荐大家统统使用大内存模式(-ml)选项。47. Error: file grlib.lib was built without VFP coprocessor support while a previously seen file was; combining incompatible files,是神马意思?这个错误与上面那个错误的原因是类似的,表明链接器所链接的目标文件中存在不同的浮点支持模式。修改方法则是让所有的目标文件和库文件使用相同的浮点支持-float_support选项。48. 为什么编译的时候总是提示Warning: creating output section xxx without a SECTIONS specification?在使用默认的cmd文件进行编程,而工程中有使用了某些cmd中未明确定义的段的时候,就会出现这个警告。因为没有在cmd中定义这个段,所以链接器会使用默认的算法来创建和分配输出段“XXX”;这样虽然能保证程序的工作,却不被建议这样做,因为它不利于内存地址空间的有效分配和管理。通常来说,最好不要有任何的链接器警告,以消除程序运行时潜在的bug。49. 莫名其妙的gmake: Access is denied。在编译程序的时候,编译器会生成一系列的中间文件,包括obj、lib、asm等等,这个过程被一些带有主动防御系统的杀毒软件和安全软件当作危险行为,因此就被禁止掉了,导致编译失败,如下图所示:所以在编译程序的时候,最好禁用安全软件,不然即使是安全软件没有直接阻止编译,也会跳出各种各样的询问信息,不胜其扰。50. Type xyz or Symbol abc could not be resolved。这些错误一般是由Eclipse CDT (C/C+开发工具)错报出的,而不是由TI本身的编译器所给出的。目前的解决方法是:从CCSv4的工程升级到CCSv5或者更高版本的时候,如果选择的是project-导入工程,一般会有一定的兼容性问题,可能会产生这样的错误。解决方案则是创建一个新的工作区,然后把所有的源程序、库文件、cmd文件等导入到新的工程中,重新配置工程选项,然后再编译。或者干脆忽略CDT的语法错误,方法是在CCS中点击Window-Preferences-General-Editors-Text Editors-Annotations, 选择C/C+ Indexer Markers,然后清除掉所有的选择。51. Warning: build attribute vendor section TI missing in : compatibility cannot be determined。是什么属性丢失了?出现这个问题,说明使用的库文件是由一个老版本的编译/链接工具所创建的,在使用新版本的工具进行编译/链接时,这个老的库文件缺失了某些属性,导致了这个警告的产生。在C2000DSP的开发中,有几个场合特别容易出现此警告: 在新的编译环境中,使用了一个老版本的IQmath库文件。

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论