【阿福的隨筆】NXP i.MXRT 系列之淺談 嵌入的 OS 使用方式(上)

關鍵字 :NXPi.MXRTRTOS

一、說明

NXP i.MXRT 通常都有嵌入的 OS

那什麼是 OS ?  OS 就是 Operating System 作業系統

那什麼是 RTOS ? Real Time OS 即時作業系統

而 FreeRTOS 是一種免費可使用  RTOS ,但它比較精簡,沒有控制週邊,比較像是即時的分時多工的程序。以下是 FreeRTOS 的下載點

FreeRTOS V10.0.0

下載點 : https://sourceforge.net/projects/freertos/files/FreeRTOS/V10.0.0/FreeRTOSv10.0.0.zip/download

Amazon FreeRTOS

下載點 : https://github.com/aws/amazon-freertos

二、FreeRTOS程式碼的架構的淺談

先說一下如何處理記憶體的,FreeRTOS提供了四種記憶體組態的模式:

  • 僅組態(allocate only) => 需要才分配
  • 以非常簡易但快速的演算法進行組態與釋放
  • 搭配記憶體合併,以較複雜但快速的演算法進行組態與釋放
  • 搭配互斥保護,以 C 函式庫組態進行組態與釋放

 

程式碼的架構分為三個主要區塊:任務、通訊和硬體界面。=>

任務 (task) 是在 FreeRTOS 中執行的基本單位,每個 task 都是由一個 C 函數所組成,意思是你需要先定義一個 C 的函數,然後再用 xTaskCreate() 這個 API 來建立一個 task,這個 C 函數有幾個特點,它的返回值必須是 void,其中通常會有一個無限迴圈,為什麼要無限迴圈,程式不就卡住了,其實可以想像,每個任務都有能執行的時間,一但分配的時間到了,執行的權限也會被 FreeRTOS 收回,所有關於這個 task 的工作都會在迴圈中進行,而且這個函數不會有 return,FreeRTOS 不允許 task 自行結束(使用 return 或執行到函數的最後一行)

Task 被建立出來後,它會配置有自己的堆疊空間和 stack variable(就是 function 中定義的變數),可以想像就是獨立的一塊程式,有自已專屬的執行區域,別的程式的無法干擾的。

Task  若要是需要 Delay,一般是設定 vTaskDelayUntil,將此 TASK 設定fwakeup 的時間後,進 IDLE ,將執行權給次高優先權的 TASK,而不是浪費時間在一個固定的程序點等待,計數時間到了之後,再進入分時執行的排序。

 

Task 的狀態

  • Ready:準備好要執行的狀態
  • Running:正在由 CPU 執行的狀態
  • Blocked:等待中的狀態(通常是在等待某個事件)
  • Suspended:等待中的狀態(透過 API 來要求退出排程)

 

Blocked vs Suspended

blocked 是說如果有個 task 將要等待某個目前無法取得的資源(被其他 task 佔用中),則會被設為 blocked 狀態,這是被動的,並不會讓 TASK 下 Command直接進入 Blocked ,OS 會呼叫 blocking API 來設定 task 進入 blocked queue。若是資源釋放之後,會將之前受阻的 task 從blocked queue 取出執行。

 

suspended 與 blocked 的差異在於,suspended 是 task 主動呼叫 API 來要求讓自己進入暫停狀態的,所以在 TASK 下完 suspended 之後,可將控制權轉移到其它的 TASK 。

 

運行的基本規則

工作排程

  • Scheduler 中 context switch 的作法
  1. 參考TaskYield(),此函數會產生PendSV中斷,對應的中斷處理程序則是xPortPendSVHandler()
  2. 儲存 Stack Pointer(psp) 與 current TCB ( Task control block )。
  3. 呼叫 vTaskSwitchContext(),找出 ready queue 內 highest priority item當成欲執行的Task。
  4. 將要執行的 Task 放至 pxCurrentTCB。
  5. 此時 pxCurrentTCB 已經指向下一個要執行的 Task。跳離 xPortPendSVHandler()。
  • SVCall: supervisor call(在OS的環境下的請求管理程序)
  • Pending : 如果一個發生的Event不能被立即響應,則稱為 pending
  • PendSV:Pending supervisor ( 停掉請求管理程序 ) 在 OS 的環境下,通常是用於 Task switch

 

  • 當 FreeRTOS 要進行scheduling時。其作法參考 vTaskStartScheduler()

 建立一個任務,此任務名稱為 prvIdleTask,此Task具有最低的優先級別 (priority=0),因此不會妨礙其他高優先級的任務。一般可以在Idle Task加上以下功能:將CPU設定為低功耗模式,進入省電模式。根據Idel task獲得執行的時間,來判斷系統是否忙碌。

prvSetupTimerInterrupt(),設定 SysTick Interrupt 產生的時間為 ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL,並啟動timer。

產生 SVC 中斷以運行開機後的第一個Task,即IdleTask。

之後,每次當timer expired發生 SysTick interrupt,便會呼叫xPortSysTickHandler(),強制產生PendSV中斷,進行 context switch,進行上述 context switch 的工作,並且累加xTickCount。

  • FreeRTOS的Delay()
  1. vTaskDelay():

設定任務從調用TaskDelay()開始,到離開suspended狀態(進入ReadyState),共需要多少的時間Tick週期,xTimeToWake = xTickCount(此時系統的時間) + xTicksToDelay

  1. vTaskDelayUntil():

設定任務從上一次離開suspended狀態,到此次離開suspended狀態(進入ReadyState),共需要多少的Tick週期,xTmeToWake = *pxPreviousWakeTime(上一次離開suspended狀態的時間) + xTimeIncrement

  1. 此兩個函數主要差異點在於Delay時間的計算,若是需要一個固定執行週期,使用 vTaskDelayUntil() 可以獲得較準確的延遲時間。

 

 

通訊

在 FreeRTOS 中,task 之間的溝通是透過把資料傳送到 queue 和讀取 queue 中資料實現的

 

硬體驅動

是與實際上的板子線路有關,例如要如何驅動 GPIO , I2C ,SPI 等等,一般會使用  Polling mode 或是與 DMA 搭配使用,若要使用中斷的話,直接使用很容易會造成 RTOS 出問題,要先做優先權管理規劃

 

Task錯誤

這種可能性存在於如果在 loop 中發生執行錯誤 (fail) ,則需要跳出迴圈並終止 Task (自己)執行,或是由其它 Task 來刪除,此時就需要使用 vTaskDelete 來刪除 Task

發生 Task fail 的情形,大部分是使用了,不能使用的資源。

不外乎是 存取的 memory 不存在,或是 address 錯誤或是呼叫了,沒辦法執行的裝置,例如 沒有 init UART port,而丟出 UART message,或是要連到 web server ,但是沒有網路的情形。如果繼續執行也是會一直沒有回應,就需要使用 vTaskDelete 來刪除自己目前所執行的 Task 。若直接卡住,就需要由其它的 Task 來執行 vTaskDelete 刪除卡住的 Task了。

 

三、參考資料

https://zh.wikipedia.org/wiki/FreeRTOS

http://wiki.csie.ncku.edu.tw/embedded/freertos

 

★博文內容均由個人提供,與平台無關,如有違法或侵權,請與網站管理員聯繫。

★文明上網,請理性發言。內容一周內被舉報5次,發文人進小黑屋喔~

評論