版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第6章使用C语言操作DSP的寄存器6.1C/C++编译器概述6.2TMS320X28xx的C/C++编程6.3寄存器的C语言访问6.4CMD文件6.5寄存器文件的空间分配汇编语言与C语言DSP软件开发有两种途径:专用汇编语言程序开发和高级C语言程序开发。•专用汇编语言程序开发——直接用汇编语言编写源程序,经过汇编、链接后生成可执行代码(out),然后再进行调试、固化;•高级C语言程序开发——采用高级C语言编写源程序,先利用C编译器把C源程序转换成汇编语言源程序,然后与汇编语言程序一样处理。引言引言生成源程序(*.asm)、头文件(*.h)与命令文件(*.cmd)。生成目标文件(*.obj)及列表文件(*.lst)生成可执行代码文件(*.out)及用于存储器分配的映射文件(*.map)。通过JTAG接口下载到目标系统通过JTAG接口将程序烧写到Flash存储器C源文件编辑C编译器如果用C语言作为编程语言。使用C语言开发DSP的原因引言基于DSP芯片的软件开发,用DSP芯片的汇编语言编写程序是一件比较繁杂的事情。一般来说,各个公司的DSP芯片所提供的汇编语言并不相同,即使是同一公司的芯片,由于芯片的类型不同(如定点和浮点)、芯片的升级换代,其汇编语言也有所不同,使用汇编语言开发DSP产品的周期相对较长,因为开发人员在编写DSP程序之前必须熟悉这种DSP芯片的汇编语言。产品一旦开发完毕,如果需要对软件进行修改和升级都将非常困难,这是因为汇编语言的可读性和可移植性比高级语言差。一般高级语言具有很好的可移植性,但是难以实现汇编语言的某些功能(如对内存地址的操作、位操作等)。C/C++语言作为一种高级语言,既可以访问物理地址又可以进行位操作,能直接对硬件进行操作,适合用作DSP开发语言。基于上述原因,各个DSP芯片公司都相继推出了相应的高级语言(如C语言)编译器,使得DSP芯片的软件可以直接用高级语言编写而成,从而大大提高了DSP芯片的开发速度,也使程序的修改和移植变得简单易行。6.1C/C++编译器概述
TMS320X28xx的C编译器是一个功能齐全的优化编译器,优化编译结果达手工编写的汇编语言效率的90%以上。可以利用该编译器将标准的ANSIC/C++程序直接转换成TMS320X28xx处理器的汇编代码。为了提高执行效率,关键的DSP运算程序仍然应用汇编语言进行编写,同时按照规定的接口,然后通过C语言程序对其调用。
1.标准的ANSIC/C++语言
CCS的C/C++编译器接收标准ANSIC/C++源文件(.c或.cpp),并将其编译成C28x的汇编语言源文件(.asm)。2.ANSI标准实时运行支持
TMS320X28xx编译器工具为各种处理器提供完整的实时运行库。库中包括动态内存分配、对字符串的操作、数学运算(如求绝对值、计算三角函数和指数函数等)以及一些标准的输入/输出操作等,只要在源程序中加入对应的头文件(如stdlib.h、string.h、math.h和stdio.h等)就可以调用和使用。rts.src
TMS320X28xx的C/C++编译器包含了两个经过编译的运行时支持目标文件库:rts2800.lib和rts2800_ml.lib。6.1.1C语言主要特征6.1C/C++编译器概述6.1.1C语言主要特征6.1C/C++编译器概述编译器支持两种存储器模型:小存储模式大存储器模式链接器不允许同时存在大存储器模式和小存储器模式。6.1.2编译、汇编和链接6.1C/C++编译器概述C编译器(CCompiler):产生汇编语言源代码。汇编器(Assembler):把汇编语言源文件翻译成机器语言目标文件,机器语言格式为通用目标格式(COFF)。链接器(Linker):把多个目标文件组合成单个可执行的输出文件(.out)。汇编器生成的COFF目标文件中各代码段或数据段只具有相对地址,它与系统的物理存储器地址之间没有任何关系,必须对其进行地址定位和分配后,这些目标文件才能变成可执行的文件。6.1C/C++编译器概述6.1.2编译、汇编和链接编译器为用户提供了灵活方便的函数调用接口,可以非常方便地实现C/C++函数和汇编语言的相互调用。通常情况下,程序的主架构采用C/C++编写,对于代码的效率要求较高的程字段采用汇编语言。在C/C++程序中调用汇编主要有以下3种实现方法。
(1)使用独立的汇编语言模块或文件,在目标代码链接过程中将汇编代码链接到C/C++程序模块中,这种方法也是最通用的方法。
(2)直接在C/C++程序中嵌入汇编程序。
(3)直接在C/C++程序中调用汇编函数。6.1.3灵活的汇编语言接口
6.1C/C++编译器概述DSP中的工程文件C源文件编辑C编译器工程文件(.pjt),源文件(.c,.asm),头文件(.h),库文件(.lib),CMD文件(.cmd),目标文件(.obj),列表文件(.lst),可执行代码文件(.out),映射文件(.map)6.2.1数据类型6.2TMS320X28xx的C/C++编程6.2.2关键字6.2TMS320X28xx的C/C++编程在CCS环境中使用C语言开发程序,可以使用C语言中常用的一些关键字和表达式。如:定义数据类型的关键字:char,int,double等。条件判断关键字:if,else,switch,case等。循环语句关键字:for,while等注:在C语言中,三目运算符:表达式?语句一:语句二;6.2.2关键字6.2TMS320X28xx的C/C++编程const使用:const数据类型变量名,优化存储器的分配,表示变量的内容是常数,在程序运行中不会改变。有助于更好地控制对特定数据对象存储空间的分配。如果定义一个对象为const,则const段会为此对象在程序存储器中分配特定的存储空间。volatile使用:volatile数据类型变量名;用于声明存储器或外设寄存器,以此来说明所定义的变量是“可变的”,是可以被DSP的其他硬件修改的,而不仅仅由C程序本身修改。举例:volatilestructSYS_CTRL_REGSSysCtrlRegs;6.2.2关键字6.2TMS320X28xx的C/C++编程cregister使用:cregister数据类型变量名;允许采用高级语言直接访问控制寄存器。注意:在F281x的C语言中,cregister仅限于声明寄存器IER和IFR。如:externcregistervolatileunsignedintIFR;externcregistervolatileunsignedintIER;interrupt使用:interruptvoid中断函数名(void);说明函数是中断函数,这样编译器会自动为中断函数产生保护现场和恢复现场所需执行的操作。举例:interruptvoidXINT1_ISR(void);6.2.3在C语言中嵌入汇编语言6.2TMS320X28xx的C/C++编程TMS320C28x编译器允许在C程序中嵌入汇编指令,通过下面声明实现:asm(“assemblertext”);其中assemblertext指汇编代码。asm指令一般用来处理C/C++语句较难实现的硬件操作。举例:#defineEINTasm("clrcINTM")#defineDINTasm("setcINTM")6.3寄存器的C语言访问由于DSP的寄存器能够实现对系统和外设功能的配置与控制,因此在DSP的开发过程中,对于寄存器的操作是极为重要的,也是很频繁的,也就是说对寄存器的操作是否方便会直接影响到DSP的开发是否方便。对DSP内部寄存器的访问和控制有两种方式,一种是传统宏定义的方式,一种是位定义和寄存器结构体的方式。6.3寄存器的C语言访问6.3.1传统的宏定义方法传统的C/C++编程访问处理器的硬件寄存器主要采用#define宏的方式。为了说明宏定义方法,下面以SCI接口的编程为例进行介绍。下表给出了SCI-A和SCI-B的寄存器文件及相关的地址。1.SCI-A寄存器寄存器名称地址大小(×16位)功能描述SCICCR0x000070501SCI-A通信控制寄存器SCICTL10x000070511SCI-A控制寄存器1SCIHBAUD0x000070521SCI-A波特率寄存器,高位SCILBAUD0x000070531SCI-A波特率寄存器,低位SCICTL20x000070541SCI-A控制寄存器2SCIRXST0x000070551SCI-A接收状态寄存器SCIRXEMU0x000070561SCI-A接收仿真数据缓冲器寄存器SCIRXBUF0x000070571SCI-A接收数据缓冲器寄存器SCITXBUF0x000070591SCI-A发送数据缓冲器寄存器SCIFFTX0x0000705A1SCI-AFIFO发送寄存器SCIFFRX0x0000705B1SCI-AFIFO接收寄存器SCIFFCT0x0000705C1SCI-AFIFO控制寄存器SCIPRI0x0000705F1SCI-A优先级控制寄存器寄存器名称地址大小(×16位)功能描述SCICCR0x000077501SCI-B通信控制寄存器SCICTL10x000077511SCI-B控制寄存器1SCIHBAUD0x000077521SCI-B波特率寄存器,高位SCILBAUD0x000077531SCI-B波特率寄存器,低位SCICTL20x000077541SCI-B控制寄存器2SCIRXST0x000077551SCI-B接收状态寄存器SCIRXEMU0x000077561SCI-B接收仿真数据缓冲器寄存器SCIRXBUF0x000077571SCI-B接收数据缓冲器寄存器SCITXBUF0x000077591SCI-B发送数据缓冲器寄存器SCIFFTX0x0000775A1SCI-BFIFO发送寄存器SCIFFRX0x0000775B1SCI-BFIFO接收寄存器SCIFFCT0x0000775C1SCI-BFIFO控制寄存器SCIPRI0x0000775F1SCI-B优先级控制寄存器2.SCI-B寄存器6.3寄存器的C语言访问6.3.1传统的宏定义方法(SCI寄存器的宏定义)/*******************************************************采用宏定义的方法定义的头文件******************************************************/
#defineUint16unsignedint#defineUint32unsignedlong#defineSCICCRA(volatileUint16*)0x7050//0x7050SCI-A通信控制寄存器#defineSCICTL1A(volatileUint16*)0x7051//0x7051SCI-A控制寄存器1第一步,首先定义各寄存器的符号及其对应的入口地址/*******************************************************采用#definemacros访问寄存器******************************************************
…..*SCICTL1A=0x0003;//写整个控制寄存器1*SCICTL1B|=0x0001;//使能RX
6.3寄存器的C语言访问6.3.1传统的宏定义方法第二步,采用宏定义的方法访问寄存器(采用指针形式)SCI控制寄存器1SCICTL1SCI的发送使能位和接收使能位缺点:(1)不能直接对寄存器的位进行读写,为了独立的操作寄存器中的某些位,必须屏蔽其他位;(2)不能直接在CCS中显示各个位的定义;(3)不能利用CCS自动完成输入的特点;(4)对相同的外设,不方便外设的重复使用。优点:(1)宏定义相对比较简单,快捷,容易分类;(2)直接采用寄存器的名字进行定义,易于操作。6.3寄存器的C语言访问6.3.1传统的宏定义方法SCI控制寄存器1SCICTL16.3寄存器的C语言访问6.3.1传统的宏定义方法
…..*SCICTL1B|=0x0002;//使能RX
相对于#definemacros的方法访问寄存器,位定义和寄存器结构体的方法,更加灵活,可有效提高编程效率。6.3寄存器的C语言访问6.3.2位定义和寄存器结构体的方法(1)位域定义及用位域方法定义寄存器在使用处理器的外设时,经常需要直接操作寄存器中的某些位,而采用位域定义的方法实现寄存器的直接操作对编程来讲十分方便。位域定义可以为寄存器内的特定功能位分配一个相关的名字和相应的宽度,允许采用位域定义的名字直接操作寄存器中的某些位。按位来划分区域6.3寄存器的C语言访问6.3.2位定义和寄存器结构体的方法通俗的讲,“位域”就是把一个字节中的二进制位划分为几个不同的区域,并说明每个区域的位数。每个域都有一个域名,允许在程序中按域名进行操作。位域的定义和位域变量的说明同结构体定义和其成员说明类似,其语法格式为:struct位域结构名{
类型说明符位域名1:位域长度类型说明符位域名2:位域长度
…
类型说明符位域名n:位域长度};基本的数据类型,可以是int、char等可以任意取,尽量反应位的功能这个位域由多少位组成大括号后面的“;”不可缺少!6.3寄存器的C语言访问6.3.2位定义和寄存器结构体的方法structbs//定义位域bs{inta:8;intb:2;intc:6;};structbsbs1;加起来一共是16位!声明bs型变量bs1。位域是C语言的一种数据结构,也要遵循先声明后使用的原则。例如,声明了bs1,表明bs1是bs型的变量,共占2个字节,其中位域a占8位,位域b占2位,位域c占6位。6.3寄存器的C语言访问6.3.2位定义和寄存器结构体的方法
关于位域定义的几点说明:
(1)位域的定义在存储空间中必须按由右向左的顺序,从最低为开始定义。也就是说寄存器的低有效位或者是第0位存放在定义区的第一个位置;
(2)一个位域必须存储在同一个字节中,不能跨两个字节。如果一个字节不够,放另一域时,应该从下一个单元起存放该域。structbs//定义位域bs{inta:4;int:0;//空域intb:5;//从第2字节开始存放intc:3;};6.3寄存器的C语言访问6.3.2位定义和寄存器结构体的方法
关于位域定义的几点说明:
(3)位域长度不能大于一个字节的长度,也就是说位域不能超过8位。?(4)位域可以无位域名,这时,它只用作填充或调整位置。无名的域位不能使用。structbs//定义位域bs{inta:4;int:2;//该2位不能使用intb:2;intc:5;intd:3;};6.3寄存器的C语言访问6.3.2位定义和寄存器结构体的方法
以SCIA的通信控制寄存器SCICCR为例,说明如何使用位域的方法来定义寄存器:6.3寄存器的C语言访问6.3.2位定义和寄存器结构体的方法structSCICCR_BITS{Uint16SCICHAR:3;//2:0字符长度控制位
Uint16ADDRIDLE_MODE:1;//3多处理器模式控制位
Uint16LOOPBKENA:1;//4回送测试模式使能位
Uint16PARITYENA:1;//5极性使能位
Uint16PARITY:1;//6奇/偶极性选择位
Uint16STOPBITS:1;//7停止位个数
Uint16rsvd1:8;//15:8保留};structSCICCR_BITSbit;//SCI字符长度控制位为8位bit.SCICHAR=7;6.3寄存器的C语言访问6.3.2位定义和寄存器结构体的方法structSCICCR_BITS{Uint16SCICHAR:3;//2:0字符长度控制位
Uint16ADDRIDLE_MODE:1;//3多处理器模式控制位
Uint16LOOPBKENA:1;//4回送测试模式使能位
Uint16PARITYENA:1;//5极性使能位
Uint16PARITY:1;//6奇/偶极性选择位
Uint16STOPBITS:1;//7停止位个数
Uint16rsvd1:8;//15:8保留};structSCICCR_BITSbit;bit.SCICHAR=7;//SCI字符长度控制位为8位被保留的空间也要在位域中定义,只是定义的变量不会被调用。声明了SCICCR_BITS型变量bit,这样就可以通过bit来实现对寄存器位的访问了。1
2
36.3寄存器的C语言访问6.3.2位定义和寄存器结构体的方法//SCICTL1控制寄存器1位定义:structSCICTL1_BITS//位功能描述{
Uint16RXENA:1;//0SCI接收模式
Uint16TXENA:1;/1SCI发送器使能
Uint16SLEEP:1;//2SCI睡眠
Uint16TXWAKE:1;//3发送唤醒方法
Uint16rsvd1:l;//4保留
Uint16SWRESET:1;//5软件复位
Uint16RXERRINTENA:1;//6接收中断使能
Uint16rsvd2:9;//15--7保留};SCI控制寄存器1SCICTL16.3寄存器的C语言访问6.3.2位定义和寄存器结构体的方法(2)声明共同体使用位定义方法可以方便地对寄存器功能位进行操作,但有时还是需要将整个寄存器作为一个值操作。为此引入共同体,使寄存器的各位可以作为一个整体操作。6.3寄存器的C语言访问6.3.2位定义和寄存器结构体的方法unionSCICCR_REG{Uint16all;//可实现对寄存器整体操作
structSCICCR_BITSbit;//可实现位操作};unionSCICCR_REGSCICCR;SCICCR.all=0x007F;SCICCR.bit.SCICHAR=5;例6.3SCICCR的共同体定义声明了一个SCICCR_REG变量SCICCR通过变量SCICCR对寄存器实现整体操作?通过变量SCICCR对寄存器实现位操作?注意:整个共同体的总的存储空间为2个字节。1
2
3
46.3寄存器的C语言访问6.3.3创建结构体文件
前面通过位域和共同体,已经可以对单个寄存器的功能位或整体进行访问。而我们知道,SCI模块除了寄存器SCICCR还包括很多寄存器。因此,为了便于管理,就需要创建一个结构体文件,用来包含SCI模块所有的寄存器。寄存器结构体文件实际上是将某些外设的所有寄存器采用一定的结构体在一个文件中定义,其成员为某外设的所有寄存器。下面即为SCI寄存器的结构体文件。structSCI_REGS{unionSCICCR_REGSCICCR;//通信控制寄存器
unionSCICTL1_REGSCICTL1;//控制寄存器1Uint16SCIHBAUD;//波特率寄存器(高字节)Uint16SCILBAUD;//波特率寄存器(低字节)unionSCICTL2_REGSCICTL2;//控制寄存器2unionSCIRXST_REGSCIRXST;//接收状态寄存器
Uint16SCIRXEMU;//接收仿真缓冲寄存器
unionSCIRXBUF_REGSCIRXBUF;//接收数据寄存器
Uint16rsvd1;//保留
Uint16SCITXBUF;//发送数据缓冲寄存器
unionSCIFFTX_REGSCIFFTX;//FIFO发送寄存器
unionSCIFFRX_REGSCIFFRX;//FIFO接收寄存器
unionSCIFFCT_REGSCIFFCT;//FIFO控制寄存器
Uint16rsvd2;//保留
Uint16rsvd3;//保留
unionSCIPRI_REGSCIPRI;//FIFO优先级控制寄存器
};externvolatilestructSCI_REGSSciaRegs;externvolatilestructSCI_REGSScibRegs;1
2
36.3寄存器的C语言访问
SCI寄存器结构体SCI_REGS中,有两种形式的成员,union形式和Unit16形式,定义为union形式的成员既可以实现对寄存器整体的操作,也可以实现对寄存器进行位操作;而定义为Unit16形式的成员只能直接对寄存器进行操作。无论是SCIA或SCIB,在寄存器的存储空间中,有3个存储单元是被保留的,在对SCI寄存器进行结构体定义时,也要将其保留。保留的寄存器空间采用变量代替,但是该变量不会被调用,如rsvd1、rsvd2、rsvd3。6.3.3创建结构体文件6.3寄存器的C语言访问定义了结构体SCI_REGS后,需要声明SCI_REGS型变量SciaRegs和ScibRegs,分别代表外设SCIA和外设SCIB的寄存器。声明中的关键字extern,“外部的”,只能说明变量,不能定义变量,表明这个变量在外部文件中被调用,是一个全局变量。volatile表明变量能够被外部代码改变,例如可以被外部硬件或中断任意改变。结构体定义时寄存器名字出现的顺序要与存储空间安排的顺序一致。6.3.3创建结构体文件6.3寄存器的C语言访问
C语言访问寄存器(以SCI模块的寄存器为例)步骤:使用位域定义的方式对SCI模块中各个寄存器的位功能进行操作;根据需要定义共同体,可以对某些寄存器的整体或位进行操作;对整个SCI模块所有的寄存器建立结构体文件。
可以发现,这就是F2812的头文件DSP28_Sci.h的内容。6.3.3创建结构体文件6.3寄存器的C语言访问6.3寄存器的C语言访问6.3寄存器的C语言访问定义了结构体SCI_REGS型的变量SciaRegs和ScibRegs之后,就可以方便地实现对寄存器的操作了。例6.5对SCIA的寄存器SCICCR按位进行操作SciaRegs.SCICCR.bit.STOPBITS=0;//1位停止位寄存器结构体文件共同体位域整体按位操作Uint16/326.3寄存器的C语言访问例6.6对SCICCR整体进行操作SciaRegs.SCICCR.all=0x0007;例6.7对定义为Unit16的成员SCIHBAUD和SCILBAUD进行操作SciaRegs.SCIHBAUD=0;SciaRegs.SCILBAUD=0xF3;例6.5、6.6、6.7中的3种操作涵盖了在F2812开发过程中对寄存器操作的所有方式,也就是说掌握了这3种方式,就可以实现对F2812各种寄存器的操作。6.3寄存器的C语言访问建立结构体文件步骤(以SCI模块的寄存器为例):使用位域定义的方式对SCI模块中各个寄存器的位功能进行操作;根据需要定义共同体,可以对某些寄存器的整体或位进行操作;对整个SCI模块所有的寄存器建立结构体文件。6.4CMD文件值得注意的是,之前所做的工作只是将F2812的寄存器按照C语言中位域定义和寄存器结构体的方式组织了数据结构,当编译时,编译器会把这些变量分配到存储空间中,但是很显然还有一个问题要解决,那就是如何将代表寄存器数据的变量同实实在在的物理寄存器结合起来呢?这就是寄存器文件的空间分配问题,在此之前,我们先需要对分配存储空间的CMD文件进行了解。6.4CMD文件链接命令文件(LinkerCommandFiles),以后缀.cmd结尾,简称CMD文件。其作用就是为程序代码和数据分配存储空间。单片机:在程序设计时,经过编译汇编链接,直接下载到硬件中调试。DSP:在2812的程序设计时,编写的程序代码首先经过编译器编译产生几个代码块和数据块,也就是我们所说的段,然后需要编写CMD文件,也就是链接命令文件,来指示链接器将编译器产生的这些段进行链接,分配到目标存储器,也就是硬件存储器。6.4CMD文件6.4.1COFF格式和段的概念6.4.2C语言生成的段6.4.3pragma伪指令6.4.4CMD文件的编写6.4.5实际工程中的CMD文件6.4CMD文件6.4.1COFF格式和段的概念
编译、汇编与链接程序建立的目标文件采用通用目标文件格式(CommonObjectFileFormat,COFF)。COFF格式是一种很流行的二进制格式。例如库文件(.lib)、目标文件(.obj)、最终的可执行文件(.out)等都是采用COFF格式。COFF文件格式包括文件头、段落头、段数据、重定位信息等,我们不管COFF文件格式的具体信息,只需要知道TI公司的汇编器和链接器创建目标文件都使用这种COFF格式。
6.4CMD文件6.4.1COFF格式和段的概念
COFF格式的核心是在编写DSP程序时,基于代码段和数据段的概念,而不是一条条命令或一个个数据,使得程序可读性和可移植性大大增强。这些代码段和数据段简称为段(section,也称为块),是目标文件的最小单位(基本单元),是在存储器中占据连续空间的代码和数据块,各段相互独立。汇编器和链接器提供了一些伪指令来建立和管理各种各样的段。例如pragma,MEMRY,SECTIONS等。告诉汇编程序如何进行汇编的指令,既不控制机器操作也不被汇编成代码,只能为汇编程序所识别,并指导汇编如何进行。(没有对应的机器码!)6.4.1COFF格式和段的概念6.4CMD文件1.把每个源文件都编译成独立的目标文件(以后缀.obj结尾),每个目标文件都含有自己的段。Compilefile2.连接器把这些目标文件中相同段名的部分连接在一起,生成最终的可执行文件(以后缀.out结尾)Build。编译器处理段的过程:编译器产生可重定位的代码,允许链接器将代码和数据分配到适当的存储器空间。而链接器将根据链接命令文件(CMD文件),将代码和数据分配到目标存储器。6.4.2C语言生产的段6.4CMD文件F2812的C编译器将存储器作为程序存储器和数据存储器两个线性区来处理,每个由C程序生成的代码子模块或数据子模块被放到各自的连续存储空间中。
程序存储器:包含可执行的代码和常量、变量初值。
数据存储器:包含外部变量、静态变量和系统堆栈。6.4.2C语言生产的段6.4CMD文件由C语言程序生成的可重定位的代码和数据模块,称作“sections”。可以分为两大类:已初始化的段和未初始化的段。
已初始化的段:含有真实的指令和数据,存放在程序存储空间。
未初始化的段:只是保留变量的地址空间(通常是RAM),或者说为未初始化的数据保留存储空间。一段程序可以在运行期间,使用这个空间创造和存储变量。在DSP上电调用_c_int0初始化库前,未初始化的段并没有真实的内容。未初始化的段存放在数据存储空间。6.4.2C语言生产的段6.4CMD文件已初始化的段
.text编译C语言中的语句时,生成的汇编指令代码存放于此,换句话说,包含所有的可执行代码和常量。
.cinit存放用来对全局和静态变量初始化的常数。(C程序).pinit全局构造器(C++)程序列表。(C++程序)
.const包含字符串常量和由const声明的全局变量和静态变量。
.econst包含字符串常量和初始化的全局变量和静态变量(由farconst声明或大存储器模式)的初始化和说明。.switch存放switch语句产生的常数表格。6.4.2C语言生产的段6.4CMD文件未初始化的段
.bss:为全局变量和局部变量保留的空间,在程序上电时,.cinit空间中的数据复制出来并存储在.bss空间中。.ebss:为使用大寄存器模式时的全局变量和静态变量预留的空间,在程序上电时,.cinit空间中的数据复制出来并存储在.ebss中。.stack:为系统堆栈保留的空间,主要用于与函数传递变量或为局部变量分配空间。.sysmem:为动态存储分配保留的空间。如果有宏函数(malloc),此空间被宏函数占用,如果没有的话,此空间保留为0。.esysmem:为动态存储分配保留的空间。如果有farmalloc函数,此空间被相应的占用,如果没有的化,此空间保留为0。6.4.2C语言生产的段6.4CMD文件段的存储特性为什么已初始化的段可以放到Flash或者ROM里面呢?
这主要跟2812的调试模式有关,可以放到RAM里调试也可以放到Flash里调试。已初始化的段未初始化的段6.4.3pragma伪指令6.4CMD文件上面介绍的段都是C语言预先已经定义好的段,我们还可以根据自己的需要通过伪指令来定义自己的段。
#pragma是标准C语言中保留的预处理命令,它的作用就是告诉编译器如何对待或处理特定函数、对象或代码段。通过#pragma定义段的格式如下:#pragmaCODE_SECTION(symbol,”sectionname”);#pragmaDATA_SECTION(symbol,”sectionname”);为代码定义段,定义代码段为数据定义段,定义数据段6.4.3pragma伪指令6.4CMD文件说明:
symbol是符号,可以是函数名或全局变量名。sectionname是用户自己定义的段名。
CODE_SECTION用来定义代码段,而DATA_SECTION用来定义数据段。不能在函数体内声明#pragma,必须在函数外。必须在符号被定义和使用前使用#pragma。#pragmaCODE_SECTION(symbol,”sectionname”);CODE_SECTION用于为函数symbol在一个名为sectionname的段中指定空间。
#pragmaDATA_SECTION(symbol,”sectionname”);CODE_SECTION用于为变量symbol在一个名为sectionname的段中指定空间。6.4.3pragma伪指令6.4CMD文件#pragmaCODE_SECTION(sum,“codeA”);intsum(inta,intb);voidmain(void){inta=1,b=2,c;c=sum(a,b);}intsum(inta,intb){return(a+b);}举例不能在函数体内声明#pragma,必须在函数外。6.4.3pragma伪指令6.4CMD文件
#pragmaDATA_SECTION(s,”newsect”);
unsignedints[100];
voidmain(void){……}将全局数组变量s[100]单独编译成一个新的段,取名为”newsect”。举例必须在符号被定义和使用前使用#pragma6.4CMD文件段存储器类型分配的存储空间.textROMORRAM(FLASH)Page0.cinitROMORRAM(FLASH)Page0.constROMORRAM(FLASH)Page1.econstROMORRAM(FLASH)Page1.pinitROMORRAM(FLASH)Page0.switchROMORRAM(FLASH)Page0/page1.bssRAMPage1.ebssRAMPage1.stackRAMPage1.systemRAMPage1.esystemRAMPage1通过#pragmaCODE_SECTION定义的段ROMORRAM(FLASH)Page0通过#pragmaDATA_SECTION定义的段RAMPage16.4.4CMD文件的编写6.4CMD文件CMD文件支持C语言中的块注释符“/*”和“*/”,但不支持行注释符“//”。CMD文件会使用到为数不多的几个关键字,下面会根据需要来介绍一些常用的关键字。CMD文件的两大主要功能是指示存储空间和分配段到存储空间,CMD文件其实也就是由这两部分内容构成的。在编写CMD文件时,主要采用MEMORY和SECTIONS
两条伪指令。在281x调试时,可以将程序代码链接到Flash或者RAM,因此对应两种CMD文件。6.4.4CMD文件的编写(分为2个步骤)6.4CMD文件1.通过MEMORY伪指令来指示存储空间MEMORY伪指令语法如下:MEMORY{PAGE0:name0[(attr)]:origin=constant,length=constantPAGEn:namen[(attr)]:origin=constant,length=constant}PAGE用来标识存储空间的关键字。PAGEn的最大值为PAGE255。X281x的DSP中用到是PAGE0、PAGE1,其中PAGE0为程序空间,PAGE1为数据空间。(实际应用中一般分为2页)6.4.4CMD文件的编写6.4CMD文件1.通过MEMORY伪指令来指示存储空间name代表某一属性或地址范围的存储空间名称。名称可以是1~8个字符,在同一页内名称不能相同,不同页内名称可以相同。
attr用来规定存储空间的属性。共有4个属性,只读R,只写W,该空间可包含可执行代码X,该空间可以被初始化I。实际使用为了简化,通常会忽略此选项,表示存储空间具有所有的属性。
origin用来定义存储空间的起始地址。
length用来定义存储空间的长度。6.4.4CMD文件的编写6.4CMD文件1.通过MEMORY伪指令来指示存储空间(举例)
MEMORY{PAGE0:FLASH:origin=0x3D8000,length=0x01FF80/*FLASH*/BEGIN:origin=0x3F7FF6,length=0x000002ROM:origin=0x3FF000,length=0x000FC0RESET:origin=0x3FFFC0,length=0x000002RAML0:origin=0x008000,length=0x001000PAGE1:RAMM0:origin=0x000000,length=0x000400/*RAMM0*/RAMM1:origin=0x000400,length=0x000400/*RAMM1*/RAML1:origin=0x009000,length=0x001000/*RAML1*/RAMH0:origin=0x3F8000,length=0x002000/*RAMH0*/}6.4CMD文件6.4.4CMD文件的编写6.4CMD文件2.通过SECTIONS伪指令来将段分配到存储空间(也就是指定段的实际硬件地址空间)SECTIONS{name:[property,property,property,…]name:[property,property,property,…]……}SECTIONS伪指令语法如下:name为输出段的名称;property为输出段的属性。6.4.4CMD文件的编写6.4CMD文件输出段的属性主要有以下几个:load定义输出段将被装载到哪里的关键字,其语法:
load=allocation或者allocation或者>allocation其中,allocation可以是绝对地址,如“load=0x000400”;更多的时候,allocation是存储空间的名称,这也是最通常的用法。
run定义输出段从哪里运行的关键字,其语法:run=allocation或者run>allocation
CMD文件规定,当只出现一个关键字load或者run时,表示load地址和run地址是重叠的,大部分时候都是重叠的。
PAGE定义段分配到存储空间的类型,其语法:PAGE=0或者PAGE=1,前者说明段分配到程序空间,后者说明段分配到数据空间。6.4.4CMD文件的编写6.4CMD文件2.通过SECTIONS伪指
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GB/T 21477-2024船舶与海上技术非金属软管组件和非金属补偿器的耐火性能试验方法
- 《数字电子技术基础》课程教学大纲
- 2024年低价物高价抵押合同范本
- 2024年出售叠加别墅合同范本
- 2024年承接土方垫资合同范本
- 浙江省宁波市镇海区部分学校2024-2025学年二年级上册语文期中试卷(含答案)
- 医药代表培训
- 培训拼音教学的课件
- 乡镇四所环保监察培训
- 卫生院秋季传染病培训
- 中华人民共和国保守国家秘密法实施条例培训课件
- 2024年秋一年级上册8升国旗 公开课一等奖创新教案
- 儿童心理健康培训课件
- 2024年煤矿主要负责人安全考试题库(浓缩500题)
- 2024年全国统一高考英语试卷(新课标Ⅰ卷)含答案
- 2024年全新公司股权期权协议书
- 口腔牙科诊所技工室工作制度
- 七年级语文上册15梅岭三章课件
- 2024年国家电投山西公司招聘高频难、易错点500题模拟试题附带答案详解
- Unit 4 The Earth【速记清单】含答案解析
- 《中国饮食文化》课件-中国饮食文化溯源
评论
0/150
提交评论