µC/OS-II 在AndesCore™ N1033A-S 上的移植

Facebook
Twitter
LinkedIn

周傑,應用工程師,晶心宏科技(杭州)有限公司

µC/OS-II 是一種代碼公開、可裁剪的嵌入式即時多工作業系統。該內核通過實現搶佔式任務調度演算法和多工間通信等功能,使之具有執行效率高、即時性能優良等特點。另外,其佔用空間非常小(最小可裁剪至 2KB)並且具有高度可攜性,因此被廣泛的應用於微處理器和微控制器上。

晶心科技 (Andes)作為亞洲首家原創性32 位元微處理器IP 與系統晶片平臺設計公司,推出的 AndesCore™ N10 系列產品 N1033A-S, 搭配應用廣泛的嵌入式即時操作系統 µC/OS-II 以及相關的軟硬體開發資源,有效的説明客戶降低現有成本、提升系統效能、減少系統功耗,並縮短產品開發上市時程。本文將介紹如何將 µC/OS-II 移植到 AndesCore™ N1033A-S 處理器上。

1. 開發環境及處理器介紹
  1.1 軟/硬體開發環境
   本移植過程使用的軟體環境是 AndeSight™ v1.4 集成開發套件,它是晶心科技最新推出的針對各種 AndesCore™的軟體整合式開發環境,包括編譯器、調試器、分析器以及強大的 ESL 工具。硬體平臺採用晶心科技的 FPGA 評估板ADP-XC5,該評估板採用 AndesCore™ N1033A-S 作為處理器內核,並具有豐富的片上資源。

AndesCore™ N1033A-S 介紹
  AndesCore™ N10 系列產品 N1033A-S 是一款哈弗結構的 32 位RISC 處理器內核,具有 5 級流水線(pipeline)及動態分支預測(Dynamic branch prediction) 架構。N1033A-S 新加入了最新 AndeStar™ V2 指令集,把 CPU 效能推至1.66DMIPS/Mhz 之上。同時還實現完整的 Audio 指令集,達到完全整合 CPU 與 DSP 功能的目標。N1033A-S 還支援向量中斷模式以及 2D 直接記憶體存取(DMA)功能,更為即時信號處理添增效能。

2.µC/OS-II 在 N1033A-S 上的可攜性分析
  µC/OS-II 具有高度可攜性,目前已經移植到近 40 多種處理器體系上,涵蓋從 8 位到 64 位的各種 CPU(包括 DSP)。
  µC/OS-II 的正常運行需要處理器平臺滿足以下要求: 1)處理器的 C 編譯器能產生可重入代碼;2)用 C 語言就可以打開和關閉中斷;3)處理器支援中斷,並且能產生定時中斷;4)處理器支援能夠容納一定量資料的硬體堆疊;5)處理器有將堆疊指標和其它 CPU 寄存器讀出和存儲到堆疊或記憶體中的指令。
  AndesCore™ N1033A-S 內部提供了 32 個通用寄存器,其中 R31 被用來做專門的堆疊指標。32 根位址線最多可訪問 4GB 存儲單元,因此只要系統 RAM 空間允許,堆疊空間理論不會產生限制。N1033A-S 處理器提供的 AndeStar™ V2 指令集包含了豐富且十分高效的對堆疊進行操作的指令。例如指令 SMW(store multiple word)可實現僅使用一條指令將多個寄存器的值存儲到堆疊中並同時更新堆疊指標位置,而且還能很好的處理位址非對齊字的存取。N1033A-S 支援中斷並能產生計時器中斷,處理器中的 PSW(Processor Status Word)寄存器中包含一個全域中斷禁止位 GIE,控制它便可實現打開和關閉中斷。此外, AndeSight™整合式開發環境中內置的編譯器可以產生可重入代碼,並且支援內聯彙編,C 環境中可以任意進行開關中斷的操作。綜上所述,µC/OS-II 完全可以移植到 N1033A-S 上運行。

3. 移植步驟
  為了方便移植,大部分的 µC/OS-II 代碼是用 C 語言寫的,使用者只需要用 C 語言和組合語言寫一些與處理器相關的代碼就可以實現移植。這部分工作的內容包括:一個完成基本設置的標頭檔 os_cpu.h、一個與處理器相關的彙編檔os_cpu_a.S 和一個與作業系統相關的 C 代碼檔 os_cpu_c.c。

3.1 在 os_cpu.h 中完成基本的配置和定義
   3.1.1. 定義與處理器相關的資料類型
  為保證可攜性,µC/OS-II 沒有直接使用 C 語言中的 short、int 和 long 等資料類型的定義,因為不同的處理器有不同的字長。對於 N1033A-S 這樣的 32位處理器,其資料類型定義實現如下:

   3.1.2. 定義中斷禁止/允許宏
  做為即時內核,µC/OS-II 需要先禁止中斷再存取碼臨界區,並且在訪問完畢後重新允許中斷。µC/OS-II 定義了兩個宏來禁止和允許中斷: OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。在N1033A-S 處理器上的實現代碼如下:

GIE_SAVE 和 GIE_RESTORE 的實現如下:

中斷禁止時間是判斷系統即時性的重要指標之一。中斷禁止時間能否達到最短,不僅與作業系統的設計有關,還依賴於處理器結構和編譯器產生的代碼品質。

從上面的實現代碼看到,由於 Andes 處理器提供了 setgie.d 和 setgie.e 兩條直接控制中斷的開關的指令,整個禁止/允許中斷的過程經過編譯器產生的機器碼只有 3/2 條,最大限度地減小了中斷禁止時間。

   3.1.3. 定義棧增長方向
  µC/OS-II 使用結構常量 OS_STK_GROWTH 來指定堆疊的增長方式,設置為 0 表示堆疊從下往上增長,設置為 1 表示從上往下增長。這裡我們定義成後者, 即堆疊的增長方向是從記憶體高位址向低位址方向遞減並且堆疊指標總是指向棧 頂數據:

   3.1.4. 定義 OS_TASK_SW()宏
  OS_TASK_SW()是一個宏,它在 µC/OS-Ⅱ 從低優先順序任務切換到最高優先順序任務時被調用的。任務切換只是簡單的將處理器寄存器保存到將被掛起的任務的堆疊中,並且將更高優先順序的任務從堆疊中恢復出來。可採用兩種方式定義這個巨集,使用軟中斷將中斷向量指向 OSCtxSW()函數;或者直接調用 OSCtxSW() 函數,這裡我們採用後者(OSCtxSW()函數的實現將在後面介紹):

3.2 處理器相關部分彙編實現
    µC/OS-Ⅱ 的移植需要使用者編寫三個最基本的組合語言函數: OSStartHighRdy(),OSCtxSw(),OSIntCtxSw()。它們會共用一些代碼,為了方便閱讀將它們寫在同一個彙編文件 os_cpu_a.S 中。

   3.2.1 OSStartHighRdy():運行優先順序最高的就緒任務。
   OSStartHighRdy()函數是在 OSStart()多工啟動之後,負責從最高優先順序任務的 TCB 控制塊中獲得該任務的堆疊指標 SP,並通過SP 恢復 CPU 現場以啟動最高優先順序的任務執行。另外 OSStartHighRdy()還必須在最高優先順序任務恢復之前和調用 OSTaskSwHook()之後設置OSRunning 為 TRUE。其實現代碼如下:

   3.2.2 OSCtxSw()和OSIntCtxSw()
   OSCtxSw()是任務優先順序切換函數,它的作用是先將當前任務的 CPU 現場保存到該任務的堆疊中,然後獲得最高優先順序任務的堆疊指標,並從該堆疊中恢復此任務的 CPU 現場,使之繼續執行,該函數就完成了一次任務切換。
OSIntCtxSw()是中斷級的任務切換函數。由於中斷可能會使更高優先順序的任務進入就緒態,因此為了讓更高優先順序的任務能立即運行,在中斷服務副程式最後會調用 OSIntCtxSw()做任務切換。這樣做能夠儘快的讓高優先順序的任務得到相應的處理,保證系統的即時性能。
OSCtxSw()和OSIntCtxSw()都是用於任務切換的函數,其區別在於,在OSIntCtxSw()中無需再保存處理器寄存器,因為在OSIntCtxSw()之前已發生中 斷,所以可以保證所有的處理器寄存器都被正確地保存到了被中斷的任務的堆疊之中。OSCtxSw()和OSIntCtxSw()實現代碼如下:

  N1033A-S 處理器定義了四級(0-3)中斷,在各級中斷的轉換時需要保存當前中斷層級的寄存器。調用 OSCtxSw()時,中斷將由 0 級(即沒有中斷)轉到 1 級,所以需要將第 0 級的寄存器 PSW 和 PC 保存到第 1 級的寄存器 IPSW 和 IPC 中。CtxSave 和 CtxRestore 兩個宏用來保存和恢復任務上下文。需要保存或恢復的寄存器包括 32 個通用寄存器(R0-R31)的值、程式計數器(PC)的值以及處理器狀態字寄存器(PSW)的值。宏IntlSwitch n 通過修改 PSW.INIT的值來切換中斷層級。CtxSave 和 IntlSwitch的彙編實現如下(由於 CtxRestore 與CtxSave 過程類似,這裡不做贅述):

3.3 移植 C 語言編寫的幾個與作業系統相關的函數
    µC/OS-Ⅱ 有六個與 CPU 相關的函數:OSTaskStkInit()、OSTaskCreateHook()、OSTaskDelHook()、OSTaskSwHook()、 OSTaskStatHook()、OSTimeTickHook(),它們被定義在 ucos_ii.h 中。其中唯一必須移植的函數是任務堆疊初始化函數 OSTaskStkInit(),其它五個函數必須的得聲明但沒必要包含代碼。因此這裡我們只介紹 OSTaskStkInit(),其代碼的實現如下:

  OSTaskStkInit()在任務創建時被調用,負責初始化任務的堆疊結構並返回新堆疊的指標,使得堆疊看起來就像剛發生過中斷並將所有的寄存器保存到堆疊中的情形一樣。除了要保存任務的位址、變數的指標以及處理器狀態字的值外, Andes N1033A-S 處理器還要求用戶保存所有 32 個通用寄存器(R0-R31)、四個用戶寄存器(d0.hi, d0.lo, d1.hi, d1.lo)。還有一點需要注意,在 N1033A-S 處理器中,堆疊指標的地址必須滿足 8Byte 對齊,程式最後一段邏輯即將堆疊指標調整到正確的位置,這一點在編寫其他代碼例如在宏 CtxSave 中同樣需要注意。

4. 結語
  基於 AndesStar™架構的優勢,可以很容易的實現 µC/OS-Ⅱ 在 N1033A-S 處理器上的移植。不僅 µC/OS-Ⅱ ,其它嵌入式作業系統也可以很方便地移植到AndesCore™相應的處理器上,例如 Nuclues、FreeRTOS 以及 Contiki。
  晶心科技利用 AndesCore™ N1033A-S 高效能的Audio ISA 和 FPGA 開發平臺彈性的設計架構,基於各種 RTOS,為客戶提供了豐富的軟體資源(中介軟體、優化的函式程式庫、應用實例等)以及完整的多媒體語音解決方案,從而説明客戶更快地在Andes 平臺上進行產品開發。