ucos ii作業系統

2021-07-26 19:28:17 字數 3795 閱讀 6089

ucos-ii是乙個多工的作業系統,其最大優點即為實時性。任務通常是乙個無限的迴圈,其中包括了使用者**,而實時性即指最快的響應優先順序最高的任務。

確實,對於乙個初步接觸ucos-ii的新手來講,想要完全理解是要花時間的。

我們想用ucos-ii,在移植成功後(以後在寫移植方面吧),我們首先就得進行初始化,ucos是用函式osinit()來完成的。

呼叫osinit()的目的是建立一些資料結構,比如初始化os_max_task數目的ostcbfreelist,以及使用者定義的各項oseeventfreelist,osqfreelist,osflagfreelist,osmemfreelist(將os_max_???設定為實際需求數目可減小核心ram量,以後在寫篇移植方面的文章詳談吧)。以ostcbfreelist

為例,這可看作一條快取鍊錶。一開始,列表中指標全部指向null,當任務建立時,就從ostcbfreelist

上取出一塊賦予給任務控制塊。

顯然,這樣做的好處在於:緩衝池更快的將事先已初始化的記憶體空間有序的賦予給任務。這樣,我們用ostaskcreate()或ostaskcreateext()

建立任務時,這兩個函式會呼叫底層的os_tcbinit(),就從ostcbfreelist中分配了乙個任務控制塊os_tcb。

初始化ucos-ii後,我們就該建立任務了。在啟動osstart()之前,一定要建立乙個應用任務。假設我們已建立了若干個任務,就可以啟動osstart()了。

osstart()的作用就是找乙個優先順序最高的任務的tcb,然後執行。這就有了兩個疑惑:

1. 怎樣找到優先順序最高的任務;

2. 任務控制塊tcb有些什麼東西。

我們先來解決第乙個問題吧。

首先,任務一被建立,它們就會被賦予相應的堆疊,相應的優先順序prio等。然後就進入就緒態等待執行。核心根據優先順序作了乙個就續表。核心只需找出進入就緒表中優先順序最高的任務進行執行即可。

非常奇妙的事就是作者構思了一套機理,一方面可由任務優先順序推知其在就緒表中的位置,另一方面可由就緒表中的置位推知表中的最高優先順序任務。

其原理是這樣的:

作者建立了乙個8位變數osrdygrp

和乙個8位變數陣列osrdytbl[8];

那麼要使乙個優先順序為prio的任務進入就續表就需要在相應位置置1.

osrdygrp 

|= osmaptbl[prio >> 3];

osrdytbl[prio >> 3] |= osmaptbl[prio & 0x07];

當然,一開始很難讓人接受,我們先來講講prio。由於prio最高為63,所以其8位bit中高兩位一定為0.

這樣的話,prio>>3就為00000yyy,而y就代表了就緒表中的行數。不過這需要一層轉換,即通過osmaptbl.(讀者可將其看作調製器理解)。

osmaptbl[0]=00000001

osmaptbl[1]=00000010

osmaptbl[2]=00000100

………….

osmaptbl[7]=10000000

y即00yyy000,將通過osmaptbl置位osrdygrp;同樣,prio & 0x07代表了x(00000***),將同樣置位osrdytbl[prio>>3]了。

(讀者可能已經看出了,切記這裡的置一是置8位bit中的1位bit.)

我來舉個例子吧,如將prio為8的任務在就緒表中置位。

8轉換成二進位制為

00(001)(000)

,則y = prio>>3=1,那麼可查osmaptbl表得出osmaptbl[prio>>3] = 00000010;所以它通過osrdygrp |= osmaptbl[prio>>3];在osrdygrp (_ _ _ _ _ _ a _)

的a位置1,即相當於通知就緒表,在就續表的第二行會有任務就緒;

那麼x= prio & 0x07 = 0,則osmaptbl[prio & 0x07] = 00000001;所以它通過osrdytbl[prio >> 3] |= osmaptbl[prio & 0x07];在osrdytbl[1](_ _ _ _ _ _ _ b)中的b位置1。

那麼又怎樣從就緒表中找出最高優先順序的任務呢?

理解了上面所述的置位,那麼這個問題也就大致相同了:我們通過借助osmaptbl來編碼使其進入就緒態,這兒又將借助osunmaptbl(讀者可看作解調器)來解碼,使系統找出優先順序最高的任務。

找出所有就緒表中優先順序最高的任務:

y = osunmaptbl[ osrdygrp ];

x = osunmaptbl[ osrdytbl[y] ];

那麼prio =y *8 + x

osunmaptbl表如下:

int8u 

const 

osunmaptbl[256] = ;  

在舉乙個例子來理解吧。比如同時有

6 7 8 9

四個任務就緒。

那麼osrdygrp = 00000011;

找出最高優先順序任務所在行,y = osunmaptbl[ osrdygrp ];

查表會得到0,即y=0,這裡表明優先順序最高的任務在就緒表中的第一行。然後再找出其在第一行的位置osrdytbl[y] = osrdytbl[0] =11000000;

通過查表可得

x = osunmaptbl[ osrdytbl[0] = 6

則[prio = y *8 + x = 6

即就續表中優先順序最高的任務為優先順序為6的任務。

想想一般的從頭到尾的查詢,再想想這種方法,真的很值得欣賞。

再回頭看看第二個問題吧,來講講os_tcb.

可以這樣理解:tcb就是任務的資訊,以確保任務在切換時無誤差地還原執行任務。tcb這個結構體其下有指向當前任務堆疊棧頂的指標ostcbstkptr,雙向鍊錶指標ostcbnext和ostcbprev,優先順序ostcbprio等。那麼系統找到最高優先順序的任務後是怎樣通過tcb進行任務切換的呢?

這裡還應介紹兩個指標,ostcbcur和ostcbhighrdy。我們通過任務優先順序的值,查詢任務控制塊優先順序表ostcbpriotbl,得到指向相應任務控制塊os_tcb,用ostcbhighrdy得到了即將執行任務的tcb,然後進行任務切換。

我們來看看系統是怎樣儲存當前cpu值以及重新裝入任務。首先,我們來了解一下os_task_sw()這個函式。這其實就是乙個軟中斷或者陷阱中斷,執行切換任務時,中斷就將依次儲存psw和pc的當前值,通用暫存器的值,最後將被掛任務的堆疊指標儲存在os_tcb中,這時有ostcbcur->ostcbstkptr指向了sp。當遇到要切換的任務時,將ostcbcur指向了ostcbhighrdy(即將執行的任務),由於儲存了cpu的值ostcbcur->ostcbstkptr此時指向的就是該任務的sp了。這樣,重新裝入只需從反方向彈出暫存器值,然後通過中斷返回指令把pc和psw裝回到cpu中,任務便重新執行了。

那麼任務的排程就應該是這樣的:任務以各種方式(得到某資源或延時到達等)進入就緒態,系統根據就續表找到了優先順序最高的任務,然後將被掛起於將執行任務的tcb分別儲存與載入,達到了任務的切換。

任務切換函式其實就是儲存被掛起任務的暫存器值,把被掛起任務的sp儲存在被掛起任務tcb的ostcbstkptr。然後將tcbcur指向任務棧,依次彈出將執行任務的暫存器值,然後中斷返回。

ucos-ii任務切換是模擬的中斷,當然也存在使用者自定義的中斷函式,時鐘節拍就是中斷。只不過ucos-ii中的中斷在退出中斷時還需判斷是否有優先順序更高的任務就緒,如時鐘節拍,就像脈搏一樣,利用定時的中斷來標誌或給郵箱等等發訊息,以通知延時任務就緒。

ps : ucos-ii的核心而言,還可以寫很深,由於時間問題,不在多述了。第一次寫博文,感覺很累啊。第一次我堅持寫完這篇文章,其實應該分好幾篇來講訴,這樣的話,我也可以輕鬆點,也可以將問題講述得更徹底點。

uCOS II作業系統

簡介 ucos ii是乙個簡單 高效的嵌入式實時作業系統核心 支援x86 arm powerpc mips等多種體系結構 www.ucos ii.com ucos ii的各種商業應用 醫療器械 移動 路由器 工業控制 gps 導航系統 智慧型儀器 更多 計算機作業系統的作用 從使用者的角度來看它就是...

UCOSII作業系統

1 ucosii作業系統是怎麼管理任務的?用圖是最能表現的 1 任務控制塊是來管理任務的。2 其中ucosii把所有的任務都是通過雙向鍊錶來連線到一起的,為什麼?我難道不能使用陣列來分配空間嗎?關鍵原因 在整個作業系統中,因為我們不知道使用者到底需要多少個任務,所以使用鍊錶的話,在編譯後才確認的話,...

uc os ii作業系統筆記

作業系統是應用程式與硬體的之間的介面,只有硬體構成的電腦成為裸機,作業系統的功能主要是對計算機的資源進行管理。主要的功能 1.處理器的管理,主要兩項工作 一是對中斷的管理,二是對處理器的工作的進行排程。因為處理器的硬體只能發現外部時間的中斷的請求,不能對中斷進行管理和處理。2.儲存的管理 3.裝置的...