CMD文件有两种产生方式:一种是手写,一种是由DSP/BIOS配置工具产生。CMD的作用很多,但它的最基本的功能就是实现对存储空间的说明和配置。
如下关于CMD配置的例程主要完成的功能有:
1. 说明系统有片内静态RAM(ISRAM,256KB)和片外动态RAM(SDRAM,32MB)组成,其起始地址和长度分别为...
2. 构建一个C工程需要多个段,SECTIONS中说明如何分配这些段。都放在ISRAM里当然快,但是工程大了肯定放不下,如何权衡自己考虑了。
3. 指明系统的堆和栈的大小。
-heap 0x800000
-stack 0x8000
MEMORY {
ISRAM : origin = 0x0, len = 0x40000
SDRAM : origin = 0x80000000, len = 0x2000000
}
SECTIONS
{
.vectors > ISRAM
.text > ISRAM
.satext > ISRAM
.wjpdata > ISRAM
.sadata > ISRAM
.bss > ISRAM
.cinit > ISRAM
.const > ISRAM
.far > ISRAM
.stack > ISRAM
.cio > SDRAM
.switch > SDRAM
.sysmem > SDRAM
.wjpout > ISRAM
}
这里各段(包括程序区,静态数据和动态数据区)注释为:
.vectors 中断向量表所在的段;
.text 程序代码所在的段;
.satext 非标准段,放置线性汇编程序代码;
.bss 非初始化变量段
.cinit 程序初始化段,经常放置一些没有用const说明的带初值变量的初始化值。
.const 使用const声明的变量和数组
.far 不可使用DP指针而必须使用全地址访问的变量所在的段,与far关键字和编译选项有关
.stack 系统栈使用的段
.cio printf等输入输出函数使用的缓冲区所在的段
.switch 程序中switch语句的跳转地址表
.system 系统堆,内存的动态开辟即使用这个段
最近开始研究TI的DSP。初步接触,对CMD文件很有些头疼,经过多方学习,也和TI的一些第三方支持如北京瑞泰等接触学习了一下,终于弄明白的CMD文件的相关信息,特此共享之。
CMD的专业名称叫链接器配置文件,是存放链接器的配置信息的,我们简称为命令文件。从其名称可以看出,该文件的作用是指明如何链接程序的。
那么我们知道,在编写TI DSP程序时,是可以将程序分为很多段,比如text、bss等,各段的作用均不相同。实际在片中运行时,所处的位置也不相同。比如text代码一般应该放在flash内,而bss的变量应该放在ram内。等等。但是对于不同的芯片,其各存储器的起止地址都是不一样的,而且,用户希望将某一段,尤其是自定义段,放在什么存储器的什么位置,这也是链接器不知道的。为了告诉链接器,即将使用的芯片其内部存储空间的分配和程序各段的具体存放位置,这就需要编写一个配置文件,即CMD文件了。
所以,CMD文件里面最重要的就是两段,即由MEMORY和SECTIONS两个伪指令指定的两段配置。简单的说,MEMORY就是用来建立目标存储器的模型,而SECTIONS指令就是根据这个模型来安排各个段的位置。
MEMORY指令可以定义目标系统的各种类型的存储器,及容量。MEMORY的语法如下:
其中。PAGE关键词对独立的存储空间进行标记,页号n的最大值为255,实际应用中一般分为三页,PAGE 0程序存储器、PAGE 1数据存储器和PAGE 2 IO空间存储器。name为自定义的存储区间的名字,不超过8个字符,不同的PAGE上可以出现相同的名字(最好不用,免的搞混),一个PAGE内不许有相同的name。 attr的属性标识,为R表示可读;W可写X表示区间可以装入可执行代码;I表示存储器可以进行初始化,什么属性代码也不写,表示存储区间具有上述的四种属性,基本上我们都选择这种写法。origin标识了该段存储区间的起始地址,而length则是标识了该段存储区间的长度。以2407A为例,根据这个定义,参考2407A的Datasheet,可以得出2407A内存储器的标准描述为:
有了这个模型。我们就可以定义各个代码段在内存的具体位置了。就是使用SECTIONS伪指令。其格式为:
SECTIONS必须用大写字母,其后的大括号里是输出段的说明性语句,每一个输出段的说明都是从段名开始,段名之后是如何对输入段进行组织和给段分配存储器的参数说明。以.text段的属性语句为例,“{所有.text输入段名}”这段内容用来说明连接器输出段的.text段由哪些子目标文件的段组成。接下来的load和run,链接器为每个输出段都在目标存储器里分配两个地址:一个是加载地址,一个是运行地址。通常情况下两个地址是相同的,可以认为输出段只有一个地址,这时就可以不加“run =运行地址”这条语句了;但有时需要将两个地址分开,比如将程序加载到FLASH,然后放到RAM中高速运行,这就用到了运行地址和加载地址的分别配置了。
load和run有一些简化写法,首先“load”关键字可以省略,“=”可以写成“>”, “加载地址”可以是:地址值、存储区间的名字、PAGE关键词等,所以大家见到“.text:{ } > 0×0080”这样的语句可千万不要奇怪。“run =运行地址”中的“ = ”可以用“>”其它的简化写法就没有了。大家不要乱用。
由此,一个简单的SECTIONS的代码就是:
这样的话,基本就可以理解CMD文件了。至于CMD的其他高级应用,暂时可以不用关心。
这里还需要补充说明的是:以2407A为例,0×40-0×43是加密位,一般编写CMD时最好错开此位,以免误加密。如果使用我这里的示例代码,那就应该在代码中以.word之类预留出加密位位置。否则一旦误加密,那。。。。本人不承担任何责任。。。呵呵
文章评论(0条评论)
登录后参与讨论