從0開始的FreeRTOS(3)

2022-03-24 15:56:06 字數 3850 閱讀 8429

這次我們開始介紹freertos的任務管理機制。

在第一講中,我們知道了作業系統是在乙個在記憶體中自動對任務進行排程的硬體和使用者的『中間層』,這一講中我們來介紹作業系統所作用的物件——任務

當然,在講述作業系統原理時我們不會使用任務這種說法,一般被使用的術語是——程序

我們先簡單介紹一下程序的概念,對於程序,我們很難找到乙個準確的定義,一般我們會將程式的一次執行當成乙個程序,更準確的說,我們將乙個程式在乙個資料集合上的執行過程當成乙個程序,這說明程序包含著動態的概念,一段程式執行時,我們一般劃分成三個階段,開始執行--->執行中--->執行完成。這也恰好對應了程序的工作狀態:就緒態--->執行態--->終止態。

程序除了以上三種狀態,還有乙個重要的狀態被稱位阻塞態,關於阻塞態以及狀態之間的轉換關係我們將在程序排程的部分詳細講解。

值得一提的是,在freertos中,程序的四種基本工作狀態是就緒態(ready),執行態(running),阻塞態(blocked)和掛起態(suspended),和常見的作業系統有微小的區別。

在作業系統中,我們將程序作為排程和資源分配的基本單位。也就是說,作業系統真正做的事情,就是在這些使用者建立的程序之間來回切換,按照使用者的需求進行管理。

實際的**中,我們看見的'程序'是這樣的

可以發現程序中存在著無限迴圈執行的部分,這個迴圈中的內容就是我們需要程序執行的內容,顯然我們在執行作業系統時,不可能只讓乙個程序無限的執行下去,因此這個無限迴圈一定是會被打斷的。

而何時打斷這個無限迴圈,也就是阻塞這個程序,並切換成另乙個程序來執行,就是我們的排程所要解決的基本問題。

結合我們之前所說的程序的工作狀態的概念,實際上排程的主要任務就是將程序從乙個工作狀態切換到另乙個工作狀態,比如傳送將乙個正在執行的程序阻塞,或者喚醒乙個阻塞的程序讓它開始執行。

每乙個程序都會有乙個自己專屬的資料區域用來儲存程序的基本資訊,比如程序的名稱,目前的工作狀態等,這個資料區域被成為程序控制塊(tcb),作業系統在進行程序排程時實際上就是對程序控制塊進行操作。

在freertos中,tcb被稱為任務控制塊。在freertos的原始碼task.c中,我們可以找到如下的結構體(為了方便截圖刪去了巨集的部分),可以發現其中就包含了xgenericlistitem這樣乙個成員用來記錄程序的工作狀態。

關於freertos的核心究竟是通過何種手段來操作程序控制塊,繼而操作程序,我們就不加以介紹了,有興趣者可以檢視如下資料

下面我們開始介紹本講真正的重頭戲——排程機制

我們已經知道了,排程的主要任務是執行任務的工作狀態切換,那麼排程時我們的作業系統會遵循什麼原則呢?

首先我們明確這樣一件事,一般在使用freertos時,我們會設定程序為可打斷的,這種時候我們稱作業系統的排程為剝奪方式(也可稱為搶占式)。在freertosconfig.h中,我們通過這樣乙個巨集定義完成這個設定

如果將1改為0的話,則程序不能被打斷,稱之為非剝奪式或者合作式排程。

下面我們來重點介紹三種排程演算法,分別是——

先來先服務(first come first service)演算法的機制是系統按照程序的就緒順序進行排程,在fcfs演算法中,程序是不會發生打斷的,我們舉乙個簡單的例子,假如程序p1,p2,p3依次就緒,那麼最後排程的結果就會是p1-p2-p3。fcfs的優點是簡單和公平的排程演算法,但是其效率很低,由於程序不能被打斷,如果執行時間很長的程序先就緒,程序的平均等待時間就會很大。

優先順序排程演算法與fcfs演算法不同,優先順序排程演算法是剝奪式的,其機制是給每乙個任務分配優先順序,當乙個程序在執行時,如果有另乙個更高優先順序的程序就緒了,則阻塞當前的程序,轉而執行更高優先順序的程序。這個機制和32的中斷巢狀比較相似。

一般優先順序排程演算法可以分為靜態優先順序和動態優先順序排程演算法,靜態優先順序演算法即一開始給程序分配完優先順序之後就不再改變,動態優先順序則是在程序執行時還會根據情況對程序的優先順序進行改動。

用cubemx生成的freertos預設有七個優先順序,這七個優先順序定義在了cmsis_os.h中。優先數越大,則系統優先順序越高。

如果覺得不夠用,在freertosconfig.h中,我們可以通過更改這個巨集定義來更改優先順序的總個數

時間片輪轉排程演算法,為了避免出現乙個程序持續過久,導致後面的程序過長時間等待,系統會劃分時間片,當乙個程序的執行時間超出了時間片長度時,系統會阻塞該程序,下面是乙個時間片輪轉排程演算法的例子

在freertos中,時間片輪轉排程演算法應用在同優先順序的任務上,可以通過設定freertosconfig.h中的巨集定義為0來關閉時間片輪轉排程,否則freertos會預設採用。

時間片長度由 configtick_rate_hz 這個巨集定義決定, 如果設定為1000則 表示時間片的長度為1/1000 s ,即1ms.

介紹完上面的三種排程演算法之後,我們就可以總結出freertos的基本排程方式了,對於freertos而言,不同優先順序的程序之間採用優先順序排程演算法,對於同優先順序的程序之間採用時間片輪轉排程演算法+fcfs演算法。

最後我們關心一下系統進行排程的時機,綜合以上演算法,一共有以下幾種情況時會發生排程

當前程序執行時,有更高優先順序的程序就緒了,則切換成更高優先順序的程序來執行

當前程序執行時長超出了時間片,切換成同優先順序的已經就緒的程序來執行

當前程序執行完畢,或在執行過程中進入了掛起態,則切換成已經就緒的同優先順序任務

最後需要注意的是,freertos工程依然是可以響應硬體產生的中斷的,如下圖所示,硬體產生的中斷可以打斷任意優先順序的程序並執行相應的中斷服務程式。但也有特殊的情況,當乙個程序工作在臨界段中時,外界的中斷是會被遮蔽掉的,這部分的內容我們會在中斷管理章節進行詳述。

最後回答一下第二講中提到的乙個問題,為什麼在建立工程時我們會設定timebase為tim1而非systick呢?

我們假設將systick設為時基。

因為在實際進行程序排程,比如時間片輪轉排程時,我們需要使用到systick的中斷,由於我們需要任意硬體中斷可以打斷系統程序,我們就必須將systick的中斷優先順序設定為最低。

但與此同時,硬體中斷在執行時,也需要乙個時基來協助中斷的進行,因此這個時基就必須比任何乙個中斷的優先順序都要高(也就是這個時基一定是一直在穩定的記時,永遠不會被任何中斷打斷)。

這樣就產生了乙個矛盾,systick不可能既是最高優先順序又是最低優先順序,解決這個矛盾的方法就是使用另乙個定時器來代替systick充當時基。

在這一講中,我們介紹了freertos中的任務(程序)的概念,並詳細說明了freertos的排程機制,在下一講中,我們將通過乙個實驗來學習freertos中的有關任務管理的api的使用 ,並加深對freertos的任務排程機制的理解。

從0開始的FreeRTOS(1)

這個系列的教程的主要目的是帶大家了解實時系統 real time operating system 的基本概念,熟悉freertos的api使用方法,具備基本的使用rtos進行工程開發的能力 系列計畫分幾期錄完,內容分別為 本教程的開發環境 我們這節課主要解決兩個問題 什麼是rtos?為什麼要用rt...

從0開始 二

slam是指當某種移動裝置 如機械人 無人機 手機等 從乙個未知環境裡的未知地點出發,在運動過程中通過感測器 如雷射雷達 攝像頭等 觀測定位自身位置 姿態 運動軌跡,再根據自身位置進行增量式的地圖構建,從而達到同時定位和地圖構建的目的。sfm structure from motion 是一種和sl...

VC usb程式設計從0開始

課題 通過usb來顯示外部電子羅盤的資料.環境 vs.net 2003,usb使用方法 第3方庫 ntddk 日期 2010 02 25 進度 完成指南針顯示ui 未完成 1,微控制器部分工作 2.usb通訊部分.目前遇到的問題 第三方庫新增進來之後,還未移植,編譯的出現問題.日期 2010 02 ...