关于tsk和mbx
這兩個都是DSP/BIOS中的,先大概介紹一下
tsk:
??? task,任務.在Scheduling中,其優先級高于IDL(背景程序),低于SWI(軟中斷)和HWI(硬中斷).可以被軟硬中斷打斷,也可以被其它事件阻塞(blocked),順便說一下,SWI和HWI是不能阻塞的.(阻塞和中斷的不同,見我的另外一篇文章:CCS的一些問題)
tsk和swi和hwi類似,可以調用一個函數,還可以傳遞多達8個參數,不同的tsk可以有15個優先級,執行任務的順序相當于一個優先隊列,如果一個tsk被阻塞,會自動將這個tsk放到同優先級tsk的后面,等待條件滿足的時候執行.
tsk有個重要的函數TSK_yield,當一個tsk調用這個函數的時候,會將自己掛起(pend),將控制權交給接下來的一個tsk,讓他執行.
查看不同的tsk的狀態,可以選擇"DSP/BIOS -> Kernel/Object View ",在出現的窗口左邊點擊tsk,就可以在右邊看到所有tsk的狀態(ready:準備好,running:運行中,blocked:被阻塞,terminal:結束)
------------------------------------------------------------------------------
mbx:
??? mailbox,郵箱.在Synchronization中.一般作為不同的任務(tsk)之間傳遞數據.
mbx有兩個屬性,
Size:這里面可以存放的單個數據的大小,比如想在這里面存放int類型的數值,那么Size就設為4.
Length:里面最多能存放多少個大小為Size的數據,如果設為2,那么就能存放2個.
主要函數:
MBX_pend:
語法:
status = MBX_pend(mbx, msg, timeout);
參數:
MBX_Handle mbx; /* 句柄*/?
Ptr msg; /* 用以保存讀取出來的數據的地址*/?
Uns timeout; /* 超時時間*/
返回值:
Bool status; /* 如果成功,返回TRUE if successful,如果timeout設定的時間內沒有讀取到數據,則返回 FALSE*/
描述:
??? 如果mbx不為空,將復制其中的第一個數據到msg指定的地址并且返回TRUE.如果為空,這個任務將被掛起,直到MBX_post函數被調用或者timeout設置的時間到.
??? 如果timeout的值是SYS_FOREVER,那這個任務將一直掛起,直到MBX_post函數被調用,如果timeout的值是0,那么將立即返回FALSE.
MBX_post:
語法:
status = MBX_post(mbx, msg, timeout);
參數:
MBX_Handle mbx; /* 句柄*/?
Ptr msg; /* 存放寫入數據的地址*/?
Uns timeout; /*等待時間,如果超過此時間仍然不能寫入,返回FALSE*/
返回值:
Bool status; /* 成功寫入返回TRUE,超時返回FALSE */
描述:
??? MBX_post 檢查mbx中是否有空閑的位置,如果有,則將msg的內容寫入mbx.同時將下一個MBX_post任務(如果有的話)設為ready狀態.
??? 如果mbx已經滿了,而且timeout等于SYS_FOREVER,這個任務將被掛起,等待MBX_pend函數被調用.如果timeout等于0,那么立即返回FALSE.如果timeout是不為0的數,這個任務將等待這么長的時間,如果還是沒有MBX_pend函數被調用,則返回FALSE.
A task switch occurs when calling MBX_post if a higher priority task is made ready to run, or if there are no free message slots and timeout is not 0.
這兩個東西還有不少可以測試的地方,比如tsk的優先隊列是怎么排的,調用TSK_yield后排到什么地方,mbx未放滿是不是能讀取,未讀完是不是能放入,pend和post的Timeout值有什么用,這些等下次有空研究的時候補充.
===================================================
在調試TI的一個例程tsktest(位置:X:\CCStudio_v3.1\tutorial\sim64xx\tsktest,其中的sim64xx根據你使用的DSP類型而定)的時候,花了不少時間,才終于理解了這里面任務調度的順序.
程序中有一個mbx,能放2個8B的數據,有4個tsk,1個是讀mbx,3個寫mbx,這三個寫mbx的tsk調用的是同一個函數,不過為了區分,調用的時候傳遞了一個不同的參數.程序運行的結果這里就不寫了.
我經過改變mbx的length和write函數的循環寫入次數后,可以確定mbx有自己的一個任務隊列,當mbx滿的時候,post過來的tsk會被blocked,但是這個post的動作已經是放在mbx的任務隊列中,等到mbx被讀空的時候,會自動開始這個post動作.如果在這個post動作后面還排著其它的動作,那么會接著執行后面的動作.
舉個現實中的例子,假設有ABC三隊人在排隊買票,每隊3人,分別叫A1A2A3B1B2B3C1C2C3.他們在售票大廳外面的廣場排隊,售票大廳有一個門,要進大廳的人,必須在門前排成一隊,然后才能進去.從各自的隊伍排到門口的隊伍,按照ABC的順序,門口的隊伍每隊只能有一人.大廳里面有2個窗口在賣票,如果兩個窗口都有人在買,那么后面的人只能排在門口,不能進大廳.只有當在兩個窗口買票的人都離開后,排在后面的前兩個人才能進大廳.進入大廳的人,如果自己的隊伍還有人,必須通知下一個人過來排隊.
那么看一下買票和排隊的順序.
一開始A1A2到門口,大廳空,
兩人進去,通知A3過來排隊
A3到門口,里面滿了,在門口排隊,
A隊已經一人在門外,就輪到B隊了
B1到門口排隊,排在A3后面,B組結束,
輪到C隊,C1排到B1后面,C隊結束.
現在開始第一輪賣票,
A1A2買完走人,大門可以進人,
A3進大廳,因為A隊沒人了,不用通知,
接著B1進入大廳,順便通知B隊的B2過來排隊,B2只能排在C1后面.
大廳又滿,禁止進人,
開始賣票,
A3B1買完走人.大門開,
C1進門,通知C2過來排隊,C2排在B2后面,
B2進門,通知B3來排隊,B3排在C2后邊.
大廳滿,
開始賣票,
C1B2買完走人.大廳空,門開,
C2進,通知C3,C3排在B3后邊,
B3進大廳,B隊沒人,不用通知,
大廳滿,
開始賣票,
C2B3買完走人,大廳空,門開
,C3進,后邊沒人,不用通知,
由于所有隊都排完,大廳雖然沒滿,也開始賣票,
C3買完走人.
賣票的人等了一會,發現沒人來買了,就關門回家了.
買票的順序就是A1A2 A3B1 C1B2 C2B3 C3
再和tsk和mbx類比,三個tsk就是ABC三條隊伍,每次要post一個數據,就是來門口排隊,而門口的隊伍就是mbx的任務隊列,只有mbx中的內容被讀完,才會依次啟動任務隊列中的任務
1、它們都是任務間通信的手段,但是應用場合不同?
信號量用作任務同步或者資源的互斥訪問?
至于郵箱,名副其實的,可以“郵寄”一些東東給別的任務?
舉個例子的話,我覺得可以說信號量就像別人打你電話只響一下(具體代表什么含義在于你們之間的約定),而郵箱就像短信哇,寫啥都行。當然,二進制信號量也可以用郵箱實現。?
2、任務與事件的概念不同?
任務作為一個競爭系統資源的單位,各個待執行的任務被系統統一調度;?
而任務之間(或者任務與中斷之間)的互動體現在信號上,也就是事件。某些事件的發生可以使任務的運行狀態發生變化。?
比如兩個任務A、B同時競爭某個資源,以信號量為途徑實現互斥。?
在A獲得了信號量后,在使用資源的時候,B由于等待信號量而處于阻塞狀態。?
A使用完畢資源后,告知B“我用完了,你們用吧”,這個事件的傳達是通過信號量完成的。?
3、這個問題懶得敲了,復制粘貼之?
“對信號量的初始計數值賦值。該初始值為0到65,535之間的一個數。如果信號量是用來表示一個或者多個事件的發生,那么該信號量的初始值應設為0。如果信號量是用于對共享資源的訪問,那么該信號量的初始值應設為1(例如,把它當作二值信號量使用)。最后,如果該信號量是用來表示允許任務訪問n個相同的資源,那么該初始值顯然應該是n,并把該信號量作為一個可計數的信號量使用。”?
可以一個任務對應多個事件吧,看你怎么設計了,比較簡單的情況的話,一個任務可能也就關注一個事件。?
關于初始值的問題,你說的應該是信號量的初始值吧,信號量最大的作用就是共享和競爭資源?
初始值為n的情況,比如有n臺打印機,每個時間點上一臺打印機只有一個任務可以訪問,如果有m個任務都想使用打印機,而且m>n的話,就有資源的征用問題,引入一個初始值為n的信號量,此信號量的數值所代表的就是“當前還有多少打印機可以使用”。想用打印機的任務去看信號量,如果還有的話就Take之,否則就等待(阻塞)或者先干別的去(不等待立即返回),同樣的,使用過打印機的就Give之,以便其他任務可以使用打印機。?
初值為0的情況也是普遍存在的,例如一個數據處理系統,任務A產生數據,緩存到一定數目后交給任務B做處理,這個事件使用信號量做通知的手段。那么系統初始化時,對B而言,是沒有數據要處理的,那么信號量自然為0了。每當任務A提交一次數據,對信號量加1(做SemGive),任務B發現信號量非0后,就去處理數據,處理一個,對信號量減1(做SemTake)
DSP/BIOS內核的應用程序中,優先級從低到高有四個線程:
后臺線程(IDL)線程;
TSK(任務)線程;
SWI線程(軟件中斷);
HWI線程(硬件中斷);
應用程序從默認進入點_c_int00開始運行,首先完成系統的初始化,包括DSP/BIOS配置中指定的各個寄存器的設置以及PLL倍頻時鐘的設置等,然后調用main()函數,在main()函數結束返回,調用BIOS_start(),開始按優先級檢測并執行HWI,SWI,TSK,當前面所有線程都沒有執行時(沒有HWI和SWI,有的任務已經完成,而有的被掛起),開始進入IDL_F_LOOP循環,執行后臺的IDL線程(LOG模塊的信息顯示就是在IDL線程中完成的,CPU負荷圖的數據也是這時讀取并送到PC主機,以便完成圖形繪制等)。在IDL_F_LOOP中,若有HWI,則立即暫停IDL,切換到硬件中斷服務子程序。當硬件ISR完成后,根據具體情況判定有無SWI或喚醒任務,最后才回到IDL繼續運行。
注意,DSP/BIOS內核仍然是個多任務的內核,但并不是一個嚴格意義上的搶先式內核。除了HWI,其他所有線程都必須自己自動放棄對CPU的控制,以便完成切換。當然,當硬件中斷發生后,也會產生線程的切換,這時所有線程都將按優先級重新安排運行,所以從這點講,DSP/BIOS內核也具有搶先的特點。
在DSP/BIOS內核應用中,用戶可以將自己的處理代碼(如G723的編碼、解碼,MP3 解壓等)放到硬件中斷,軟件中斷,任務或后臺線程中的任何一個線程中調用運行。一般推薦在SWI和TSK中調用。用戶可以在DSP/BIOS的配置文件中簡單說明這些軟件中斷或任務(即所謂的靜態說明),也可以在運行過程中通過DSP/BIOS內核提供的API函數調用動態創建。
API函數調用幾乎都可以使用C或C++語言直接調用。通過這些API,用戶可以完成硬件中斷的管理,軟件中斷的啟動,任務的切換,各線程之間的同步和數據通信等。
轉載于:https://www.cnblogs.com/fpga/archive/2009/09/19/1570051.html
總結
- 上一篇: 玩通信设备的,来这里学习
- 下一篇: log4j配置日志系统成功 (转)