DSP集成開(kāi)發(fā)環(huán)境中的混合編程及FFT算法的實(shí)現
1 引言
CCS(Code Composer Studio)是TI公司的DSP集成開(kāi)發(fā)環(huán)境。它提供了環(huán)境配置、源文件編輯、程序調試、跟蹤和分析等工具,幫助用戶(hù)在一個(gè)軟件環(huán)境下完成編輯、編譯鏈接、調試和數據分析等工作。與TI提供的早期軟件開(kāi)發(fā)工具相比,利用CCS能夠加快軟件開(kāi)發(fā)進(jìn)程,提高工作效率。CCS一般工作在兩種模式下:軟件仿真器和與硬件開(kāi)發(fā)板相結合的在線(xiàn)編程。前者可以脫離DSP芯片,在PC機上模擬DSP指令集與工作機制,主要用于前期算法實(shí)現和調試。后者實(shí)時(shí)運行在DSP芯片上,可以在線(xiàn)編制和調試應用程序。
2 C語(yǔ)言和匯編語(yǔ)言的混合編程
TMS320 C5000系列的軟件設計通常有三種方法:
(1
) 用C語(yǔ)言開(kāi)發(fā);
(2) 用匯編語(yǔ)言開(kāi)發(fā);
(3) C和匯編的混合開(kāi)發(fā)。
其中用C語(yǔ)言開(kāi)發(fā)具有兼容性和可移植的優(yōu)點(diǎn),有利于縮短開(kāi)發(fā)周期和減少開(kāi)發(fā)難度,但是在運算量較大的情況下,C代碼的效率還是無(wú)法和手工編寫(xiě)的匯編代碼的效率相比,比如FFT運算,用匯編語(yǔ)言開(kāi)發(fā)的效率高,程序執行速度快,而且可以合理利用芯片的硬件資源,但是開(kāi)發(fā)難度較大,開(kāi)發(fā)周期長(cháng),而且可讀性和可移植性差。C和匯編的混合編程則可以充分利用前兩者的優(yōu)點(diǎn),以達到最佳利用DSP資源的目的。但是,采用C和匯編語(yǔ)言混合編程必須遵循相關(guān)函數調用規則和寄存器調用規則,否則會(huì )給程序的開(kāi)發(fā)帶來(lái)意想不到的問(wèn)題。
2.1 C語(yǔ)言和匯編語(yǔ)言混合編程的四種方法
(1) 獨立編寫(xiě)匯編程序和C程序,分開(kāi)編譯或匯編成各自的目標代碼模塊,再用鏈接器將二者鏈接起來(lái)。這種方法比較靈活,但是設計者必須自己維護各匯編模塊的入口和出口代碼,自己計算傳遞的參數在堆棧中的偏移量,工作量較大,但是能做到對程序的絕對控制。
(2) 在C程序中使用匯編程序中定義的變量和常數。
(3) 在C程序中內嵌匯編語(yǔ)句。這種方法可以實(shí)現C語(yǔ)言無(wú)法實(shí)現的一些硬件控制功能,如修改中斷控制寄存器。
(4) 將C語(yǔ)言編譯生成相應的匯編代碼,手工修改和優(yōu)化C編譯器生成的匯編代碼。采用這種方法可以控制C編譯器,從而產(chǎn)生具有交叉列表的匯編程序,而設計者可以對其中的匯編語(yǔ)句進(jìn)行修改,然后對匯編程序進(jìn)行編譯,產(chǎn)生目標文件。
后3種方法由于在C中直接嵌入了匯編語(yǔ)言,易造成程序混亂,破壞C環(huán)境,甚至導致程序崩潰,而開(kāi)發(fā)者又很難對不良結果進(jìn)行預期和有效控制。而如果采用第一種方法,只要遵循有關(guān)C語(yǔ)言函數調用規則和寄存器規則,就能預見(jiàn)到程序運行的結果,保證程序正確。
2.2 編程注意事項
C編譯器對函數調用制定了一組嚴格的規則。除了特殊的運行時(shí)間支持庫函數外,任何調用函數和被C函數調用的函數都必須遵守這些規則。結合作者在編程中的實(shí)際情況和切身體會(huì ),提出在編程時(shí)要注意以下幾點(diǎn):
(1) 必須保護任何被函數修正的專(zhuān)用寄存器。這些專(zhuān)用寄存器包括:AR1,AR6,AR72和堆棧指針(SP)。其中,如果對SP正常使用,則不必明顯的保存。換句話(huà)說(shuō),只要匯編函數在調用返回時(shí)彈出壓入的對象,實(shí)際上就已經(jīng)保護了SP。
(2) 中斷函數必須保存其使用的所有寄存器。
(3) 從匯編函數中調用C函數時(shí),第一個(gè)參數(最左邊的)必須放入累加器A中,剩下的參數按照自右向左的順序壓入堆棧。
(4) 如果函數有返回值,則返回值存放在累加器A中。
(5) 調用C函數時(shí),注意C函數只保護了幾個(gè)特定的寄存器,對于其他寄存器C函數是可以自由使用的。
(6) 長(cháng)整數和浮點(diǎn)數存儲在存儲器中的方法是最高有效字在低位地址。
(7) 匯編語(yǔ)言模塊不能改變由C模塊產(chǎn)生的.cinit段,如果改變其中的內容將會(huì )引起不可預測的后果。
(8) 在匯編語(yǔ)言模塊中,對可以從C中訪(fǎng)問(wèn)的變量和函數名需加上前綴“_”。對于僅用于匯編語(yǔ)言模塊中的標識符,不用加下劃線(xiàn)。而且如果僅在匯編中使用,只要不加下劃線(xiàn),即使與C程序中定義的對象名相同,也不會(huì )造成沖突。
(9) 任何在匯編語(yǔ)言模塊中聲明的將要從C訪(fǎng)問(wèn)或調用的對象或函數,都必須在匯編語(yǔ)言中用.global偽指令聲明為全局變量。同樣,任何在C程序中定義而將在匯編中訪(fǎng)問(wèn)或調用的對象或函數,在匯編中也必須用.global聲明。
(10) 在默認的情況下,編譯器總是認為CPL為1。因此,若在匯編程序中將CPL清0,則在返回C環(huán)境時(shí),必須將其恢復為1;在默認的情況下,編譯器總是認為 OVM為0。因此,若在匯編程序中將OVM置為1,則返回C環(huán)境時(shí),必須將其恢復為0;ARP在函數進(jìn)入和返回時(shí),必須為0,即當前輔助寄存器為AR0。函數執行時(shí)可以為其他值。 {{分頁(yè)}}
3 編程實(shí)例
3.1 FFT算法簡(jiǎn)介
FFT是一種高效實(shí)現離散傅立葉變換的算法,在數字信號處理系統中,FFT作為一個(gè)非常重要的工具,甚至成為DSP運算能力的一個(gè)考核因素。如何將FFT算法很好的應用到DSP系統中對于DSP系統的設計具有重要的意義。
一個(gè)優(yōu)化的實(shí)數FFT算法是一個(gè)組合以后的算法。該算法主要分為以下幾步,首先將輸入的2N點(diǎn)實(shí)序列進(jìn)行位倒序組合成一個(gè)N點(diǎn)的復序列,之后對復序列進(jìn)行N 點(diǎn)的FFT運算,最后再由N點(diǎn)的復數輸出拆散成2N點(diǎn)的復數序列,這2N點(diǎn)的復數序列與原始的2N點(diǎn)的實(shí)數輸入序列的DFT輸出一致。(詳細的算法介紹可參考相關(guān)信號處理書(shū)籍)。
3.2 C主程序
#include "stdlib.h"
extern void fft(); // FFT運算函數
int DisData[256]; // 輸出結果
int SimData[256]={
0,6270,11585,15137, 16384, 15137, 11585,6270,
0, -6270, -11585,-15137,-16384,-15137,-11585,-6270,
……
0,6270,11585,15137,16384,15137,11585,6270,
0,-6270,-11585,-15137,-16384,-15137,-11585,-6270
};
// 輸入數據
int main()
{
rfft();
// 調用FFT函數
while(1) ;
}
本程序中FFT運算所用到的數據是通過(guò)matlab仿真產(chǎn)生的,然后通過(guò)全局數組進(jìn)行傳值,這種方式的優(yōu)點(diǎn)是數據的通用性強,方便對數據進(jìn)行其他相關(guān)處理; 也可通過(guò)其他C程序產(chǎn)生然后保存到一個(gè)文本文件中,再由匯編程序將該數據文件拷到數據存儲器中參與FFT運算。這種方式的優(yōu)點(diǎn)是程序的可讀性強,缺點(diǎn)是當輸入數據修改后,必須進(jìn)行重新編譯、匯編和鏈接。
3.3 匯編程序
.mmregs
.global sav_sin,sav_idx,sav_grp,_rFFT,_DisData
.data
DATA .space 1024 ;數據緩沖區
INPUT .set 0x9000 ;輸入數據起始地址
N .set 128 ;復數點(diǎn)數
LOGN .set 7 ;碟形運算級數
sav_grp .usect "tempv",3 ;定義組變量值
sav_sin .set sav_grp+1 ;定義旋轉因子表
sav_idx .set sav_grp+2
.copy "twiddle1.inc" ;正弦表系數
.copy "twiddle2.inc" ;余弦表系數
.text
_rfft:
SSBX TC
SSBX C
RSBX OVA
RSBX OVB
LD #0,DP
RSBX CPL
SSBX XF
SSBX SX
M
LD #00,ASM
SSBX FRCT
…… {{分頁(yè)}}
本程序主要是對輸入的256點(diǎn)實(shí)數作FFT運算,通過(guò)修改N和LOGN可以完成16-1024點(diǎn)的FFT運算。在編寫(xiě)匯編程序的時(shí)候要注意以下幾個(gè)方面:
(1) 由于采用循環(huán)尋址來(lái)對旋轉因子表尋址,因此每張表的開(kāi)始地址必須是10個(gè)LSB位為0的地址。如:正弦表系數可以放在0400h開(kāi)始的地址,余弦表系數可以放在0800h開(kāi)始的地址;
(2) 在匯編程序的入口處要注意設置好匯編程序所需要的運行環(huán)境(見(jiàn)前述程序),如果此處按照編譯器默認的環(huán)境將得不到正確的結果。詳細的匯編程序可參考TI公司提供的例程。
3.4 運算結果
輸入正弦信號的頻率為f=16Hz,幅值為1(單位),采樣長(cháng)度為2N=256點(diǎn),采樣頻率為fs=256Hz。CCS提供了很多方法將程序產(chǎn)生的數據畫(huà)圖顯示,包括時(shí)域/頻域波形顯示等??赏ㄟ^(guò)查看相關(guān)圖像來(lái)檢驗FFT運算的正確性。由鏈接命令文件可以知道輸入信號存儲在程序存儲區0900h開(kāi)始的256 個(gè)單元中,經(jīng)程序計算得到的信號幅值譜存放在數據存儲區0200h開(kāi)始的256個(gè)單元中。在CCS中選擇View——>Graph——> Time/Frequency命令,相關(guān)設置可參考圖1:
圖1 FFT運算結果查看選項設置參考
輸入信號的時(shí)域波形見(jiàn)圖2。
圖2 輸入信號的時(shí)域波形
經(jīng)FFT運算后得到的信號幅值譜圖見(jiàn)圖3。
圖3 信號幅值譜圖
將輸入信號通過(guò)Matlab仿真進(jìn)行驗證。輸入信號的時(shí)域波形見(jiàn)圖4。 {{分頁(yè)}}
圖4 輸入信號的時(shí)域波形
經(jīng)FFT運算后得到的信號幅值譜圖見(jiàn)圖5。
圖5 信號幅值譜圖
通過(guò)比較CCS中的輸出圖形和Matlab中的仿真輸出圖形, 可以看到二者是一致的,說(shuō)明本程序的結果是正確的。
4 結束語(yǔ)
本文通過(guò)實(shí)例,說(shuō)明了TMS320 C5000系列DSP芯片的混合編程方法,利用混合編程達到了提高程序的可讀性與編程效率的目的,是開(kāi)發(fā)DSP軟件的常用方法。本文介紹的混合編程方法不但適用于TI C5000系列DSP芯片,同樣也適用于TI其他系列的DSP芯片,如C2000系列、C6000系列,甚至對其他芯片,如51系列單片機等,實(shí)現混合編程也有很大參考價(jià)值。
評論