应用笔记 · 2014年8月31日

TI C2000 Delfino TMS320F28335的28335_Ram_lnk.cmd文件 详解

摘自:http://bbs.ednchina.com/BLOG_ARTICLE_3009305.HTM

      写在最前,不喜请略过。本博文的主要内容已在QQ空间、人人网、网易博客、百度空间等平台发表过,最近进行了排错和修改,作者为Mr_D_prince(斌斌-龙臻),也就是本人,前两者均为我在非技术论坛的昵称。在技术论坛我更喜欢newofcortexm3这个昵称,原因无他,我就是个技术新人。之所以文章类型为什么是整理,是因为博文的主要内容均来自TI相关的技术手册,我只是做了下解读或者整理。

    参与了一款两轮自平衡机器人的研究项目。随着项目实践深入,要实现的功能越来越复杂,所定义的常量、变量也越来越多。某一天,当我增加了串口通信的代码之后,CCSV4.12竟然提醒编译不通过,提醒的内容是“.econst”的容量超限,如下图1所示,而把增加的代码删除之后,程序可以正常编译且运行。

问题.jpg
图1:编译出现的问题

    既然是容量问题,那我削减变量、常量的个数总可以吧,当我费了九牛二虎之力把可删减的常变量去掉之后,这个问题依然存在,。而此问题的原因恰恰是CCS安装完C2000目录下自带的28335_Ram_lnk.cmd文件(09年之后)上的那些“段”的空间映射的太细,太小。新版本的28335_Ram_lnk.cmd文件上“.econst”段空间长度为0x1000,只有之前的版本的四分之一。

    先来简单介绍下cmd文件。CCS的每一个项目都必须有CMD文件,CMD文件主要是用来对存储区域进行划分并对输出端进行地址分配。说的笼统点,就是将处理器的片内外存储器进行空间分配。

    在CMD文件中,可以通过MEMORY伪指令确定目标存储器的属性及存储区域。每个存储区域包括:名字,起始地址,长度,属性选项,指定填充选项。F28xx系列DSP的数据和程序空间是相互独立的,在默认状态下,一部分存储器作为程序区域,一部分存储器作为数据区域。一般来说,MEMORY伪指令的PAGE0配置程序空间,PAGE1配置数据空间。使用MEMORY伪指令必须指明转载代码要用到的存储区域,以便链接器进行配置。MEMORY的一般指令格式如图2所示:

memory.jpg
图2:MEMORY指令格式

 

 

 

    在链接时,一般通过SECTIONS伪指令把输出段分配到MEMORY伪指令定义的存储区域。每一个输出段以名称开头,定义一个输出文件中的段。段名后面是段的属性,段的属性可能有以下几种:装载位置,运行位置,输出端,段类型,填充值。链接器为每一个输出段在目标存储器中分配两个地址,一个是段的装载位置,一个是段的运行位置。通常情况下,这两个地址相同。

 

 

 

    可以通过一个或多个定位参数来控制地址分配,每一个参数包含一个关键字、可选的符号为等号或大于号。所用到的关键字有:LOAD(装载),Binding(绑定),Named MEMORY(命名存储器),Alignment(定位),Blocking(分块),Page(页)。相比较而言,Page的使用率远远高于其他几个关键字。SECTIONS的一般指令格式如图3所示:sections.jpg

图3:SECTION指令格式

    在图3SECTIONS的指令格式中,我们看到了一些段名,有必要对这些段名做些解释。链接器定义了两种基本类型的段:一种是包括数据表格或执行代码的已初始化的段,另一种是分配在RAM空间的未初始化的段。

.text  此段存储所有执行代码和常数

.cinit此段存放初始化变量和常数,包含未用const声明的外部(extern)或静态(static)数据表

.pinit此段存放初始化变量和常数

.const此段存放字符串常量,声明,具备常数性质的全局和静态变量,包括已经用const声明的外部或静态数据表以及字符串常量

.econst此段的属性与.const相同。不同的是,.const的分配范围被限制在低64K16位数据区内,而.econst的分配范围是4M22位数据区

.switch  此段存放switch语句的常数表格 

以上的段都是已经初始化了的段。

链接器定义的未初始化的段为:.bss,.ebss,.stack,.sysmem,.esysmem。

.bss此段为全局和静态变量保留空间。它是一种默认的COFF(Common Object File Format)(如有兴趣了解,请查看TI的手册)段。

.ebss此段的属性与.bss相同。不同的是,.bss的分配范围被限制在低64K16位数据区内,而.ebss的分配范围是4M22位数据区

.stack  此段为C系统的栈存储区,用来向函数传递数值与分配局部变量空间。

.sysmem此段为堆存储区

.esysmem此段为22位堆存储区

通过以上的解释,想必对CMD文件的框架应当有所了解,但要完全读懂CMD文件可能还要假以时日,当初笔者也是这样过来的。在阅读CMD文件时要前后对应,要将MEMORY指令中的名字与SECTIONS中的装载位置一一对应,并注意Page,弄清楚是在程序空间还是数据空间。

    在09年之后的CMD文件中,.econst段存放在程序区以RAML1命名的程序空间,其空间存储量为0x001000。虽然以RAML1命名的程序空间有0x001000的容量,但并不是全部用来作为.econst段的,因此当代码中,字符串常量等数据量超过.econst段的容量时,就出现了图1的报错。只要扩大容量即可解决问题。