热度 22
2012-10-28 21:42
1787 次阅读|
2 个评论
CCS 中对 F2812 进行编程时,有个重要的文件,是以 .cmd 为后缀的,称为链接命令文件( Linker Command File ),简称 CMD 文件。这个 CMD 文件是跟 2812 的存储器结构有关的。 2812 的存储器分为程序存储器和数据存储器,程序存储器中的主要内容是可执行代码、初始化数据、开关量等,数据存储器中存储的是外部变量、静态变量、系统堆栈等。 CCS 编译产生若干可重定位的代码和数据块,称为 section (段),这些段会通过 CMD 文件重定位到相应地存储空间中。这些段可分为初始化段和非初始化段。 初始化段包含可执行代码和数据表,编译器产生以下各初始化段: 1 ) .text 段:包含所有可执行的代码和常量。 2 ) .cinit 段:初始化的变量和常量表,主要用于 C 程序中; 3 ) .pinit 段:初始化的变量和常量表,主要用于 C++ 程序中; 4 ) .const 段:包含字符串常以及用 const 声明的全局变量和静态变量; 5 ) .econst 段:同 .const 段,但用于 far const 声明的变量或编译器采用大存器模式时; 6 ) .switch 段:为开关语句( switch )建立的数据表。 非初始化段是在存储器中保留空间,通常是中 RAM 中,程序在运行时,可此空间创建和存储变量。编译器会产生的非初始化段如下: 1 ) .bss 段:为全局变量和静态变量保留的空间,在程序引导时,引导程序会将 ROM 中的 .cinit 段中的数据复制到 .bss 段中; 2 ) .ebss 段:为 far 声明的或大存储器模式下声明的全局变量和静态变量保留空间。在程序引导过程中,引导程序会将 ROM 中的 .cinit 段中的数据复制到 .ebss 段中; 3 ) .stack 段:为 C 系统堆栈分配的空间,用于函数调用时传递参数以及为局部变量分配空间。 4 ) .sysmem 段:为动态存储器分配保留空间,如果没有用到 malloc 函数,则该段空间大小为 0 ; 5 ) .esysmem 段:为动态存储器分配保留空间,如果没有用到 far malloc 函数,则该段空间大小为 0. 除了上述 C 编译器产生的段,在 F281x 中用户还可以通过 #pragma 预编译指令产生用户定义的段。 #pragma 的用法有两种: 1 ) #pragma CODE_SECTION(symbol, ”section name” ) 2 ) #pragma DATA_SECTIOM(symbol, “section name”) 说明: 1 ) symbol 既可以是函数名,也可以是全局变量名, section name 是用户自定义的段名; 2 ) CODE_SECTION 为用户自定义代码段, DATA_SECTION 为用户自定义的数据段; 3 )使用 #pragma 预编译指定要注意,一是不能在函数体中声明 #pragma ,二是必须在 symbol 被定义之前使用 #pragma. 举例 1 : #pragma CODE_SECTION(sum, “sectionA”) int sum(int a, int b) { return(a + b); } void main(void) { …… } 这里编译器就把函数 sum 的代码编译到段名为 sectionA 的程序段中。 举例 2 : #pragma DATA_SECTION(sin , “sinesection”) int sin = {……}; 这里编译器把数组 sin 编译到段名为 sinesection 的数据段中。 在 CMD 文件中,上述这些段都被分配到如下的页中,其中 PAGE 0 表示程序存储空间, PAGE 1 表示数据存储空间。 段 被分配的存储空间 .text PAGE 0 .cinit PAGE 0 .pinit PAGE 0 #pragma CODE_SECTION 定义的段 PAGE 0 .switch PAGE 1 .const PAGE 1 .econst PAGE 1 .bss PAGE 1 .ebss PAGE 1 .stack PAGE 1 .sysmem PAGE 1 .esysmem PAGE 1 #pragma DATA_SECTION 定义的段 PAGE 1 在 CMD 文件中主要通过两个伪指令 MEMORY 和 SECTIONS ,来实现指示存储空间和分配段到相应存储空间两个功能的。 MEMORY 语法如下: MEMORY { PAGE 0: name 0 : origin=constant, length=constant PAGE n: name n : origin=constant, length=constant } 说明: 1 ) PAGE 用来标示存储空间的关键字, n 最大为 255 , 2812 中,如前面所述, PAGE 0 表示程序存储空间, PAGE 1 表示数据存储空间; 2 ) name 表示某一属性和地址范围的存储空间名称,名称可以是 1~8 个字符,在同一页内,名称不能相同,不同页的名称可以相同; 3 ) attr 表示该存储空间的属性,共有四种属性——只读 R 、只写 W 、该空间包含可执行代码 X 、该空间包含被初始化代码 I ,此选型通常忽略; 4 ) origin 是用来定义存储空间起始地址的关键字; 5 ) length 是用来定义存储空间起始地址的关键字。 SECTIONS 语法如下: SECTIONS { name 0: 存储空间名称 , PAGE= 页数 name n: 存储空间名称 , PAGE= 页数 } 说明: 1 ) name 表示编译器输出段的名称; 2 ) 存储空间名称,是指用 MEMORY 伪指令指示的存储空间名称; 3 ) PAGE 是对应的页。 在 C 程序中,有如下的声明: #pragma DATA_SECTION(sin , “sinetable”) int sin ={………..}; 在 CMD 文件中: MEMORY { PAGE 0: SIN: origin=0x0000, length=0x0100 /* 起始地址为 0x0000 ,长度为 256*/ …… PAGE 1: …… } SECTIONS { …… sinetable :SIN, PAGE=0 …… } 这样 CCS 在编译时,就将程序中定义的正弦表 sin ,放到程序存储器地址以 0x0000 开头的长度为 256 的存储空间中。