天天看點

多核DSP 6678 IPC的使用+執行個體分析

       IPC是SYS/BIOS處理核間通信的元件        IPC的幾種應用方式(下面中文名字是自行翻譯,旁邊有英文=_=||,另外下面的配圖中的藍色表示需要調用子產品的APIs,而紅色子產品表示僅僅需要配置(如在.cfg中配置),而灰色子產品表示是非必須的):        (1)最小使用(Minimal use):這種情況是通過核間的通知機制(notification)來實施的,而一個通知所攜帶的資訊是非常小的(一般是32bits),是以稱為最小使用。這種方式一般是用于處理核間的簡單同步,卻無法處理複雜的消息傳遞。

多核DSP 6678 IPC的使用+執行個體分析

       這種情況下,需要利用到Notify子產品的APIs函數,比如通過Notify_sendEvent()函數給某個特定核傳遞一個事件,我們可以給特定事件動态注冊回報函數。由于一個通知(notification)所攜帶的資訊是極少的,是以隻能給處理器發送一個事件号,而這個事件号所代表的回報函數決定之後的動作。另外一些資料以函數參數方式,也可以被送出。        (2)增加資料通路(Add data passing):這種情況是在前面的最小使用機制下,在核間增加了一個傳遞連結清單元素的資料通路,這個連結清單的實施一般是使用共享内容并通過門(gates)來管理同步。

多核DSP 6678 IPC的使用+執行個體分析

       這種情況是在最小使用上,增加了一個ListMP子產品用于共享連結清單元素。        ListMP子產品是一個雙向連結清單,另外ListMP需要用到共離記憶體,是以SharedRegion子產品也需要被使用,另外ListMP通過NameServer子產品中來管理名稱/值,同時使用GateMP子產品來防止連結清單元素被多個處理器同時讀取。        (3)增加動态配置設定(Add dynamic allocation):這種情況下,增加了從堆中動态配置設定連結清單元素的功能。

多核DSP 6678 IPC的使用+執行個體分析

       這種情況在上種情況下,增加了一個Heap*MP子產品,這個子產品主要用于從堆中給連結清單動态配置設定記憶體        (4)強大但易用的消息機制(Powerful but easy-to-use messaging):這種情況下利用MessageQ子產品來傳遞消息。

多核DSP 6678 IPC的使用+執行個體分析

       除了Notify通知機制,還可以利用MessageQ來實作更為複雜的核間通信,在這種情況下,隻需要配置MultiProc和SharedRegion子產品就可以了,而Ipc_start()函數将自動為我們實作上面灰色子產品的配置。        本節,我們暫時隻以一個簡單的最小使用(Minimal use)情況為例,分析CCS自帶一個多核通信例子,這個例子在八核之間互相傳遞資訊,之後我們總結核間傳遞方法實作步驟,實作一個主從核之間傳遞資訊的功能。

一、打開CCS自帶例程        打開CCS自帶例程的方法和建立CCS項目是一緻,隻是需要在Project templates and examples中選擇我們需要的例子,這裡的例子是在IPC and I/O Examples中選擇C6678 Examples中的Notify,然後輸入項目名稱後,CCS會自行将例子複制到項目下。

多核DSP 6678 IPC的使用+執行個體分析

二、生成項目後,編譯調試檢視運作結果 (1)點選編譯後,檢視有無出錯 (2)導入目标配置檔案.ccxml,這裡選擇的仍然是C6678 Device Functional Simulator, Little Endian. (3)點選調試,選擇所有的核 (4)全選所有的核(通過Shift),然後Groups

多核DSP 6678 IPC的使用+執行個體分析

(5)選中Group,點選運作 三、分析運作結果        這個例程除了調用Notify子產品,在核間傳遞消息,通過回報函數觸發核的動作,同時通過Semaphore子產品來保證核間依次執行,防止搶占,這裡每個核都有一個信号量,來表明其目前是否執行或等待其它核執行完成。 (1)各核列印

多核DSP 6678 IPC的使用+執行個體分析

       這段是在main()中出現的結果,每個核都會執行各自的main()。

多核DSP 6678 IPC的使用+執行個體分析

       各核注冊事件,并表明其回報函數

多核DSP 6678 IPC的使用+執行個體分析

(2)核0執行同時釋放信号量,在核0釋放信号量semHandle之前,其他核都處理等待信号量釋放中

多核DSP 6678 IPC的使用+執行個體分析

       核0通過給核1發送事件,觸發回報函數,在回報函數中semHandle歸一,注意這個激活的信号量是在核1中的

多核DSP 6678 IPC的使用+執行個體分析

       激活核1的信号量後,核0列印結果,并等待其信号量的結果,所有核的信号量都初始為0

多核DSP 6678 IPC的使用+執行個體分析

(3)以下是總共八個核,分别執行了NUMLOOPS次(這裡設定的是10次)

多核DSP 6678 IPC的使用+執行個體分析

       下一個核信号被激活,開始執行

多核DSP 6678 IPC的使用+執行個體分析

       同時通過回報函數将目前核的下一個核激活

多核DSP 6678 IPC的使用+執行個體分析

       完成發送事件

多核DSP 6678 IPC的使用+執行個體分析

(4)退出任務循環,同時退出目前核的BIOS

多核DSP 6678 IPC的使用+執行個體分析

四、多核IPC的配置 (1)IPC的啟動非常簡單,在導入Ipc頭檔案後,在main()函數中調用Ipc_start()就能根據.cfg檔案中配置啟動IPC所需要的子產品,比如預設情況下Ipc_start()會調用Notify_start()之類,不過要啟動這些子產品,需要保證提前在.cfg中添加了這些子產品(如右擊子產品,選擇Use) (2)IPC的配置是在.cfg中完成的,配置IPC首先需要申明,目前Notify等相關子產品也需要提前申明,這裡如果不清楚IPC所需要的相關子產品,最好使用自帶IPC例程作為子產品。        var Ipc = xdc.useModule('ti.sdo.ipc.Ipc'); (3)設定同步的核數        Ipc.procSync = Ipc.ProcSync_ALL;        這裡 Ipc.ProcSync_ALL 表示Ipc_start會自動将所有的核都啟動了        Ipc.ProcSync_PAIR 表示隻啟動部分核,需要啟動的核要通過Ipc_attach()來啟動,這個預設選項        Ipc.ProcSync_NONE 表示Ipc_start()不會同步任何核 (4)核間的連接配接方法Ipc_attach()及Ipc_detach()        這兩個函數的使用,需要.cfg檔案中配置了Ipc.ProcSync_PAIR          Ipc_attach的使用方法非常簡單,在Ipc_start()之後直接輸入:        Ipc_attach(#coreID),#coreID表示需要連接配接的核ID号,如Ipc_attach(0)表示連接配接核0。        不過需要注意的是:        a) 核的連接配接一定要按照ID号從小到大的順序進行,比如目前核必須先連接配接了核0,才能連接配接核1,之後才能連接配接核        b) 另外兩核之間的互相連接配接必須先滿足ID号小的先連接配接ID号大的,比如隻有當核0連接配接核1後,核1才能連接配接到核0        c) 由于核的連接配接并不是一次就能成功的,是以一般需要加一個循環等待的過程,一般使用方法如下:            while(Ipc_attach(#coreID)<0){                 Task_sleep(1);             }        Ipc_detach()的使用方法同Ipc_attach()是類似的,不過它的功能是解除連接配接。

五、主從核之間的通信        前面介紹IPC核間通信例子,是每個核同所有核之間都有連接配接,而各核之間連接配接都是相同且雙向,而在很多情況下,我們并不需要如此多的核,或者許多核間連接配接也是不必要的,這些情況下使用Ipc.ProcSync_ALL未免太不高效。        下面我們介紹的例子是核間的主從通信,選擇三個核,選擇一個主核,另外兩個是副核,主核core0同副核之間有互相連接配接,而副核core1與副核core2之間沒有連接配接,這個主從通信主要完成以下事件        a) 主核向兩從核發送事件,激活從核,使其執行任務        b) 兩核完成任務後,向主核發送事件,主核繼續執行其任務。        這個例程主要有如下内容: (1)在.cfg檔案中設定procSync       改為Ipc.procSync = Ipc.ProcSync_PAIR;

(2)定義主從核ID

多核DSP 6678 IPC的使用+執行個體分析

(3)在main()函數Ipc_start()後增加如下代碼:

多核DSP 6678 IPC的使用+執行個體分析

       a) 這裡主要根據主核和從核的角色分别添加連接配接任務: 主核同兩個從核都有連接配接,而從核隻與主核有連結        b) 在添加核間連接配接後,分别給核間連接配接注冊事件 (3)在任務函數tsk0_func内分别根據主核及從核的角色添加發送與接收函數,下面是以主核為例

多核DSP 6678 IPC的使用+執行個體分析

       主核在給從核分别發送事件後,通過Semaphore_pend等從核将主核的信号量激活,之後繼續主核任務。        同時隻有當主核通過給從核發送事件,從核的注冊函數激活信号量,從核才能開始任務。 (4)仿真調試的結果

多核DSP 6678 IPC的使用+執行個體分析

       從結果上看,當從核分别收到了來自主核的事件時,同時開始任務,當從核任務全部完成後,主核才開始其任務

Tips:         a) 這裡需要注意的是在注冊函數内不要加System_printf()函數,這個函數會導緻如下錯誤産生: ti.sysbios.gates.GateMutex: line 97: assertion failure: A_badContext: bad calling context. See GateMutex API doc for details. xdc.runtime.Error.raise: terminating execution        b) 上面的代碼并不是全部        例程代碼下載下傳位址: https://github.com/tostq/EasyMulticoreDSP/tree/master/6.IPC_notify