ucos實時操作系統學習筆記——操作系統在STM32的移植


      使用ucos實時操作系統是在上學的時候,導師科研項目中。那時候就是網上找到操作系統移植教程以及應用教程依葫蘆畫瓢,功能實現也就罷了,沒有很深入的去研究過這個東西。后來工作了,閑來無聊就研究了一下這個只有幾千行代碼的操作系統,也沒所有的代碼都看,只是看了其中部分內容。自己還自不量力的嘗試着去寫過簡單的操作系統,最后寫着寫着就被帶到了ucos的設計思路上了,后來干脆就“copy”代碼了,雖說對操作系統內核的理解有很大的幫助,但是很是慚愧啊,智力不夠,對操作系統內核的設計者更加仰慕,O(∩_∩)O哈哈~

      之前項目開發用的STM32,接下來就從ucos在STM32的移植開始講一下學習過程吧。當時系統移植也是根據開發板例程來的,像OS_STK,OS_CPU_SR以及堆棧的增長方式等設置都已經根據ARM-CoreM3的硬件特性設置好了,所以移植過程相對簡單一點。以下所講內容純屬個人理解,如果不對的地方,請批評指正。

      首先,講一下個人對ucos操作系統整體架構的理解,網上有很多對ucos每個文件是干什么的做介紹的文章,在這里不做詳細介紹,可以網上搜一下。ucos主要包括TIMER管理(os_tmr.c),任務(os_task.c),任務間通信(os_sem.c,os_mutex.c等),內存管理(os_mem.c),和處理器相關底層實現。除了處理器相關底層實現外,其他的算是操作系統內核的東西,處理器相關實現卻因處理器的不同而具體實現不同。操作系統移植主要的操作就是做這部分內容。

  其次,講一下個人對ucos操作系統工作原理的理解,主要分為四點:

1. 操作系統給每個任務分配一個優先級,當有任務切換時,cpu的使用權會分配給優先級最高的任務;

2. 在操作系統內核中,當有比較重要的數據操作時,會通過開關中斷來保證數據的可靠性和正確性;

3. 通過手動設置異步中斷寄存器的值觸發中斷處理函數,實現任務的切換(此操作主要是任務間的通信操作實現的);

4. 中斷會自動保存寄存器的值,完成中斷處理之后,會檢查有沒有比當前任務優先級更高的任務,從而決定是否進行任務切換操作(此中斷中比較重要的是“心跳”定時器中斷保證了沒有外部中斷的情況下,實現任務切換);

 

      ucos在STM32上的移植主要是針對上面提到的工作原理中的后面三點實現的,其中講到的第一點是操作系統內核中做得事情。移植中的函數聲明是在操作系統內核中,對於STM32的移植,函數的具體實現是在os_cpu_a.asm中。接下來分析一下移植過程中使用到的各個函數的。

1. 和工作原理第2條相關的進出臨界區函數(其實是開關中斷函數)。

#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();};

#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);}.

2. 和工作原理第3條相關的任務切換函數

#define OS_TASK_SW() OSCtxSw()

3. 和工作原理第4條相關的中斷退出任務切換函數

OSIntCtxSw(), 該函數是當中斷處理函數完成操作之后由OSIntExit函數調用,實現原理和OSCtxSw相同,但是意義不同。

以上這三個函數是這樣組織的:

對應1,對於進入臨界區的函數,主要是通過修改中斷寄存器中的值實現的。OS_CPU_SR_Save()通過將中斷寄存器中的值取出並存入到cpu_sr中,修改中斷寄存器的值,屏蔽中斷(NMI和硬件fault是不能被屏蔽的)。OS_CPU_SR_Restore()是將之前存到cpu_sr中的值寫入到中斷寄存器,從而恢復到沒有屏蔽中斷之前的狀態。

對應2和3,對於進行任務切換的函數,其主要是通過觸發中斷,在中斷處理函數中通過將高優先級任務的堆棧中的數據填入到cpu寄存器中,從而實現任務的切換。這兩步需要注意的是在STM32啟動的過程中(即startup_stm32f10x_hd.s),需要設置中斷向量對應的中斷處理函數OS_CPU_PendSVHandler(),將原來的Pend_SVHandler()替換掉。

 

      對於在STM32上的移植,比較重要的是設置操作系統的“心跳”函數SysTick_Handler,函數代碼如下:

void SysTick_Handler(void)
{
    OS_CPU_SR  cpu_sr;

    OS_ENTER_CRITICAL();        /* Tell uC/OS-II that we are starting an ISR  */
    OSIntNesting++;
    OS_EXIT_CRITICAL();

    OSTimeTick();               /* Call uC/OS-II's OSTimeTick()               */

    OSIntExit();
}

      該函數首先是對操作系統嵌套計數自加操作,當退出中斷處理程序時,會對該計數變量減操作。其他對方對OSIntNesting的引用都會判斷如果該值大於0,則是出於中斷中,如果該值等於0,則說明已經從中斷中退出,加操作(OSIntNesting++)必須對應於退出中斷的減操作(OSIntNesting--),否則會其他地方對OSIntNesting的操作會認為始終出於中斷處理程序中。

      OSTimeTick是對所有出於等待狀態的task等待delay時間片減操作,如果有任務的等待時間已經變成0,則需要將該任務加入到readytable中,為任務切換到該任務做准備。

  OSIntExit函數首先會判斷嵌套等級變量OSIntNesting是否大於0,如果是會做減操作,然后判斷是否所有的中斷都已經處理完成,如果是,則會任務調度,會切換到高優先級的任務;如果不是,則說明只是退出當前中斷處理函數,還有其他中斷處理沒有結束。

 

      操作系統的移植,一個比較重要的設計操作系統切換的任務堆棧,ucos在創建任務的時候會有一個OSTaskStkInit操作,該操作的目的是為當前創建的task構建一個stack,該棧中存儲的內容是像該任務剛被中斷一樣,模擬保存一些寄存器的值,當任務切換到當前task時,由任務調度函數操作從棧中彈出保存的內容,從而實現任務的切換。雖然說在中斷等發生時cpu會自動保存一部分寄存器,但是我們是通過模擬的方式實現的類中斷操作,所以cpu自動保存的內容,我們在創建task的時候也要給模擬實現。因為中斷操作會pop出cpu自動保存的寄存器的值,在任務切換過程中,也會pop我們模擬存儲的自動保存的寄存器的值,比如在STM32中的xPSR, PC, LR, R12, R3-R0等。

      以上這些操作是ucos操作系統移植在STM32上的一些關鍵步驟和原理,在此作為學習筆記記錄下來,為以后使用。網上有很多關於該操作系統移植的詳細介紹,可供參考,其中百度文庫中有一篇《ucosii在STM32上的移植詳解》講解的很不錯,可供大家學習。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM