一個完整的DSP程式至少包含三個部分:程式碼、中斷向量表、連結命令檔案(或稱連結設定檔)(*.cmd)。
連結設定檔確定了程式連結成最終可執行代碼時的選項,其中有很多條目,實現不同方面的選項,其中最常用的也是必須的有兩條:1.存貯器的分配;2.標明程式入口。如:
-e CodeStart
MEMORY {
page 0: PRAM: org="0100h" len="0F00h"
}
SECTIONS{
.text:>PRAM page 0
}
由於每個程式都需要一個連結設定檔,可以編寫一個滿足通常需要的連結設定檔。一個比較通用的連結設定檔:
-e CodeStart
-m map.map
MEMORY {
PAGE 0: VECT: org=0080h len="0080h"
PARAM: org="100h" len="0F00h"
PAGE 1: DARAM: org="1000h" len="1000h"
}
SECTIONS {
.text :> PARAM PAGE 0
.vectors :> VECT PAGE 0
stack :> DARAM PAGE 1
.bss :> DARAM PAGE 1
.data :> DARAM PAGE 1
}
MEMORY偽指令在命令檔案中的書寫方式為:以大寫MEMORY開始,後面跟著由大括弧括起來的一系列儲存空間範圍說明。每一個儲存空間區間具有一個名稱、起始地址以及儲存空間的長度。下面的執行個體為實用MEMORY偽指令的簡單例子。在該例中,起始地址為資料存放區器中的60H;B1塊為256位元組的RAM,起始地址為資料存放區器中的200H;B0塊為256位元組的RAM,起始地址為資料存放區器中的300H。
MEMORY
{
PAGE0: ROM: origin=0h,length=1000h
PAGE1: B2: origin=60h,length=20h
B1: origin=200h,length=100h
B0: origin=300h,length=100h
}
MEMORY偽指令的一般文法為:
MEMORY
{
PAGE0:name 1[(attr)]:origin=constant,length=constant
PAGE1:name n[(attr)]: origin="constant",length=constant
}
其中,PAGE:對一個儲存空間加以標記,每一個PAGE代表一個完全獨立的地址空間。頁號n最大可以為255(因為DSP最大定址可以到64K),取決於目標儲存空間的配置。通常PAGE0為程式儲存空間,PAGE1為資料存放區器。如果沒有規定的PAGE,則連結器就當作PAGE0。
Name:對一個儲存空間區間名。可以包含8個字元。只是起到標記的作用。同一個PAGE內不能重名,不同PAGE可以。
Attr:這是一個任選項。為命名區規定1-4個屬性。如果有選項,應寫在括弧內。當輸出段定位到儲存空間時,可以利用屬性加以限制。屬性選項有如下四項:
R:規定可以對儲存空間執行讀操作。
W:規定可以對儲存空間執行寫操作。
X:規定儲存空間可以裝入可執行檔程式碼。
I:規定可以對儲存空間進行初始化。
如果一項屬性都沒有選,則可以將輸出段不受限制定位到任何一個儲存空間位置。就是任何一個沒有規定的儲存空間都有四項屬性。
Origin:規定一個儲存區的起始地址。
Length:規定一個儲存區的長度。
SECTION指令:
1、SECTIONS指令任務:
(1)說明如何將輸入段組合成輸出段;
(2)在可執行程式中定義輸出段;
(3)指定輸出段在儲存空間中的存放位置;
(4)允許重新命名輸出段。
2、SECTIONS指令的一般文法如下:
SECTIONS
{
name:[property,property,property,……]
name:[property,property,property,……]
name:[property,property,property,……]
……
}
在連結器命令檔案中,SECTIONS命令用大寫字母,緊隨其後並用大括弧括起來的是關於輸出段的說明語句。每一個輸出段的說明都從段名開始,段名後是一行說明段的內容和如何給段分配儲存單元的屬性參數。一個段的屬性參數包括:
(1) Load allocation,由它定義將輸出段載入到儲存空間中的什麼位置。文法為:
Load=allocation(這裡的allocation指的是地址)
或者> allocation
其中allocation是關於輸出段地址的說明,即給輸出段分配儲存單元。具體寫法有多種,例如:
.text:load=0x1000 ;將輸出段.text定位到一個特定的地址
.text:load>ROM ;將輸出段.text定位到命名為ROM的儲存區
.text: PAGE 0 ;將輸出段定位到PAGE 0
(2) Run allocation,由它定義輸出段在儲存空間的什麼開始運行。其文法為:
run=allocation 或者
run>allocation
連結器為每個輸出段在目標儲存空間中分配兩個地址:一個是載入的地址,另一個是執行程式的地址。通常,這兩個地址是相同的,可以認為每個輸出段只有一個地址。有事要想吧程式的載入區和運行區分開,只要用SECTIONS命令讓連結器對這個段定位兩次就行了。一次是設定載入地址,另一次是設定運行地址。例如:
.fir:load=ROM,run=RAM
.data:load=ROM,align=32,run=RAM
3、為輸出段指定地址
(1) binding,將段定位到指定的地址。例如:
.text:load=0x1000
(2) memory,將段定位到由MEMORY偽指令定義的具有指定的名稱(例如ROM)或屬性的位址範圍。例如:
.text:load>ROM
(3) alignment,使用對準關鍵字,指定段的其真實位址邊界。例如:
.text:align=0x80
(4) blocking,使用塊關鍵字指定段必須放置在2個地址邊界之間,若段太大,將從一個地址邊界開始。例如:
.text:block(0x80)
(5) page,指定要使用的儲存空間頁面。例如:
.text:PAGE 0
4、MEMORY和SECTIONS指令的預設演算法
如果沒有利用MEMORY和SECTIONS命令,連結器就按預設演算法來定位輸出段
************************************************************************************************
************************************************************************************************
GEL是通用擴充語言(General Extension Language)的英文縮寫,GEL是一個大小寫敏感但缺少類型檢測的解釋性語言,只有int類型,在文法上可看作是C語言的一個子集。GEL主要用來擴充CCS的功能,方便使用者偵錯工具,但不是必需的。當我們希望上電後立刻開啟或實現某些功能,那麼可以在項目中裝載GEL檔案(由TI提供或使用者自行編寫)來實現這個目的。此外,項目添加TI公司提供的GEL檔案後往往會在CCS的GEL菜單中出現相關的子功能表,使用者可以使用它,主要用於程式的調試控制。GEL檔案可以看成你所建項目的“秘書”,可以幫你打打雜,處理一些繁瑣的事情。
下面是一段VC5509的通用GEL檔案代碼:
StartUp()
{
GEL_MapOn();
GEL_MapReset();
GEL_MapAdd(0x0000C0,0,0x00FF40,1,1);
GEL_MapAdd(0x010000,0,0x030000,1,1);
GEL_MapAdd(0x040000,0,0x3C0000,1,1);
GEL_MapAdd(0x400000,0,0x400000,1,1);
GEL_MapAdd(0x800000,0,0x400000,1,1);
GEL_MapAdd(0xC00000,0,0x400000,1,1);
GEL_MapAdd(0xFF0000,0,0x010000,1,0);
GEL_MapAdd(0x000000,1,0x000050,1,1);
GEL_MapAdd(0x000060,1,0x007FA0,1,1);
GEL_MapAdd(0x008000,1,0x018000,1,1);
GEL_MapAdd(0x020000,1,0x1E0000,1,1);
GEL_MapAdd(0x200000,1,0x200000,1,1);
GEL_MapAdd(0x400000,1,0x200000,1,1);
GEL_MapAdd(0x600000,1,0x200000,1,1);
GEL_MapAdd(0x0001,2,0x0002,1,1);
GEL_MapAdd(0x0400,2,0x0300,1,1);
GEL_MapAdd(0x07FE,2,0x0002,1,1);
GEL_MapAdd(0x0800,2,0x0014,1,1);
GEL_MapAdd(0x0C00,2,0x000C,1,1);
GEL_MapAdd(0x0C20,2,0x000C,1,1);
GEL_MapAdd(0x0C40,2,0x000C,1,1);
GEL_MapAdd(0x0C60,2,0x000C,1,1);
GEL_MapAdd(0x0C80,2,0x000C,1,1);
GEL_MapAdd(0x0CA0,2,0x000C,1,1);
GEL_MapAdd(0x0E00,2,0x0001,1,1);
GEL_MapAdd(0x0E03,2,0x0001,1,1);
GEL_MapAdd(0x1000,2,0x0004,1,1);
GEL_MapAdd(0x1800,2,0x000D,1,1);
GEL_MapAdd(0x1C00,2,0x0001,1,1);
GEL_MapAdd(0x1E00,2,0x0001,1,1);
GEL_MapAdd(0x2400,2,0x0004,1,1);
GEL_MapAdd(0x2800,2,0x001F,1,1);
GEL_MapAdd(0x2C00,2,0x001F,1,1);
GEL_MapAdd(0x3000,2,0x001F,1,1);
GEL_MapAdd(0x3400,2,0x0002,1,1);
GEL_MapAdd(0x3800,2,0x0005,1,1);
GEL_MapAdd(0x3C00,2,0x000D,1,1);
GEL_MapAdd(0x4000,2,0x0004,1,1);
GEL_MapAdd(0x4400,2,0x0006,1,1);
GEL_MapAdd(0x4800,2,0x001B,1,1);
GEL_MapAdd(0x4C00,2,0x001B,1,1);
GEL_MapAdd(0x5800,2,0x1000,1,1);
GEL_MapAdd(0x6800,2,0x0004,1,1);
GEL_MapAdd(0x6C00,2,0x0001,1,1);
GEL_MapAdd(0x7000,2,0x0002,1,1);
GEL_MapAdd(0x7400,2,0x0001,1,1);
GEL_TextOut("Gel StartUp Complete./n");
}
OnTargetConnect()
{
C5509_Init();
}
menuitem "C5509_Configuration";
hotmenu CPU_Reset()
{
GEL_Reset();
GEL_TextOut("CPU Reset Complete./n");
}
hotmenu C5509_Init()
{
GEL_Reset();
TMCR_Reset();
GEL_TextOut("C5509 Memory Map Initialization Complete./n");
}
hotmenu C5509_USB_Enable()
{
GEL_MemoryFill(0x7000,2,1,0x0004);
GEL_TextOut("C5509 USB Module enabled./n");
}
menuitem "C5509 EBSR Config";
hotmenu Data_EMIF_En()
{
GEL_MemoryFill(0x6C00,2,1,0x0200);
GEL_TextOut("C5509 Ext. Bus set to Data EMIF./n");
}
hotmenu Full_EMIF_En()
{
GEL_MemoryFill(0x6C00,2,1,0x0201);
GEL_TextOut("C5509 Ext. Bus set to Full EMIF./n");
}
hotmenu NonMuxed_EHPI_En()
{
GEL_MemoryFill(0x6C00,2,1,0x0202);
GEL_TextOut("C5509 Ext. Bus set to Non Muxed EHPI./n");
}
hotmenu MuxEHPI_En()
{
GEL_MemoryFill(0x6C00,2,1,0x0203);
GEL_TextOut("C5509 Ext. Bus set to Muxed EHPI./n");
}
menuitem "C5509 EMIF CE0 Config";
hotmenu CE0_Async16_En()
{
GEL_MemoryFill(0x0803,2,1,0x1FFF);
GEL_TextOut("C5509 CE0 set to 16-bit Async mode./n");
}
menuitem "C5509 EMIF CE1 Config";
hotmenu CE1_Async16_En()
{
GEL_MemoryFill(0x0806,2,1,0x1FFF);
GEL_TextOut("C5509 CE1 set to 16-bit Async mode./n");
}
menuitem "C5509 EMIF CE2 Config";
hotmenu CE2_Async16_En()
{
GEL_MemoryFill(0x0809,2,1,0x1FFF);
GEL_TextOut("C5509 CE2 set to 16-bit Async mode./n");
}
menuitem "C5509 EMIF CE3 Config";
hotmenu CE3_Async16_En()
{
GEL_MemoryFill(0x080C,2,1,0x1FFF);
GEL_TextOut("C5509 CE3 set to 16-bit Async mode./n");
}
TMCR_Reset()
{
#define TMCR_MGS3 0x07FE
#define TMCR_MM 0x07FF
*(short *)TMCR_MGS3@IO = 0x0510;
*(short *)TMCR_MM@IO = 0x0000;
}
可以看到:GEL檔案主要用來對VC5509的程式空間、資料空間、I/O空間等進行初始化,同時配置CCS開發環境,建立子功能表供使用者在偵錯工具時選擇使用。CCS啟動時,Startup()函數被執行。支援Connect/Disconnect的CCS啟動時,Startup()函數中不包括訪問目標處理器的代碼,目標處理器由回呼函數OnTargetConnect()來初始化。
注意:GEL檔案在CCS啟動後常駐記憶體,在模擬器和目標系統上電的時候起到初始DSP的作用。在上電後再改變GEL檔案將不會對DSP產生影響。