RF5架構(gòu)簡(jiǎn)介 RF5是德州儀器TI公司新近推出的DSP軟件開(kāi)發(fā)的起步代碼參考框架,它以DSP/BIOS為基礎(chǔ),利用其中的數(shù)據(jù)處理元素和數(shù)據(jù)通信元素方便快捷地完成DSP軟件的設(shè)計(jì)與開(kāi)發(fā)。RF5是RF的最新版本,其區(qū)別于RF1和RF3的顯著特點(diǎn)是其支持動(dòng)態(tài)對(duì)象創(chuàng)建和支持線程(任務(wù))掛起功能,因此適合系統(tǒng)較復(fù)雜的應(yīng)用場(chǎng)合。 RF5 主要實(shí)現(xiàn)三個(gè)功能,存儲(chǔ)管理,線程模型和通道封裝,對(duì)于不同的應(yīng)用,我們只需在這三個(gè)元素上做修改,而對(duì)于整個(gè)應(yīng)用程序,不用從頭設(shè)計(jì),這樣大大簡(jiǎn)化了開(kāi)發(fā)者的開(kāi)發(fā)難度,縮短了開(kāi)發(fā)時(shí)間。
RF5適用于包含大量的算法,且要求多線程,多通道的應(yīng)用,如圖像處理,多媒體應(yīng)用等,以Ti提供的實(shí)例mpeg2loopback為例,對(duì)RF5進(jìn)行分析。
RF5包含的元素有:
1 線程(Thread):
RF5框架包含四個(gè)基本的數(shù)據(jù)處理元素,處在最頂層的是線程,線程總是順序的執(zhí)行所包含的通道,線程在一個(gè)比較高級(jí)的級(jí)別上把數(shù)據(jù)組織在一起,他們可以與別的線程,設(shè)備驅(qū)動(dòng)以及別的類似結(jié)構(gòu)進(jìn)行通訊,在mpeg2lookback實(shí)例中,創(chuàng)建了三個(gè)線程分別是tskVideoInput, tskVideoOutput和tskProcess。每個(gè)線程都在不斷的等待消息,處理數(shù)據(jù),并將結(jié)果發(fā)送給其他的線程,同時(shí)有可能還要發(fā)送同步消息給其他線程以實(shí)現(xiàn)線程間的通訊,這里使用的機(jī)制是SCOM模塊。
每個(gè)線程都是進(jìn)行數(shù)據(jù)處理的一個(gè)單元,有的處理是簡(jiǎn)單的,有的處理是相對(duì)復(fù)雜的過(guò)程,簡(jiǎn)單的線程可以不包括任何的通道,而進(jìn)行復(fù)雜數(shù)據(jù)處理的線程有可能包含多個(gè)的通道。
2 通道(Channel):
RF5提供了一種通道結(jié)構(gòu)是為了更方便的封裝算法,這可以理解通道為并行里的串行,因?yàn)榫程的執(zhí)行就是由通道的串行執(zhí)行來(lái)完成的,一個(gè)通道包含一組核(Icell)。其主要任務(wù)就是依次順序的執(zhí)行所包含的核,主要執(zhí)行的流程為:首先需要初始化通道模塊,然后建立通道對(duì)象,注冊(cè)該通道所包含的核對(duì)象,接著依次執(zhí)行每個(gè)核,執(zhí)行完成了后就銷毀對(duì)象,最后退出。每個(gè)通道可以包含多個(gè)核,每個(gè)核都要進(jìn)行初始化后再調(diào)用CHAN_regCell注冊(cè)。
通道對(duì)象的結(jié)構(gòu)如下:
typedef struct CHAN_Obj {
ICELL_Obj *cellSet; /* set of cells in the channel */
Uns cellCnt; /* number of cells in the cellSet */
CHAN_State state; /* state of the channel */
Bool (*chanControlCB)(CHAN_Handle chanHandle); /* optional control function */
} CHAN_Obj;
線程一般不定義通道對(duì)象,但是在CHAN_open()調(diào)用中初始化它們。CHAN_open()的最后一個(gè)參數(shù)是通道屬性(CHAN_Attrs)結(jié)構(gòu)體的地址。如果最后一個(gè)參數(shù)是NULL,那么CHAN_open()使用默認(rèn)的參數(shù)。如果要想使用不同的參數(shù),就要聲明一個(gè)CHAN_Attrs的結(jié)構(gòu)體,并需初始化為CHAN_ATTRS宏所定義的初值,然后根據(jù)需要可以修改其中相應(yīng)的域的值。通常,其中的通道狀態(tài)參數(shù)CHAN_State state域默認(rèn)為CHAN_ACTIVE,通道控制回調(diào)函數(shù)參數(shù)域Bool (*chanControlCB)(CHAN_Handle chanHandle)默認(rèn)為NULL。如果通道控制回調(diào)函數(shù)不是空,那么在任何的cell調(diào)用執(zhí)行之前都會(huì)先調(diào)用此回調(diào)函數(shù)。
一個(gè)典型的設(shè)置:一個(gè)線程為每一個(gè)通道建立一個(gè)CHAN_Obj對(duì)象(或者一組類似的對(duì)象),并且為每一個(gè)cell建立一個(gè)ICELL_Obj對(duì)象(或者是與每個(gè)通道相對(duì)應(yīng)的一組ICCE_Obj對(duì)象)。在線程初始化ICELL_Obj之后就會(huì)調(diào)用下面的函數(shù):
備注其中的cell 指向cell 對(duì)象的指針, inputIcc/outputIcc是相應(yīng)的cell的 ICC 對(duì)象,這個(gè)調(diào)用計(jì)算單元需要的空間,并分配給定的ICC對(duì)象給單元cell。
CHAN_regCell( cell, inputIcc, 1, outputIcc, 1 );
當(dāng)所有的cells都已經(jīng)創(chuàng)建并初始化之后,線程調(diào)用CHAN_open()函數(shù)來(lái)為每一個(gè)指定的通道(chanNum)傳遞cell對(duì)象(cellList)。這個(gè)函數(shù)創(chuàng)建所有的XDAIS算法,并且如果單元細(xì)胞定義了cellOpen函數(shù),則會(huì)調(diào)用每一個(gè)單元細(xì)胞的cellOpen函數(shù),.
CHAN_open( chanList[ chanNum ], cellList, numCells, NULL/* default attributes */ );
最后,在運(yùn)行時(shí),線程為每一個(gè)通道(chanNum)調(diào)用CHAN_execute函數(shù)開(kāi)始執(zhí)行:
CHAN_execute( chanList[ chanNum ], NULL /* arg to cells */ );
3 核(Icell):
核實(shí)際上就是ICELL接口對(duì)象,基于RF5的應(yīng)用常常包含大量的算法和通道。為了便于算法集中到應(yīng)用中,RF5提出了核的概念。一個(gè)核就是包含一種 XDAIS算法的容器,一個(gè)RF5通道對(duì)象可以包含多個(gè)核,也即是包含多個(gè)算法。通道通過(guò)核來(lái)調(diào)用算法,實(shí)際上,真正的數(shù)據(jù)處理是在XDAIS算法中進(jìn)行的,核只是提供一個(gè)調(diào)用算法的接口,這大大簡(jiǎn)化了工作量,便于移植。
該接口包含一個(gè)重要的結(jié)構(gòu):ICELL_Fxns,該結(jié)構(gòu)包含一組函數(shù)指針。通道通過(guò)調(diào)用這些函數(shù)來(lái)調(diào)用算法,其中包含一個(gè)關(guān)鍵的函數(shù) cellExecute,這個(gè)函數(shù)的功能是調(diào)用XDAIS算法來(lái)執(zhí)行,上面的通道執(zhí)行函數(shù)CHAN_execute就包含了每個(gè)cellExecute的調(diào)用。
4 ICC模塊
ICC模塊是用來(lái)管理在核之間以及核與其他線程之間的數(shù)據(jù)通訊,我們知道線程間的數(shù)據(jù)傳輸是通過(guò)SCOM模塊來(lái)實(shí)現(xiàn)的,每個(gè)ICC模塊管理一個(gè)或者多個(gè) ICC對(duì)象,每個(gè)核都有一組輸入和輸出ICC對(duì)象。這些對(duì)象是通過(guò)CHAN_regCell()來(lái)注冊(cè)到相應(yīng)的通道里。
5 同步通訊機(jī)制(SCOM)
ThrProcess中包含兩個(gè)SCOM對(duì)象,RF5使用SCOM對(duì)象來(lái)實(shí)現(xiàn)線程間的通訊。SCOM消息是用戶自定義的一個(gè)機(jī)構(gòu),一個(gè)線程通過(guò)調(diào)用 SCOM_putMsg()函數(shù)將SCOM消息放置到一個(gè)SCOM隊(duì)列中,發(fā)送給其他的線程,或者通過(guò)調(diào)用SCOM_getMsg()函數(shù)從隊(duì)列中獲取消息。一般情況下,發(fā)送消息指明接收線程所要讀取的數(shù)據(jù)緩沖區(qū)的地址(以指針形式),接收消息指明發(fā)送線程所要寫(xiě)入的數(shù)據(jù)緩沖區(qū)的地址。在 mape2loopback實(shí)例中,thrProcess要從thraVideoInput接收消息,并發(fā)送消息給thrVideoOutput輸出圖像。RF5使用SCOM來(lái)實(shí)現(xiàn)線程間的通訊:thrProcess擁有一些緩沖區(qū),需要thrVideoInput寫(xiě)或thrVideoOutput讀,所以thrProcess通過(guò)SCOM告訴thrVideoIput和thrVideoOutput線程數(shù)據(jù)緩沖區(qū)的地址,同時(shí)還要保證兩個(gè)線程不會(huì)同時(shí)訪問(wèn)同一個(gè)緩沖區(qū)。thrProcess創(chuàng)建了兩種消息以分別和兩個(gè)線程進(jìn)行通訊,scomMsgRx和scomMsgTx。scomMsgRx指定了被 thrVideoInput寫(xiě)的緩沖區(qū)地址,scomMsgTx指定了被thrVideoOutput讀的緩沖區(qū)地址。
在實(shí)際的操作中,可以將SCOM看作是一種同步標(biāo)記,它用來(lái)區(qū)分模塊內(nèi)存是否正在被其他線程所使用,這樣就可以防止內(nèi)存訪問(wèn)的沖突。整個(gè)系統(tǒng)中包含很多存儲(chǔ)區(qū),這些存儲(chǔ)區(qū)很有可能在某一時(shí)刻正在被某一線程訪問(wèn),為了保證在任意時(shí)刻只有一個(gè)線程訪問(wèn)某該存儲(chǔ)區(qū),當(dāng)前正在訪問(wèn)這一內(nèi)存塊的線程通過(guò)發(fā)送SCOM消息給與這一內(nèi)存塊有關(guān)聯(lián)的線程,告訴它們,“我正在訪問(wèn)呢,你等會(huì)再來(lái)吧”。當(dāng)它訪問(wèn)完后,放棄了這一內(nèi)存塊的占有權(quán),再通過(guò)SCOM消息告訴相關(guān)聯(lián)的線程,“我用完了,你可以用了。”于是相關(guān)聯(lián)的線程就可以訪問(wèn)了。
6 ALGRF模塊—算法的實(shí)例化Algorithm Instantiation
ALGRF Module用DSP/BIOSMEM內(nèi)存管理器來(lái)創(chuàng)建和刪除XDAIS算法的模塊。參考框架服務(wù)簡(jiǎn)化XDAIS部件的使用。所有符合XDAIS標(biāo)準(zhǔn)的算法都必須使用一個(gè)標(biāo)準(zhǔn)的接口——IALG接口。ALGRF使用算法的IALG來(lái)實(shí)現(xiàn)對(duì)XDAIS算法的實(shí)例化。任何符合XDAIS標(biāo)準(zhǔn)的算法都可以被 ALGRF所使用。
用戶代碼不必直接的調(diào)用ALGRF函數(shù),這個(gè)工作由CHAN和其他的庫(kù)函數(shù)來(lái)完成。例外的是cell wrappers中的ALGRF_activate/deactivate序列化:如果cell中的XDAIS算法執(zhí)行 IALG_active/deactivate函數(shù),細(xì)胞需要調(diào)用兩個(gè)ALGRF函數(shù)來(lái)完成。
三個(gè)模塊來(lái)簡(jiǎn)化IALG接口創(chuàng)建算法對(duì)象:RF5使用ALGRF模塊來(lái)創(chuàng)建,配置,刪除XDAIS算法實(shí)例;ALG模塊使用CCStudio作為通用目的使用;并且不用DSP/BIOS MEM模塊分配內(nèi)存。ALGMIN是三個(gè)中的最小應(yīng)用。
一般情況下,三個(gè)模塊是相互包含的,但是只有一個(gè)能在應(yīng)用程序中使用。ALGRF適于RF5的需要和別的RF級(jí)別,而不適合緊湊和底端的如RF1級(jí)別的系統(tǒng)。
ALGRF與ALG相比,有以下的優(yōu)勢(shì):
1 更小的代碼腳本(代碼量):
作為一個(gè)通用的模塊,ALG支持malloc/free 運(yùn)行庫(kù)和DSP/BIOS MEM_alloc/MEM_free動(dòng)態(tài)內(nèi)存分配方式,ALGRF只支持DSP/BIOS分配,這為設(shè)計(jì)者省了代碼空間,另外ALGRF保證沒(méi)有無(wú)用代碼的存在。只有被調(diào)用的函數(shù)才被連接到執(zhí)行程序中。
2 暫存區(qū)支持:
下面為API在ALGRF中介紹的實(shí)例:
ALGRF_Handle ALGRF_createScratchSupport(IALG_Fxns *fxns, IALG_Handle parent,
IALG_Params *params, Void *scratchBuf, Uns scratchSize)
除了當(dāng)IALG_SCRATCH內(nèi)存區(qū)域(內(nèi)部數(shù)據(jù)緩沖區(qū))被請(qǐng)求,該函數(shù)能根據(jù)算法請(qǐng)求分配內(nèi)存。作為替代,scratchBuf和 scratchSize這兩個(gè)參數(shù)表明這一緩沖區(qū)已經(jīng)在應(yīng)用中存在,而且可以被當(dāng)前的算法重新使用。這就可以受約束的共享資源有限的內(nèi)存區(qū)。
3 從DSP/BIOS堆標(biāo)簽中做提。
ALGRF使用DSP/BIOS 的MEM模塊動(dòng)態(tài)分配內(nèi)存。一個(gè)堆標(biāo)記或內(nèi)存段名可以傳給
MEM_alloc()來(lái)表明分配到哪一個(gè)堆.如下:
/* Configure the ALGRF module to use:
* 1st argument - memory for internal heap
* 2nd argument - memory for external heap
*/
ALGRF_setup( INTERNALHEAP, EXTERNALHEAP );
這讓我們可以指定算法的數(shù)據(jù)分配位置。例如,如果使用EXTERNALHEAP作為兩個(gè)參數(shù),那么算法的數(shù)據(jù)就被定位在外部存儲(chǔ)器。
|