DSP

C6000 DSP技术深度探索(2)---链接命令文件(cmd)

2019-07-13 15:54发布

一个DSP工程中主要包含如下几种类型文件:
<1>C文件(*.c及*.h);
<2>汇编文件(*.asm),注意有两种比较特殊的汇编文件,一种是中断向量表(vectors.asm-常见于不包含DSP/BIOS的程序中),
另一种是bootloader文件(该文件实现二级启动功能);
<3>库文件(*.lib、*.a、*.a64等),该类型文件是对源文件的一种封装,通常只提供API调用接口,不提供源码,既可以防止对
源文件的误修改,也可以起到保护知识产权的作用;
<4>dsp/bios(*.tcf),该文件见于使用DSP/BIOS中的工程中,是DSP/BIOS的配置文件,可以使用图形或文本方式进行DSP/BIOS的配置
<5>链接命令文件,该文件主要是定义存储器的物理空间(MEMORY)及程序段与物理空间的映射关系(SECTIONS);
    这里先从CMD文件说起,首先说一下MEMORY部分,这里以TMS320C6455的一个实例进行讲解:
MEMORY {
    L1PRAM:     o = 0x00E00000  l = 0x00008000  /* 32kB L1 Program SRAM/CACHE */
    L1DRAM:     o = 0x00F00000  l = 0x00008000  /* 32kB L1 Data SRAM/CACHE */
    L2RAM:       o = 0x00800000  l = 0x00200000  /* 2MB L2 Internal SRAM */
    EMIFA_CE2:  o = 0xA0000000  l = 0x00800000  /* 8MB EMIFA CE2 */
    EMIFA_CE3:  o = 0xB0000000  l = 0x00800000  /* 8MB EMIFA CE3 */
    EMIFA_CE4:  o = 0xC0000000  l = 0x00800000  /* 8MB EMIFA CE4 */
    EMIFA_CE5:  o = 0xD0000000  l = 0x00800000  /* 8MB EMIFA CE5 */
    DDR2_CE0:   o = 0xE0000000  l = 0x10000000  /* 256MB EMIFB CE0 */

上面的MEMORY部分主要分三个部分:存储器名    存储器起始地址     存储器长度;
该段定义与相应DSP芯片及硬件板卡(外部扩展存储部分)是密切相关的,大家可以查一下6455的手册的memory map部分,可以看到该部分
与上面的代码是一一对应的,上面定义的存储器名部分是用于SECTIONS后面段分配的。
接下来再说说SECTIONS部分,如下:
SECTIONS {
    .vector        >      0x00800000, RUN_START(_ISTP_START)
    .text          >  L2RAM
    .stack         >  L2RAM
    .bss           >  L2RAM
    .cio           >  L2RAM
    .const         >  L2RAM
    .data          >  L2RAM
    .switch        >  L2RAM
    .sysmem        >  L2RAM
    .far           >  L2RAM
    .args          >  L2RAM
    .ppinfo        >  L2RAM
    .ppdata        >  L2RAM


    /* COFF sections */
    .pinit         >  L2RAM
    .cinit         >  L2RAM
}
上面这种是最简单的一种SECTIONS定义,这个SECTIONS部分的格式如下:
段名    >    存储器名
首先说一下什么是“section”,所谓的section是一个目标文件(*.obj)中的最小单元,它通常是占据一段连续存储空间的代码或数据,
借助“section”,程序员就可以使用模块化的编程思想,将相近功能的代码或数据放在一起(这类似于C语言中过程式编程语言,将一段
代码放在一个函数中)如果你是一个使用汇编语言编写代码的工程师,你对这点一定深有体会。


在上面的代码段中,段主要有两种(也可以说三种,因为.bss,.data和.text是汇编器默认创建的段,只是对于C编译器来说,它会创建自
己的.bss和.text,并且它不使用汇编器创建的.data段),一种是用户自定义段,一种是编译器创建的段,上面的.vector段就是用户自定
义段(该段通常是在vectors.asm中定义的,用于存储中断向量表,至于为什么将该段存放在000800000起始的段地址,就要查看6455的启动
方式(No BOOT方式)了),其余段就是C编译器创建的段了。
首先说一下如何使用自定义段,如果你使用汇编语言,你有两种方式创建自定义段,一个是".sect",一个是".usec",前者创建初始化段,
后者创建未初始化段,例如上面.vector段的创建语法如下:
标号(可选) 汇编指令    (段名)
__vector    .sect       ".vector"
在上面的这条语句之后到下一个段名之前的程序将被存储在.vector段中,然后就可以通过cmd文件中的section将该段
分配到特定存储空间


如果你使用C语言,你可以使用如下的方式将一些代码或数据存放到指定存储段,例如:

#pragma DATA_SECTION (my_array,".self_section")
unsigned char my_array[100];

SECTIONS
{    
    .self_section         >  L2RAM
}
这样就将一个数组分配到了L2RAM。
接下来说一下编译器创建的段,这里对于COFF ABI和EABI来说,编译器创建的段是不一样的,
如下为COFF ABI创建的初始化段
=====================================================================================================
Name                  Contents
-----------------------------------------------------------------------------------------------------
.args      |  Command argument for host-based loader; read-only (see the --arg_size option)
-----------------------------------------------------------------------------------------------------
.cinit      |  Tables for explicitly initialized global and static variables
-----------------------------------------------------------------------------------------------------
.const    |  Global and static const variables that are explicitly initialized and contain string
             |  literals
-----------------------------------------------------------------------------------------------------
.pinit     |  Table of constructors to be called at startup
-----------------------------------------------------------------------------------------------------
.ppdata  |  Data tables for compiler-based profiling (see the --gen_profile_info option)
-----------------------------------------------------------------------------------------------------
.ppinfo  |  Correlation tables for compiler-based profiling ( see the --gen_profile_info option)
-----------------------------------------------------------------------------------------------------
.switch  |  Jump tables for large switch statements
-----------------------------------------------------------------------------------------------------
.text    |  Executable code and constants
=====================================================================================================
如下是EABI创建的初始化段:
=====================================================================================================
Name          |          Contents
.args           | Command argument for host-based loader; read-only (see the --arg_size option)
-----------------------------------------------------------------------------------------------------
.binit           |  Boot time copy tables (See the TMS320C6000 Assembly Language Tools User's
                   |  Guide for information on BINIT in linker command files.)
-----------------------------------------------------------------------------------------------------
.cinit           |  In EABI mode, the compiler does not generate a .cinit section. However, when the --
                   |  rom_mode linker option is specified, the linker creates this section, which contains
                   |  tables for explicitly initialized global and static variables.
-----------------------------------------------------------------------------------------------------
.const         |  Far, const global and static variables, and string constants
-----------------------------------------------------------------------------------------------------
.c6xabi.exidx |  Index table for exception handling; read-only (see --exceptions option)
-----------------------------------------------------------------------------------------------------
.c6xabi.extab |  Unwinded instructions for exception handling; read-only (see --exceptions option)
-----------------------------------------------------------------------------------------------------
.fardata      |  Far non-const global and static variables that are explicitly initialized
-----------------------------------------------------------------------------------------------------
.init_array   |  Table of constructors to be called at startup
-----------------------------------------------------------------------------------------------------
.name.load    |  Compressed image of section name; read-only (See the TMS320C6000 Assembly
                      |  Language Tools User's Guide for information on copy tables.)
-----------------------------------------------------------------------------------------------------
.neardata     |  Near non-const global and static variables that are explicitly initialized
-----------------------------------------------------------------------------------------------------
.ppdata       |  Data tables for compiler-based profiling (see the --gen_profile_info option)
-----------------------------------------------------------------------------------------------------
.ppinfo       |  Correlation tables for compiler-based profiling (see the --gen_profile_info option)
-----------------------------------------------------------------------------------------------------
.rodata       |  Global and static variables that have near and const qualifiers
-----------------------------------------------------------------------------------------------------
.switch       |  Jump tables for large switch statements
-----------------------------------------------------------------------------------------------------
.text         |  Executable code and constants
=====================================================================================================
如下是EABI和COFF ABI创建的未初始化段:
=====================================================================================================
 Name       Contents
 -----------------------------------------------------------------------------------------------------
.bss        Global and static variables
-----------------------------------------------------------------------------------------------------
.far        Global and static variables declared far
-----------------------------------------------------------------------------------------------------
.stack      Stack
-----------------------------------------------------------------------------------------------------
.sysmem     Memory for malloc functions (heap)
=====================================================================================================


上面就是CMD文件的详细说明,理解了这些只是第一步,对于CMD文件最重要的作用还是对程序的优化,需要编程人员
深入理解以上各段的含义,将不同的段分配到合适的存储器中,例如将需要重复运行的代码及数据放到速度最快的一级存储空间,
对于只需要运行一次的代码及数据,放到速度较慢的外部存储。