用RTDX實(shí)現數據的實(shí)時(shí)雙向傳輸
2004年8月A版
摘 要:講述實(shí)時(shí)數據傳輸(RTDX)的使用,描述一個(gè)用RTDX雙向傳遞大量多媒體數據的實(shí)現方法。該方法可以方便的應用于其他TI DSP的系統設計中。
關(guān)鍵詞:TI DSP;RTDX
引言
TI DSP在數字電路中作為信號處理、電路控制的核心設備,廣泛應用于各個(gè)行業(yè)。在TI DSP系統設計階段,實(shí)時(shí)數據交換(RTDX)提供了一種目標板和主機之間的雙向實(shí)時(shí)數據傳輸的方法。它可以應用于大量數據的雙向傳輸,例如應用在多媒體數據進(jìn)行仿真處理中。但是由于它的實(shí)現難度較大以及不處于系統設計的核心位置,所以沒(méi)有得到廣泛使用。本文的目的是向讀者描述一種RTDX的具體實(shí)現。
RTDX的使用方法
RTDX提供了目標板與主機之間的實(shí)時(shí)數據通信。當系統使用該功能時(shí),DSP上駐留一個(gè)小的RTDX片上軟件庫,片上程序通過(guò)調用這個(gè)軟件庫的API實(shí)現JTAG與主機之間的數據傳輸。與DSP目標板相連的主機上也存在一個(gè)相應的RTDX主機端軟件庫,客戶(hù)編寫(xiě)的主機端程序通過(guò)對象嵌入,實(shí)現DSP目標板的實(shí)時(shí)數據分析,以及向目標板提供新的數據。
在編寫(xiě)DSP的軟件上,RTDX的使用方式和C語(yǔ)言文件的IO操作非常相似,如圖1、2所示,在實(shí)現數據由DSP到主機的過(guò)程中,首先聲明一個(gè)RTDX輸出通道,然后對該通道進(jìn)行操作,最后查詢(xún)狀態(tài),看數據是否被發(fā)送出去;而從主機端到DSP端的數據傳輸過(guò)程中,則聲明一個(gè)RTDX輸入通道,然后讀取該通道上的數據。
在主機端,TI 提供的RTDX庫使用了微軟公司的COM技術(shù),數據的傳輸過(guò)程分別如圖3、圖4所示。
用RTDX實(shí)現多媒體數據的
雙向傳輸
多媒體數據原始信息往往擁有極大的數據量,DSP在多媒體數據處理中的應用主要是壓縮和解壓縮,但由于DSP自身的限制,它沒(méi)有大量的空間存儲多媒體數據,即便這些數據是已經(jīng)被壓縮過(guò)的。在系統的調試階段,如何單獨測試DSP的編碼效率呢?一種可行的解決辦法就是借用DSP目標板相連的主機空間,用RTDX把原始數據傳遞給DSP,DSP對數據處理后再通過(guò)RTDX傳回主機。
系統的整體構架
由于DSP片上存儲空間有限, TI對RTDX一次在主機和目標DSP之間傳輸的數據長(cháng)度做了限制,此值不應該超過(guò)253個(gè)字長(cháng)為16bit的數據,如果一次傳輸的數據量超過(guò)253,則要對數據分片傳遞。本應用中每次傳遞的數據遠遠大于253,所以主機端和目標板都定義了分片長(cháng)度RTDXBLOCK,RTDXBLOCK=200。傳輸時(shí)兩邊同時(shí)進(jìn)行相反的工作,目標板寫(xiě)數據的時(shí)候主機等著(zhù)讀數據,主機寫(xiě)數據的時(shí)候目標板進(jìn)行相反的操作。每傳輸RTDXBLOCK大小的數據,兩者的工作進(jìn)行交換。分段傳遞數據還帶來(lái)了很多好處,它可以方便主機與目標板之間的同步,每次數據的發(fā)出也是對上一次收到數據的應答;RTDX的特性是讀一個(gè)字節,寫(xiě)一個(gè)字節,讀寫(xiě)采用相同大小段節省了將近一半的時(shí)間;inbuffer與outbuffer可以指向相同的地址,又節省了一些內存。
采用相同大小的段傳輸數據還有一些細節問(wèn)題要考慮,目標板的第一次操作是否應該先是寫(xiě)出?以便空出地方來(lái)接收下一次被處理的數據。由于每次傳輸數據總量的不對稱(chēng)性,大部分情況下是輸入的數據比輸出的數據多,目標板先寫(xiě)出數據會(huì )多占用一次傳輸的時(shí)間。另一個(gè)問(wèn)題就是數據總量的不對稱(chēng)性,總是主機或目標板先寫(xiě)完數據,只剩下某一種操作,這部分時(shí)間沒(méi)有辦法節省。
對于數據傳遞過(guò)程中可能傳送的一些命令字如,跳過(guò)當前幀、程序終止等。做了這樣的考慮,由主機和目標板主程序來(lái)填寫(xiě)和解釋這些命令字,命令字不單獨傳輸,本應用中放在inbufferoutbuffer的第0個(gè)位置,與下一塊數據同時(shí)傳送。另外,本應用中inbuffer與outbuffer的第1個(gè)位置存放的是數據段的實(shí)際長(cháng)度,常用于向主機端指示壓縮后數據的實(shí)際長(cháng)度,以便用于不定長(cháng)壓縮方式的數據輸出。inbuffer/outbuffer的實(shí)際數據的起始位置是可以根據應用自定義的。傳輸程序不負責這些問(wèn)題,只管從buffer的第一個(gè)字節開(kāi)始傳輸數據。
軟件設計
DSP片上實(shí)現了一次數據輸入輸出的函數dataIO,它采用C語(yǔ)言編寫(xiě),返回值1表示運行過(guò)程均正常。有4個(gè)參數,分別是輸出Buffer起始位置,輸出Buffer的大小,輸入Buffer的起始位置,輸入Buffer的大小。使用時(shí),在主函數中使用兩個(gè)RTDX宏聲明:RTDX_CreateOutput Channel(ochan),RTDX_CreateInput Channel(ichan),然后可以直接調用dataIO進(jìn)行數據傳輸,dataIO會(huì )在第一次運行中自動(dòng)初始化環(huán)境。如圖7所示。dataIO函數經(jīng)過(guò)簡(jiǎn)單的修改甚至不修改即可以適用于不同的環(huán)境。
主機端的RTDX過(guò)程使用C++實(shí)現,因為程序的主要目的就是向目標板傳遞數據和取得數據,所以直接在主程序中作了一個(gè)大的循環(huán),同目標板一樣用了4個(gè)參數:inbuffer,outbuffer,inbufferlength,outbufferleng。執行時(shí),主程序首先被阻塞,不停的試圖從目標板讀取經(jīng)過(guò)壓縮的數據,直到目標板DSP把壓縮好的數據放到輸出通道上。得到數據后,主程序把這些數據存放在本地文件中,然后把要壓縮的數據寫(xiě)到輸入通道上傳遞給DSP。這樣反復執行直到傳輸雙方中的一方表示傳輸終止。
執行過(guò)程
首先把程序寫(xiě)入目標板DSP中,然后在DSP集成開(kāi)發(fā)環(huán)境CCS的tools菜單中選擇RTDX,啟用輸入通道和輸出通道。先后運行DSP程序和主機端程序即可實(shí)現數據的雙向傳輸。因為兩邊都使用了阻塞機制,所以程序運行的先后順序無(wú)所謂。
結語(yǔ)
本應用實(shí)現了如下功能:主機端把44.1KHz,16bit采樣的音頻數據傳遞到DSP內存中,每次傳遞1152個(gè)數據。DSP對這些數據進(jìn)行Mp3格式的壓縮,壓縮后的數據長(cháng)度不確定,最后DSP把這些數據傳回主機端,然后等待下一次傳輸開(kāi)始。實(shí)現基于DSK5416,用CCS2.0作為DSP綜合開(kāi)發(fā)環(huán)境。主機端程序用MS VC6.0編譯。
這種RTDX的實(shí)現方法用于2003年德州儀器公司數字信號處理大學(xué)挑戰賽決賽項目“使用TMS320C547X實(shí)現多媒體數據在TCP/IP網(wǎng)絡(luò )傳輸”的設計中,該項目最終獲得大賽三等獎。
參考文獻:
1. 彭啟琮,‘TMS320C54x 實(shí)用教程’ ,電子科技大學(xué)出版社,1999
2. 張雄偉、陳亮、徐光輝,‘DSP集成開(kāi)發(fā)與應用實(shí)例’,電子工業(yè)出版社,2002
RTDX_CreateOutputChannel( ochan ); //創(chuàng )建一個(gè)輸出通道,該操作為宏操作
...
TARGET_INITIALIZE();
RTDX_enableOutput( &ochan ); //初始化目標板以及通道使能
...
status = RTDX_write( &ochan, outp , RTDXBLOCK );
//發(fā)送outp指針所指數據到輸出通道,數據長(cháng)度由RTDXBLOCK指定,返回實(shí)際發(fā)送的數據長(cháng)度*
*:數據長(cháng)度指類(lèi)型為發(fā)送數據類(lèi)型轉換為16位無(wú)符號所占長(cháng)度,outp的數據類(lèi)型也應為16位無(wú)符號數。
圖1 目標板向主機輸出數據
RTDX_CreateInputChannel( ochan ); //創(chuàng )建一個(gè)輸入通道,該操作為宏操作
...
TARGET_INITIALIZE();
RTDX_enableInput( &ochan ); //初始化目標板以及通道使能
...
status = RTDX_read( &ichan, inp, RTDXBLOCK )
//發(fā)送inp指針所指數據到輸出通道,數據長(cháng)度由RTDXBLOCK指定,返回實(shí)際接收的數據長(cháng)度*
*:數據長(cháng)度指類(lèi)型為發(fā)送數據類(lèi)型轉換為16位無(wú)符號所占長(cháng)度,inp的數據類(lèi)型也應為16位無(wú)符號數。
圖2 目標板從主機端獲取數據
hr = rtdx_in.CreateInstance( __uuidof(RTDXINTLib::RtdxExp) ); //創(chuàng )建rtdx實(shí)例
status = rtdx_in->Open( "ichan", "W" ); //創(chuàng )建ichan ,以便向目標板輸入數據*
status = rtdx_in->Write( sa, &bufferstate); //把安全數組sa**中的數據寫(xiě)入目標板
status = rtdx_in->Close(); //關(guān)閉輸入通道
*:讀寫(xiě)狀態(tài)標志"W"應該大寫(xiě),否則會(huì )帶來(lái)不可預知的錯誤。
**:在寫(xiě)入數據時(shí),應該把要寫(xiě)入的數據放在一個(gè)安全數組中。然后調用Write。
圖3 主機端向目標板傳輸數據
hr = rtdx_out.CreateInstance( __uuidof(RTDXINTLib::RtdxExp) ); //創(chuàng )建rtdx實(shí)例
status = rtdx_out->Open( "ochan", "R" ); //創(chuàng )建ochan ,以便從目標板獲取數據
status = rtdx_out->ReadSAI2( &sb ); //把目標板上的數據寫(xiě)入安全數組sb*,**
status = rtdx_out->Close(); //關(guān)閉輸出通道
*:從目標板讀取的數據首先被放在安全數組中,然后由使用者讀出。
**:可以根據目標板的數據格式,通過(guò)調用ReadSAI1,ReadSAI2,ReadSAI4,讀取所占字節數不同的數據。例如讀取占用4個(gè)8位字節的word類(lèi)型數據,應該使用ReadSAI4。
圖4 主機端從目標板獲取數據
圖5 輸入輸出Buffer的數據格式
圖6 主機端與目標板的數據傳輸過(guò)程圖
int dataIO(unsigned int * inbuffer,
unsigned int * outbuffer,
int inbuffer_length,
int outbuffer_length);
int main()
{ unsigned int inbuffer[FLUSH+2];
unsigned int outbuffer[FRAME+2];
while(1)
{
if (dataIO(inbuffer,outbuffer,FLUSH+2,FRAME+2)!=1)
return;
encode();/*進(jìn)行數據處理*/
}
}
圖7 經(jīng)過(guò)封裝的RTDX函數
評論