TMS320LF240x DSP控制器的應(yīng)用實(shí)踐
TI公司在1982年成功推出其第一代DSP芯片之后,相繼推出了多種適合不同應(yīng)用、不同規(guī)格的DSP系列。TMS320F240x DSP是為了滿足控制應(yīng)用而設(shè)計(jì)的,屬于TMS320C2xx系列。通過把一個(gè)高性能的DSP內(nèi)核和微處理器的片內(nèi)外部設(shè)備集成在一個(gè)芯片的方案,TMS320LF240x DSP成為傳統(tǒng)微控制器和昂貴的多片設(shè)計(jì)的一種廉價(jià)替代產(chǎn)品。3OMIPS的處理速度,使TMS320IF240x DSP可以遠(yuǎn)遠(yuǎn)超過傳統(tǒng)的16位微控制器和微處理器的性能。筆者曾用該系列芯片中的TMS320F2406開發(fā)過電動(dòng)執(zhí)行機(jī)構(gòu),得到了滿意的結(jié)果。結(jié)合自己的開發(fā)經(jīng)驗(yàn),筆者簡要介紹TMS320LF240xDSP的硬件結(jié)構(gòu)、C程序開發(fā)過程中若干關(guān)鍵的問題。其中很多包括筆者的心得和體會(huì)。
1 TMS320LF240X DSP硬件結(jié)構(gòu)特點(diǎn)
TMS320LF240x DSP有以下一些特點(diǎn):采用高性能靜態(tài)CMOS技術(shù),使得供電電壓降為3.3V,減少了功耗;基于TMS320C2xxDSP的CPU核,保證與TMS320系列DSP代碼兼容;片內(nèi)有高達(dá)32K字的Flash程序存儲(chǔ)器,544字的雙口RAM(DARAM)和2K字的單口RAM(SARAM);兩個(gè)事件管理器模塊EVA和EVB,適用于控制各類電機(jī);看門狗定時(shí)器模塊(WDT);控制器局域網(wǎng)絡(luò)(CAN)2.0B模塊;串行通信接口(SCI)模塊;16位的串行外設(shè)接口(SPI)模塊;JTAG接口,使得在系統(tǒng)編程(ISP,)很容易實(shí)現(xiàn);10位A/D轉(zhuǎn)換器最小的轉(zhuǎn)換時(shí)間為500ns,可選擇由兩個(gè)事件管理器來觸發(fā)2個(gè)8通道輸入A/D轉(zhuǎn)換器或1個(gè)16通道輸入A/D轉(zhuǎn)換器,而每次要轉(zhuǎn)換的通道都可通過編程來選擇。需要說明的是,TMS320LF240x DSF是定點(diǎn)l6位芯片,存儲(chǔ)數(shù)據(jù)的最小單位是16位的字,每個(gè)地址(包括程序地址、數(shù)據(jù)地址及I/O地址)所存的數(shù)據(jù)都是16位。
1.1 改進(jìn)的哈佛結(jié)構(gòu)和流水線操作
DSP采用程序空間和數(shù)據(jù)空間完全分開的哈佛(Havard)結(jié)構(gòu),允許同時(shí)取指令和操作數(shù),而且允許在程序空間和數(shù)據(jù)空間之間相互傳遞數(shù)據(jù),即改進(jìn)的哈佛結(jié)構(gòu)。TMS320LF240x DSP的cPu核心具有獨(dú)立的內(nèi)部數(shù)據(jù)和程序總線結(jié)構(gòu)。數(shù)據(jù)和程序總線分為6條l6位的總線,分別為:PAB,程序地址總線,為讀寫程序空間提供地址;DRAB,數(shù)據(jù)讀地址總線,為讀數(shù)據(jù)空間提地址;DWAB,數(shù)據(jù)寫地址總線,為寫數(shù)據(jù)空間提供地址;PRDB,從程序空間向c.PU傳送代碼、立即操作數(shù)和表信息的程序讀總線;DRDB,從數(shù)據(jù)空間向中央算術(shù)邏輯單元(CALU)和輔助寄存器算術(shù)單元(ARAU)傳送數(shù)據(jù)的數(shù)據(jù)讀總線;DWEB,可以傳送數(shù)據(jù)到程序空間和數(shù)據(jù)空間的數(shù)據(jù)寫總線。數(shù)據(jù)讀地址總線(DRAB)和數(shù)據(jù)寫地址總線(DWAB)是相互獨(dú)立的地址總線,CPU 在相同的機(jī)器周期內(nèi)可以同時(shí)進(jìn)行數(shù)據(jù)讀寫操作。
TMS320LF240x DSP流水線具有四個(gè)獨(dú)立的階段:取指令、指令譯碼、取操作數(shù)以及指令執(zhí)行。一般情況下,取指令占用PAB和PRDB;指令譯碼不占用任何程序和數(shù)據(jù)總線;取操作數(shù)占用DRAB和DRDB;指令執(zhí)行包括將執(zhí)行結(jié)果寫回?cái)?shù)據(jù)存儲(chǔ)器,將占用DWAB和DWEB??梢?,TMS320LF240x DSP獨(dú)特的總線結(jié)構(gòu)大大減少了流水線沖突,極大提高了指令的運(yùn)行速度。
1. 2事件管理器模塊
事件管理器模塊提供了許多適用于運(yùn)動(dòng)控制和電機(jī)控制的功能。每個(gè)240x器件都包括兩個(gè)事件管理器模塊:EVA和EVB。每個(gè)事件管理器模塊包括兩個(gè)16位69通用定時(shí)器、比較單元、捕獲單元、8個(gè)16位的脈寬調(diào)制(PWM)通道以及正交編碼脈沖輸入電路。它們能夠?qū)崿F(xiàn):三相反相器控制;PWM的對(duì)稱和非對(duì)稱波形;編程的PWM死區(qū)控制以防止上下橋臂同時(shí)導(dǎo)通而引起短路。事件管理器模塊適用于控制交流感應(yīng)電機(jī)、無刷直流電機(jī)、開關(guān)磁阻電機(jī)、步進(jìn)電機(jī)、多級(jí)電機(jī)以及逆變器。
2 C0FF目標(biāo)文件
TI公司匯編器所創(chuàng)建的目標(biāo)文件采用的是一種稱為COFF(Common Object File Format)的文件格式,即共同目標(biāo)文件格式。目的是提高編程和程序執(zhí)行的效率,同時(shí)也有利于使用TI公司的BIOS(Basic Input Output System)。
COFF文件格式的核心概念就是使用代碼段、數(shù)據(jù)段編程,而不是指令或數(shù)據(jù)簡單的順序編寫。代碼段和數(shù)據(jù)段的概念不僅是現(xiàn)代軟件編制的重要技術(shù)概念,同時(shí)也是嵌入式系統(tǒng)的重要編程技術(shù)。使用這種技術(shù)的優(yōu)點(diǎn)是:程序具有良好的可讀性;程序具有良好的可移植性;能與系統(tǒng)存儲(chǔ)單元充分配合。
在COFF目標(biāo)文件中,段(section)是其最小的單位。所謂“段”就是最終在TMS320 DSP的存儲(chǔ)器映像中占據(jù)連續(xù)空間的一塊代碼或數(shù)據(jù)。這些段在目標(biāo)文件中是相互獨(dú)立的。由于大多數(shù)系統(tǒng)都包含有不同類型的存儲(chǔ)器(ROM、RAM、EEPROM),所以使用段可使用戶更有效地利用目標(biāo)存儲(chǔ)器;所有段都能夠獨(dú)立進(jìn)行重定位,因此可以將不同的段分配至不同類型的存儲(chǔ)器中去。
通常,一個(gè)COFF目標(biāo)文件中都包含三個(gè)缺省段:text段(通常包含可執(zhí)行代碼)、.data段(通常包含已初始化數(shù)據(jù))和.bss段(通常為未初始化的數(shù)據(jù)保留所需的空間)。除了這三個(gè)缺省的段之外,編程人員可使用匯編器指示符(.sect和usect)自定義段。
TMS320LF240x DSP C編譯器產(chǎn)生可重定位的數(shù)據(jù)段和代碼段。這些段以不同方式分配到內(nèi)存中,以滿足不同的系統(tǒng)配置。編譯器創(chuàng)建兩種基本的段:初始化段和未初始化段。
初始化段包括數(shù)據(jù)表和可執(zhí)行代碼。C編譯器創(chuàng)建下初始化段:
◆.text段一包含所有的可執(zhí)行代碼和浮點(diǎn)常數(shù);
◆.cinlt段一包含用于初始化全局變量和靜態(tài)變量的表:
◆.const段一包含字符常量以及用關(guān)鍵字const聲明的全局和靜態(tài)變量:
◆.switch段一包含switch語句的跳轉(zhuǎn)表。
未初始化段在內(nèi)存(通常是RAM)中保留空間。程序在運(yùn)行時(shí)用這些空間創(chuàng)建和保存變量。編譯器創(chuàng)建以下未初始化段:
◆.bss段一為全局變量和靜態(tài)變量保存空間,在程序開始運(yùn)行時(shí),C初始化boot程序?qū)?shù)據(jù)從.Clnlt拷貝到bss段中;
◆.stack段――為系統(tǒng)堆棧分配存儲(chǔ)空間,用于將變量傳遞至函數(shù)以及為局部變量分配空間;
◆.system段一為動(dòng)態(tài)內(nèi)存分配保留空間,為動(dòng)態(tài)存儲(chǔ)函數(shù)malloc、callo和realloc分配存儲(chǔ)空間。當(dāng)然,若C程序沒有用到這些函數(shù),那么編譯器就不用創(chuàng)建system段了。
3 C程序運(yùn)行環(huán)境
TMS320LF240x DSP提供兩種編程語言:匯編語言和C語言。如果源程序?yàn)镃語言,需調(diào)用TMS320LF240x DSP的C編譯器將其編譯成匯編語言,然后送匯編器進(jìn)行匯編。匯編后產(chǎn)生COFF格式的目標(biāo)文件,再用鏈接器進(jìn)行鏈接(鏈接過程包括將編譯器的運(yùn)行支持庫相關(guān)代碼鏈接進(jìn)來以及代碼段和數(shù)據(jù)段的重定位),生成在TMS320LF240x DSP上可執(zhí)行的COFF格式的目標(biāo)代碼(如有必要,可使用目標(biāo)代碼格式轉(zhuǎn)換工具),并調(diào)用下載程序?qū)⒛繕?biāo)代碼下載到目標(biāo)芯片上。
TMS32OC2xx DSP(當(dāng)然包括TMS320LF240x DSP)C語言編譯器包含兩個(gè)庫:rts2xx.1ib和rts.src。
(1)rts2xx.Ii b
rts2xx.1ib運(yùn)行支持目標(biāo)庫。具有COFF文件格式。運(yùn)行支持目標(biāo)庫(即rts2xx1ib)是由rts.src中的C和匯編源程序通過編譯和匯編而得到的。rts2xx lib包含三部分內(nèi)容:ANSI C標(biāo)準(zhǔn)庫、系統(tǒng)啟動(dòng)程序c int00、允許C訪問特殊指令的函數(shù)和宏。
鏈接程序時(shí),必須指明具體的目標(biāo)庫并把該庫作為鏈接輸入文件之一,這樣對(duì)目標(biāo)庫所包含的運(yùn)行支持函數(shù)的引用就得到了解決。鏈接運(yùn)行目標(biāo)庫時(shí),鏈接器只是將目標(biāo)庫中被引用部分加進(jìn)目標(biāo)文件。這里所說的目標(biāo)庫指的就是rts2xx.lib。由于運(yùn)行支持函數(shù)符合函數(shù)調(diào)用規(guī)約,可以直接被C訪問。
(2)rts.src
rts.src運(yùn)行支持源文件庫,由c和匯編源程序組成,可在集成開發(fā)環(huán)境(CCS)下打開,任何一個(gè)運(yùn)行支持函數(shù)的源代碼都可以在rts.src找到。
rts.src中包含有用匯編語言編寫的算術(shù)程序。由于這些函數(shù)的特殊調(diào)用規(guī)約,它們不能從C中被訪問:但可以對(duì)它們作擴(kuò)展或修改以作為自己的程序。只要修改后的程序遵循函數(shù)特定的調(diào)用規(guī)約和保護(hù)規(guī)約,它們就可以被C直接訪問。
算術(shù)程序中包含浮點(diǎn)運(yùn)算函數(shù)。浮點(diǎn)數(shù)采用IEEE754單精度浮點(diǎn)數(shù)格式為
浮點(diǎn)數(shù)由3部分組成,即符號(hào)位(“S”)、指數(shù)和尾數(shù)。指數(shù)是有+127偏置的無符號(hào)整數(shù)。一個(gè)浮點(diǎn)數(shù)占有32位,占用TMS320LF240x DSP兩個(gè)字的空間。32位規(guī)格化數(shù)的值由值(規(guī)格化)=(-1)3l.尾數(shù)2(指數(shù)-127)給出。這樣,浮點(diǎn)數(shù)O.5的單精度浮點(diǎn)數(shù)為3F000000h,格式為
例如,源庫rts.src中的匯編函數(shù)F$$ITOF是將16位有符號(hào)整形數(shù)轉(zhuǎn)換為浮點(diǎn)數(shù),只要在匯編程序中加入“ref F$$ITOF”指令,即可直接調(diào)用該函數(shù)。查看F$$ITOF函數(shù)的說明文檔可知,該函數(shù)不遵循C子程序調(diào)用規(guī)約,所以它不能直接被C調(diào)用。
下面介紹C程序的系統(tǒng)初始化。
在運(yùn)行C程序之前,必須創(chuàng)建C運(yùn)行環(huán)境。這個(gè)程序由C引導(dǎo)程序使用名為c_intO的函數(shù)來執(zhí)行。運(yùn)行支持源庫(rts.src)在名為boot.asm的模塊中包含這個(gè)程序的源程序。c_intO執(zhí)行如下初始化C環(huán)境的任務(wù):
①為系統(tǒng)堆棧定義一個(gè)名為stack的段,并設(shè)置初始化指針;
②初始化全局變量,將.Clnlt段中的初始化表中的數(shù)據(jù)復(fù)制到bss段中;
③調(diào)用函數(shù)main來運(yùn)行C程序。
運(yùn)行堆棧(即.stack段)被分配在存儲(chǔ)器的一個(gè)連續(xù)塊中,并且從低地址向高地址增加。寄存器ARl通常指向堆棧中下一個(gè)可獲得的字(堆棧頂加一個(gè)字)。代碼不會(huì)檢查運(yùn)行時(shí)堆棧是否會(huì)溢出,因此要確保分配給堆棧足夠的空間。
有些全局變量在C程序開始運(yùn)行前必須賦初值,檢索這些變量的數(shù)值并用數(shù)值將它們初始化的過程成為自動(dòng)初始化。編譯器在名為.clnlt(該段位于程序空間)的特殊段中建立表。該段包含了用于初始化全局變量和靜態(tài)變量的數(shù)據(jù)。每個(gè)被編譯模塊都包含這些初始化表,鏈接器將它們組成單個(gè)表(單個(gè)的clnlt段)。引導(dǎo)程序使用這個(gè)表初始化所有的系統(tǒng)變量。
.clnlt段中的表是由多項(xiàng)初始化記錄組成的。每個(gè)必須自動(dòng)初始化的變量在.cinit段中都有記錄,.clnlt段中初始化記錄的格式如圖l所示。
初始化記錄包括三部分:字節(jié)長度,即需要初始化的變量個(gè)數(shù);.bss中變量的指針,為該記錄第一個(gè)變量在.bss段中的地址;初始化數(shù)據(jù),指的是用于初始化變量的數(shù)據(jù)。初始化數(shù)據(jù)的個(gè)數(shù)必須和字節(jié)長度相等。在變量的自動(dòng)初始化過程中,為了能讓初始化程序識(shí)別初始化記錄的結(jié)尾,最后一項(xiàng)初始化記錄的第一個(gè)字用0填充,即該初始化記錄的字節(jié)長度為0。至此初始化程
序完成了全局變量的初始化。
全局變量的初始化包括運(yùn)行時(shí)變量的自動(dòng)初始化和加載時(shí)變量的初始化。筆者認(rèn)為,加載時(shí)變量的初始化沒有實(shí)用價(jià)值。因?yàn)楫?dāng)DSP斷電后,這些變量的值就丟失了。當(dāng)DSP重新上電后,由于初始化程序不給這些全局變量賦初值,使得系統(tǒng)的初始化失敗。
4 C語言和匯編語言的混合編程
開發(fā)DSP芯片可以用匯編語言或C語言。兩種語言各有所長:用C語言開發(fā)DSP芯片,開發(fā)速度快,可讀性好,可移植性強(qiáng);而用匯編語言開發(fā)DSP芯片,則能充分利用DSP芯片的軟硬件資源,程序代碼的執(zhí)行效率高。在DSP運(yùn)算能力比較寬裕,實(shí)時(shí)性要求不是很強(qiáng)的場合,用C語言非常合適。在對(duì)運(yùn)算速度以及實(shí)時(shí)性要求極高或者是在不能擴(kuò)展外部存儲(chǔ)器而且片內(nèi)存儲(chǔ)器又非常有限的條件下,使用匯編語言幾乎是必須的。在程序的開發(fā)過程中,幾乎不可避免地要使用C語言和匯編語言的混合編程。
用C語言和匯編語言進(jìn)行混合編程主要有以下三種方法:
①獨(dú)立編寫C程序和匯編程序,分開編譯或匯編形成各自的目標(biāo)代碼模塊,然后用鏈接器將C語言模塊和匯編模塊鏈接起來。這其實(shí)就是一個(gè)C模塊和匯編模塊的接口問題。
②直接在C程序中的相應(yīng)位置嵌入?yún)R編語句。
③對(duì)C程序進(jìn)行匯編生成相應(yīng)代碼,然后對(duì)這些匯編代碼進(jìn)行手工優(yōu)化與修改。
在用c語言和匯編語言進(jìn)行混合編程時(shí),必須遵循寄存器規(guī)約和函數(shù)調(diào)用規(guī)約。
(1)寄存器規(guī)約
在C環(huán)境中,對(duì)什么寄存器用于完成什么樣的操作有嚴(yán)格規(guī)定。所有這些規(guī)定統(tǒng)稱為寄存器規(guī)約(registcr conventions)。如果想編寫出正確的C語言DSP程序,將C程序和匯編程序接口,則必須理解和遵循這些規(guī)約寄存器規(guī)約規(guī)定編譯器如何使用寄存器以及在函數(shù)的調(diào)用過程中如何保護(hù)寄存器。在函數(shù)的調(diào)用過程中有兩種保護(hù)寄存器的方法:一種是在調(diào)用時(shí)保護(hù)寄存器(由調(diào)用函數(shù)來完成),另一種是在被調(diào)用函數(shù)程序的入口處保護(hù)寄存器(由被調(diào)用函數(shù)來完成)。限于篇幅,不再詳細(xì)介紹。在編程的過程中,一定要嚴(yán)格遵循這些規(guī)約,否則,會(huì)出現(xiàn)錯(cuò)誤。
(2)函數(shù)調(diào)用規(guī)約
C編譯器對(duì)函數(shù)調(diào)用有一系列嚴(yán)格的規(guī)約。任何函數(shù)不管是調(diào)用C函數(shù),還是被C函數(shù)調(diào)用,都必須遵循這些規(guī)約。不遵循這些規(guī)約將破壞C環(huán)境,導(dǎo)致程序運(yùn)行失敗。函數(shù)調(diào)用規(guī)約(function calling conyentions)l確規(guī)定在函數(shù)調(diào)用的全過程中,調(diào)用函數(shù)和被調(diào)用函數(shù)所必須執(zhí)行的操作,以保證調(diào)用前后C環(huán)境的一致性。
當(dāng)父函數(shù)調(diào)用子函數(shù)時(shí),必須保證當(dāng)前的輔助寄存器為ARl。父函數(shù)執(zhí)行以下操作:①將被調(diào)用函數(shù)所需參數(shù)的值壓入堆棧(按從右到左的順序),使最左邊的參數(shù)位于堆棧的頂部;②調(diào)用子函數(shù),即開始執(zhí)行子函數(shù)程序代碼;③父函數(shù)認(rèn)為,當(dāng)函數(shù)調(diào)用返回時(shí),ARl是當(dāng)前的輔助寄存器;④當(dāng)被調(diào)用函數(shù)完成時(shí),父函數(shù)將堆棧指針移回到函數(shù)調(diào)用前的位置。直接把壓入堆棧中參數(shù)的值丟棄。
由上可看出,函數(shù)調(diào)用過程中參數(shù)的傳遞是值傳遞,并沒有改變參數(shù)的值,只是把被調(diào)用函數(shù)所需參數(shù)的值拷貝進(jìn)堆棧中。子函數(shù)使用的是堆棧中的拷貝。子函數(shù)對(duì)拷貝部分的修改并不改變參數(shù)的值。當(dāng)函數(shù)調(diào)用完成時(shí),父函數(shù)直接將堆棧中的拷貝丟棄。
子函數(shù)所執(zhí)行的操作相對(duì)復(fù)雜一些,這里不再敘述。讀者可參閱TI公司技術(shù)手冊(cè):TMS320C2x/C2xx/C5xOptlmizing CCompiler Users’s Guide。
結(jié)語
從普及、推廣的角度來看,TI公司的TMS320C2xx系列具有較好的應(yīng)用基礎(chǔ)和較高的性能價(jià)格比,在我國有著廣泛的應(yīng)用前景。TMS320LF240x DSP是TMS320C2xx系列中的新成員,其性能遠(yuǎn)遠(yuǎn)超過傳統(tǒng)的l6位微控制器和微處理器,非常適用于電機(jī)的數(shù)字化控制,是電機(jī)數(shù)字化控制的升級(jí)產(chǎn)品。用高級(jí)語言進(jìn)行DSP的開發(fā)是DSP開發(fā)的重要方向。C語言在滿足控制應(yīng)用程序運(yùn)行速度的基礎(chǔ)上可以更好地維護(hù)程序和移植程序,是開發(fā)控制應(yīng)用程序的必然趨勢。因此,我們有必要深入了解C程序的運(yùn)行環(huán)境和編譯器的工作原理。DSP軟硬件開發(fā)過程中綜合了多方面的知識(shí),只有在充分了解硬件資源的基礎(chǔ)上,才能開發(fā)出好的程序。
評(píng)論