OSRunning:??用于標識多任務環境是否已經開啟運行,在OSStart()函數里啟動任務后就置為True。
OSIntNesting:用于標識中斷嵌套層數。產生一次中斷可以調用OSIntEnter()函數使該值自增1,處理完一次中斷再調用OSIntExit()自減1。
OS_TCB:一個結構體變量,每建立一個任務都會為該任務指定一個OS_TCB,包含該任務的棧頂指針,任務優先級,任務狀態字,延時節拍等所有相關信息。每個任務的OS_TCB都存在于一個雙向鏈表內,并使變量OSTCBList指向最后建立的那個任務的OS_TCB。
OS_STK:任務堆棧,每個任務都有一個自己的堆棧空間,用于保存寄存器,狀態值,和任務的入口地址。這個堆棧與系統棧沒有什么關系,只是用戶為一個任務分配的存儲任務信息的空間,只需要是一個連續的存儲空間即可。
OSRdyGrp,OSRdyTbl[ ]:用于標識就緒的任務。uC/OS根據優先級唯一確定一個任務,也即一個優先級只能分配給一個任務。OSRdyTbl[ ]里保存(MAX_TASKS/8+1)個字節,每個字節又有8個Bit,從最低位開始分別對應0~LOWEST_PRIO優先級的任務,任務就緒時就將該任務的優先級所在Bit置1,否則清0。
OSRdyGrp完全是為了找到最高優先級方便而設立的,將OSRdyTbl[ ]里每個字節代表的8個任務劃為一個組,只要某一組內有就緒任務時,OSRdyGrp的相應位就置1。比如,只要OSRdyTbl[0]不為0,則OSRdyGrp的第0位就置1,依次類推。
OSPrioCur:這是一個整型數,表示當前執行任務的優先級數。
OSPrioHighRdy:一個整型數,表示當前最高級別的就緒任務的優先級數。
OSTCBHighRdy:這是一個指針,它指向最高優先級就緒任務的OS_TCB。
OSTCBCur:一個指針,指向當前執行任務的OS_TCB。
OSTCBTbl[ ]:初始化時建立的一塊存儲空間,一共建立了MAX_TASKS個OS_TCB空間。并令變量OSTCBFreeList總是指向下一個可用的OS_TCB空間。當新建立一個任務時,就將一個空的OS_TCB空間分配給它使用。
OSTCBPrioTbl[]:這是一個指針數組,用于保存就緒任務的OS_TCB地址,一共有MAX_TASKS個值,依次對應0~LOWEST_PRIO優先級的任務。當某一優先級未分配給一個任務時,該數組對應元素的值為(void *)0,當某優先級的任務分配給一個處于就緒態的任務時,對應元素的內容就被寫入該任務的OS_TCB所在地址。
拿到沒用過的系統,首先就想知道它是怎么用的,對于一個實時操作系統,先要解決以下幾個問題:
如何切換任務
uC/OS多任務的原理是,在某個任務重新獲得CPU控制權的時候,先把上一個執行的任務的所有寄存器以及它的返回地址保存起來,然后把現在要執行的任務的所有變量恢復到操作寄存器里,然后使PC指向這個任務的處理函數。而保存和恢復變量的重要媒介就是每個任務獨有的堆棧空間,這點跟中斷處理的過程幾乎一樣,重新獲得CPU的任務可以看成是中斷函數,原先執行的看成是被中斷的函數,只不過uC/OS是模擬中斷來切換任務,所有堆棧的保存和恢復要在移植不同處理器的時候根據實際情況來完成,目的只有一個,就是模擬中斷的壓棧和出棧操作。
uC/OS引起任務切換的功能函數主要是兩個,任務級的切換是OSSched(),中斷級的切換由OSIntExit()完成。而前者中真正實現切換操作的是OS_TASK_SW()宏,后者真正實現切換功能的是OSIntCtxSw(),這個宏如何實現,移植不同的處理器有不同的處理方法,目的仍然是,把現場處理的跟真正發生了中斷一樣,該保存的保存,該恢復的恢復。
因此可以得到,uC/OS切換任務時可以有兩種方法,第一種是擁有CPU控制權的任務主動調用函數OSTimeDly()、OSTaskSuspend()等這類函數把控制權交出來,重新分配給下一個優先級高的任務,實際上是依靠OSSched()調度任務。第二種方法是CPU產生中斷,把當前任務的控制權剝奪掉,令它掛起,從而使下一優先級的任務得以執行,當然,如果中斷沒有令當前任務掛起,中斷返回后它依然是最高優先級的話,CPU將繼續被它控制。
如何查找最高優先級
uC/OS把一個字節可能的256個值的所有優先級狀況都做成一個表OSUnMapTbl[ ],比如,如果字節的值為7,即0000 0111,那么任務0,1,2都處于就緒態,最高優先級當然是0,那么OSUnMapTbl[7] == 0,因此,先通過y = OSUnMapTbl[OSRdyGrp]找到最高優先級的組y,然后通過x = OSUnMapTbl[OSRdyTbl[OSRdyGrp]]得到這個組里的最高優先級任務號x。因為uC/OS最大任務數不超過64,可以把優先級數看成是一個六位的二進制數,高三位表示所在組,低三位表示組內的號,因此y<<3+x就是找到的最高優先級數了,實在佩服OSUnMapTbl[ ]的設計。
作者進行很多查表的設計,為的是提高運行的速度。很想知道作者是如何創造出來的這些巧妙的查表設計的。uc/os-II源代碼算是在嵌入式OS中比較小巧玲瓏的啦,例如嵌入式linux的系統是怎么寫出來的呢?