淺析μC/OS-ⅡAPI的設計思想及實現機制
3.5查詢一個信號量的當前狀態, OSSemQuery()
INT8U OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata)
在應用程序中,用戶隨時可以調用函數OSSemQuery()來查詢一個信號量的當前狀態。該函數有兩個參數:一個是指向信號量對應事件控制塊的指針pevent。該指針是在生產信號量時,由OSSemCreate()函數返回的;另一個是指向用于記錄信號量信息的數據結構OS_SEM_DATA(見uCOS_II.H)的指針pdata。因此,調用該函數前,用戶必須先定義該結構變量,用于存儲信號量的有關信息。在這里,之所以使用一個新的數據結構的原因在于,調用函數應該只關心那些和特定信號量有關的信息,而不是象OS_EVENT數據結構包含的很全面的信息。該數據結構只包含信號量計數值.OSCnt和等待任務列表.OSEventTbl[]、.OSEventGrp,而OS_EVENT中還包含了另外的兩個域.OSEventType和.OSEventPtr。
μC/OS-Ⅱ(其它內核也一樣)要求用戶提供定時中斷來實現延時與超時控制等功能。這個定時中斷叫做時鐘節拍,它應該每秒發生10至100次。時鐘節拍的實際頻率是由用戶的應用程序決定的。時鐘節拍的頻率越高,系統的負荷就越重。
下面主要講述五個與時鐘節拍有關的API函數。
4.1 任務延時函數,OSTimeDly()
void OSTimeDly (INT16U ticks)
這應該程序員們調用最多的一個函數了,這個函數完成功能很簡單,就是先掛起當起當前任務,然后進行任務切換,在指定的時間到來之后,將當前任務恢復為就緒狀態,但是并不一定運行,如果恢復后是優先級最高就緒任務的話,那么運行之。簡單點說,就是可以任務延時一定時間后再次執行它,或者說,暫時放棄CPU的使用權。一個任務可以不顯式的調用這些可以導致放棄CPU使用權的API,但那樣多任務性能會大大降低,因為此時僅僅依靠時鐘機制在進行任務切換。一個好的任務應該在完成一些操作主動放棄使用權。
4.2 按時分秒延時函數 OSTimeDlyHMSM()
INT8U OSTimeDlyHMSM (INT8U hours, INT8U minutes, INT8U seconds, INT16U milli)
OSTimeDly()雖然是一個非常有用的函數,但用戶的應用程序需要知道延時時間對應的時鐘節拍的數目。增加了OSTimeDlyHMSM()函數后,用戶就可以按小時(H)、分(M)、秒(S)和毫秒(m)來定義時間了,這樣會顯得更自然些。與OSTimeDly()一樣,調用OSTimeDlyHMSM()函數也會使μC/OS-Ⅱ進行一次任務調度,并且執行下一個優先級最高的就緒態任務。任務調用OSTimeDlyHMSM()后,一旦規定的時間期滿或者有其它的任務通過調用OSTimeDlyResume()取消了延時,它就會馬上處于就緒態。同樣,只有當該任務在所有就緒態任務中具有最高的優先級時,它才會立即運行。
4.3 讓處在延時期的任務結束延時,OSTimeDlyResume()
INT8U OSTimeDlyResume (INT8U prio)
μC/OS-Ⅱ允許用戶結束延時正處于延時期的任務。延時的任務可以不等待延時期滿,而是通過其它任務取消延時來使自己處于就緒態。這可以通過調用OSTimeDlyResume()和指定要恢復的任務的優先級來完成。實際上,OSTimeDlyResume()也可以喚醒正在等待事件的任務,雖然這一點并沒有提到過。在這種情況下,等待事件發生的任務會考慮是否終止等待事件。
4.4 系統時間,OSTimeGet()和OSTimeSet()
INT32U OSTimeGet (void)
void OSTimeSet (INT32U ticks)
用戶可以通過調用OSTimeGet()來獲得該計數器的當前值。也可以通過調用OSTimeSet()來改變該計數器的值。注意,在訪問OSTime的時候中斷是關掉的。這是因為在大多數8位處理器上增加和拷貝一個32位的數都需要數條指令,這些指令一般都需要一次執行完畢,而不能被中斷等因素打斷。
和其它內核一樣,μC/OS-Ⅱ為了處理臨界段代碼需要關中斷,處理完畢后再開中斷。這使得μC/OS-Ⅱ能夠避免同時有其它任務或中斷服務進入臨界段代碼。
μC/OS-Ⅱ定義兩個宏(macros)來關中斷和開中斷,以便避開不同C編譯器廠商選擇不同的方法來處理關中斷和開中斷。μC/OS-Ⅱ中的這兩個宏調用分別是:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。因為這兩個宏的定義取決于所用的微處理器,故在文件OS_CPU.H中可以找到相應宏定義。每種微處理器都有自己的OS_CPU.H文件。
5.1 OS_ENTER_CRITICAL宏
很多人都以為它是個函數,其實不然,仔細分析一下OS_CPU.H文件,它和下面馬上要談到的OS_EXIT_CRITICAL都是宏。他們都是涉及特定CPU的實現。一般都被替換為一條或者幾條嵌入式匯編代碼。由于系統希望向上層程序員隱藏內部實現,故而一般都宣稱執行此條指令后系統進入臨界區。其實,它就是關個中斷而已。這樣,只要任務不主動放棄CPU使用權,別的任務就沒有占用CPU的機會了,相對這個任務而言,它就是獨占了。所以說進入臨界區了。這個宏能少用還是少用,因為它會破壞系統的一些服務,尤其是時間服務。并使系統對外界響應性能降低。
5.2 OS_EXIT_CRITICAL宏
這個是和上面介紹的宏配套使用另一個宏,它在系統手冊里的說明是退出臨界區。其實它就是重新開中斷。需要注意的是,它必須和上面的宏成對出現,否則會帶來意想不到的后果。最壞的情況下,系統會崩潰。我們推薦程序員們盡量少使用這兩個宏調用,因為他們的確會破壞系統的多任務性能。
6. 結束語
通過對μC/OS-II中這幾類API的簡單分析,我們可以看出μC/OS-II作為一個多任務、搶占式嵌入式操作系統,其API都是為多任務及其多任務之間的調度和通信的實現來設計的。μC/OS-II提供的API簡潔而靈活,使用戶在設計實際應用時能夠很方便的利用系統提供的各種調用,充分發揮μC/OS-II實時、高效的優點。
評論