DSP[1](DigitalSignalProcessor)自從誕生以來,由于其在數字信號處理方面專用的結構和硬件邏輯,比如,處理器使用不同于普通處理器的哈佛結構,獨特的桶型移位器等,使其在某些特定的領域的應用得到了飛速的發展。DSP在某些功能上與普通的嵌入式處理器相似,因而通常以傳統嵌入式處理器編程的方法來編程,即,使用C語言和匯編語言混合編程,直接訪問硬件外設,并且由于性能的原因,總是很少使用標準操作系統的支持。這樣,像傳統的微處理器一樣,幾乎沒有零售的DSP中間件可用。然而,DSP又不同于通用的嵌入式處理器,他是用來運行復雜的信號處理算法的。這些成熟的算法通常是多年的博士研究的成果。
由于DSP算法缺乏統一的標準,算法從一個系統移植到另外一個系統時,或一種算法要應用于多個系統中時,通常要做很大的改動。算法的繼承性和重用性都很差,因此基于DSP的產品上市時間往往以年,而不是以月來計算。對一個產品開發商來說,不可能僅從一個算法開發商那里購買全部所需的DSP算法;另一方面不同算法開發商的算法產品由于實現風格不同,相互不兼容。因此,常常出現這樣的情況,系統集成商不得不選擇能提供他們所需的大部分算法的算法開發商,并與他們談判來開發所需的其他算法。
為改變這種狀況,TI公司推出了一套編寫和使用DSP算法的標準,讓系統集成商可以快速集成和使用已有的商用DSP算法軟件,可以大大減少基于DSP產品的上市時間。
2 DSP算法標準的相關背景和概念
2.1 通用算法的特征
由于DSP應用十分廣泛,支持數字信號處理器的平臺或操作系統又很多,這些復雜的平臺對于算法標準就提出了很高的要求。一個算法要真正實現“即插即用”或應用于多種操作系統,他必須具備幾個基本的特征。
(1)算法對于應用程序透明,相同的算法可以用于任何應用程序。
(2)算法既能用于靜態系統,又能用于動態系統。
(3)算法必須能用二進制形式分發,即能以目標文件發行。
(4)算法既能用于單任務,也能用于多任務,即
(5)算法的使用不需要重新編譯,但可以重新連接和配置。
(6)算法是C語言可調用的。
(7)算法獨立于任何特殊的I/O設備。
算法要具有上述特征,在編碼上就必須遵循一定的規范,在處理器資源的使用上,也必須作一些限制,這些規范和限制就是算法標準。有關算法標準的詳細規定,可參閱文獻[1]。
2.2 算法標準的分級
在算法標準出來之前,DSP算法開發商已開發了大量的算法,有些算法在一定程度上遵循了標準;有些算法由于應用領域的不同,移植(指相同DSP,不同軟件平臺)時的限制不同,這就提出了算法標準的等級問題。通常算法標準分為4級,每一級標準對算法編寫的要求和限制不同,級數越高,限制越嚴格,其中第4級是具體到各種特殊行業的。比如,語音編碼器有語音編碼器的行業標準和特征;電機控制算法有電機控制方面的特殊要求等等,如此細致的規定不可能上升為通用的標準,所以通用的算法只要遵循前三級即可。下面是各等級分別包含的范圍:
第1級 包含適用于各種DSP結構,而不管應用領域的各種算法的編程準則。幾乎所有近來開發的軟件模塊都已經遵循了這些準則,所以該級別只是將他們規范化。
第2級 包含可使所有算法和諧運行于單一系統的編程規則和準則。例如,約定用于數據內存算法和外部標示的統一命名等。此外,還規定了算法如何封裝的規范。
第3級 包含具體DSP系列的算法編程準則。如C54XX,C6X等。現在關于處理器資源的使用還沒有統一的準則。由于不同的DSP結構不同,因而總有偏離準則的情況,標準要求算法提供商必須清楚地在相關頭文件和文檔中標注這種偏差。
2.3 基于DSP算法標準的通用軟件結構和相關概念
算法標準如何在實際中應用,TI公司給出了一個通用的軟件編程思路。將一個基于DSP的軟件分成了若干模塊,每一個模塊都有嚴格的定義,使得模塊之間有明確的界線。圖1是一個基于主機-目標機的軟件結構圖(圖中主機端沒有畫出)。從中可以清楚地看到通用的DSP程序分為4個部分:FrameWork,ALG,Core run time Support,CMDand Status。
FRAMEWORK為應用程序框架,是一些支持 DSP運行的平臺或操作系統,例如pSos,vxworks,UC-OS-II等;ALG為獨立于處理器的DSP算法;Core run time support為運行支持內核,例如rts54.lib等;ALG為獨立于處理器的DSP算法; Core run time support為運行支持內核,例如rts54.lib等;CMD為主機發給目標機的命令,Status為目標機返回給主機的狀態信息。主機和目標機模式只在開發狀態或某些控制場合使用,大部分的DSP軟件都是獨立于主機運行的。所以我們只討論獨立于主機的工作模式,下面分別詳細討論上述幾方面的作用和相互關系。
(1)應用框架(FrameWork)
應用框架通常是一個與設備相對獨立的I/O子系統,即他提供一個通用的I/O接口,并規定算法和應用程序如何使用這個接口。所有可能的外設都以接口形式存在,算法通過框架提供的接口訪問外設。典型的應用框架就是操作系統。例如,Windows操作系統,應用程序不能直接訪問串口、并口等外設,只能通過Windows操作系統提供的API(應用程序接口)與外設相互作用。任何外設只要提供接口(驅動程序)就可以接入操作系統。
在DSP和微處理器領域,的應用框架就是Wind River公司的pSos和VxWorks操作系統。有些應用框架由于應用領域的不同或者應用方案比較簡單,僅僅提供一些基本的I/O功能,難以稱為操作系統。例如,CCS(Code Compose Stdio)中嵌入的DSP/BIOS(基本輸入輸出系統)實時內核。框架的基本功能就是提供數據出入的接口。
此外,框架還定義了內部應用模塊的等級,也就是操作系統中任務的優先級。通過優先級,框架可以實現對模塊的控制,比如中斷模塊或恢復模塊的運行,或決定哪個模塊先運行,這就是操作系統中所謂的任務調度。
應用框架負責I/O接口和任務的調度,實質上就是基于硬件平臺之上的軟件平臺。
(2)算法(ALG)
算法是一種純粹的數據變換器,只是簡單地接收 94和處理輸入的數據。算法獲取數據通常有兩種方法,這兩種方法均離不開應用框架的支持。一種是中斷輸入方式,算法通過應用框架的中斷服務函數獲得數據;一種是查詢方式,應用框架提供一個周期性的函數,通過該函數周期性地在某個端口獲得數據。在所有情況下,算法在系統中被設計成獨立于I/O設備的。即,算法不能直接訪問外設寄存器的地址,也就是在算法中不能出現外設的物理地址,只能通過指針參數或模塊接口指針將地址傳到函數中。
這一實現通常要依靠一個I/O接口模塊。通過這種方法,可以減小對框架的依賴,提高算法的通用性。一個算法可以有多種實現,實現方法的不同意味著性能的不同,的算法實現代碼短小,執行效率高。而這兩者通常不可兼得,執行效率的提高,通常以增加代碼長度為代價,這意味著需要更多的存儲空間。反之,算法實現代碼小,執行性能通常會降低。同時,不同的算法實現價格也不相同。這給了算法集成商或開發商更多的選擇余地。
當然,性能和算法的這種折衷,必須以遵循算法標準為前提,不然,算法不可相互“替換”,算法的多個實現也就失去了意義。
(3)運行支持內核
為了使算法滿足可重入、與I/O外設獨立以及可調試性的小需求,算法需要一系列總是穩定存在的內核服務。比如C語言運行支持內核。該內核提供基本的打印函數printf()、內存管理函數memcpy()、字符串函數、時間函數等標準C語言的基本運行環境。該內核的相關的函數經過封裝,形成一個支持庫rtsxx.lib。xx代表處理器的類型。
由于大部分的算法仍舊是用匯編語言生成的,內核提供的許多服務也必須適合匯編語言,并能用其訪問。這也是標準C語言和匯編語言能夠混合編程的基礎。TIDSP運行支持內核還包含一個DSP/BIOS的子集,提供基本輸入輸出功能,該功能比標準C的基本輸入輸出函數執行速度快。此外,還附帶一些對控制和狀態寄存器微小操作的子集,例如,設置溢出模式等。
算法、應用框架、運行支持內核各自的代碼相對獨立,相互作用,共同協作構成一個有效的應用軟件。他們之間有各自的界線,在標準中有各自定義的功能范圍。算法只有相對獨立于應用框架和運行支持內核,才能支持“即插即用”,才能在無需大量修改源代碼的情況下,用一種算法替代另一種算法。
3 通用算法標準
TIDSP算法標準包括許多規則和準則。一種算法為了實現與遵循標準的其他算法相兼容,必須遵循算法標準規則,同時為了便于程序的可讀性和維護,也強烈要求遵循算法編寫準則。算法標準共有34條規則和若干條準則,詳細情況請參閱文獻[1],筆者著重討論算法標準中有關多任務的規定。
規則1 所有的算法必須遵循由于使用C編程語言而帶來的運行時約定。
該規則并不要求算法必須用C語言實現,實際上算法可以完全用匯編語言實現。但是,算法必須能在C語言中調用,同時,也必須遵循C語言的運行時約定部分重要的算法都不是僅用一個函數實現的,同其他復雜的軟件一樣,算法軟件也是由許多內部函數組成。這些內部函數不必全部遵循C語言的RTC,只需頂層的接口函數遵循C語言的RTC即可。同時,也要保證接口函數不會通過調用內部函數改變C語言的RTC。
規則2 所有的算法在一個占先的環境下(包括時間片占先)具有可重入性。
該規則比較抽象,需要先了解幾個概念才容易理解。
“重入性”是一個程序的屬性,他允許多個線程同時使用程序的相同拷貝。簡而言之,代碼不具有記憶性,相同的輸入參數不論在什么情況下得到的函數結果都相同。
“占先[2]”是指應用框架或操作系統具有依據模塊或任務的優先級決定模塊是否能被中斷,并進行相應調度的能力,或指代碼是否能被中斷的特性。
由于應用框架的多樣性,代碼的可重入性變的十分復雜。硬件平臺有單通道、多通道之分,應用程序有多線程、多進程、多任務之分,應用框架有占先(又叫搶先)式環境和非占先式(常常指時間片輪訊)之分。在非占先環境中,算法函數可以自由地使用全局變量,不用擔心由于函數在運行中被中斷,從而造成的全局變量數據的混亂。在占先的環境下,如果在算法函數內部使用了全局變量,并且函數修改了該全局變量的值,則該函數不具有重入性。由于算法自身并不能知道所應用的環境的“占先性”,所以算法必須保證在所有的情況下,算法具有可重入性。實際中,算法是否具有可重入性的檢查比較困難,因而,這需要算法開發人員遵循3條準則:
一是算法只能修改堆棧中的或者實例對象的數05據;
二是算法視全局數據和靜態數據為只讀數據;三是算法不能調用可自我修改的代碼。
在多線程和多任務下,還可通過禁止中斷的方法,禁止任務的占先,來保證滿足函數的可重入性。
規則3 算法數據的引用必須是完全可重新定位的。也就是算法中不能有“硬編碼”出現。
因為DSP應用程序在生成可運行代碼時,必須進行連接,在連接中對DSP代碼進行存儲空間分配,所以一個算法如果要順利接入另一個系統,算法必須能夠重新定位。這就要求算法中不能有“硬編碼”存在。
所謂硬編碼,就是一個具有具體的物理地址的代碼。算法中一旦有了硬編碼,導致代碼只能固定位于某一塊或訪問某一塊內存,將使該算法不能重新定位,失去了可移植性。算法中對數據內存的訪問,可以通過連接命令文件,定義一個符號,指向某一內存區域,當應用程序需要將算法重新定位時,只在命令文件中修改符號指向的內存地址即可。
以上介紹的是多任務算法編程中相對重要的規定,限于篇幅,其他規定請參閱文獻[1]。
4 算法標準在實際中的應用
筆者的硬件開發平臺是基于2片TMS320VC5402 DSP的自研發板,軟件開發平臺是TI公司的CCS2.0,所有的算法使用ANSIC語言編寫,框架應用程序使用C語言和匯編語言的混合編程,算法先通過軟仿真調試,再進行硬仿真在線實時調試,終的算法將成為通用的算法,可移植到其他的數字信號處理器上。基于上述思想,軟件從算法標準的角度做了如下整體設計:
(1)軟件算法和框架應用程序相對獨立。即,框架應用程序是一個相對獨立的模塊,從AD轉換器數據的采集、中斷的調用都屬于框架應用程序的工作;算法僅對采集到的數據處理。算法是一個相對獨立的模塊。
(2)每一個算法都有一個頭文件(.h)和一個實現文件(.C),整個算法模塊有一個算法接口模塊。算法頭文件支持重復包含功能,即頭文件中用預處理指令做了防多重進入處理(#ifndef...#define...#endif)。
(3)所有對片內存儲器的訪問都定義了相應的寄存器指針或結構指針,并通過參數傳入應用程序,算法和程序函數中不出現具體的寄存器地址,有效防止代碼中有“硬編碼”。
(4)全局變量如果是只讀屬性,即,只讀取而不改變全局變量的值,則可以在函數中直接使用,否則,只能通過指針傳入函數,函數體中禁止直接修改全局變量的值,保證了函數的可重入性。
(5)串口和DMA的操作有自己相應的接口文件,算法通過調用接口函數進行外設操作。串口和DMA等外設的操作由框架應用程序控制。
遵循DSP算法標準,對動態系統會有一些性能下降,但對靜態系統沒有顯著的影響,筆者的系統采用的是靜態方法,因而在實際系統中,性能改變不太明顯。
5 結 語
TIDSP算法標準的出現,無論對算法提供商還是對算法集成商來說,在技術上都是一個進步。對目前繁雜的算法編寫和市場應用是一個很好的規范,為DSP算法的開發和使用提供了一個較為行之有效的標準。相信隨著DSP的算法標準的逐漸推廣,市場上DSP算法組件會越來越多,DSP的應用會越來越廣泛。
參考文獻
[1] TMS320 DSPAlgorithmStandard Rules andGuidelines.Texas Instruments Incorporated,2001.源碼公開的實時嵌入式操作系統[M].北京:中國電力出版社,1999.