基于C语言的DSP芯片开发补充:C语言、汇编语言程序设计特点汇编语言:执行速度快,但程序开发的效率低、难度大。可读性和可移植性差。TMS320C54XC语言:开发效率高。修改和移植都比较方便。能调用汇编程序。C编译器有很强的优化功能优化效率从15%提高到35%。某些情况下C代码的效率甚至接近于手工汇编的效率但在某些场合无法取代汇编,不能最佳利用DSP芯片的内部资源,如C54x提供位反转寻址、滤波等,有时甚至无法用C语言实现,如标志位/寄存器设置等。常采用:C语言和汇编语言的混合编程关键代码用汇编编程。以最佳利用DSP芯片软硬件资源,也可利用DSP开发商提供的优化算法库(汇编程序)一般性的代码均采用C语言编写。软件调试工具也支持C源码,C/汇编混合模式优化的C编译器C源文件C编译器汇编源文件汇编器COFF目标文件链接器可执行COFF文件C编译器的基本功能对C文件进行文法分析,生成.IF文件对代码进行多级优化,以改进C/C++程序的效率,生成.OPT文件生成汇编程序.ASM文件优化器使用了几种先进的优化技术。优化选项的激活,“-o,-x”选项,多级优化(共3级:0、1、2)-g调试选项C源码调试开关参数,调试时选中,则优化功能被抑制调试时不用优化编译,程序调试成功后再用优化方法分为两类C语言通用优化1.优化与循环有关的变量2.优化跳转3.简化控制流4.数据流优化等DSP芯片的特定优化1.采用块循环块重复指令、并行指令、乘累加、延迟跳转、自动增量寄存器寻址等2.充分使用辅助寄存器、累加器3.数组尽量用寄存器间接寻址C应用程序的开发过程需要以下几种类型的文件.C源文件.lib库文件,如rts.lib,evm54.lib等(汇编无).cmd文件(与汇编源程序有区别!)C编译器产生的段四个已初始化的段.text:可执行代码、编译器产生的常数.cinit:已初始化全局变量和静态变量.const:已初始化的字符串常量、全局常量和静态常量,与关键字const有关。.switch:大型的switch语句的跳转表三个未初始化段.bss:未初始化全局变量和静态变量.stack:系统软件堆栈.sysmem:动态存储器为malloc,calloc,realloc等函数分配存储器空间.cmd文件举例(C应用程序)-stack400h-heap100h-lrts.libMEMORY{PAGE0:VECT:o=0ff80h,l=80hPRAM:o=100h,l=1f00hPAGE1:DRAM:o=2000h,l=1000h}SECTIONS{.vectors:{}VECTPAGE0.text:{}PRAMPAGE0.cinit:{}PRAMPAGE0.switch:{}PRAMPAGE0.const:{}DRAMPAGE1.bss:{}DRAMPAGE1.stack:{}DRAMPAGE1.sysmem:{}DRAMPAGE1}cmd文件总结(C应用程序).text,.cinit,.switch段链接在程序存储空间(PAGE0),可映射到ROM或RAM.const,.bss,.stack,.sysmem段链接在数据存储空间(PAGE1)..const,可映射到ROM或RAM.bss,.stack,.sysmem,只能映射到RAMC中存储器映射寄存器的使用#defineTIM*(int*)0x24#definePRD*(int*)0x25#defineTCR*(int*)0x26#defineIMR*(int*)0x0#definePMST*(int*)0x1d#defineSPSA1*(unsignedint*)0x48注意:每个存储器映射寄存器所对应的存储单元地址。C中存储器映射寄存器的使用main(){IMR=0x8;TCR=0x41f;TIM=0;。。。。。。}汇编程序:STM#0008H,IMRSTM#41fh,TCR常用关键字ioport关键字允许访问DSP的I/O端口空间。interrupt关键字中断关键字:指定将函数作为中断函数处理。Ioport关键字举例:ioportunsignedintport3002,port3003;main(){inti;for(;;){i=port3003;/*读端口数据*/i=i&0xff;port3002=i;/*向端口写数据*/}}汇编程序LD#i,DPPORTR3003h,iANDM#0ffh,iPORTWi,3002h说明:3002h:EVM板上指示灯控制寄存器3003h:DIP拨动开关控制寄存器程序功能:通过开关控制不同的指示灯亮Interrupt关键字应用举例voidinterrupttime(void){。。。。。}汇编程序vectors.asm。。。。。int2:RETENOPNOPNOPtint:B_time.ref_timeNOPNOP。。。。。。系统初始化C_int00函数系统开始运行时,由硬件复位调用该函数。链接器将程序入口点设置为_c_int00。功能:定义堆栈段.stack将.cinit的数据拷贝到.bss段设置页指针DP调用main()函数。汇编与C程序设计的区别工程中是否包括库文件rts.lib。编译选项的设置不同。汇编:执行时直接从用户指定入口开始,常见标号为“start”。C:执行时,先调用C标准库中的初始化程序(入口标号为“_c_init00”)。编译时,出现如下提示:warning:entrypointsymbol_c_int00undefinedC:可能是没有添加库文件rts.lib汇编:没有设置入口点(如:start)C54X系列DSP的C语言开发C和汇编混合编程的3种方法独立编写C和汇编程序,各自形成.obj1和.obj2等,再链接C中嵌入汇编语句,完成C中无法实现的硬件控制,寄存器初始化等编写C程序,对C编译器生成的汇编程序,进行手工优化和修改在C程序中访问汇编程序变量在汇编中:用.bss命令定义变量;用.global命令定义为外部变量。在变量名前加“_”。在C中:用extern说明为外部变量举例:汇编程序:.bss_var,1.global_varC程序中:externintvar;………………var=1;在汇编程序中访问C程序变量在C中:说明为全局或静态变量。在汇编中:用.global命令定义为外部变量,且在变量名前加“_”。举例:在C中:inti;intx;main(){…}在汇编中:.global_i.global_x‘C54x函数调用规范和堆栈的使用C系统的堆栈机制寄存器:SP:堆栈指针,指向堆栈顶部AR7:必要时,用作帧指针增长方向:从高地址向低地址增长函数调用规范调用函数需进行的操作:传递参数反序入栈,第一个参数放进累加器A调用函数调用完毕,弹出先前压入堆栈的传递参数子程序(函数)需进行的操作:入口处:若函数修改AR1,AR6或AR7,则保护相应寄存器的值SP减去一个常数,为局部帧和局部参数区分配存储器其中,常数=局部帧长度+局部参数区长度函数调用规范子程序(函数)需进行的操作:出口处若子程序有返回值,则返回值放入累加器A中SP加上一常数,恢复局部帧和局部参数区若AR1、AR6和AR7已保护,则恢复它们的值返回函数调用时堆栈的使用情况局部参数区和局部帧保护寄存器返回地址参数2….参数n调用函数局部变量低地址高地址参数1累加器ASP举例被调函数add():.global_add.text_add:PSHMAR1PSHMAR6PSHMAR7FRAME#-15调用函数:externintadd();inti,a,b,c;main(){…………i=add(a,b,c);………}………….FRAME#15POPMAR7POPMAR6POPMAR1RET举例:C和汇编混合编程/*example.c*/externintadd();inta,i,result,b[10];main(){a=1;for(i=0;i10;i++)b[i]=i+1;result=add(a,b);}举例:(续)汇编函数_add:.titleadd.asm().mmregs.text_add:FRAME#-4NOPLD*SP(5),BSTLMB,AR2STLA,*SP(2)RPT#9ADD*AR2+,ASTLA,*SP(1)()RET思考1。画出此时堆栈的使用情况图2。把程序补充完整3。程序执行到以下语句时,累加器A的值分别为多少?(1)STLA,*SP(2)(2)STLA,*SP(1)4。NOP语句能否删除?5。程序执行后,主函数中变量a,i,result和数组b[10]各元素的值分别为多少?6。在调用函数时,各调用参数及函数返回值分别是怎样传递的?链接命令文件(volume.cmd)-stack10hMEMORY{PAGE0:VECT:o=0ff80h,l=80hPRAM:o=100h,l=1f00hPAGE1:DRAM:o=2000h,l=1000hDRAM1:o=4000h,l=2000h}链接命令文件(续)SECTIONS{.text:{}PRAMPAGE0.data:{}PRAMPAGE0.cinit:{}PRAMPAGE0.switch:{}PRAMPAGE0.const:{}DRAMPAGE1.bss:{}DRAMPAGE1.stack:{}DRAM1PAGE1.vectors:{}VECTPAGE0}堆栈使用情况观察各变量的值访问参数和局部变量的方法C编译器置CPL=1可采用直接寻址方式,SP加一偏移量如:ADD*SP(4),A注:直接寻址方式,只能最多访问连续的128个单元当偏移量大于127时,可用辅助寄存器代替SP,采用间接寻址方式如:MVMMSP,AR7ADD*AR7(129),A