对于TMS320F2812的CMD文件的理解.docx

上传人:b****9 文档编号:25223125 上传时间:2023-06-06 格式:DOCX 页数:12 大小:501.52KB
下载 相关 举报
对于TMS320F2812的CMD文件的理解.docx_第1页
第1页 / 共12页
对于TMS320F2812的CMD文件的理解.docx_第2页
第2页 / 共12页
对于TMS320F2812的CMD文件的理解.docx_第3页
第3页 / 共12页
对于TMS320F2812的CMD文件的理解.docx_第4页
第4页 / 共12页
对于TMS320F2812的CMD文件的理解.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

对于TMS320F2812的CMD文件的理解.docx

《对于TMS320F2812的CMD文件的理解.docx》由会员分享,可在线阅读,更多相关《对于TMS320F2812的CMD文件的理解.docx(12页珍藏版)》请在冰豆网上搜索。

对于TMS320F2812的CMD文件的理解.docx

对于TMS320F2812的CMD文件的理解

对于TMS320F2812的CMD文件的理解

1.COFF格式

   要谈CMD文件,首先不可避免的要谈下COFF格式,COFF格式是通用目标文件格式(CommonObjectFileFormat)的缩写,它是一种流行的二进制可执行文件格式,在DSP里二进制可执行文件包括库文件(.lib)、目标文件(.obj)和最终可执行文件(.out)。

详细的COFF格式文件包括段头、可执行代码、初始化数据、可重定位信息、行号入口、符号表、字符串。

对于DSP的C语言编程我们只需要了解定义段和给段分配空间即可。

采用COFF格式更利于我们对其进行模块化编程,我们可以自由的把哪些段分配到哪些空间。

2.Section

(1)其次,在编写CMD文件得时候要碰到SectionS命令,SectionS命令的英文理解就有区域的意思,我们利用SectionS来将目标文件的代码放到指定的区域中。

SectionS目标文件中最小的单位我们称之为块,一个块就是最终在存储器映像中占据连续空间的一段代码或者数据。

COFF文件格式默认有三个块:

.text      存放可执行代码;

.data      存放已初始化数据;

.bss       为未初始化数据留下的保留空间。

(2)汇编器对块的处理和设置

未初始化块的设置:

.bss       变量存放空间;

.usect     用户自定义的未初始化段;

初始化块的设置:

.text      汇编指令代码

.data      常数数据(比如对变量的初始化数据)

.sect      用户自定义的已初始化段

.asect     类似于.sect,多了绝对地址定位功能,一般不用

(3)C语言对块得的设置和处理

未初始化块(data)

.bss       存放全局和静态变量

.ebss      长调用的.bss(超过了64K地址限制)

.stack     存放C语言的栈

.sysmem    存放C语言的堆

.esysmem    长调用的.sysmem(超过了64K地址限制)

初始化块

.text      可执行代码和常数(program)

.switch    switch语句产生的常数表格(program/低64K数据空间)

.pinit     Tablesforglobalconstructors(C++)(program)

.cinit     用来存放对全局和静态变量的初始化常数值(program)

.const     全局和静态的const变量初始化值和字符串常数,(data)

.econst    长.const(可定位到任何地方)(data)

(4)C语言自定义块

#pragmaDATA_SECTION(函数名或者全局变量名,“用户自定义在数据空间的段名”);

#pragmaCODE_SECTION(函数名或者全局变量名,“用户自定义在程序空间的段名”);

必须注意:

不能在函数体内声明,必须在定义和使用前声明。

#pragma可以阻止对未调用的函数的优化(优化我也不太理解)。

3.2812的CMD文件

(1)在CMD文件中有两个伪指令MEMORY和SECTIONS,其中SECTIONS的用法在上面已经有了介绍,就是将生成的代码或者数据分配到指定的存储器的映射空间去。

哪里是映射空间呢,这个就是由MEMORY这个伪指令来定义的,它的作用就是对整个存储器进行分区,然后给每个存储器进行命名,DSP只认物理地址(在我的第一篇日志里已经详细阐述了)。

下面先写下这两个伪指令的语法格式:

MEMORY{

 PAGE0:

name1[(attr)]origin=constant,length=constant;

 PAGEn:

name1[(attr)]origin=constant,length=constant;}

PAGEn中页号的最大值是255,每个PAGE代表一个完全独立得地址空间,通常n=0为数据空间,n=1为程序空间,name是对存储区间命名,attr规定了存储器得属性,R-读,W-写,一般我们不写的 

 ,origin,起始地址,length,该存储区间的大小。

SECTIONS{

       Name:

[property,property,…]

       Name:

[property,property,…]

       Name:

[property,property,…]}

Name:

源程序中的段名。

如.text,Property:

段的属性参数。

一个段的属性参数包括下列五种:

(1)Loadallocation,由它定义将输出段加载到存储器中的什么位置。

语法:

load:

>allocation       (allocation是将逻辑段定位的地址说明)

例如:

    .text:

       load=0x1000       ;将输出段定位到一个特定的地址

         .text:

       load>ROM       ;将输出段定位到命名为ROM的存储区

         .text:

       align=0x80       ;关键词align规定输出段.text定位到从地址边界0x80开始

         .text:

       block(128)       ;关键词bolck规定段必须在两个地址边界之内,如果段太

                                               ;大,就从一个地址边界开始

         .text:

       PAGE0               ;将输出段定位到PAGE0

如果输出段只定位一个位置,帽可省去关键字load。

如:

.text:

>ROM

如果要用到一个以上参数,可以将它们排成一行。

如:

.text:

 >ROMalign16PAGE2

或.text:

load(ROMalign(16)PAGE

(2))

(地址边界是2的N次方幂的地址,如地址边界定为16,则其地址为xxx0h。

(2)Runallocation,由它定义输出段在存储器的什么位置开始运行。

语法:

run=allocation或run>allocation

链接器为每个输出段在目标存储器中分配两个地址:

加载地址和执行地址。

通常这两个地址是相同的。

但如要先将程序加载到ROM,然后在RAM中以较快的速度运行。

则可两次定位,如:

       .fir:

       load=ROM,run=RAM

(3)Inputsections,由它定义哪些输入段组成输出段。

 语法:

{input_sections}

       .text:

         {*(.text)}

       这样就把所有的.text段链接成.text段输出。

也可以明确的用文件名和段名来确定输入段:

       .text:

       {

               F1.obj(.text,sect)       ;链接F1.obj的.text、.sect段

               F2.obj(sect)             ;

               F3.obj                     ;链接f3.obj的所有段

       }

(4)Sectiontype,用它为输出段定义特殊形式的标志

   语法:

Type=COPY、Type=DSECT、Type=NOLOAD

(5)Fillvalue,当初始化段中存在未初始化的存储区间时,对其填充一指定值。

   语法:

fill:

value或name:

…{…}=value

4.2812的CMD文件的编写

下面就来谈谈我对2812在写CMD文件的时候的一点理解,不足的地方希望各位看官拨冗指正

 。

(1)片内存储器分区MEMORY

先翻开相关芯片的存储空间的资料,然后分配一下你得程序存储空间和数据存储空间,即PAGE0和PAGE1,程序存储空间里通常放XINTF的ZONE0,1,2,6,7FLASHA-J,OPT,H0,bootROM,其中BOOTROM和XINTF得ZONE7是复用得,在不同得模式下选取不同的方式,MP/MC=0----BOOTROM,MP/MC=1----XINTFZONE7,在片内数据空间上定义各个存储器,这是也可以翻开你的书本,查下每章开头,一般都有这一章所涉及的所以的寄存器的地址,然后根据这些地址分配一下存储的单元的起始地址和空间的大小。

(2)SECTIONGS分块

这里举一个例子阐述一下分块的方法,例如我们在数据存储空间定义了SYSTEM块,主要就是给系统的时钟、看门狗、锁存器等分的一个空间,这个空间的大小是0x0020H,也就是10进制得32个字节单元,为什么要分32个字节单元呢,在书上我们可以查的系统得这一部分所对应的寄存器的名称和寄存器的字节数如下:

Reserved:

10;HISPCP:

1;LOSPCP:

1;PCLCR:

1;Reserved:

1;LPMCR0:

1;LPMCR1:

1;Reserved:

1;PLLCR:

1;SCSR:

1;WDCNTR:

1;

Reserved:

1;WDKEY:

1;Reserved:

3;WDCR:

1;Reserved:

6;计算一下,整个的存储器空间的大小是10+1+1+1+1+1+1+1+1+1+1+1+1+3+1+6=32.这就是为什么是32个字节的原因。

记住,此时这一块的名字是SYSTEM(当然你也可以另行定义)。

在SECTIONS中我们定义输出段的名字是SysCtrlRegsFile,其指向的就是SYSTEM.即

SysCtrlRegsFile:

>SYSTEM,PAGE0

然后我们在自己的头文件中定义结构体和联合体的时候,例如定义了一个SYSTEM_REGS的结构体,里面包含了系统的控制寄存器的联合体或者结合体,可以这么写:

structSYSTEM_REGS

{

Unit32 Reserved:

10;

union  HISPCP_REGSHISPCP;

union  LOSPCP_REGSLOSPCP;

union  PCLKER_REGSPCLKER;

Unit32 Reserved:

1;

union LPMCR0_REGSLPMCR0;

union LPMCR1_REGSLPMCR1;

Unit32Reserved:

1;

unionPLLCR_REGS PLLCR;

unionSCSR_REGS SCSR; 貌似这个是不用定义联合体的,Unit32SCSR:

1;

unionWDCNTR_REGSWDCNTR;

Unit32Reserved:

1;

unionWDKEY_REGSWDKEY;

Unit32Reserved:

3;

unionWDCR_REGSWDCR;

Unit32Reserved:

6;

}SysCtrlRegsFile;

这里面得联合体都有其自己的定义,例如PLLCR_REGS

structPLLCR_BITS

{

Unit16DIV:

4;

Unit16Reserved:

12;

};

unionPLLCR_REGS{

Unit16all;

structPLLCR_BITSbit;

};

这样我们要对PLLCR寄存器操作得时候就只需这么写:

SysCtrlRegsFile.PLLCR.all=0xXXXX;或者SysCtrlRegsFile.PLLCR.bit.DIV=0xXXXX;bit是结构体的一个变量 

 ,相信C语言得结构体和联合体(也叫共用体)大家都学得不比偶差吧。

对其操作过程就是自动得找到了SysCtrlRegsFile对应得那片空间0x00007010-0X0x702F,然后PLLCR就是就是里面的第18个空间即0x00007021,相信这么理解大家都应该明白了撒。

所有的寄存器都是这样写得哦。

 

 。

这就是我的理解,希望各位看官指教,拨冗指正,坚信成功源于共享!

 

TMS320F2812代码运行性能的研究

发布:

2008-4-0922:

23|作者:

王效东|来源:

单片机与嵌入式系统应用|查看:

7次

引言

TMS320F2812是目前性能非常优秀的32位定点DSP,集成了多种外设。

对TMS320F2812开发通常利用TI公司的CCS2集成开发环境,使用JTAG接口仿真器连接目标板,可以不占用用户资源实现全速/断点调试;仿真调试完成后对CMD文件进行相关修改,并用RTS2800_FL04830.LIB替换RTS2800N.LIB,必要时对程序中变量与函数分配的空间做部分调整后,编译项目得到输出文件;在CCS2集成开发环境中完成下载、加密等操作后,断电脱离仿真机,成为独立运行的嵌入式系统。

然而,相当多的应用设计者常常面临程序仿真通过,但独立运行失败的情况,表现均为程序代码运行性能比估计的要差很多,以致来不及处理实时数据。

由于代码在Flash中运行的时间比在SARAM中仿真的时间长,有的设计试验出现在Flash中运行比仿真慢4倍以上的结果,使设计只能停留在仿真通过的层次上。

1分析

TI公司提供的一篇文档资料spra958e.pdf,描述了在内部Flash中运行程序的相关知识,说明当在RAM中仿真速度为150MIPS时,相应Flash中的执行速度可达90~lOOMIPS;同时。

在此文档资料中提供了参考实例,但介绍性文字较多,实现高性能的具体配置方式描述不够具体。

经反复阅读TI公司的其他相关文档资料,并编程对比实验,笔者摸索出实现Flash中运行速度达到RAM中仿真速度的75%左右的方法,与TI指标相符合。

下面详细说明试验程序与方法。

限于篇幅,只列出与试验过程密切相关部分的配置情况。

试验程序使用的空间分配如表1所列。

试验程序如下:

下面是CMD文件关键内容。

因RAM仿真与下载Flash所用CMD文件有差异,故为节省篇幅,混合写在一起,差异部分参见说明。

试验程序运行时,用示波器在TMS320F2812的XF输出脚可以测量到重复脉冲(如图1所示),表2为对应的测量结果。

函数InitFlash()设置了等待参数。

在100MHz的系统时钟条件下,笔者的实例能保证正常执行的最佳参数;而其他设置会产生运行速度慢,或过快但运行不稳定的结果。

观察表2的测量结果,可以发现各方式下T1时间不变,原因为指令“asm(“RPT#248||NOP”)”取指令只执行一次,然后在DSP中内部循环执行250次,而只有取指令才涉及等待参数问题,所以在试验的4种条件下T1基本相同(毕竟还是存在取指令过程,每种条件下T1并非完全一致,有微小差别)。

因Flash本身访问速度比SARAM要慢,指令需要插入等待周期。

表2说明了下载到Flash中运行时的速度与在SARAM中仿真时相比,有所下降。

T2/T3/T4虽然同为数据传送花费时间,但因分布空间不同,对应汇编指令数和指令类型相应有增减,故表现出不同的执行时间,其中数据在外部RAM中传输比在内部SARAM中传输要慢。

表2还显示出下载到Flash中运行,如果同时对芯片加密,则应当特别注意变量分配的空间位置。

加密后Flash处于安全模块中,如果变量分配到HO,那么由于H0是非安全块,DSP工作时可以在两种模块中动态切换,不需要开发者附加代码。

描述参见TI文档资料中的CSM章节,但并未说明需要额外增加时间开销。

LOL1是安全块,如果变量分配到L0L1或是没有加密,则因不存在安全与非安全模块的切换时间开销,速度比较快。

当采用保护芯片知识产权而需要加密Flash时必须注意分配变量空间,把对运行速度敏感的参数分配到LOLl中,否则会发现程序执行速度降低到仿真时的1/4。

由于内部SARAM空间有限,应用系统往往需要外扩RAM,数据交换将比在内部SARAM执行时有所增多。

2结论

通过前面的试验,可以得到几个在TMS320F2812应用开发中,运行于Flash中的代码如何提高性能的指导原则:

①根据系统时钟选择合适的等待参数;

②数据分配空间从指令类型与数量上影响程序执行效率;

③Flash加密后,对执行速度有快速性要求的应用系统,应当在CMD文件中指定运行空间在SARAM的L0L1段,并注意变量分配的段空间。

设计系统如果满足上面几个原则,那么程序执行效率就可达到SARAM仿真时的70%。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 哲学历史

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1