CMD 文件那些事(上)—希望缄默 - 创龙小识堂 - 嵌入式开发者社区 - 51ele.net
设为首页收藏本站

嵌入式开发者社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 4833|回复: 0
打印 上一主题 下一主题

CMD 文件那些事(上)—希望缄默

[复制链接]

26

主题

29

帖子

158

积分

QQ游客

积分
158
跳转到指定楼层
楼主
发表于 2016-9-20 15:32:31 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 522066584 于 2016-9-20 15:43 编辑

本文介绍CMD 文件的基本功能及一些小技巧
概述
如果从事 TI DSP 处理器开发,CMD 文件一定是不可忽略的重要文件。当然,CMD 文件也并不是 DSP 处理器的专利,开发 TI ARM(不运行 HLOS 高阶操作系统),MCU 等处理器也都会遇到 CMD 文件。本文就以C6000 DSP CMD 文件为例,给大家说说 CMD 文件的那些事。
首先,需要知道 CMD 文件到底是什么文件?
CMD 即Linker Command Files 命令链接文件。CMD 发挥作用的阶段是在我们程序开发的链接阶段。即下图 Linker 阶段。
需要注意的是英文 LinkerCommand Files 中的 Files 是复数,也就是说在一个 DSP 项目中,CMD 文件可以不止一个。不论是否运行实时操作系统,都可以有多个 CMD 文件,但是不同的 CMD 文件中的内容不能有冲突,否则编译工具链会报链接错误!
既然 CMD 文件在链接阶段发挥作用,那么就需要知道编译工具链在链接阶段究竟做了些什么?
n  分配段到目标系统可配置内存区域
n  重新定位符号和段并指派最终地址
n  解析不同文件中未定义的外部引用
n  分配段到特定的内存区域
n  合并目标文件段
n  定义或重定义链接时全局符号
说了这么多,简而言之链接过程主要是一些对符号和程序段内存分配的操作。而 CMD 文件最主要的功能就是内存分配。


使用 CMD 文件CMD 文件结构
CMD 文件主要有三部分内容
1、链接选项
   可以在 CMD 文件修改链接选项,比如
   -heap 0x1000
   -stack 0x1000
   这两个参数是指定堆和栈的大小,这里需要注意的是堆栈,虽然一般都放在一起描述,但它们可不是一回事。
-l../../../Library/Codec/h264hpvdec_ti.le66
还可以链接静态库(-l 小写英文字母 L),这里使用的是相对路径。
2、MEMORY 指令 - 目标处理器内存区域描述
      这一部分主要是描述目标处理器中内存区域,只要是可访问的内存区域都可以在这里描述,当然需要用到的内存空间要描述,不用到的可以不用描述。需要注意的是,这个内存描述仅在 CMD 文件中有效,不会影响其它文件,也不可以在其它文件中引用。
语法
MEMORY
{
name 1 [( attr )] : origin = expression , length = expression [, fill = constant]
.
.
name n [( attr )] : origin = expression , length = expression [, fill = constant]
}
name 命名一段内存区域,长度 1 - 64 个字符,可以使用 A - Za - z$.以及 _
attr 为这段内存区域指定 1 - 4 个属性。可选参数。属性限制对于段的分配。如果,不指定该参数即代表不限制该内存段属性。有效的属性有
R 内存区域可读
W 内存区域可写
X 内存区域包含可执行代码
I  内存区域可被初始化
origin 指定内存区域起始地址,也可以写作 origin,org 或 o。地址以字节为单位的 32 位常量表达式,可以是十六进制、十进制或者八进制。
length 指定内存区域长度,也可以写作 length,len 或 l。可以是十六进制、十进制或者八进制。
fill 使用指定字符填充内存区域,也可以写作fill 或 f。可选参数。填充字符为一个整数常量,可以是十六进制、十进制或者八进制。 fill 用于填充一段不用来分配段的内存区域。
地址操作可以使用的表达式,表达式的规则与标准 C语言一致。
单目运算符 - ~ !
双目运算符 * / % + -<<>> == = <<= >>= & | && ||
其它 START SIZE END 这三个关键字分别用于获取引用内存区域的起始地址、大小及结束地址。

使用表达式描述地址的范例。
/********************************************************/
/* 范例*/
/********************************************************/
file1.obj file2.obj /* 输入文件 */
--output_file=prog.out /* 选项 */
#define ORIGIN 0x00000000
#define BUFFER 0x00000200
#define CACHE 0x0001000

MEMORY
{
FAST_MEM (RX): origin =ORIGIN + CACHE length = 0x00001000 + BUFFER
SLOW_MEM (RW): origin = end(FAST_MEM)length = 0x00001800 - size(FAST_MEM)
EXT_MEM (RX): origin = 0x10000000 length = size(FAST_MEM) - CACHE
}

3、SECTIONS 指令 - 分配程序段到内存
描述输入段如何合并到输出段;
定义可执行文件中的输出段;
指定输出段放置到的内存区域;
允许重命名输出段。

SECTIONS
{
name : [property [, property] [, property] . . . ]
name : [property [, property] [, property] . . . ]
name : [property [, property] [, property] . . . ]
}

加载分配 定义段被加载到的内存区域
语法:     load = 区域或
          区域或
> 区域
运行分配 定义段运行的内存区域
语法:     run = 区域 或
run > 区域
输入段定义用于组成输出段的输入段(目标文件)
语法:     { 输入段 }
段类型   定义特定段标志
语法:     type = COPY 或
type = DSECT 或
type = NOLOAD
填充值   定义用来填充未初始化区域(Hole)值
语法:     fill = 值 或
          名称: [属性= 值]

SECTIONS 指令范例
/**************************************************/
/* 范例*/
/**************************************************/
file1.obj file2.obj /* 输入文件 */
--output_file=prog.out /* 选项 */
SECTIONS
{
.text: load =EXT_MEM, run = 0x00000800
.const: load =FAST_MEM
.bss: load =SLOW_MEM
.vectors: load =0x00000000
{
t1.obj(.intvec1)
t2.obj(.intvec2)
endvec = .;
}
.data:alpha: align =16
.data:beta: align =16
}

结合前面的范例,最终的内存分配如下图所示
此外,有部分段由编译器及程序设计语言(C++ / C / 汇编)定义,当然开发人员也可以自行定义段。
编译工具创建的已初始化的程序段(EABI
  
名称
  
说明
.args
宿主加载器命令参数(host-based loader),只读段 (参阅 --arg_size 选项)
.binit
启动(boot)时复制表(参阅 TMS320C6000 Assembly  Language Tools User's
  
Guide 中关于 binit CMD 文件中的应用)
.cinit
EABI 模式下默认不创建该段,但是使用了 --rom_mode链接选项之后,会创建该段。包含已初始化表(全局及静态变量)。
.const
远程(far)已初始化的全局及静态常量包括字符串
.c6xabi.exidx
C++ 异常(exception)处理索引表,只读段 (参阅 --exceptions  选项)
.c6xabi.extab
C++ 异常(exception)处理 Unwinded instructions,只读段 (参阅 --exceptions 选项)
.fardata
远程(far)已初始化的全局及静态变量
.init_array
启动(startup )调用的构造器表
.name.load
程序段名称压缩镜像,只读段 (参阅 TMS320C6000  Assembly
  
Language Tools User's  Guide 关于 copy tables 的相关信息)
.neardata
近程(near)已初始化的全局及静态变量
.ppdata
基于编译工具的性能分析(compiler based profiling)数据 (参阅 --gen_profile_info 选项)
.ppinfo
基于编译工具的性能分析相关系数(Correlation) (参阅  --gen_profile_info 选项)
.rodata
近程(near)全局及静态常量
.switch
large switch 语句跳转表
.text
可执行代码和常数

编译工具创建的未初始化的程序段(COFFABI EABI
  
名称
  
说明
.bss
全局及静态变量
.far
远程(far)全局及静态变量
.stack
.sysmem
malloc 函数内存()
自行定义段名称不能跟这些名称冲突。




3.jpg (266.19 KB, 下载次数: 356)

3.jpg

4.jpg (41.83 KB, 下载次数: 333)

4.jpg
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|嵌入式开发者社区 ( 粤ICP备15055271号

GMT+8, 2024-4-29 08:00 , Processed in 0.042526 second(s), 27 queries .

Powered by Discuz! X3.2

© 2001-2015 Comsenz Inc.

快速回复 返回顶部 返回列表