DSP第八章C语言编程基础课件_第1页
DSP第八章C语言编程基础课件_第2页
DSP第八章C语言编程基础课件_第3页
DSP第八章C语言编程基础课件_第4页
DSP第八章C语言编程基础课件_第5页
已阅读5页,还剩48页未读 继续免费阅读

下载本文档

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

文档简介

第8章

C语言编程基础为了提高程序开发的效率,同时使程序能与高级语言接轨,目前所有生产DSP芯片的公司都提供了C语言编译器。这样,除了对于一些运算量较大或对运算时间要求很严格的程序代码外,一般性的代码都可采用C语言编程,从而缩短程序的开发周期。C编译器还同时提供了汇编语言接口,可使汇编模块方便地被C语言调用。(1)C编译器(2)C代码优化(3)C代码链接(4)C语言(5)C运行环境和库函数以上5部分不再关注C语言本身的语法,而是关注如何在CCS集成环境中对拥护已经编写好的C代码有效地进行编译、汇编和链接,以生成可执行代码这样的工程问题。CCS开发环境可以看成是一个大的软件包,里面包含了源代码编辑器,以及工程文件组织、编译和调试等一切功能模块。该软件包里,shell程序可以完成3个功能:编译、汇编和链接。shell程序缺省在C盘安装时,被安装在C:\ti\c2400\cgtool子目录下,对应的文件名为dspcl.exe。 (1)编辑器:包括分析器、优化器、代码产生器。把C语言程序编译成汇编语言程序。 (2)汇编器:把汇编语言源代码或C语言已经编译成汇编语言代码进行汇编,以产生COFF目标文件。 (3)链接器:将文件链接,产生可执行的目标文件。8.1.2Shell程序8.1.3C代码优化

C编译器中含有一个C优化程序。启用C优化程序可以提高程序执行速度,减少C程序代码长度。对于C语言,可以采用简化循环,使用软件流水线,重新安排、语句和表达式以及将变量分配到寄存器等方法实施优化。在CCS中,选择菜单Project/BuildOptions选项,可以直接在弹出的对话框中对优先级别进行设置。8.2C程序代码链接

C编译器和汇编语言工具为用户链接程序提供了以下两种方法。(1)先编译各个模块,最后将他们链接在一起。(2)一次执行Shell程序的dspcl命令,直接完成各个模块的编译、汇编和链接。在CCS集成环境下,还有少量设置CCS环境和工程文件组织工作需要人工干预。为链接C程序,需要DSP开发人员做以下工作:(1)把运行支持库包含到工程文件中;(2)指定程序运行时的初始化类型;(3)确定如何将由C语言程序编译、汇编和链接产生出的可执行代码分配到物理存储器中。 boot.obj包含了用于初始化运行环境的代码和数据。该模块执行以下任务:(1)建立堆栈;(2)处理运行时,初始化表和自动初始化全局变量;(3)调用C语言主程序main();(4)当C语言主程序main()结束时,调用exit()。

boot.obj中有一个重要的汇编语言函数_c_int0。它是boot.obj中的起点。链接时,_c_int0被自动定义为程序的入口点。如果程序从复位开始运行,则应将复位向量转移到_c_int0,以便DSP首先执行_c_int0。8.2.2指定初始化类型用C语言编程时,会根据需要定义全局变量和静态变量。有些全局变量和静态变量具有初始值,有些全局变量和静态变量没有初始值。C编译器对C程序编译后,为具有初始值的全局变量和静态变量建立了一个专门的数据块.cinit。该块在程序运行后调入到RAM的.bss中。.cinit调入到RAM中有两种方法: (1)在运行时,自动初始化全局变量和静态变量; (2)在加载时,自动初始化全局变量和静态变量。 当创建新工程时,第一种是缺省状态。8.2.3把块分配到物理存储器中把块分配到物理存储器中就是把程序和数据分配到物理存储器中。当使用C编译器对C程序编译后,可产生数据块和代码块。这些块根据各种不同的应用系统硬件配置和扩展情况,可以使用不用的方法将这些块分配到物理存储器中。8.3.2创建main()函数在C语言应用软件中,用户必须定义一个main()函数作为自己应用程序的开始。因为系统完成C语言环境设置后,boot.obj会自动调用main()函数作为程序的开始。因此,程序员在程序中编写main()函数是一种预定,也是一种强制。voidmain(void){sys_ini();for(;;){delay();/*xf管脚置低*/asm("clrcxf");delay();/*xf管脚置高*/asm("setcxf");}}8.3.3创建2407芯片初始化函数初始化内容包括: (1)2407芯片初始化; (2)工程应用中所甬道的片内外设初始化; (3)片内外存储器初始化; (4)应用系统硬件接口初始化。8.3.4创建假中断处理函数(1)2407工作时,如果意外引发了内核级中断,但是却没有低层外设中断向量装入外设中断寄存器中时,假中断向量0000h装入PIVR;(2)CPU执行一个软件中断指令INTR时,使用了参数1~6,企图用软件中断去服务于外设中断INT1~INT6。这显然是一个错误,这时,假中断向量装入PIVR;(3)中断请求线发生故障,外设发出中断请求,而其INTn标志却在CPU应答请求之前被软件清0,此时,外设中断的请求可能还没有被中断控制器确认,中断控制器也不知道哪个外设中断向量应装PIVR,这时,假中断向量装入PIVR

.interruptvoidnothing()//假中断子程序{return;}8.3.5_c_int0函数在运行C程序之前,用户必须首先建立起C语言运行环境。

建立C语言运行环境的函数在库rts2xx.lib中。把_c_int0函数作为硬件复位后的中断矢量入口来运行_c_int0函数。

rsvectB_c_int0

这样,当系统复位后,通过执行一条无条件转移指令来调用_c_int0函数,以建立C语言运行环境。_c_int0函数初始化C环境时执行了如下任务:

(1)为系统堆栈定义一个名为.stack的块,并建立初始化堆栈和帧指针; (2)将.cinit块的初始化数据表中的数据复制到.bss块,对全局变量和静态变量进行初始化; (3)调用main函数,开始运行C程序。8.4.2C语言标准库函数的使用

TI公司的C编译器提供了C语言标准库函数。它与boot.asm等一起封装在rts2xx.lib中。

在使用标准库函数时,首先要声明这一函数。TI公司的所有标准库函数以分类的形式在不同的头文件中声明,全部声明库函数的头文件为assert.h、limits.h、stddef.h、ctype.h、math.h、stdlib.h、setjmp.h、string.h、stdarg.h、time.h、和ioports.h。为了使用一个库函数,用户必须首先使用#include来包含声明函数的头文件。8.5TMS320C24xC语言程序开发TMS320C24xC语言具有特定的运行环境,为了确保C语言程序正确运行,C语言程序开发必须维护这个环境。8.5.1存储器模式TMS320C24x的C编译器将存储器分为程序存储器和数据存储器。程序存储器包含可执行代码,数据存储器包含外部变量、静态变量和系统堆栈。

由C程序生成的每一块代码或数据存放于存储空间的一个连续块中。

存储器映射及代码和数据存储空间的分配由链接器决定。编译器不考虑可用存储空间类型,也不考虑存储空间是否可以被代码和数据使用或者存储空间是否保留以用于I/O或控制。编译器只生成可重新分配的代码,链接器完成将代码和数据分配到合适的存储空间。.text、.cinit和.switch块通常被链接到ROM或RAM,必须处于程序存储器中;.const块可以被链接到ROM或RAM,但必须处于数据存储器中;.bss、.stack和.sysmem块必须被链接到RAM,并必须处于数据存储器中。这些块根据不同的系统配置以不同的方式被放到存储器中。链接器将不同模块相同的块组合为输出块。完整的程序由这些输出块组成,包括汇编器的.data块。2、C系统堆栈C编译器使用软件堆栈实现以下功能: (1)分配局部变量 (2)给函数传递参数 (3)保存处理器状态 (4)保存函数返回值 (5)保存临时变量 (6)保存寄存器堆栈运行时从低地址向高地址增加。编译器使用2个辅助寄存器管理堆栈: (1)AR1为堆栈指针(SP)。指向当前堆栈顶部。 (2)AR0为帧指针(FP)。指向当前帧的起始处。每个函数调用会在堆栈顶创建一个新的帧,用于保存局部和临时变量。4、静态和全局变量的存储器分配在C程序中说明的每一个外部或静态变量都是被分配给一个唯一的连续空间的,空间的地址由链接器确定,编译器保证这些变量的空间分配多个字,以便每个变量按字边界对准。5、结构的对准编译器为结构分配空间时,它将分配足够的字以包含所有的结构成员。在一组结构中,每个结构开始于字边界。6、域的对准非域类型对准于字的边界。对域分配足够多的位,相邻域组装进一个字的相邻位,但不跨越两个字。如果一个域要跨越两个字,则整个域将分配到下一个字中。8.5.2存储器规则

TMS320C2xx编译器严格规定:在C语言环境中,特殊的寄存器和特殊的操作联系在一起。如果要将汇编语言与C程序接口,必须遵循对这些寄存器的规定。寄存器规则定义编译器如何使用寄存器和在函数调用时如何保存值。寄存器使用调用是否保存AR0帧指针是AR1堆栈指针是AR2局部变量指针否AR2~AR5表达式分析否AR6~AR7寄存器变量是Accumulator表达式分析/返回值否P表达式分析否T表达式分析否上表列出了编译器如何使用寄存器,并说明了在函数调用时寄存器在保存值时所起的具体作用。域名称预设值修改ARP辅助寄存器指针1是C进位位-是DP数据页指针-是OV溢出位-是OVM溢出模式-是PM乘积移位模式0否SXM符号扩展模式-是TC测试控制位-是上表列出了编译器所使用的所有状态位。预设值是编译器在函数进入和返回时的期望值,修改栏是编译器产生的代码是否修改该域。2、堆栈指针、帧指针和局部变量指针编译器创建和使用自己的软件堆栈以用于保存函数返回地址、分配局部变量和给函数传递参数。当函数需要存储局部变量时,可以在堆栈中创建自己的工作空间(局部帧)。局部帧在函数入口时分配,在函数返回时释放。系统提供堆栈指针(SP)、帧指针(FP)和局部变量指针(LVP)3个寄存器来管理堆栈和局部帧。寄存器AR1用做堆栈指针。堆栈从低地址向高地址增长,SP指向堆栈中下一个可用的字。寄存器AR0用做帧指针。FP指向当前函数局部帧的起始地址。PF直接指向局部帧的第一个字,该字用做临时存储单元,可以用于实现寄存器到寄存器值的传递,同时在创建可重入C函数时也必须使用该存储单元。寄存器AR2用做局部变量指针,所有存储在局部帧的对象包括参数都要通过LVP间接引用。3、寄存器变量寄存器变量是指存储于寄存器而不是RAM的局部变量或编译器临时变量。(1)不使用优化器不使用优化器时,编译器至多为使用register关键字的两个变量分配寄存器。变量必须在参数列表中或函数的第一块中定义。编译器采用AR6和AR7作寄存器变量寄存器。AR6保存第一个变量,AR7保存第二个变量。(2)使用优化器使用优化器时,所有寄存器变量定义将被忽略,由优化器决定寄存器分配。优化器直接将变量而不是地址分配给寄存器。优化器可以将AR5、AR6和AR7用作寄存器变量。AR5在函数调用时不保存,所以它在使用时可以跨越多个函数使用。4、表达式寄存器编译器使用没有用做寄存器变量的寄存器来计算表达式值和存储临时结果。在函数调用时不保留表达式寄存器内容。在函数调用时,用做临时存储的寄存器保存到局部帧,被调函数不用保存和恢复表达式寄存器。5、返回值如果函数返回值为标量类型(integer、pointer或float),则返回值保存在累加器中。当返回值为16位类型变量时,返回值在累加器中符号扩展。8.5.3函数结构和调用规则

1、函数如何进行调用主调函数在调用另一个函数时完成以下工作(ARP必须为AR1):(1)主调函数以逆顺序将参数压入堆栈(最右边的参数最先压入,最左边的参数最后压入)。函数调用时最左边的放在堆栈顶部。(2)主调函数调用被调函数。(3)主调函数假定在函数返回时ARP会被设定为AR1。(4)当被调函数结束,主调函数用以下命令将参数弹出堆栈。SBRKn2、被调函数响应(函数入口时ARP应该设为AR1,AR1用作SP)(1)从硬件堆栈中弹出返回地址,并将其压入软件堆栈;(2)将帧指针FP压入软件堆栈;(3)分配局部帧;(4)如果被调函数修改AR6或AR7,将其压入堆栈。其他被修改的寄存器可以不保存;(5)执行函数代码;(6)如果函数返回标量值,将返回值放入累加器。如果返回值为16位整型和指针,在用累加器保存返回值时进行正确的符号扩展;(7)将ARP改为AR1;(8)如果保存了AR6或AR7,则恢复AR6或AR7;(9)释放局部帧;(10)恢复FP;(11)将返回地址从软件堆栈中弹出并压入硬件堆栈;(12)返回。 ;假定ARP=AR1POPD*+ ;将返回地址从硬件堆栈弹出,压入软件堆栈SARAR0,*+ ;将AR0(FP)压入堆栈SARAR1,* ;*SP=SPLARAR0,#SIZE ;FP=帧大小LARAR0,*0+ ;FP=SP,SP+=SIZE→分配局部帧空间SARAR6,*+ ;AR6压栈SARAR7,*+ ;AR7压栈…… ;函数代码MAR*,AR1 ;设置ARP=SPMAR*- ;指针指向AR7LARAR7,*- ;弹出AR7LARAR6,*- ;弹出AR6SBRKSIZE+1 ;释放局部帧LARAR0,*- ;弹出局部帧指针FPPSHD* ;将返回地址从软件堆栈弹出,压入硬件堆栈RET ;返回8.5.4中断处理遵循中断原则就是在不影响C环境的情况下实现中断处理并返回C代码。c_int0为C程序入口点,它同时也是引导函数,用来完成C环境初始化。在初始化工作中,没有对中断进行任何处理,中断的全部控制寄存器和状态位处于缺省状态。在缺省状态下,中断没有使能。如果系统中要使用中断,用户必须作相应处理,使中断使能。这些操作很容易用asm语句实现,或调用汇编函数来实现,对C环境没有影响。调用中断程序时,首先应调用运行时支持库中的子程序I$$SAVE。这个子程序保存了所有的寄存器。同样,在中断程序返回时,应调用调用运行支持库中的子程序I$$RET,用于恢复被保存的寄存器。以上过程都是自动的,不需要用户编程时干预。

interrupt是C编译器中的中断关键字,用来声明中断函数。格式如下:interruptvoidnothing()//哑中断子程序{return;}8.6C语言和汇编语言混合编程用C语言和汇编语言的混合编程方法主要有以下四种:(1)独立编写C程序和汇编程序,分开编译或汇编形成各自的目标代码模块,然后用链接器将C程序和汇编程序链接起来。(2)直接在C语言程序的相应位置嵌入汇编程序。(3)在C语言程序中使用汇编程序的变量。(4)对C程序进行编译生成相应的汇编程序,然后对汇编程序进行手工优化和修改。8.6.1独立的C和汇编程序模块接口(1)不论是用C编写的函数还是汇编编写的函数,都必须遵守寄存器使用规则。(2)必须保护C函数要用到的几个特定寄存器。(3)如果要改变状态寄存器的任何位,必须确保恢复出它们的值。(4)中断程序必须保护所有用到的寄存器。(5)从汇编程序调用C函数时,以逆序方式将参数压入堆栈,调用之后,将参数弹出。(6)调用C函数时,注意C函数只保护了几个特定的专用寄存器,其他寄存器C函数可以自由使用。(7)长整型和俘点数在存储器中存放的顺序是低位字在低地址,高位字在高地址。(8)如果函数有返回值,返回值存放在累加器ACC中。(9)汇编模块不能改变由C产生的.cinit块。(10)编译器在所有的标识符(函数名、变量名等)前加一下划线“_”。因此,编写汇编语言程序时,必须在C程序可以访问的所有对象前加“_”。(11)任何在汇编中定义的对象或函数,如果需要在C中访问或调用,则必须用汇编指令.global定义。同样,如果在C中定义的对象或函数,需要在汇编中访问或调用,在汇编中也必须用.global定义。(1)C主程序: /*cmian.c*/ externintasmfunc() ;定义外部的汇编函数

intgvar ;定义全局变量

main() { inti; i=asmfunc(i) ;调用函数(2)汇编语言函数_asmfunc: /*asmsub.c*/ .global_asmfunc .global_gvar .text_asmfunc: POPD*+ ;将返回地址保存至C堆栈 SAR AR0,*+ ;保护FP SAR AR1,* ;保护SP LAR AR0,#1 ;帧长度 LAR AR-,*0+,AR2 ;建立FP和SP LDP #_gvar ;指向_gvar SETC SXM LACC _gvar LAR AR2,#_3 ;参数偏移 MAR *0+ ;指向参数 ADD *,AR0 ;将参数加至gvar SACL _gvar MAR *,AR1 SBRK 2 LAR AR0,*- ;恢复帧指针 PSHD* ;返回地址压入C24x堆栈 RET .end8.6.2在C语言中直接嵌入语句是一种直接的C和汇编接口方法。可以在C程序中实现用C语言无法实现的一些硬件控制功能。

asm(“汇编语句”)注意以下几点:(1)防止嵌入的asm语句破坏C环境。(2)在C代码中插入跳转或标号可能会影响代码产生器的寄存器跟踪算法,产生不可预测的结果。(3)插入影响编译环境的伪指令也可能会造成麻烦。(4)不要改变C变量值,但可以读取变量值。如上,在程序中直接嵌入汇编语句的典型应用是控制芯片的一些硬件资源。#include"exp4_2407.h"voidsys_ini()//系统初始化子程序10008AA0POPD*+100180A0SARAR0,*+10028180SARAR1,*1003B001LARAR0,#1h100400E0LARAR0,*0+{/*关总中断*/asm("setcINTM");1005BE41SETCINTM/*抑制符号位扩展*/asm("clrcSXM");1006BE46CLRCSXM/*累加器中结果正常溢出*/asm("clrcOVM");1007BE42CLRCOVM/*禁止看门狗*/*WDCR=0x00E8;1008BD00LDP#100h10090300LARAR3,0h100AB9E8LACL#e8h100B8B8BMAR*,AR3100C908CSACL*,0,AR4/*CLKIN=10M,CLKOUT=40M*/*SCSR1=0x0000;100D0401LARAR4,1h100EB900LACL#0h100F9089SACL*,0,AR1}10107C02SBRK#2h10110090LARAR0,*-10127680PSHD*1013EF00RETvoiddelay()10148AA0POPD*+101580A0SARAR0,*+10168180SARAR1,*1017B004LARAR0,#4h101800EALARAR0,*0+,AR2

{

unsignedintk;for(k=0;k<60000;k++);1019B900LACL#0h101AB201LARAR2,#1h101B8BE0MAR*0+101C9080SACL*,0101D6980LACL*101EE302BCND1020h,NOV10208BA0MAR*+102190A0SACL*+,010229890SACH*-,0102373A0LT*+1024C001MPY#1h10257580LPH*1026BE46CLRCSXM1027BF80LACC#ea60h,01029BE05SPAC102AE302BCND1030h,NOV102CE304BCND104bh,GT102E7980B1032h,*1030E3CCBCND104bh,LEQ10327C02SBRK#2h10331080LACC*,01034B801ADD#1h10359080SACL*,01036

温馨提示

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

评论

0/150

提交评论