CMD文件
主要是有FLASH和RAM两种下载模式:FLASH是把程序烧录到FLASH中运行,RAM模式则是把程序烧录到RAM里边运行,以TMS320F28379D为例,它支持2837xD_FLASH_lnk_cpu1.cmd和2837xD_RAM_lnk_cpu1.cmd两种下载调试模式,下载模式可以在对应工程的Properties -> General -> Linker command file
里边指定

FLASH
FLASH模式主要包括MEMORY
和SECTIONS
两个字段;至于内存块怎么用,SECTIONS
会告诉你
1 2 3 4 5 6 7 8 9
| MEMORY {
}
SECTIONS {
}
|
一般MEMORY会分成两个PAGE:PAGE0和PAGE1,PAGE0存放program代码(FLASH),PAGE1存放data代码(RAM);每个PAGE包含若干个内存块,每个内存块的字段名
、起始地址
和大小空间
会在MEMORY
里边给出,原则上合起来的空间不能超过物理内存空间大小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| MEMORY { PAGE 0 : /* 程序存储区(Flash) */ BEGIN : origin = 0x080000, length = 0x000002 FLASHA : origin = 0x080002, length = 0x001FFE /* 方案一:合并FLASHB/C/D为一个更大的区域(已应用) */ FLASHBCD : origin = 0x082000, length = 0x006000 /* 24KB (合并B+C+D) */ /* 方案二:分别保留各区(如需用方案二,注释上面的FLASHBCD,取消下面三行的注释) FLASHB : origin = 0x082000, length = 0x002000 FLASHC : origin = 0x084000, length = 0x002000 FLASHD : origin = 0x086000, length = 0x002000 */ FLASHE : origin = 0x088000, length = 0x008000 FLASHF : origin = 0x090000, length = 0x008000 RESET : origin = 0x3FFFC0, length = 0x000002
PAGE 1 : /* 数据存储区(RAM) */ RAMM0 : origin = 0x000123, length = 0x0002DD RAMM1 : origin = 0x000400, length = 0x0003F8 RAMLS0 : origin = 0x008000, length = 0x000800 RAMLS5 : origin = 0x00A800, length = 0x000800 RAMGS0 : origin = 0x00C000, length = 0x001000 RAMGS1 : origin = 0x00D000, length = 0x001000 CPU1TOCPU2RAM : origin = 0x03FC00, length = 0x000400 }
|
至于内存块怎么用,SECTIONS
会告诉你,SECTIONS会把MEMORY里边定义的内存块安排得明明白白,以下代码跟ARM里边的link script差不多,我们可以看到下边代码段(eabi、text、const)主要是存放在FLASH空间,数据段(bss、func、stack、data)主要是存放RAM空间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| SECTIONS { codestart : > BEGIN, PAGE = 0 .reset : > RESET, PAGE = 0, TYPE = DSECT
.cinit : > FLASHA, PAGE = 0, ALIGN(8) .text : > FLASHBCD, PAGE = 0, ALIGN(8)
.const : > FLASHF, PAGE = 0, ALIGN(8) .init_array : > FLASHA, PAGE = 0, ALIGN(8) .bss : > RAMLS5, PAGE = 1, ALIGN(8) .sysmem : > RAMGS1, PAGE = 1, ALIGN(8)
.TI.ramfunc : { *(.TI.ramfunc) *(.ramfunc) } LOAD = FLASHE, PAGE = 0 RUN = RAMLS0, PAGE = 1 LOAD_START(RamfuncsLoadStart), LOAD_END(RamfuncsLoadEnd), LOAD_SIZE(RamfuncsLoadSize), RUN_START(RamfuncsRunStart), RUN_SIZE(RamfuncsRunSize), RUN_END(RamfuncsRunEnd), ALIGN(8)
.stack : > RAMGS0, PAGE = 1 .data : > RAMGS0, PAGE = 1 .cio : > RAMLS5, PAGE = 1
.pinit : > FLASHA, PAGE = 0, ALIGN(8) .ebss : > RAMLS5, PAGE = 1 .econst : > FLASHA, PAGE = 0, ALIGN(8) .esysmem : > RAMGS1, PAGE = 1
GROUP : > CPU1TOCPU2RAM, PAGE = 1 { PUTBUFFER PUTWRITEIDX GETREADIDX }
ramgs0 : > RAMGS0, PAGE = 1 ramgs1 : > RAMGS1, PAGE = 1 }
|
link script里边每个字段的功能
段名称 |
内存位置 |
页面 |
说明 |
codestart |
BEGIN |
PAGE = 0 |
代码起始部分,位于Flash初始地址,包含程序入口点 |
.reset |
RESET |
PAGE = 0 |
复位向量段,TYPE = DSECT表示只是描述性的,不占用实际空间 |
.cinit |
FLASHA |
PAGE = 0 |
C语言全局变量初始化表,ALIGN(8)表示按8字节对齐 |
.text |
FLASHBCD |
PAGE = 0 |
主要代码段,放在合并的大Flash区域(24KB)以容纳更多代码 |
.const |
FLASHF |
PAGE = 0 |
常量数据段,存放在Flash中的只读数据 |
.init_array |
FLASHA |
PAGE = 0 |
用于C++全局对象构造函数的表 |
.bss |
RAMLS5 |
PAGE = 1 |
未初始化的全局和静态变量段,位于RAM中 |
.sysmem |
RAMGS1 |
PAGE = 1 |
动态内存分配的堆区域,用于malloc()等函数 |
.TI.ramfunc |
FLASHE→RAMLS0 |
PAGE = 0→1 |
RAM函数段,特殊处理:在Flash中存储但运行时复制到RAM中执行 |
.stack |
RAMGS0 |
PAGE = 1 |
系统堆栈段,已移至更大的内存区域RAMGS0 |
.data |
RAMGS0 |
PAGE = 1 |
已初始化的全局和静态变量段 |
.cio |
RAMLS5 |
PAGE = 1 |
C标准I/O缓冲区 |
.pinit |
FLASHA |
PAGE = 0 |
用于C++全局对象初始化的表(旧格式) |
.ebss |
RAMLS5 |
PAGE = 1 |
扩展的.bss段,COFF格式兼容性 |
.econst |
FLASHA |
PAGE = 0 |
扩展的常量段,COFF格式兼容性,存放在Flash中 |
.esysmem |
RAMGS1 |
PAGE = 1 |
扩展的系统内存段,COFF格式兼容性 |
GROUP (CPU1TOCPU2RAM) |
CPU1TOCPU2RAM |
PAGE = 1 |
CPU1到CPU2的通信缓冲区,包含多个子段 |
ramgs0/ramgs1 |
RAMGS0/RAMGS1 |
PAGE = 1 |
明确指定这些内存区域的段名,以消除链接警告 |
RAM
RAM模式主要包括MEMORY
和SECTIONS
两个字段,这个跟FLASH模式是一样的,但不同的是:
1 2 3 4 5 6 7 8 9
| MEMORY {
}
SECTIONS {
}
|
一般MEMORY会分成两个PAGE:PAGE0和PAGE1,PAGE0存放program代码(RAM),PAGE1存放data代码(RAM),可以看到为了优化调试运行速度,所有的应用及数据都放在RAM运行了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| MEMORY { PAGE 0 : BEGIN : origin = 0x000000, length = 0x000002 RAMM0 : origin = 0x000123, length = 0x0002DD RAMD0 : origin = 0x00B000, length = 0x000800 RAMLS0 : origin = 0x008000, length = 0x000800 RAMLS1 : origin = 0x008800, length = 0x000800 RAMLS2 : origin = 0x009000, length = 0x000800 RAMLS3 : origin = 0x009800, length = 0x000800 RAMLS4 : origin = 0x00A000, length = 0x000800 RESET : origin = 0x3FFFC0, length = 0x000002
PAGE 1 : BOOT_RSVD : origin = 0x000002, length = 0x000121 RAMM1 : origin = 0x000400, length = 0x0003F8 RAMD1 : origin = 0x00B800, length = 0x000800 RAMLS0 : origin = 0x008000, length = 0x000800 RAMLS5 : origin = 0x00A800, length = 0x000800 RAMGS0 : origin = 0x00C000, length = 0x001000 RAMGS1 : origin = 0x00D000, length = 0x001000 RAMGS2 : origin = 0x00E000, length = 0x001000 /* 合并RAMGS3~5为一个大区 */ RAMGS3_5 : origin = 0x00F000, length = 0x003000 /* 注释掉原有的RAMGS3~5 RAMGS3 : origin = 0x00F000, length = 0x001000 RAMGS4 : origin = 0x010000, length = 0x001000 RAMGS5 : origin = 0x011000, length = 0x001000 */ RAMGS6 : origin = 0x012000, length = 0x001000 RAMGS7 : origin = 0x013000, length = 0x001000 RAMGS8 : origin = 0x014000, length = 0x001000 RAMGS9 : origin = 0x015000, length = 0x001000 RAMGS10 : origin = 0x016000, length = 0x001000 RAMGS11 : origin = 0x017000, length = 0x001000 RAMGS12 : origin = 0x018000, length = 0x001000 RAMGS13 : origin = 0x019000, length = 0x001000 RAMGS14 : origin = 0x01A000, length = 0x001000 RAMGS15 : origin = 0x01B000, length = 0x000FF8 CPU2TOCPU1RAM : origin = 0x03F800, length = 0x000400 CPU1TOCPU2RAM : origin = 0x03FC00, length = 0x000400 CANA_MSG_RAM : origin = 0x049000, length = 0x000800 CANB_MSG_RAM : origin = 0x04B000, length = 0x000800 }
|
我们可以看到下边代码段(eabi、text、const)以及数据段(bss、func、stack、data)全都存RAM空间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| SECTIONS { codestart : > BEGIN, PAGE = 0 .reset : > RESET, PAGE = 0, TYPE = DSECT
/* 让.text段放入合并后的大区 */ .text : > RAMGS3_5, PAGE = 1 .cinit : > RAMM0, PAGE = 0 .switch : > RAMM0, PAGE = 0 .bss : > RAMLS5, PAGE = 1, ALIGN(8) .init_array : > RAMM0, PAGE = 0 .const : > RAMLS5, PAGE = 1 .data : > RAMLS5, PAGE = 1 .sysmem : > RAMLS5, PAGE = 1
.TI.ramfunc : > RAMLS0, PAGE = 1, ALIGN(8)
.stack : > RAMM1, PAGE = 1, ALIGN(8) .pinit : > RAMM0, PAGE = 0 .ebss : > RAMLS5, PAGE = 1 .econst : > RAMLS5, PAGE = 1 .esysmem : > RAMLS5, PAGE = 1
Filter_RegsFile : > RAMGS0, PAGE = 1 ramgs0 : > RAMGS0, PAGE = 1 ramgs1 : > RAMGS1, PAGE = 1
/* SDFM例程段移到后面未用的RAM区 */ Filter1_RegsFile : > RAMGS6, PAGE = 1, fill=0x1111 Filter2_RegsFile : > RAMGS7, PAGE = 1, fill=0x2222 Filter3_RegsFile : > RAMGS8, PAGE = 1, fill=0x3333 Filter4_RegsFile : > RAMGS9, PAGE = 1, fill=0x4444 Difference_RegsFile : > RAMGS10, PAGE = 1, fill=0x3333
GROUP : > CPU1TOCPU2RAM, PAGE = 1 { PUTBUFFER PUTWRITEIDX GETREADIDX } GROUP : > CPU2TOCPU1RAM, PAGE = 1 { GETBUFFER : TYPE = DSECT GETWRITEIDX : TYPE = DSECT PUTREADIDX : TYPE = DSECT } }
|
每个SECTIONS字段功能详解
段名称 |
内存位置 |
页面 |
说明 |
codestart |
BEGIN |
PAGE = 0 |
代码起始部分,通常包含程序入口点和初始化代码 |
.reset |
RESET |
PAGE = 0 |
复位向量段,用于处理CPU复位后的跳转地址,TYPE = DSECT表示只是描述性的,不占用实际空间 |
.text |
RAMGS3_5 |
PAGE = 1 |
主要代码段,包含程序的执行代码,放在合并的大内存区域中以容纳更多代码 |
.cinit |
RAMM0 |
PAGE = 0 |
C语言全局变量初始化表段,用于存储全局变量的初始值 |
.switch |
RAMM0 |
PAGE = 0 |
用于C语言switch语句的跳转表 |
.bss |
RAMLS5 |
PAGE = 1 |
未初始化的全局和静态变量段,ALIGN(8)表示按8字节对齐 |
.init_array |
RAMM0 |
PAGE = 0 |
用于C++全局对象构造函数的表 |
.const |
RAMLS5 |
PAGE = 1 |
常量数据段,存放程序中的常量值 |
.data |
RAMLS5 |
PAGE = 1 |
已初始化的全局和静态变量段 |
.sysmem |
RAMLS5 |
PAGE = 1 |
动态内存分配的堆区域,用于malloc()等函数 |
.TI.ramfunc |
RAMLS0 |
PAGE = 1 |
RAM函数段,存放需要在RAM中执行的高性能函数 |
.stack |
RAMM1 |
PAGE = 1 |
系统堆栈段,用于函数调用和局部变量 |
.pinit |
RAMM0 |
PAGE = 0 |
用于C++全局对象初始化的表(旧格式) |
.ebss |
RAMLS5 |
PAGE = 1 |
扩展的.bss段,COFF格式兼容性 |
.econst |
RAMLS5 |
PAGE = 1 |
扩展的常量段,COFF格式兼容性 |
.esysmem |
RAMLS5 |
PAGE = 1 |
扩展的系统内存段,COFF格式兼容性 |
Filter_RegsFile |
RAMGS0 |
PAGE = 1 |
滤波器寄存器文件,用于数字滤波器的配置数据 |
ramgs0/ramgs1 |
RAMGS0/RAMGS1 |
PAGE = 1 |
明确指定这些内存区域的段名,以便在代码中直接引用 |
Filter1_RegsFile等 |
RAMGS6-10 |
PAGE = 1 |
SDFM(Sigma-Delta滤波器模块)例程数据区,fill值用于特定的初始化模式 |
GROUP (CPU1TOCPU2RAM) |
CPU1TOCPU2RAM |
PAGE = 1 |
CPU1到CPU2的通信缓冲区,包含多个子段用于数据传输和同步 |
GROUP (CPU2TOCPU1RAM) |
CPU2TOCPU1RAM |
PAGE = 1 |
CPU2到CPU1的通信缓冲区,TYPE = DSECT表示这些段在CPU1中只是描述性的 |