DSP原理及应用-TMS320DM6437 课件 第五章:TMS320DM6437的C语言程序设计与优化_第1页
DSP原理及应用-TMS320DM6437 课件 第五章:TMS320DM6437的C语言程序设计与优化_第2页
DSP原理及应用-TMS320DM6437 课件 第五章:TMS320DM6437的C语言程序设计与优化_第3页
DSP原理及应用-TMS320DM6437 课件 第五章:TMS320DM6437的C语言程序设计与优化_第4页
DSP原理及应用-TMS320DM6437 课件 第五章:TMS320DM6437的C语言程序设计与优化_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

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

文档简介

DSP原理及应用第5章TMS320DM6437的C语言程序设计与优化第5章TMS320DM643的C语言程序设计与优化5.1TMS320C64x系列DSP的C/C++语言的特点5.2TMS320C64x系列DSP的C/C++语言程序设计基础5.3运行时环境5.4DSP的C/C++代码优化5.5C语言与汇编语言混合编程5.6实验和程序实例5.1TMS320C64x系列DSP的C/C++语言的特点5.1.1.TMS320C64x系列C/C++语言特点(1)并不包括完整的C++标准库支持。但是包括C子集和基本的语言支持。(2)支持C的库工具(Clibraryfacilities的头文件不包括:<clocale>、<csignal>、<cwctype>、<cwchar>。(3)所包括的C++标准库头文件为<typeinfo>、<new>和<ciso646>。(4)对bad_cast和bad_type_id的支持并不包括在typeinfo文件中。(5)不支持异常事件的处理。(6)默认情况下,禁止运行时类型的信息(RTTI)。RTTI允许在运行时确定各种类型的对象。它可以使用-rtti编译选项来使能。(7)如果两个类不相关,reinterpret_cast类型指向其中一个类成员的指针,不允许这个指针再指向另一个类的成员。(8)不支持标准中[tesp_ess,[temp.dep]里描述的“在模板中绑定的二相名”。(9)不能实现模板参数。(10)不能实现模板的export关键字。(11)用typedef定义的函数类型不包括成员函数cv-qualifiers。(12)类成员模板的部分说明不能放在类定义的外部。5.1TMS320C64x系列DSP的C/C++语言的特点5.1.2.数据表示1)标识符和常量●标识符的所有字符都是有意义的并且区分大小写,此特征适用于内部和外部的所有标识符;●源(主机)和执行(目标)字符集为ASCII码,不存在多字节字符;●字符常量、字符串常量中的十六进制(Hex)、八进制(Octal)转义序列或者字符串常量具有高达32位的值;●具有多个字符的字符常量按序列中的最后一个字符来编码,如:'abc'='c'。5.1TMS320C64x系列DSP的C/C++语言的特点5.1.2.数据表示2)数据类型类型位数表示方式取值范围最小值最大值char,signedchar8ASCII-128127unsignedchar8ASCII0255short162scomplement-3276832767unsignedchar16Binary065535int.signedint322scomplement-21474836482147483647unsignedint32Binary04294967295long,signedlong402scomplement-549755813888549755813887unsignedlong40Binary01099511627775enum322scomplement-21474836482147483647float32IEEE32-bit1.175494e-383.40282346e+38double64IEEE64-bit2.22507385e-3081.79769313e+308longdouble64IEEE64-bit2.22507385e-3081.79769313e+308pointers,references,pointerItodatamembers32Binary00xFFFFFFFF5.2TMS320C64x系列DSP的C/C++语言程序设计基础5.2.1TMS320C64x系列C/C++程序结构5.2.1.1.TMS320C64x系列C/C++必须包含的文件一个最小的C应用程序项目中必须至少包含以下几个文件。(1)主程序main.c这个文件必须包含一个main()函数作为C程序的人口点。(2)连接命令文件.cmd这个文件包含了DSP和目标板的存储器空间的定义以及代码段、数据段是如何分配到这些存储器空间的。这个文件由用户自己编辑产生。(3)C运行库文件rts6200.1ib(或者和DSP兼容的rtsxxx.lib)C运行库提供了诸如pint等标准C函数还提供了C环境下的初始化函数Cin000。这个文件位于CCS安装目录下的\000\gtools\lib子目录。(4)Vectors.asm如果用户的程序是准备写进外部非易失性存储器并在上电之后直接运行的,那么还必须包含这个文件5.2TMS320C64x系列DSP的C/C++语言程序设计基础5.2.1.2C主程序的一般框架//#include包含语句,定义程序中使用的函数库对应的.h头文件#include“函数库1”//包含头文件#include<函数库2> …//#define定义程序中所有的宏替换#define宏名指定内容//宏定义 …//全局变量声明 变量类型全局变量名;inti,j; //全局变量定义 …//主函数main() voidmain(void) { //局部变量定义 … for(;;) //或者使用while(1) { //数据的输入 … //调用子函数来处理数据 … //数据的输出 … } }//本程序的内部函数定义 函数类型函数名(函数参数列表) { //本函数的局部变量定义 … //本函数中的算法 … }//中断服务程序(函数)的声明interruptvoidfunction_name(void);5.2TMS320C64x系列DSP的C/C++语言程序设计基础5.2.2TMS320C64x系列C/C++语言关键字5.2.2.1.const关键字TMS320C64xC/C++编译器支持ISO标准的关键字const,此关键字可以更好地控制对一定的数据对象进行存储分配。用户可以将const限定词应用到任何变量或者数组,以确保其值不变。5.2.2.2.cregister关键字TMS320C64xC/C++编译器扩展了C/C++语言的功能,通过增加cregister关键字允许高级语言可以访问并控制寄存器。5.2.2.3.innerrupt关键字TMS320C64xC/C++编译器通过增加inerrupt关键字扩展了C/C++语言的功能,该关键字指定一个函数为一个中断函数。5.2.2.4.nea和far关键字T1S320C64xC/C++编译器通过使用near和far关键字扩展了CIC++语言的功能,该关键字来指定函数如何被调用。5.2.2.5.restrict关键字为了帮助编译器确定存储器相关性,可以使用restrict关键字来限定指针、引用和数组。5.2TMS320C64x系列DSP的C/C++语言程序设计基础5.2.2TMS320C64x系列C/C++语言关键字5.2.2.6.volatile关键字优化器会分析数据流,以尽可能地避免存储器的访问。如果用户将依赖于存储器访问的代码写在C/C++程序中,则必须使用volatile关键字以识别这种访问。编译器不会优化任何对volatile变量的引用。5.2.2.7.asm语句TMS320C64xC/C++编译器可以将C6000汇编指令或者伪指令直接嵌入编译器输出的汇编语言文件。改功能是对C/C++语言的扩展,即asm语句。5.2TMS320C64x系列DSP的C/C++语言程序设计基础5.2.3pragma伪指令pragma伪指令告诉编译器如何处理特定的函数、对象或者代码段。TMS320C64xC/C++编译器支持下列伪指令:CODE_SECTIONDATA_ALIGNDATA_MEM_BANKDATA_SECTIONFUNC_CANNOTINLINEFUNC_EXTCALLEDFUNC_INTERRUPTTHRESHOLDFUNC_IS_PUREFUNC_IS_SYSTEMFUNC_NEVER_RETURNSFUNC_NOGLOBAL_ASGFUNC_NOIND_ASGINTERRUPTMUST_ITERATENMI_INTERRUPTFROB_ITERATESTRUCT_ALINGUNROLL5.2TMS320C64x系列DSP的C/C++语言程序设计基础5.2.4初始化静态变量和全局变量ISOC标准要求在程序开始运行前,对没有明确初始化的静态和全局变量必须初始化为0,这一般在程序加载时执行。由于加载过程在很大程度上与目标应用系统特定的环境有关,编译器本身对预初始化变量没有规定,预初始化变量由满足这些要求的应用程序完成。如果加载器不预初始化变量,则可以使用连接器在目标文件中将变量预初始化为0。例如,在连接命令文件中,在.bss段中填充0值,代码如下:SECTIONS{….bss:fill=0x00;…}5.3运行时环境5.3.1存储器模型TMS320C6000编译器把整个存储区当做单个线性存储块(linearblock),并将其分为子代码区和数据区。由一个C程序产生的子代码块和数据块被放在各自连续的存储空间中。编译器假定目标存储器的32位地址空间全是可用的。5.3.1.1.段编译器生成的可重定位的代码块和数据块称为段,采用不同的方式将段分配到存储器保持系统配置不变。TMS320C6000编译器产生如下几种类型的段。(1)已初始化段已初始化段包含数据和可执行代码,C/C++编译器生成的已初始化段如下。●.cinit段:包括变量初始值和常量值。●0.const段:包括字符串文字,浮点常量和在C/C++语言中被声明为const的数据●.switch段:包含大的switch语句的跳转表。●.text段:包含所有的可执行代码。(2)未初始化段存储器中的保留空间,程序在运行时用它来创建和存储变量,C/C++编译器生成的未初始化的段如下。●.bss段:为全局变量和静态变量保留。如果为连接器设定-c选项,则在程序的开始,引导程序会将cinit段的数据(可在OM)复制到bss段。编译器定义全局号$bss,并指定它为bss段的起始地址。●.far段:为声明为far的全局变量和静态变量保留。●.stack段:系统栈。该存储区用于传递函数的参数和为局部变量分配存储器空间。●.sysmem段:为动态存储空间分配保留的存储区。提请动态存储空间分配要求的有malloc、calloc、realloc等函数。如果C/C++程序未使用这些函数,编译器便不生成该段。编译器产生默认.text、.bss和data段,但C/C++编译器不使用.data段。可允许用CODE_SECTION和DATA_SECTIONpragma令编译器生成附加的段。5.3运行时环境5.3.1.2.C/C++系统栈C/C++编译器将栈用于以下几个方面:①保存函数调用后的返回值地址;②给局部变量分配存储空间:③传递函数参数;④保存临时结果。5.3.1.3.动态存储区分配动态存储器分配不是C语言的标准组成部分。TMS320C6000编译器提供的运行时支持程序库包括的函数有malloc、calloc和realloc,这些函数允许在运行时为变量动态地分配存储器空间。5.3.1.4.存储器模式(1)小存储器模式系统的默认模式。要求整个.bss段限制在32KB(32768B)范围的存储空间内,也就是程序中静态和全局变量所占用的存储空间必须加起来小于32KB。编译器在运行初始化期间设置数据页指针(DP,即B14)指向.bss段的起始地址,然后编译器便能够直接寻址访问bss段中的所有对象,而无须改变DP的值。(2)大存储器模式不限制.bss段的大小,即静态和全局变量的存储空间的大小不受限制。然而当编译器访问bss段中的一个全局或静态变量时,必须首先将该对象的地址读出寄存器中。为了完成该任务,需要两个额外的汇编指令。5.3运行时环境5.3.2

中断处理当C/C++环境初始化时,启动程序并禁止中断。若系统使用中断,必须手动设置所需的中断允许或手动屏蔽某些中断。该操作对C/C++环境没有影响,也可以使用asm或汇编语言函数来完成5.3.2.1.中断中保存寄存器当C/C++代码被中断时,中断服务程序必须保存所有用到的寄存器,该寄存器包括中断服务程序使用的、以及中断服务程序调用其他函数时需要使用的。如果中断服务程序是由C/C++语言写的,编译器会完成寄存器保存。5.3.2.2.使用C/C++中断服务程序C/C++中断服务程序和其他C/C++函数一样,可以使用局部变量和寄存器变量,但是,不能有参数和返回值。C/C++中断服务程序可以在栈中给局部变量分配32KB空间。例如:interruptvoidexample(void){…}5.3运行时环境5.3.3

系统的初始化运行一个C/C++程序之前,必须建立C/C++运行时环境。这个工作是由C/C++引导程序调用c_int00函数完成的,该函数的源代码包含在boot.asm模块中,该模块包含在运行时支持源程序库rts.src中。系统运行开始,跳转到c_int00函数或调用c_int00函数,通常是硬件复位中断的中断服务程序调用它。必须把c_int00函数和另一个对象模块连接起来。这个连接过程如下:使用-c或者-cr连接选项,并在连接器输入文件中包含一个标准的运行时支持程序库。当C/C++程序连接完成后,连接器在可执行的输出模块中将程序入口点的值设置为符号c_int00,但是这没有使用硬件复位中断服务程序自动地跳转至c_int00。5.4DSP的C/C++代码优化5.4.1C/C++代码的优化流程在编写和调试DSPC/C++程序时,为使C6000代码获得最好的性能,一般按图所示的流程分3个阶段,每个阶段完成的任务如下:5.4DSP的C/C++代码优化5.4.2分析C代码的性能①代码性能的主要衡量方法之一是代码运行占用的时间,使用C/C++语言的clock()和printf()函数可以实现计时和显示特定代码的功能,为了达到这一目的,可以利用独立的软件模拟器运行这段代码。②利用动态调试器(debugger)中的剖析(profile)模式,可以得到一个关于代码中特定代码段执行情况的统计表;该剖析结果会存储在以.vaa为扩展名的文件中。③在CCS中使用动态调试器中的中断、clk寄存器和RUN命令可以跟踪特定代码段所占用的CPU时钟周期数,使用“ViewStistis”来观察使用的周期数。④在代码中影响性能的主要代码段通常是循环。优化一个循环,最容易的方法是抽出该循环,使之成为一个单独的可重新编写、编译和运行的文件。5.4.3.选用C编译器提供的优化选项优化-o:使能软件流水和其他优化方法。-pm:使能程序级优化。-mt:使能编译器假设程序中没有数据存储混淆,可进一步优化代码。-mg:使能分析(profile)优化代码。-ms:确保不产生冗余循环,从而减小代码尺寸。-mh:允许投机执行。-mx:使能软件流水循环重试,基于循环次数对循环试用多个方案,以便选择最佳方案。5.4DSP的C/C++代码优化5.4.4软件流水在编译代码时,可以选择编译器的-o2或-o3选项,编译器将根据程序尽可能地安排软件流水线。使用软件流水线还有下面几点限制:(1)循环结构不能包含代码调用,但可以包含内联函数;(2)循环计数器应该是递减的;(3)循环结构不能包含break,if语句不能嵌套,条件代码应当尽量简单;(4)循环结构中不能包含改变循环计数器的代码;(5)循环体代码不能过长,因为寄存器(32个)的数量有限,应该分解为多个循环;(6)在软件流水线的运用上,尽量使复杂的循环分解成简单的小循环,以避免寄存器的数量不够;对于过于简单的循环,应该适当展开,以增加代码数量,增加流水线中的迭代指令。5.4DSP的C/C++代码优化5.4.5使用内联函数(Intrinsics)内联函数是C64x编译器提供的专门函数,它们与嵌入式的汇编指令一一对应,C编译器以内联函数的形式支持所有C语言代码不易表达的指令,其目的是快速优化C源程序。在C源程序中调用内联函数,与调用一般的函数相同,只不过内联函数名称前有下划线作特殊标识。当汇编指令功能不易采用C语言表达时,可采用内联函数表示。Intrinsics是直接与C6000汇编指令映射的在线函数,不易用C/C++语言实现其功能的汇编指令都有对应的intrinsics函数,使用方法与调用函数一样,也可使用C/C++变量。如以下程序:5.4DSP的C/C++代码优化5.4DSP的C/C++代码优化【例5-4】执行饱和加法的程序如下,考虑如何精简代码。intsadd(intx,inty)intresult;result=x+y;if(((x^y)&0x0000000)==0)if((resultx)&0x0000000)result=(x<0)?0x0000000:mf;returmresult);源程序由普通的C语言代码写成,执行需要多个周期,利用TMIS320C6000编译器提供的内联函数,只需要一条指令就可以完成上述程序功能,可快速优化C语言代码。result=_sadd(x,y)5.4.6调整数据类型C64xDSP内部数据总线和寄存器宽度是32位的。一般遵守的规则如下:(1)在使用过程中,注意int和long两种类型的宽度不一致,long型数据为40位,会产生额外的指令和占用更多的功能单元。(2)在使用loopcounts时应尽量使其为int型或unsignedint型数据,以避免不必要的符号位扩展。(3)尽量使用short类型进行乘法运算,因为这种数据类型适应C6000中的16位乘法器。如进行一次short*short运算只需1个时钟周期,而进行一次int*int运算则需5个时钟周期。5.4DSP的C/C++代码优化(4)循环计数器应使用int或无符号int类型,不用short。(5)short型数据的int处理,C64xDSP具有双16bit扩充功能,芯片能在一个周期内完成双16bit的乘法、加减法、比较和移位等操作。在设计时,当对连续的short型数据流操作时,应该转化成对int型数据流的操作,这样一次可以把两个16位的数据读入一个32位的寄存器,然后用内部函数来对它们处理(如_sub2等)。充分运用双16bit扩充功能,一次可以进行两个16bit数据的运算,速度将提升一倍。5.4DSP的C/C++代码优化5.4.7基于Cache的程序优化C64x系列采用了两级Cache的存储器结构用于对程序和数据的缓存,Cache的使用较好地解决了低速片外数据存储和高速CPU间的矛盾。对Cache进行优化主要是从提高Cache命中率的角度来进行的,如果Cache中的数据能多次被重复利用,即DSP运算单元可直接从高速Cache中访问数据,而不需要访问慢速的存储器,就避免了DSP的数据访问等待时间。在实际编码时,一般把L2配置为Cache和SRAM混合使用模式。程序使用的一些关键数据段和代码段放入片内内存中,在片内和片外存储器中分别设置一个用于动态分配内存的栈heap,动态内存分配函数MEM_alloc可以方便地指定在哪个堆栈里开辟动态内存空间。

5.4DSP的C/C++代码优化C语言和汇编语言的混合编程方法主要有以下几种,(1)独立编写C程序和汇编程序,分开编译或汇编形成各自的目标代码模块,然后用链接器将C模块和汇编模块链接起来。例如,主程序用C语言编写,中断向量文件(vectorasm)用汇编语言编写。这种方法工作量大,但是比较灵活,能做到对程序的绝对控制。(2)在C/C++代码中使用内核函数直接调用汇编语言。(3)在C程序中使用汇编语言变量和常量。(4)在C程序中直接内嵌汇编语句。用此种方法可以在C程序中实现C语言无法实现的一些硬件控制功能。5.5.C语言和汇编语言混合编程5.5.1在C/C++代码中调用汇编语言模块C/C++代码可以访问定义在汇编语言中的变量和调用函数,并且汇编代码可以访问C/C++的变量和调用C/C++的函数。汇编语言和C/C++语言接口需遵循如下的规则:(1)所有的函数,无论是使用C/C++语言编写还是汇编语言编写,都必须遵循寄存器的规定。(2)必须保存寄存器A10~A15、B3和B10~B15,同时还要保存A3。如果使用常规的堆栈,则不需要明确保存堆栈。即只要任何被压入堆栈的值在函数返回之前被弹回,汇编函数就可以自由使用堆栈。任何其他寄存器都可以自由使用而无须首先保存它们。(3)中断程序必须保存它们使用的所有寄存器。5.5.C语言和汇编语言混合编程(4)当从汇编语言中调用一个C/C++函数时,第一个参数必须保存到指定的寄存器,其他的参数置于堆栈中。只有A10~A15和B10~B15被编译器保存。C/C++函数能修改任何其他寄存器的内容。(5)函数必须根据C/C++的声明返回正确的值。整型和32位的浮点值返回到A4中。双精度、长双精度、长整型返回到A5:A4中。结构体的返回是将它们复制到A3的地址。(6)除了全局变量的自动初始化外,汇编模块不能使用.cinit段。(7)编译器将连接名分配到所有的扩展对象。因此,当编写汇编代码时,必须使用编译器分配的相同的连接名。在汇编语言中定义的在C/C++语言中访问或者调用的对象或者函数,都必须以.def或者.global伪指令声明。这样可以将符号定义为外部符号并允许连接器对它识别引用。下例为C/C++语言调用汇编函数的程序。C程序:extern”C”{ externintasmfunc(inta); /*声明外部函数*/ intgvar=4; /*定义全局变量*/}voidmain(){ inti=5; i=asmfunc(i); /*调用函数*/……}汇编程序:.global_asmfunc.global_gvar_asmfunc:LDW*+b14(_gvar),A3NOP4ADDa3,a4,a3STWa3,*b14(_gvar)MVa3,a4Bb3NOP55.5.2用内嵌函数访问汇编语言TMS320C6000编译器识别若干的内嵌操作。内嵌函数可以表达C/C++语言中较难处理且不易表达的汇编语句的含义。内嵌操作的使用类似于函数,内嵌操作可以像普通函数一样使用C/C++变量。内嵌操作以下画线开头,访问的方式类似于函数。例如,intxl,x2,y;y=_sadd(x1,x2);其中内嵌函数int_sadd(intsrcl,intsrc2)对应的汇编指令为SADD5.5.C语言和汇编语言混合编程5.5.3在C/C++语言中嵌入汇编语言在C/C++源代码中,可以使用asm语句将单行的汇编语言插入由编译器产生的汇编语言文件。该功能是对C/C++语言的扩展,即asm语句。该语句提供了C/C++语言不能提供的对硬件的访问。asm语句类似于调用一个名为asm的函数。其参数为一个字符串常量。语法格式为:asm("汇编正文"):如:asm("RSBXINTM");/*开中断*/asm("SSBXXF");/*XF置高电平*/asm("NOP");编译器将参数串直接复制到编译器的输出文件,汇编正文必须包含在双引号内。所有的字符串都保持它们原来的定义。使用asm

温馨提示

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

评论

0/150

提交评论