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

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

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

TMS320X28xx的C編譯器是一個(gè)功能齊全的優(yōu)化編譯器,優(yōu)化編譯結(jié)果達(dá)手工編寫的匯編語言效率的90%以上??梢岳迷摼幾g器將標(biāo)準(zhǔn)的ANSIC/C++程序直接轉(zhuǎn)換成TMS320X28xx處理器的匯編代碼。為了提高執(zhí)行效率,關(guān)鍵的DSP運(yùn)算程序仍然應(yīng)用匯編語言進(jìn)行編寫,同時(shí)按照規(guī)定的接口,然后通過C語言程序?qū)ζ湔{(diào)用。

1.標(biāo)準(zhǔn)的ANSIC/C++語言

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

TMS320X28xx編譯器工具為各種處理器提供完整的實(shí)時(shí)運(yùn)行庫(kù)。庫(kù)中包括動(dòng)態(tài)內(nèi)存分配、對(duì)字符串的操作、數(shù)學(xué)運(yùn)算(如求絕對(duì)值、計(jì)算三角函數(shù)和指數(shù)函數(shù)等)以及一些標(biāo)準(zhǔn)的輸入/輸出操作等,只要在源程序中加入對(duì)應(yīng)的頭文件(如stdlib.h、string.h、math.h和stdio.h等)就可以調(diào)用和使用。rts.src

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

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

(2)直接在C/C++程序中嵌入?yún)R編程序。

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

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

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

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

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

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

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

類型說明符位域名1:位域長(zhǎng)度類型說明符位域名2:位域長(zhǎng)度

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

關(guān)于位域定義的幾點(diǎn)說明:

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

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

關(guān)于位域定義的幾點(diǎn)說明:

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

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

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

Uint16LOOPBKENA:1;//4回送測(cè)試模式使能位

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

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

Uint16STOPBITS:1;//7停止位個(gè)數(shù)

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

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

Uint16LOOPBKENA:1;//4回送測(cè)試模式使能位

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

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

Uint16STOPBITS:1;//7停止位個(gè)數(shù)

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

2

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

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

Uint16TXENA:1;/1SCI發(fā)送器使能

Uint16SLEEP:1;//2SCI睡眠

Uint16TXWAKE:1;//3發(fā)送喚醒方法

Uint16rsvd1:l;//4保留

Uint16SWRESET:1;//5軟件復(fù)位

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

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

structSCICCR_BITSbit;//可實(shí)現(xiàn)位操作};unionSCICCR_REGSCICCR;SCICCR.all=0x007F;SCICCR.bit.SCICHAR=5;例6.3SCICCR的共同體定義聲明了一個(gè)SCICCR_REG變量SCICCR通過變量SCICCR對(duì)寄存器實(shí)現(xiàn)整體操作?通過變量SCICCR對(duì)寄存器實(shí)現(xiàn)位操作?注意:整個(gè)共同體的總的存儲(chǔ)空間為2個(gè)字節(jié)。1

2

3

46.3寄存器的C語言訪問6.3.3創(chuàng)建結(jié)構(gòu)體文件

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

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

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

unionSCIRXBUF_REGSCIRXBUF;//接收數(shù)據(jù)寄存器

Uint16rsvd1;//保留

Uint16SCITXBUF;//發(fā)送數(shù)據(jù)緩沖寄存器

unionSCIFFTX_REGSCIFFTX;//FIFO發(fā)送寄存器

unionSCIFFRX_REGSCIFFRX;//FIFO接收寄存器

unionSCIFFCT_REGSCIFFCT;//FIFO控制寄存器

Uint16rsvd2;//保留

Uint16rsvd3;//保留

unionSCIPRI_REGSCIPRI;//FIFO優(yōu)先級(jí)控制寄存器

};externvolatilestructSCI_REGSSciaRegs;externvolatilestructSCI_REGSScibRegs;1

2

36.3寄存器的C語言訪問

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

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

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

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

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

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

程序存儲(chǔ)器:包含可執(zhí)行的代碼和常量、變量初值。

數(shù)據(jù)存儲(chǔ)器:包含外部變量、靜態(tài)變量和系統(tǒng)堆棧。6.4.2C語言生產(chǎn)的段6.4CMD文件由C語言程序生成的可重定位的代碼和數(shù)據(jù)模塊,稱作“sections”??梢苑譃閮纱箢悾阂殉跏蓟亩魏臀闯跏蓟亩?。

已初始化的段:含有真實(shí)的指令和數(shù)據(jù),存放在程序存儲(chǔ)空間。

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

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

.cinit存放用來對(duì)全局和靜態(tài)變量初始化的常數(shù)。(C程序).pinit全局構(gòu)造器(C++)程序列表。(C++程序)

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

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

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

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

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

symbol是符號(hào),可以是函數(shù)名或全局變量名。sectionname是用戶自己定義的段名。

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

#pragmaDATA_SECTION(symbol,”sectionname”);CODE_SECTION用于為變量symbol在一個(gè)名為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);}舉例不能在函數(shù)體內(nèi)聲明#pragma,必須在函數(shù)外。6.4.3pragma偽指令6.4CMD文件

#pragmaDATA_SECTION(s,”newsect”);

unsignedints[100];

voidmain(void){……}將全局?jǐn)?shù)組變量s[100]單獨(dú)編譯成一個(gè)新的段,取名為”newsect”。舉例必須在符號(hào)被定義和使用前使用#pragma6.4CMD文件段存儲(chǔ)器類型分配的存儲(chǔ)空間.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文件會(huì)使用到為數(shù)不多的幾個(gè)關(guān)鍵字,下面會(huì)根據(jù)需要來介紹一些常用的關(guān)鍵字。CMD文件的兩大主要功能是指示存儲(chǔ)空間和分配段到存儲(chǔ)空間,CMD文件其實(shí)也就是由這兩部分內(nèi)容構(gòu)成的。在編寫CMD文件時(shí),主要采用MEMORY和SECTIONS

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

attr用來規(guī)定存儲(chǔ)空間的屬性。共有4個(gè)屬性,只讀R,只寫W,該空間可包含可執(zhí)行代碼X,該空間可以被初始化I。實(shí)際使用為了簡(jiǎn)化,通常會(huì)忽略此選項(xiàng),表示存儲(chǔ)空間具有所有的屬性。

origin用來定義存儲(chǔ)空間的起始地址。

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

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偽指令來將段分配到存儲(chǔ)空間(也就是指定段的實(shí)際硬件地址空間)SECTIONS{name:[property,property,property,…]name:[property,property,property,…]……}SECTIONS偽指令語法如下:name為輸出段的名稱;property為輸出段的屬性。6.4.4CMD文件的編寫6.4CMD文件輸出段的屬性主要有以下幾個(gè):load定義輸出段將被裝載到哪里的關(guān)鍵字,其語法:

load=allocation或者allocation或者>allocation其中,allocation可以是絕對(duì)地址,如“l(fā)oad=0x000400”;更多的時(shí)候,allocation是存儲(chǔ)空間的名稱,這也是最通常的用法。

run定義輸出段從哪里運(yùn)行的關(guān)鍵字,其語法:run=allocation或者run>allocation

CMD文件規(guī)定,當(dāng)只出現(xiàn)一個(gè)關(guān)鍵字load或者run時(shí),表示load地址和run地址是重疊的,大部分時(shí)候都是重疊的。

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

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論