第6章使用C語言操作DSP的寄存器0324_第1頁
第6章使用C語言操作DSP的寄存器0324_第2頁
第6章使用C語言操作DSP的寄存器0324_第3頁
第6章使用C語言操作DSP的寄存器0324_第4頁
第6章使用C語言操作DSP的寄存器0324_第5頁
已閱讀5頁,還剩74頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第6章使用C語言操作DSP的寄存器6.1C/C++編譯器概述6.2TMS320X28xx的C/C++編程6.3寄存器的C語言訪問6.4CMD文件6.5寄存器文件的空間分配匯編語言與C語言DSP軟件開發有兩種途徑:專用匯編語言程序開發和高級C語言程序開發。?專用匯編語言程序開發——直接用匯編語言編寫源程序,經過匯編、鏈接后生成可執行代碼(out),然后再進行調試、固化;?高級C語言程序開發——采用高級C語言編寫源程序,先利用C編譯器把C源程序轉換成匯編語言源程序,然后與匯編語言程序一樣處理。引言引言生成源程序(*.asm)、頭文件(*.h)與命令文件(*.cmd)。生成目標文件(*.obj)及列表文件(*.lst)生成可執行代碼文件(*.out)及用于存儲器分配的映射文件(*.map)。通過JTAG接口下載到目標系統通過JTAG接口將程序燒寫到Flash存儲器C源文件編輯C編譯器如果用C語言作為編程語言。使用C語言開發DSP的原因引言基于DSP芯片的軟件開發,用DSP芯片的匯編語言編寫程序是一件比較繁雜的事情。一般來說,各個公司的DSP芯片所提供的匯編語言并不相同,即使是同一公司的芯片,由于芯片的類型不同(如定點和浮點)、芯片的升級換代,其匯編語言也有所不同,使用匯編語言開發DSP產品的周期相對較長,因為開發人員在編寫DSP程序之前必須熟悉這種DSP芯片的匯編語言。產品一旦開發完畢,如果需要對軟件進行修改和升級都將非常困難,這是因為匯編語言的可讀性和可移植性比高級語言差。一般高級語言具有很好的可移植性,但是難以實現匯編語言的某些功能(如對內存地址的操作、位操作等)。C/C++語言作為一種高級語言,既可以訪問物理地址又可以進行位操作,能直接對硬件進行操作,適合用作DSP開發語言。基于上述原因,各個DSP芯片公司都相繼推出了相應的高級語言(如C語言)編譯器,使得DSP芯片的軟件可以直接用高級語言編寫而成,從而大大提高了DSP芯片的開發速度,也使程序的修改和移植變得簡單易行。6.1C/C++編譯器概述

TMS320X28xx的C編譯器是一個功能齊全的優化編譯器,優化編譯結果達手工編寫的匯編語言效率的90%以上。可以利用該編譯器將標準的ANSIC/C++程序直接轉換成TMS320X28xx處理器的匯編代碼。為了提高執行效率,關鍵的DSP運算程序仍然應用匯編語言進行編寫,同時按照規定的接口,然后通過C語言程序對其調用。

1.標準的ANSIC/C++語言

CCS的C/C++編譯器接收標準ANSIC/C++源文件(.c或.cpp),并將其編譯成C28x的匯編語言源文件(.asm)。2.ANSI標準實時運行支持

TMS320X28xx編譯器工具為各種處理器提供完整的實時運行庫。庫中包括動態內存分配、對字符串的操作、數學運算(如求絕對值、計算三角函數和指數函數等)以及一些標準的輸入/輸出操作等,只要在源程序中加入對應的頭文件(如stdlib.h、string.h、math.h和stdio.h等)就可以調用和使用。rts.src

TMS320X28xx的C/C++編譯器包含了兩個經過編譯的運行時支持目標文件庫:rts2800.lib和rts2800_ml.lib。6.1.1C語言主要特征6.1C/C++編譯器概述6.1.1C語言主要特征6.1C/C++編譯器概述編譯器支持兩種存儲器模型:小存儲模式大存儲器模式鏈接器不允許同時存在大存儲器模式和小存儲器模式。6.1.2編譯、匯編和鏈接6.1C/C++編譯器概述C編譯器(CCompiler):產生匯編語言源代碼。匯編器(Assembler):把匯編語言源文件翻譯成機器語言目標文件,機器語言格式為通用目標格式(COFF)。鏈接器(Linker):把多個目標文件組合成單個可執行的輸出文件(.out)。匯編器生成的COFF目標文件中各代碼段或數據段只具有相對地址,它與系統的物理存儲器地址之間沒有任何關系,必須對其進行地址定位和分配后,這些目標文件才能變成可執行的文件。6.1C/C++編譯器概述6.1.2編譯、匯編和鏈接編譯器為用戶提供了靈活方便的函數調用接口,可以非常方便地實現C/C++函數和匯編語言的相互調用。通常情況下,程序的主架構采用C/C++編寫,對于代碼的效率要求較高的程字段采用匯編語言。在C/C++程序中調用匯編主要有以下3種實現方法。

(1)使用獨立的匯編語言模塊或文件,在目標代碼鏈接過程中將匯編代碼鏈接到C/C++程序模塊中,這種方法也是最通用的方法。

(2)直接在C/C++程序中嵌入匯編程序。

(3)直接在C/C++程序中調用匯編函數。6.1.3靈活的匯編語言接口

6.1C/C++編譯器概述DSP中的工程文件C源文件編輯C編譯器工程文件(.pjt),源文件(.c,.asm),頭文件(.h),庫文件(.lib),CMD文件(.cmd),目標文件(.obj),列表文件(.lst),可執行代碼文件(.out),映射文件(.map)6.2.1數據類型6.2TMS320X28xx的C/C++編程6.2.2關鍵字6.2TMS320X28xx的C/C++編程在CCS環境中使用C語言開發程序,可以使用C語言中常用的一些關鍵字和表達式。如:定義數據類型的關鍵字:char,int,double等。條件判斷關鍵字:if,else,switch,case等。循環語句關鍵字:for,while等注:在C語言中,三目運算符:表達式?語句一:語句二;6.2.2關鍵字6.2TMS320X28xx的C/C++編程const使用:const數據類型變量名,優化存儲器的分配,表示變量的內容是常數,在程序運行中不會改變。有助于更好地控制對特定數據對象存儲空間的分配。如果定義一個對象為const,則const段會為此對象在程序存儲器中分配特定的存儲空間。volatile使用:volatile數據類型變量名;用于聲明存儲器或外設寄存器,以此來說明所定義的變量是“可變的”,是可以被DSP的其他硬件修改的,而不僅僅由C程序本身修改。舉例:volatilestructSYS_CTRL_REGSSysCtrlRegs;6.2.2關鍵字6.2TMS320X28xx的C/C++編程cregister使用:cregister數據類型變量名;允許采用高級語言直接訪問控制寄存器。注意:在F281x的C語言中,cregister僅限于聲明寄存器IER和IFR。如:externcregistervolatileunsignedintIFR;externcregistervolatileunsignedintIER;interrupt使用:interruptvoid中斷函數名(void);說明函數是中斷函數,這樣編譯器會自動為中斷函數產生保護現場和恢復現場所需執行的操作。舉例:interruptvoidXINT1_ISR(void);6.2.3在C語言中嵌入匯編語言6.2TMS320X28xx的C/C++編程TMS320C28x編譯器允許在C程序中嵌入匯編指令,通過下面聲明實現:asm(“assemblertext”);其中assemblertext指匯編代碼。asm指令一般用來處理C/C++語句較難實現的硬件操作。舉例:#defineEINTasm("clrcINTM")#defineDINTasm("setcINTM")6.3寄存器的C語言訪問由于DSP的寄存器能夠實現對系統和外設功能的配置與控制,因此在DSP的開發過程中,對于寄存器的操作是極為重要的,也是很頻繁的,也就是說對寄存器的操作是否方便會直接影響到DSP的開發是否方便。對DSP內部寄存器的訪問和控制有兩種方式,一種是傳統宏定義的方式,一種是位定義和寄存器結構體的方式。6.3寄存器的C語言訪問6.3.1傳統的宏定義方法傳統的C/C++編程訪問處理器的硬件寄存器主要采用#define宏的方式。為了說明宏定義方法,下面以SCI接口的編程為例進行介紹。下表給出了SCI-A和SCI-B的寄存器文件及相關的地址。1.SCI-A寄存器寄存器名稱地址大小(×16位)功能描述SCICCR0x000070501SCI-A通信控制寄存器SCICTL10x000070511SCI-A控制寄存器1SCIHBAUD0x000070521SCI-A波特率寄存器,高位SCILBAUD0x000070531SCI-A波特率寄存器,低位SCICTL20x000070541SCI-A控制寄存器2SCIRXST0x000070551SCI-A接收狀態寄存器SCIRXEMU0x000070561SCI-A接收仿真數據緩沖器寄存器SCIRXBUF0x000070571SCI-A接收數據緩沖器寄存器SCITXBUF0x000070591SCI-A發送數據緩沖器寄存器SCIFFTX0x0000705A1SCI-AFIFO發送寄存器SCIFFRX0x0000705B1SCI-AFIFO接收寄存器SCIFFCT0x0000705C1SCI-AFIFO控制寄存器SCIPRI0x0000705F1SCI-A優先級控制寄存器寄存器名稱地址大小(×16位)功能描述SCICCR0x000077501SCI-B通信控制寄存器SCICTL10x000077511SCI-B控制寄存器1SCIHBAUD0x000077521SCI-B波特率寄存器,高位SCILBAUD0x000077531SCI-B波特率寄存器,低位SCICTL20x000077541SCI-B控制寄存器2SCIRXST0x000077551SCI-B接收狀態寄存器SCIRXEMU0x000077561SCI-B接收仿真數據緩沖器寄存器SCIRXBUF0x000077571SCI-B接收數據緩沖器寄存器SCITXBUF0x000077591SCI-B發送數據緩沖器寄存器SCIFFTX0x0000775A1SCI-BFIFO發送寄存器SCIFFRX0x0000775B1SCI-BFIFO接收寄存器SCIFFCT0x0000775C1SCI-BFIFO控制寄存器SCIPRI0x0000775F1SCI-B優先級控制寄存器2.SCI-B寄存器6.3寄存器的C語言訪問6.3.1傳統的宏定義方法(SCI寄存器的宏定義)/*******************************************************采用宏定義的方法定義的頭文件******************************************************/

#defineUint16unsignedint#defineUint32unsignedlong#defineSCICCRA(volatileUint16*)0x7050//0x7050SCI-A通信控制寄存器#defineSCICTL1A(volatileUint16*)0x7051//0x7051SCI-A控制寄存器1第一步,首先定義各寄存器的符號及其對應的入口地址/*******************************************************采用#definemacros訪問寄存器******************************************************

…..*SCICTL1A=0x0003;//寫整個控制寄存器1*SCICTL1B|=0x0001;//使能RX

6.3寄存器的C語言訪問6.3.1傳統的宏定義方法第二步,采用宏定義的方法訪問寄存器(采用指針形式)SCI控制寄存器1SCICTL1SCI的發送使能位和接收使能位缺點:(1)不能直接對寄存器的位進行讀寫,為了獨立的操作寄存器中的某些位,必須屏蔽其他位;(2)不能直接在CCS中顯示各個位的定義;(3)不能利用CCS自動完成輸入的特點;(4)對相同的外設,不方便外設的重復使用。優點:(1)宏定義相對比較簡單,快捷,容易分類;(2)直接采用寄存器的名字進行定義,易于操作。6.3寄存器的C語言訪問6.3.1傳統的宏定義方法SCI控制寄存器1SCICTL16.3寄存器的C語言訪問6.3.1傳統的宏定義方法

…..*SCICTL1B|=0x0002;//使能RX

相對于#definemacros的方法訪問寄存器,位定義和寄存器結構體的方法,更加靈活,可有效提高編程效率。6.3寄存器的C語言訪問6.3.2位定義和寄存器結構體的方法(1)位域定義及用位域方法定義寄存器在使用處理器的外設時,經常需要直接操作寄存器中的某些位,而采用位域定義的方法實現寄存器的直接操作對編程來講十分方便。位域定義可以為寄存器內的特定功能位分配一個相關的名字和相應的寬度,允許采用位域定義的名字直接操作寄存器中的某些位。按位來劃分區域6.3寄存器的C語言訪問6.3.2位定義和寄存器結構體的方法通俗的講,“位域”就是把一個字節中的二進制位劃分為幾個不同的區域,并說明每個區域的位數。每個域都有一個域名,允許在程序中按域名進行操作。位域的定義和位域變量的說明同結構體定義和其成員說明類似,其語法格式為:struct位域結構名{

類型說明符位域名1:位域長度類型說明符位域名2:位域長度

類型說明符位域名n:位域長度};基本的數據類型,可以是int、char等可以任意取,盡量反應位的功能這個位域由多少位組成大括號后面的“;”不可缺少!6.3寄存器的C語言訪問6.3.2位定義和寄存器結構體的方法structbs//定義位域bs{inta:8;intb:2;intc:6;};structbsbs1;加起來一共是16位!聲明bs型變量bs1。位域是C語言的一種數據結構,也要遵循先聲明后使用的原則。例如,聲明了bs1,表明bs1是bs型的變量,共占2個字節,其中位域a占8位,位域b占2位,位域c占6位。6.3寄存器的C語言訪問6.3.2位定義和寄存器結構體的方法

關于位域定義的幾點說明:

(1)位域的定義在存儲空間中必須按由右向左的順序,從最低為開始定義。也就是說寄存器的低有效位或者是第0位存放在定義區的第一個位置;

(2)一個位域必須存儲在同一個字節中,不能跨兩個字節。如果一個字節不夠,放另一域時,應該從下一個單元起存放該域。structbs//定義位域bs{inta:4;int:0;//空域intb:5;//從第2字節開始存放intc:3;};6.3寄存器的C語言訪問6.3.2位定義和寄存器結構體的方法

關于位域定義的幾點說明:

(3)位域長度不能大于一個字節的長度,也就是說位域不能超過8位。?(4)位域可以無位域名,這時,它只用作填充或調整位置。無名的域位不能使用。structbs//定義位域bs{inta:4;int:2;//該2位不能使用intb:2;intc:5;intd:3;};6.3寄存器的C語言訪問6.3.2位定義和寄存器結構體的方法

以SCIA的通信控制寄存器SCICCR為例,說明如何使用位域的方法來定義寄存器:6.3寄存器的C語言訪問6.3.2位定義和寄存器結構體的方法structSCICCR_BITS{Uint16SCICHAR:3;//2:0字符長度控制位

Uint16ADDRIDLE_MODE:1;//3多處理器模式控制位

Uint16LOOPBKENA:1;//4回送測試模式使能位

Uint16PARITYENA:1;//5極性使能位

Uint16PARITY:1;//6奇/偶極性選擇位

Uint16STOPBITS:1;//7停止位個數

Uint16rsvd1:8;//15:8保留};structSCICCR_BITSbit;//SCI字符長度控制位為8位bit.SCICHAR=7;6.3寄存器的C語言訪問6.3.2位定義和寄存器結構體的方法structSCICCR_BITS{Uint16SCICHAR:3;//2:0字符長度控制位

Uint16ADDRIDLE_MODE:1;//3多處理器模式控制位

Uint16LOOPBKENA:1;//4回送測試模式使能位

Uint16PARITYENA:1;//5極性使能位

Uint16PARITY:1;//6奇/偶極性選擇位

Uint16STOPBITS:1;//7停止位個數

Uint16rsvd1:8;//15:8保留};structSCICCR_BITSbit;bit.SCICHAR=7;//SCI字符長度控制位為8位被保留的空間也要在位域中定義,只是定義的變量不會被調用。聲明了SCICCR_BITS型變量bit,這樣就可以通過bit來實現對寄存器位的訪問了。1

2

36.3寄存器的C語言訪問6.3.2位定義和寄存器結構體的方法//SCICTL1控制寄存器1位定義:structSCICTL1_BITS//位功能描述{

Uint16RXENA:1;//0SCI接收模式

Uint16TXENA:1;/1SCI發送器使能

Uint16SLEEP:1;//2SCI睡眠

Uint16TXWAKE:1;//3發送喚醒方法

Uint16rsvd1:l;//4保留

Uint16SWRESET:1;//5軟件復位

Uint16RXERRINTENA:1;//6接收中斷使能

Uint16rsvd2:9;//15--7保留};SCI控制寄存器1SCICTL16.3寄存器的C語言訪問6.3.2位定義和寄存器結構體的方法(2)聲明共同體使用位定義方法可以方便地對寄存器功能位進行操作,但有時還是需要將整個寄存器作為一個值操作。為此引入共同體,使寄存器的各位可以作為一個整體操作。6.3寄存器的C語言訪問6.3.2位定義和寄存器結構體的方法unionSCICCR_REG{Uint16all;//可實現對寄存器整體操作

structSCICCR_BITSbit;//可實現位操作};unionSCICCR_REGSCICCR;SCICCR.all=0x007F;SCICCR.bit.SCICHAR=5;例6.3SCICCR的共同體定義聲明了一個SCICCR_REG變量SCICCR通過變量SCICCR對寄存器實現整體操作?通過變量SCICCR對寄存器實現位操作?注意:整個共同體的總的存儲空間為2個字節。1

2

3

46.3寄存器的C語言訪問6.3.3創建結構體文件

前面通過位域和共同體,已經可以對單個寄存器的功能位或整體進行訪問。而我們知道,SCI模塊除了寄存器SCICCR還包括很多寄存器。因此,為了便于管理,就需要創建一個結構體文件,用來包含SCI模塊所有的寄存器。寄存器結構體文件實際上是將某些外設的所有寄存器采用一定的結構體在一個文件中定義,其成員為某外設的所有寄存器。下面即為SCI寄存器的結構體文件。structSCI_REGS{unionSCICCR_REGSCICCR;//通信控制寄存器

unionSCICTL1_REGSCICTL1;//控制寄存器1Uint16SCIHBAUD;//波特率寄存器(高字節)Uint16SCILBAUD;//波特率寄存器(低字節)unionSCICTL2_REGSCICTL2;//控制寄存器2unionSCIRXST_REGSCIRXST;//接收狀態寄存器

Uint16SCIRXEMU;//接收仿真緩沖寄存器

unionSCIRXBUF_REGSCIRXBUF;//接收數據寄存器

Uint16rsvd1;//保留

Uint16SCITXBUF;//發送數據緩沖寄存器

unionSCIFFTX_REGSCIFFTX;//FIFO發送寄存器

unionSCIFFRX_REGSCIFFRX;//FIFO接收寄存器

unionSCIFFCT_REGSCIFFCT;//FIFO控制寄存器

Uint16rsvd2;//保留

Uint16rsvd3;//保留

unionSCIPRI_REGSCIPRI;//FIFO優先級控制寄存器

};externvolatilestructSCI_REGSSciaRegs;externvolatilestructSCI_REGSScibRegs;1

2

36.3寄存器的C語言訪問

SCI寄存器結構體SCI_REGS中,有兩種形式的成員,union形式和Unit16形式,定義為union形式的成員既可以實現對寄存器整體的操作,也可以實現對寄存器進行位操作;而定義為Unit16形式的成員只能直接對寄存器進行操作。無論是SCIA或SCIB,在寄存器的存儲空間中,有3個存儲單元是被保留的,在對SCI寄存器進行結構體定義時,也要將其保留。保留的寄存器空間采用變量代替,但是該變量不會被調用,如rsvd1、rsvd2、rsvd3。6.3.3創建結構體文件6.3寄存器的C語言訪問定義了結構體SCI_REGS后,需要聲明SCI_REGS型變量SciaRegs和ScibRegs,分別代表外設SCIA和外設SCIB的寄存器。聲明中的關鍵字extern,“外部的”,只能說明變量,不能定義變量,表明這個變量在外部文件中被調用,是一個全局變量。volatile表明變量能夠被外部代碼改變,例如可以被外部硬件或中斷任意改變。結構體定義時寄存器名字出現的順序要與存儲空間安排的順序一致。6.3.3創建結構體文件6.3寄存器的C語言訪問

C語言訪問寄存器(以SCI模塊的寄存器為例)步驟:使用位域定義的方式對SCI模塊中各個寄存器的位功能進行操作;根據需要定義共同體,可以對某些寄存器的整體或位進行操作;對整個SCI模塊所有的寄存器建立結構體文件。

可以發現,這就是F2812的頭文件DSP28_Sci.h的內容。6.3.3創建結構體文件6.3寄存器的C語言訪問6.3寄存器的C語言訪問6.3寄存器的C語言訪問定義了結構體SCI_REGS型的變量SciaRegs和ScibRegs之后,就可以方便地實現對寄存器的操作了。例6.5對SCIA的寄存器SCICCR按位進行操作SciaRegs.SCICCR.bit.STOPBITS=0;//1位停止位寄存器結構體文件共同體位域整體按位操作Uint16/326.3寄存器的C語言訪問例6.6對SCICCR整體進行操作SciaRegs.SCICCR.all=0x0007;例6.7對定義為Unit16的成員SCIHBAUD和SCILBAUD進行操作SciaRegs.SCIHBAUD=0;SciaRegs.SCILBAUD=0xF3;例6.5、6.6、6.7中的3種操作涵蓋了在F2812開發過程中對寄存器操作的所有方式,也就是說掌握了這3種方式,就可以實現對F2812各種寄存器的操作。6.3寄存器的C語言訪問建立結構體文件步驟(以SCI模塊的寄存器為例):使用位域定義的方式對SCI模塊中各個寄存器的位功能進行操作;根據需要定義共同體,可以對某些寄存器的整體或位進行操作;對整個SCI模塊所有的寄存器建立結構體文件。6.4CMD文件值得注意的是,之前所做的工作只是將F2812的寄存器按照C語言中位域定義和寄存器結構體的方式組織了數據結構,當編譯時,編譯器會把這些變量分配到存儲空間中,但是很顯然還有一個問題要解決,那就是如何將代表寄存器數據的變量同實實在在的物理寄存器結合起來呢?這就是寄存器文件的空間分配問題,在此之前,我們先需要對分配存儲空間的CMD文件進行了解。6.4CMD文件鏈接命令文件(LinkerCommandFiles),以后綴.cmd結尾,簡稱CMD文件。其作用就是為程序代碼和數據分配存儲空間。單片機:在程序設計時,經過編譯匯編鏈接,直接下載到硬件中調試。DSP:在2812的程序設計時,編寫的程序代碼首先經過編譯器編譯產生幾個代碼塊和數據塊,也就是我們所說的段,然后需要編寫CMD文件,也就是鏈接命令文件,來指示鏈接器將編譯器產生的這些段進行鏈接,分配到目標存儲器,也就是硬件存儲器。6.4CMD文件6.4.1COFF格式和段的概念6.4.2C語言生成的段6.4.3pragma偽指令6.4.4CMD文件的編寫6.4.5實際工程中的CMD文件6.4CMD文件6.4.1COFF格式和段的概念

編譯、匯編與鏈接程序建立的目標文件采用通用目標文件格式(CommonObjectFileFormat,COFF)。COFF格式是一種很流行的二進制格式。例如庫文件(.lib)、目標文件(.obj)、最終的可執行文件(.out)等都是采用COFF格式。COFF文件格式包括文件頭、段落頭、段數據、重定位信息等,我們不管COFF文件格式的具體信息,只需要知道TI公司的匯編器和鏈接器創建目標文件都使用這種COFF格式。

6.4CMD文件6.4.1COFF格式和段的概念

COFF格式的核心是在編寫DSP程序時,基于代碼段和數據段的概念,而不是一條條命令或一個個數據,使得程序可讀性和可移植性大大增強。這些代碼段和數據段簡稱為段(section,也稱為塊),是目標文件的最小單位(基本單元),是在存儲器中占據連續空間的代碼和數據塊,各段相互獨立。匯編器和鏈接器提供了一些偽指令來建立和管理各種各樣的段。例如pragma,MEMRY,SECTIONS等。告訴匯編程序如何進行匯編的指令,既不控制機器操作也不被匯編成代碼,只能為匯編程序所識別,并指導匯編如何進行。(沒有對應的機器碼!)6.4.1COFF格式和段的概念6.4CMD文件1.把每個源文件都編譯成獨立的目標文件(以后綴.obj結尾),每個目標文件都含有自己的段。Compilefile2.連接器把這些目標文件中相同段名的部分連接在一起,生成最終的可執行文件(以后綴.out結尾)Build。編譯器處理段的過程:編譯器產生可重定位的代碼,允許鏈接器將代碼和數據分配到適當的存儲器空間。而鏈接器將根據鏈接命令文件(CMD文件),將代碼和數據分配到目標存儲器。6.4.2C語言生產的段6.4CMD文件F2812的C編譯器將存儲器作為程序存儲器和數據存儲器兩個線性區來處理,每個由C程序生成的代碼子模塊或數據子模塊被放到各自的連續存儲空間中。

程序存儲器:包含可執行的代碼和常量、變量初值。

數據存儲器:包含外部變量、靜態變量和系統堆棧。6.4.2C語言生產的段6.4CMD文件由C語言程序生成的可重定位的代碼和數據模塊,稱作“sections”。可以分為兩大類:已初始化的段和未初始化的段。

已初始化的段:含有真實的指令和數據,存放在程序存儲空間。

未初始化的段:只是保留變量的地址空間(通常是RAM),或者說為未初始化的數據保留存儲空間。一段程序可以在運行期間,使用這個空間創造和存儲變量。在DSP上電調用_c_int0初始化庫前,未初始化的段并沒有真實的內容。未初始化的段存放在數據存儲空間。6.4.2C語言生產的段6.4CMD文件已初始化的段

.text編譯C語言中的語句時,生成的匯編指令代碼存放于此,換句話說,包含所有的可執行代碼和常量。

.cinit存放用來對全局和靜態變量初始化的常數。(C程序).pinit全局構造器(C++)程序列表。(C++程序)

.const包含字符串常量和由const聲明的全局變量和靜態變量。

.econst包含字符串常量和初始化的全局變量和靜態變量(由farconst聲明或大存儲器模式)的初始化和說明。.switch存放switch語句產生的常數表格。6.4.2C語言生產的段6.4CMD文件未初始化的段

.bss:為全局變量和局部變量保留的空間,在程序上電時,.cinit空間中的數據復制出來并存儲在.bss空間中。.ebss:為使用大寄存器模式時的全局變量和靜態變量預留的空間,在程序上電時,.cinit空間中的數據復制出來并存儲在.ebss中。.stack:為系統堆棧保留的空間,主要用于與函數傳遞變量或為局部變量分配空間。.sysmem:為動態存儲分配保留的空間。如果有宏函數(malloc),此空間被宏函數占用,如果沒有的話,此空間保留為0。.esysmem:為動態存儲分配保留的空間。如果有farmalloc函數,此空間被相應的占用,如果沒有的化,此空間保留為0。6.4.2C語言生產的段6.4CMD文件段的存儲特性為什么已初始化的段可以放到Flash或者ROM里面呢?

這主要跟2812的調試模式有關,可以放到RAM里調試也可以放到Flash里調試。已初始化的段未初始化的段6.4.3pragma偽指令6.4CMD文件上面介紹的段都是C語言預先已經定義好的段,我們還可以根據自己的需要通過偽指令來定義自己的段。

#pragma是標準C語言中保留的預處理命令,它的作用就是告訴編譯器如何對待或處理特定函數、對象或代碼段。通過#pragma定義段的格式如下:#pragmaCODE_SECTION(symbol,”sectionname”);#pragmaDATA_SECTION(symbol,”sectionname”);為代碼定義段,定義代碼段為數據定義段,定義數據段6.4.3pragma偽指令6.4CMD文件說明:

symbol是符號,可以是函數名或全局變量名。sectionname是用戶自己定義的段名。

CODE_SECTION用來定義代碼段,而DATA_SECTION用來定義數據段。不能在函數體內聲明#pragma,必須在函數外。必須在符號被定義和使用前使用#pragma。#pragmaCODE_SECTION(symbol,”sectionname”);CODE_SECTION用于為函數symbol在一個名為sectionname的段中指定空間。

#pragmaDATA_SECTION(symbol,”sectionname”);CODE_SECTION用于為變量symbol在一個名為sectionname的段中指定空間。6.4.3pragma偽指令6.4CMD文件#pragmaCODE_SECTION(sum,“codeA”);intsum(inta,intb);voidmain(void){inta=1,b=2,c;c=sum(a,b);}intsum(inta,intb){return(a+b);}舉例不能在函數體內聲明#pragma,必須在函數外。6.4.3pragma偽指令6.4CMD文件

#pragmaDATA_SECTION(s,”newsect”);

unsignedints[100];

voidmain(void){……}將全局數組變量s[100]單獨編譯成一個新的段,取名為”newsect”。舉例必須在符號被定義和使用前使用#pragma6.4CMD文件段存儲器類型分配的存儲空間.textROMORRAM(FLASH)Page0.cinitROMORRAM(FLASH)Page0.constROMORRAM(FLASH)Page1.econstROMORRAM(FLASH)Page1.pinitROMORRAM(FLASH)Page0.switchROMORRAM(FLASH)Page0/page1.bssRAMPage1.ebssRAMPage1.stackRAMPage1.systemRAMPage1.esystemRAMPage1通過#pragmaCODE_SECTION定義的段ROMORRAM(FLASH)Page0通過#pragmaDATA_SECTION定義的段RAMPage16.4.4CMD文件的編寫6.4CMD文件CMD文件支持C語言中的塊注釋符“/*”和“*/”,但不支持行注釋符“//”。CMD文件會使用到為數不多的幾個關鍵字,下面會根據需要來介紹一些常用的關鍵字。CMD文件的兩大主要功能是指示存儲空間和分配段到存儲空間,CMD文件其實也就是由這兩部分內容構成的。在編寫CMD文件時,主要采用MEMORY和SECTIONS

兩條偽指令。在281x調試時,可以將程序代碼鏈接到Flash或者RAM,因此對應兩種CMD文件。6.4.4CMD文件的編寫(分為2個步驟)6.4CMD文件1.通過MEMORY偽指令來指示存儲空間MEMORY偽指令語法如下:MEMORY{PAGE0:name0[(attr)]:origin=constant,length=constantPAGEn:namen[(attr)]:origin=constant,length=constant}PAGE用來標識存儲空間的關鍵字。PAGEn的最大值為PAGE255。X281x的DSP中用到是PAGE0、PAGE1,其中PAGE0為程序空間,PAGE1為數據空間。(實際應用中一般分為2頁)6.4.4CMD文件的編寫6.4CMD文件1.通過MEMORY偽指令來指示存儲空間name代表某一屬性或地址范圍的存儲空間名稱。名稱可以是1~8個字符,在同一頁內名稱不能相同,不同頁內名稱可以相同。

attr用來規定存儲空間的屬性。共有4個屬性,只讀R,只寫W,該空間可包含可執行代碼X,該空間可以被初始化I。實際使用為了簡化,通常會忽略此選項,表示存儲空間具有所有的屬性。

origin用來定義存儲空間的起始地址。

length用來定義存儲空間的長度。6.4.4CMD文件的編寫6.4CMD文件1.通過MEMORY偽指令來指示存儲空間(舉例)

MEMORY{PAGE0:FLASH:origin=0x3D8000,length=0x01FF80/*FLASH*/BEGIN:origin=0x3F7FF6,length=0x000002ROM:origin=0x3FF000,length=0x000FC0RESET:origin=0x3FFFC0,length=0x000002RAML0:origin=0x008000,length=0x001000PAGE1:RAMM0:origin=0x000000,length=0x000400/*RAMM0*/RAMM1:origin=0x000400,length=0x000400/*RAMM1*/RAML1:origin=0x009000,length=0x001000/*RAML1*/RAMH0:origin=0x3F8000,length=0x002000/*RAMH0*/}6.4CMD文件6.4.4CMD文件的編寫6.4CMD文件2.通過SECTIONS偽指令來將段分配到存儲空間(也就是指定段的實際硬件地址空間)SECTIONS{name:[property,property,property,…]name:[property,property,property,…]……}SECTIONS偽指令語法如下:name為輸出段的名稱;property為輸出段的屬性。6.4.4CMD文件的編寫6.4CMD文件輸出段的屬性主要有以下幾個:load定義輸出段將被裝載到哪里的關鍵字,其語法:

load=allocation或者allocation或者>allocation其中,allocation可以是絕對地址,如“load=0x000400”;更多的時候,allocation是存儲空間的名稱,這也是最通常的用法。

run定義輸出段從哪里運行的關鍵字,其語法:run=allocation或者run>allocation

CMD文件規定,當只出現一個關鍵字load或者run時,表示load地址和run地址是重疊的,大部分時候都是重疊的。

PAGE定義段分配到存儲空間的類型,其語法:PAGE=0或者PAGE=1,前者說明段分配到程序空間,后者說明段分配到數據空間。6.4.4CMD文件的編寫6.4CMD文件2.通過SECTIONS偽指

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論