--- title: 'RTOS 原理 - 建立 RTT 運行環境' disqus: kyleAlien --- RTOS 原理 - 建立 RTT 運行環境 === ## OverView of Content [TOC] ## RTOS 概述 RTOS (**RealTime Operation System**) 的出現比起其他多用戶系統晚;PC 上的 CPU 出現比單晶片早 1. CPU:首先在 1987 年 Intel 的 8086 CPU 問世 2. 單晶片:之後才是 1981 年 Intel 的 8051 單晶片問世 在這之後 PC & 嵌入式的發展分道揚鑣 ~ ### PC & 嵌入式 - 系統差異 * PC 系統特點: 1. 多任務 2. 多用戶 3. 使用記憶體管理單元 MMU (Memory Manager Unit),無法直接觸碰到實際記憶體位置 4. 系統龐大 * 嵌入式特點: 1. 多任務 2. 實時性 3. 資源很少 (像是記憶體就特別少) 4. 大多可以直接操作晶片中的暫存器 5. 系統較小 兩者使用雙氣泡圖來表示就會如下 > ![](https://i.imgur.com/hkzNg4R.png) ### RTOS 系統 - 基礎原理 * Android、Window、Linux、iOS 等等 PC 系統跟 RTOS 最大的 **差異在 ==實時性==**,但兩者仍有相同之處 (畢竟都基於某個特定硬體特性) 1. **Thread 調度**: * **RTOS 屬於順序執行**:對於每個任務都進行排隊,在處理完一個任務後,才能開始執行下一個任務,這是屬於「非搶佔式」 > ![](https://i.imgur.com/RyqR7o0.png) * **PS 屬於 CPU 輪巡機制**:對於每個任務都給予 **固定的時間,並快速切換**,由於速度快到人無法辨別,所以像是同時處理(這也就是為什麼單核心 CPU 也可以達到多工運行的特性) > PC 系統用「`時間片` + `多工公平排程`」確保使用者體驗 > > ![](https://i.imgur.com/s3fhaTA.png) :::success * **搶佔式調度** 在 CPU 輪尋機制之後再加上每個 **Thread 的++優先性++**,優先性越高的就越會被執行到 (**可能有一些中斷是非常緊急的任務**) ::: :::warning * 但這並不代表 RTOS 不能使用搶佔式調度,同長 RTOS 是使用 🔁 搶佔式調度 + 優先權制度(像是 `RT-Thread`、`FreeeRTOS`) ::: 2. **Memory 管理**: * **RTOS 系統**:在單晶片上,很少會有記憶體管理問題 (其實仍有),記憶體通常由開發人員直接管理,通常資源也需要手動回收 > 較高效率的記憶體管理是,**動態申請內存**,在哪裡需要資源時就可以把不需要的資源釋放,改動到需要記憶體的進程 * **PC 系統**:切換到標準 PC 系統,再加上是 **Multi-Thread** 機制時,就要考慮到多個問題,其中就包括 `初始化`、`排他鎖`、`Memory 回收`... 等等問題 > PC 系統都會有記憶體管理,來自動回收記憶體,也不會讓開發者直接操作到記憶體 3. **中斷管理**: * RTOS 最大的特色就是「即時回應中斷事件」,因為很多嵌入式應用(例如馬達控制、感測器讀取、即時反應)都無法容忍延遲,所以對中斷管理特別講究 > 會有中斷向量的規劃,詳細確定中斷來源的優先權(通常數值越小優先度約高) ```shell= # 假設向量表長這樣: 0x00: Reset_Handler 0x04: NMI_Handler 0x08: HardFault_Handler ... 0x2C: UART0_IRQHandler 0x30: Timer0_IRQHandler ``` * **PC 系統**:在系統中由於有 **Multi-Thread** 所以也要考慮到,產生出的中斷要由哪個 Thread 負責處理,所以必須把中斷管理起來 4. **Thread (Process) 管理**: * RTOS 裸機 (沒有系統):沒有所謂的 Thread、Process 概念,最多只有 **子函數** 的概念,但由於只有子函數,可以間單的 **用全局變量來處理** * 操作系統:由於系統中的 Thread、Process 會將各個使用記憶體隔開,並使用 MMU 分配,需要使用系統中的進程通訊機制 ### Process、Thread - 記憶體管理 * Process 進程、Thread 線程在系統中都是很重要的概念,尤其是其記憶體的分配;Thread 都在一個 **地址空間**,而 Process 則在獨立的 **地址空間** * **地址空間**:系統的運行是 CPU 不斷的取地址、驛碼、執行 :::info * 取地址 ? MCU 根據 PC (`Program Count`) 的計數器 (指向要訪問的地址),去讀取資料,MCU 能訪問的儲存器範圍稱為 **地址空間** ::: > ![](https://i.imgur.com/0pfZt1p.png) * 在 PC 系統著重於多任務、多用戶,所以相當 **注重隱私**,所以 **CPU 新增一個 ==硬體 MMU== (`Memory Managerment Unit`)**,**CPU 不再直接訪問物理空間,而是讓 MMU 進行邏輯地址轉換 (也可稱為映射),再訪問 MMU 轉換後的物理地址** > ![](https://i.imgur.com/ayqt6Xb.png) 這樣的好處就是對於 CPU 來說他們是連續的邏輯地址 (但實際上是完全不同的物理地址) :::danger * 由於這個 MMU 硬體機制讓 RTOS 與其他作業系統分道揚鑣,**在 RTOS 中大部分只會有 Thread 概念** ::: > ![](https://i.imgur.com/V8TrAEu.png) ### RTOS 與嵌入式系統的關係 * ✅ RTOS 是不是一定會在嵌入式系統裡?不是! 嵌入式系統是軟體與硬體的結合,但嵌入式系統並不一定要加載「整個軟體系統」,可以單純的運行簡單的軟體 :::info 這裡說的簡單軟體就無處理太多功能的軟體,而 RTOS 則可以處理複雜功能(像是任務管理、排成、中斷處… 等等) ::: 它常見有兩種常見類型: * 裸機(`Bare-metal`)系統:直接在 MCU 上跑 C 程式,沒有作業系統。適合簡單、對資源要求小的應用(如:LED 閃爍、單一感測器讀值) > RTOS 是軟體,解決多任務與即時性的問題 * RTOS 系統:當系統有多任務(如同時要處理 UART、BLE、觸控螢幕)或有明確即時性需求(如工業控制、車用系統)時,就會使用 RTOS > 嵌入式系統是 「整體解決方案」,RTOS 是其中的一環(但不是必需) ## 建立 RT-Thread 環境 RT-Thread 是一款來自中國的 開源實時作業系統(Real-Time Operating System,RTOS),特別為 資源受限的嵌入式裝置 所設計,具備高度模組化、輕量化、高即時性等特性 以下我們使用 * 開發版:`AT32F407` * 開發 OS 系統環境:`Window` * IDE:`Keil IDE` > ![](https://i.imgur.com/ru4G5yt.png) * RT-Thread 是開源的,可以在 [**Github**](https://github.com/RT-Thread/rt-thread) 上下載到 source code,下載 or git clone > ![](https://i.imgur.com/hTYYzit.png) :::success 這邊使用 Keil 5.36 的版本,下載請 [**參考**](https://www.jianshu.com/p/9513cb06f96c) ::: ### RT-Thread env 工具 * RTOS 有許多組件、配置項目,手動設置、下載較為麻煩,使用官方提供的 Env 工具來進行配置… 像是可以用來下載 BSP 工具、套件管理、設定 `.config` 檔案 1. 進入 [**RT-Thread 網站**](https://www.rt-thread.org/page/download.html) 下載 Env 工具,並解壓縮 > ![](https://i.imgur.com/oFwNlyb.png) 2. 進到解壓縮的目錄中,使用 cmd 開啟 `env.bat` (它會開啟一個新視窗) > ![](https://i.imgur.com/VvCandf.png) 3. 在新開啟的 Window bar 上按右鍵,進入 `Setting` > ![](https://i.imgur.com/BJFXvWB.png) 4. 設定點擊 Integration#Register,並按下保存 > ![](https://i.imgur.com/cFPTnzI.png) 5. 在任何目錄中按下右鍵,就可以看到多出的 `ConEmuHere` 選項,點擊進入後就可以開啟 Env 工具的終端機 > ![](https://i.imgur.com/R0dbeWW.png) ### Keil Env 配置 - 開發環境 * 進入 RT-Thread Source Code 目錄下 1. 使用 `ConEmuHere` 選項開啟該目錄 > ![](https://i.imgur.com/Wtt12I9.png) 2. 輸入 `menuconfig --setting` 命令進行配置 (這邊不進行任何修改,直接 Save) > 空白鍵做選擇、Enter 進入、Esc 退出 > > ![](https://i.imgur.com/lgqPWuG.png) > 選擇 Keil MDK5 > ![](https://i.imgur.com/TrOVL12.png) * 配置 BSP 設定,以下選擇 BSP 模板 (路徑:`\rt-thread-master\bsp\at32\at32f407-start`) :::info * BSP 是什麼? BSP(`Board Support Package`)是一個基於特定晶片、開發版所提供的軟體開發包,更專注於不同硬體的不同設定 ::: 輸入 `menuconfig --setting` 命令進行配置 (這邊不進行任何修改,直接 Save) > ![](https://i.imgur.com/tSANuom.png) :::danger * 就算不做設定仍要開啟 `menuconfig --setting` 並按下 Save,否則無法產生相對應的檔案 ::: ### Keil MDK 5 開啟專案 1. 使用 Keil MDK5 開啟 `project.uvprojx` 檔案 > ![](https://i.imgur.com/IqsECoQ.png) 2. 設定 Debug -> Use 方式,按下 OK > ![](https://i.imgur.com/9QRYbh7.png) 3. 設定 Target -> Usb 燒入,按下 OK > ![](https://i.imgur.com/lE4Ps20.png) 4. 按下 Build 按鈕 > ![](https://i.imgur.com/CXTSuAh.png) 5. 燒入進 AT32F407 開發板 > 成功後會看到 3 個 LED 輪流亮起 :::danger 必須要有 MDK 5 的 License,否則無法燒入進去 ::: ### Debug 工具 - FinSH * RTT 有提供一個方便的 Debug 工具 FinSH,可以透過終端機進行函數測試,以下新增 `hello.c` 文件,簡單的輸出一段文字 ```c= // hello.c #include <rtthread.h> #include <finsh.h> int hello_func(int argc, char** argv) { rt_kprintf("Hello RT-Thread World~! \n"); return 0; } // 定義要測試的 Function MSH_CMD_EXPORT(hello_func, hello); ``` **MSH_CMD_EXPORT** 是一個宏定義,第一個參數是 function name、第二個參數是 function nick name (別名) > ![](https://i.imgur.com/Nws1RQQ.png) * 串口調適使用 Microsoft Store 中的 App (**串口調試助手**) > ![](https://i.imgur.com/btZJPf9.png) * 測試 FinSH 功能 1. 燒入 RTT 提供的 Source Code,並確認運行 2. 開啟串口調適工具,並請指定正確的 Port 號、115200、8N1 > ![](https://i.imgur.com/gr8rUxK.png) 3. 輸入要測試的 Function Name 在按下發送,RTT 就會執行指定 Function (使用這個串口工具需多輸入 Enter) > ![](https://i.imgur.com/FH7wVXK.png) ## Appendix & FAQ :::info ::: ###### tags: `RTOS`