DSP CMD文件的編寫EETOP專業(yè)博客---電子工程師自己的家園L}#gZnWr
1. COFF格式 1> 通用目標(biāo)文件格式(Common Object File Format)是一種流行的二進制可執(zhí)行文件格式,二進制可執(zhí)行文件包括庫文件(lib),目標(biāo)文件(obj)最終可執(zhí)行文件(out)。,現(xiàn)今PC機上的Windows95和NT4.0以后的操作系統(tǒng)的二進制文件格式(PE)就是在COFF格式基礎(chǔ)上的進一步擴充。 2> COFF格式:詳細的COFF文件格式包括段頭,可執(zhí)行代碼和初始化數(shù)據(jù),可重定位信息,行號入口,符號表,字符串表等,這些屬于編寫操作系統(tǒng)和編譯器人員關(guān)心范疇。而對于C只需要了解定義段和給段分配空間就可以了。 3> 采用COFF更有利于模塊化編程,程序員可以自由決定愿意把哪些代碼歸屬到哪些段,然后加以不同的處理。 2. Section目標(biāo)文件中最小單位稱為塊。一個塊就是最終在存儲器映象中占據(jù)連續(xù)空間的一段代碼或數(shù)據(jù)。 1> COFF目標(biāo)文件包含三個默認的塊: .text可執(zhí)行代碼 .data已初始化數(shù)據(jù) .bss為未初始化數(shù)據(jù)保留的空間 2> 匯編器對塊的處理 未初始化塊 .bss 變量存放空間 .usect 用戶自定義的未初始化段 初始化塊 .text 匯編指令代碼 .data 常數(shù)數(shù)據(jù)(比如對變量的初始化數(shù)據(jù)) .sect 用戶自定義的已初始化段 .asect 通.sect,多了絕對地址定位功能,一般不用 3>C語言的段 未初始化塊(data) .bss 存放全局和靜態(tài)變量 .ebss 長調(diào)用的.bss(超過了64K地址限制) .stack 存放C語言的棧 .sysmem 存放C語言的堆 .esysmem 長調(diào)用的.sysmem(超過了64K地址限制) 初始化塊 .text 可執(zhí)行代碼和常數(shù)(program) .switch switch語句產(chǎn)生的常數(shù)表格(program/低64K數(shù)據(jù)空間) .pinit Tables for global constructors (C++)(program) .cinit 用來存放對全局和靜態(tài)變量的初始化常數(shù)值(program) .const 全局和靜態(tài)的const變量初始化值和字符串常數(shù),(data) .econst 長.const(可定位到任何地方)(data) 3> 自定義段(C語言) #pragma DATA_SECTION(函數(shù)名或全局變量名,"用戶自定義在數(shù)據(jù)空間的段名"); #pragma CODE_SECTION(函數(shù)名或全局變量名,"用戶自定義在程序空間的段名"); 不能在函數(shù)體內(nèi)聲明。 必須在定義和使用前聲明 #pragma可以阻止對未調(diào)用的函數(shù)的優(yōu)化 3. 連接命令文件(CMD) 1> MEMORY指定存儲空間 MEMORY 9}8eIg5y*kOGuest{ oo)w?(lm9NRGuestPAGE 0: $HH7Tu2A+eH%K3xr}Guest name 0 [attr] : origin = constant, length = constant PAGE n: EETOP專業(yè)博客---電子工程師自己的家園2o:b1G5?c$Zz5WO name n [attr] : origin = constant, length = constant } PAGE n:標(biāo)示存儲空間,n<255;PAGE 0為程序存儲空間;PAGE 1為data存儲空間 name:存儲空間名稱 attr:存儲空間屬性:只讀R,只寫W,可包含可執(zhí)行代碼X,可以被初始化I。 orgin:用來定義存儲空間的起始地址 Lenth:用來定義存儲空間的長度 2> SECTIONS分配段 SECTIONS { name : [property,property,……] } name:輸出段的名稱 property:輸出段的屬性: load=allocation(強制地址或存儲空間名稱)同>allocation:定義輸出段將會被裝載到哪里。 run= allocation(強制地址或存儲空間名稱)同>allocation:定義輸出段將會在哪里運行。 注:CMD文件中只出現(xiàn)一個關(guān)鍵字load或run時,表示兩者的地址時表示兩者的地址時重合的。 PAGE = n,段位于那個存儲頁面空間。 例:ramfuncs : LOAD = FLASHD, RUN = RAML0, LOAD_START(_RamfuncsLoadStart), LOAD_END(_RamfuncsLoadEnd), RUN_START(_RamfuncsRunStart), PAGE = 0
3> 直接寫編譯命令 -l rts2800_ml.lib 連接系統(tǒng)文件rts2800_ml.lib -o filename.out 最終生成的二進制文件命名為filename.out -m filename.map 生成映射文件filename.map -stack 0x200 堆棧為512字 4. .const段: 由關(guān)鍵字const限定的全局變量(const限定的局部變量不產(chǎn)生)初始化值,和出現(xiàn)在表達式(做指針使用,而用來初始化字符串?dāng)?shù)組變量不產(chǎn)生)中的字符串常數(shù),另外數(shù)組和結(jié)構(gòu)體是局部變量時,其初始值會產(chǎn)生.const段,而全局時不產(chǎn)生。 例子 在結(jié)合硬件的編程中,有些變量需要特定地址. 一般可以采用指針變量. 例如: unsigned int *LedReg = (unsigned int *)0x5f00;//發(fā)光二極管地址 *LedReg = 0xFF; 但有些時候感覺不是太好時,可以像Keil那樣 unsigned int LedReg at 0x5f00;//發(fā)光二極管地址 LedReg = 0xFF; 這樣看著"比較順眼"~~~ 但在TIDSP的CCS環(huán)境下,不能采用at或__at等來定位地址. 不過CCS也提供了類似的手段,不過有些"麻煩". 具體實現(xiàn): 1.在CMD文件中 MEMORY { PAGE 0: /* Program Memory */ PAGE 1: /* Data Memory */
LED_REG : origin = 0x005f00, length = 0x00001 /*發(fā)光二極管地址*/ LCD_ComL : origin = 0x005100, length = 0x00001 LCD_ComH : origin = 0x005200, length = 0x00001 LCD_DatL : origin = 0x005300, length = 0x00001 LCD_DatH : origin = 0x005400, length = 0x00001 EINT_REG : origin = 0x005c00, length = 0x00001 KEY_REG : origin = 0x005b00, length = 0x00001 RCLK_REG : origin = 0x005500, length = 0x00001 /*數(shù)碼管鎖存地址*/ }
SECTIONS { LedDataRegsFile : > LED_REG, PAGE = 1 LcdComlRegsFile : > LCD_ComL, PAGE = 1 LcdComhRegsFile : > LCD_ComH, PAGE = 1 LcdDatlRegsFile : > LCD_DatL, PAGE = 1 LcdDathRegsFile : > LCD_DatH, PAGE = 1 KeyRegsFile : > KEY_REG, PAGE = 1 EintRegsFile : > EINT_REG, PAGE = 1 RclkRegsFile : > RCLK_REG, PAGE = 1 } 2.在C/C++文件中
#ifdef __cplusplus #pragma DATA_SECTION("LedDataRegsFile") /*C++語言格式*/ #else #pragma DATA_SECTION(LedRegs,"LedDataRegsFile");/*C語言格式*/ #endif volatile unsigned int LedRegs; /*以下為C++語言格式*/ #pragma DATA_SECTION("LcdComlRegsFile") volatile unsigned int LcdComL; #pragma DATA_SECTION("LcdComhRegsFile") volatile unsigned int LcdComH; #pragma DATA_SECTION("LcdDatlRegsFile") volatile unsigned int LcdDatL; #pragma DATA_SECTION("LcdDathRegsFile") volatile unsigned int LcdDatH; #pragma DATA_SECTION("EintRegsFile") volatile unsigned int EintRegs; #pragma DATA_SECTION("KeyRegsFile") volatile unsigned char KeyRegs; #pragma DATA_SECTION("RclkRegsFile") volatile bool SpiRclkRegs;
3.在應(yīng)用程序中 extern unsigned int LedRegs; extern volatile unsigned int EintRegs; extern volatile unsigned char KeyRegs; extern volatile bool SpiRclkRegs; //............ LedRegs = 0xff;//這樣就不需要指針變量的寫法了 //.................. [url=]//HotPower@126.com[/url] 2008.4.17 1:34 |