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模式主要包括MEMORYSECTIONS两个字段;至于内存块怎么用,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

/*--- EABI段 ---*/
.cinit : > FLASHA, PAGE = 0, ALIGN(8)

/* 方案一:使用更大的合并区(已应用) */
.text : > FLASHBCD, PAGE = 0, ALIGN(8)

/* 方案二:分配到多个区(如需用方案二,注释上面的.text行,取消下面这行的注释)
.text : >> FLASHB | FLASHC | FLASHD, 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)

/*--- RAM函数段 ---*/
.TI.ramfunc :
{
*(.TI.ramfunc)
*(.ramfunc)
}
LOAD = FLASHE, PAGE = 0 /* 将FLASHD改为FLASHE,避免冲突 */
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

/*--- COFF兼容段 ---*/
.pinit : > FLASHA, PAGE = 0, ALIGN(8)
.ebss : > RAMLS5, PAGE = 1
.econst : > FLASHA, PAGE = 0, ALIGN(8)
.esysmem : > RAMGS1, PAGE = 1

/*--- IPC通信段 ---*/
GROUP : > CPU1TOCPU2RAM, PAGE = 1
{
PUTBUFFER
PUTWRITEIDX
GETREADIDX
}

/*--- 明确指定ramgs0/ramgs1段,消除警告 ---*/
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模式主要包括MEMORYSECTIONS两个字段,这个跟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中只是描述性的

© 2025 hywing 使用 Stellar 创建
总访问 113701 次 | 本页访问 326