CMD各段定义与分配方法指引
DSP28335—CMD文件中的各個段解釋
CMD文件里有兩個基本的段:初始化段和非初始化段。初始化段包含代碼和常數等必須在DSP上電之后有效的數。故初始化塊必須保存在如片內FLASH等非易失性存儲器中,非初始化段中含有在程序運行過程中才像變量內寫數據進去,所以非初始化段必須鏈接到易失性存儲器中如RAM。
已初始化的段:.text,.cinit,.const,.econst,.pinit和.switch…
.text:所有可以執行的代碼和常量
.cinit:全局變量和靜態變量的C初始化記錄,包含未用const聲明的外部(extern)或靜態(static)數據表
.const:包含字符串常量和初始化的全局變量和靜態變量(由const)的初始化和說明
.econst:包含字符串常量和初始化的全局變量和靜態變量(由far const)的初始化和說明,與.const不同的是.const分配范圍被限制在低64K 16位數據區,而.econst的分配范圍是4M 22位數據區
.pinit:全局構造器(C++)程序列表
.switch:包含switch聲明的列表
非初始化的段:.bss,.ebss,.stack,.sysmem,和esysmem.(更好的理解就是,這些段就是存儲空間而已)
.bss: 為全局變量和局部變量保留的空間,在程序上電時.cinit空間中的數據復制出來并存儲在.bss空間中。
.ebss:為使用大寄存器模式時的全局變量和靜態變量預留的空間,在程序上電時,cinit空間中的數據復制出來并存儲在.ebss中,與.bss不同的是.bss分配范圍被限制在低64K 16位數據區,而.ebss的分配范圍是4M 22位數據區
.stack:為系統堆棧保留的空間,用于和函數傳遞變量或為局部變量分配空間。
.sysmem:為動態存儲分配保留的空間。如果有宏函數,此空間被宏函數占用,如果沒有的話,此空間保留為0
.esysmem:為動態存儲分配保留的空間。如果有far函數,此空間被相應的占用,如果沒有的化,此空間保留為0.
編譯器生成的包含代碼和數據的多個部分,稱為段。這下段被分為兩個不同的組:初始化了的和沒被初始化的,初始化的部分是由所有的代碼,常量和初始化表組成的。下表列出了由編譯器產生的初始化段。
初始化段
段名 內容 限制
.cinit 顯式初始化的全局變量和靜態變量表 代碼
.const 顯式初始化的全局和靜態的const變量和字符串常量 不超過64K長度
.econst 長調用的常量 數據中的任何地方
.pinit 全局對象的構造函數表 代碼
.switch switch語句產生的表 代碼或者數據
.text 可執行代碼和常數 代碼
沒初始化的段是由未初始化的變量,堆棧和malloc產生的內存。下表列出了由編譯器產生的沒初始化段。
沒初始化段
段名 內容 限制
.bss 全局和靜態變量 不超過64K長度
.ebss 長調用的全局或靜態變量 數據中的任何地方
.stack 堆棧空間 不超過64K長度
.sysmem malloc函數產生的內存 不超過64K長度
.esysmem far_malloc函數產生的內存 數據中的任何地方
一旦編譯器生成的這些段,連接器會從各個源文件中取出這些段,并結合它們來創建一個輸出文件。連接器命令文件(.cmd)就是用來告訴連接器去哪里找這些段的。初始化段必須分配到非易失性存儲器,如flash/ ROM,當電源被撤除時,程序不會消失。未初始化的段可以被分配到RAM中,因為它們是在代碼執行期間被初始化的。
當需要把程序從flash復制到RAM里時,各個段分配參考如下:
.cinit Flash
.cio RAM
.const Flash
.econst Flash
.pinit Flash
.switch Flash
.text Flash
.bss RAM
.ebss RAM
.stack Lower 64Kw RAM
.sysmem RAM
.esysmem RAM
.reset RAM1
具體應用實例:
(一)#pragma DATA_SECTION 利用CCS進行DSP編程時,如果不指定變量的存儲位置,那么編譯器會自動給變量分配存儲位置,但是,有些時候,需要將某個變量存放到某個特定的位置,這個時候就可以利用#pragma DATA_SECTION指令了。
第一步,利用#pragma DATA_SECTION指令將變量xxxCmdBuf關聯到SECTIONS“ramdata”;
#pragma DATA_SECTION(xxxCmdBuf,“ramdata”); uint16_t xxxCmdBuf[4];12
第二步,修改CMD文件使得“ramdata”映射到指定的地址空間。
MEMORY { PAGE 0 : /* Program Memory */ …
PAGE 1 : /* Data Memory */ … RAML_XXXCMD : origin = 0x00BFF0, length = 0x000004 } …
SECTIONS { … ramdata : > RAML_XXXCMD, PAGE = 1 … }1234567891011121314151617
只需完成上述簡單的兩步就可以將某個變量指定到特定的位置,一些博文指出采用這種方法時,需要先利用#pragma DATA_SECTION開辟一個空間,然后在定義該空間的大小,即第一步中的兩行代碼是有先后順序的。
TI 的技術文檔《Programming TMS320x28xx and 28xxx Peripherals in C/C++》(SPRAA85D–November 2005–Revised January 2013)對該方法也有相應的描述,如下所示。
(二)#pragma CODE_SECTION 利用#pragma CODE_SECTION指令可以將程序從Flash搬到RAM中運行,從而提高程序執行速率,該方法需要完成以下四步。
第一步,利用#pragma CODE_SECTION指令關聯程序和SECTIONS;
#pragma CODE_SECTION(mainISR,“ramfuncs”);1
第二步,為鏈接創建相關變量;
// Used for running BackGround in flash, and ISR in RAM extern uint16_t *RamfuncsLoadStart, *RamfuncsLoadEnd, *RamfuncsRunStart;12
第三步,復制時間關鍵代碼以及Flash設置代碼到RAM;
// Copy time critical code and Flash setup code to RAM // The RamfuncsLoadStart, RamfuncsLoadEnd, and // RamfuncsRunStart symbols are created by the linker. // Refer to the linker files. memCopy((uint16_t *)&RamfuncsLoadStart,(uint16_t *)&RamfuncsLoadEnd,(uint16_t *)&RamfuncsRunStart);1234
第四步,修改CMD文件。
SECTIONS { /* Allocate program areas: */ … ramfuncs : LOAD = FLASHD, RUN = RAML0_1, LOAD_START(_RamfuncsLoadStart), LOAD_END(_RamfuncsLoadEnd), RUN_START(_RamfuncsRunStart), PAGE = 0 1234567891011
上面代碼中, LOAD = FLASHD, //指定了要加載程序在Flash里的地址段 RUN = RAML0_1, //指定了在RAM里運行程序的RAM地址段 LOAD_START(_RamfuncsLoadStart), // 所要加載程序在Flash里的初始地址 LOAD_END(_RamfuncsLoadEnd), // 所要加載程序在Flash里的結束地址 RUN_START(_RamfuncsRunStart)
總結
以上是生活随笔為你收集整理的CMD各段定义与分配方法指引的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CAN总线抗干扰的六种解决方案
- 下一篇: 子网掩码及网络号路由表的匹配方法