FreeRTOS
ESP32 / STM32 / Pico / Pico 2 ↗
Zephyr
ESP32 / STM32 / nRF52840 ↗
NuttX / ChibiOS
Pixhawk 4
PX4 + NuttX / ArduPilot + ChibiOS ↗
Linux / PREEMPT_RT
Raspberry Pi 5 / Jetson Orin / Intel / AMD ↗本文內容
本文內容
機器人需要正確的指令,而且指令必須在還來得及發揮作用時送達。**即時作業系統(RTOS)**負責協調感測到致動之間的工作。本文以一次關節修正為例,追蹤感測器輸入如何通過 RTOS 架構,最後成為硬體輸出。
1. 處理器很快,為什麼機器人還是反應太慢?
四足機器人偵測到不平整階梯,算出正確的修正量
一台四足機器人踩上破損的鋪路石。編碼器回報關節角度改變,慣性量測單元(IMU)偵測到機身旋轉。控制器算出修正量,但指令傳往關節的途中,機器人仍持續移動。

算得正確,只是其中一部分。根據先前姿態產生的指令,可能在姿態已經改變後才送達。
修正指令送到關節時,已經錯過需要它的時刻
假設這個範例要求致動器指令在感測器取樣後的 1 ms 內生效。即使用 0.2 ms 算出答案,也不能證明完整回應過程都在時限內。
- 週期
- 排定更新之間的時間間隔
- 截止時間
- 允許完成的最晚時刻
- 反應時間
- 從取樣到指令套用
- 抖動
- 不同更新之間的時間變動
平均回應時間很短,仍可能掩蓋偶爾發生的更新延遲。即時控制要求整條路徑的耗時有足夠嚴格的上限,並維持穩定。ROS 2 即時背景說明 詳細解釋了這項差異。
2. 控制器如何協調每個步驟
CPU、記憶體與驅動程式如何將感測值變成關節指令
在以微控制器為基礎的嵌入式系統中,CPU 讀取量測值、計算目標值,再呼叫驅動程式。驅動程式設定周邊裝置,由周邊裝置將訊號送到致動器介面。
機器人硬體指南 說明馬達、傳動機構、感測器與關節負載如何共同決定致動器介面。
- 感測器IMU/編碼器擷取取樣資料
- CPU + RAM控制任務計算目標值
- 驅動程式暫存器寫入設定傳輸
- 周邊裝置計時器/CAN傳遞訊號
- 關節驅動器功率級套用指令
PWM 驅動程式可以寫入計時器的比較暫存器,接著由計時器產生脈衝,不必讓 CPU 逐一切換訊號邊緣。匯流排驅動程式則準備資料傳輸,有時也會借助 DMA。寫入暫存器、完成傳輸、套用指令,是三個不同的時刻。
從指令層級來看,記憶體映射暫存器是由周邊匯流排解碼的位址。CPU 的儲存指令改變的是硬體狀態,而非一般 RAM 變數。計時器可能直到下一個更新邊界,才鎖存新的比較值;ST 計時器應用指南 說明了這種預載機制。CAN 傳輸也必須等待匯流排存取權,之後再由驅動器決定套用指令的時機。這些等待並不是選好任務就能解決的。

- 01CPU儲存指令
- 02計時器比較暫存器
- 03PWM波形
- 04馬達驅動器
控制接腳傳遞訊號,馬達驅動器供應運轉所需的電力,也可能自行執行更快的電流迴路。支撐實體 AI 的電子系統 介紹了周邊電路與供電路徑。
xTaskCreate()設定的配置器從堆積中提供 堆疊與TCB 。
xTaskCreateStatic()應用程式提供 堆疊陣列與TCB儲存空間。
- 堆疊
- 區域變數、函式呼叫與保存的CPU執行脈絡
- TCB:任務控制區塊
- 優先順序、串列連結與指向已保存堆疊脈絡的指標
每個任務都需要 RAM 來存放執行堆疊與 TCB。堆疊保存函式呼叫狀態及已儲存的暫存器;TCB 告訴核心,這些上下文位於何處。即使任務處於阻塞(Blocked)狀態,堆疊空間仍會保留。
xTaskCreate()xTaskCreateStatic()在上游 FreeRTOS 中,xTaskCreate() 透過設定的配置器取得堆疊與 TCB,xTaskCreateStatic() 則接收應用程式提供的儲存空間。兩種方式都使用 RAM;靜態建立只是省去這些物件的堆積配置。上游 FreeRTOS 以 StackType_t 元素數量表示堆疊深度,ESP-IDF 的任務建立 API 則使用位元組。直接沿用堆疊大小之前,應核對任務 API
與 IDF 移植版本的差異
。
記憶體預算有助於理解平台分工。小型 FreeRTOS 核心與 Linux 系統提供的服務不同。用這些數據選擇晶片之前,應先比較每個數字實際包含什麼。
| 統計範圍 | FreeRTOS 參考數據 | 嵌入式 Linux 參考數據 |
|---|---|---|
| 核心程式碼 / 儲存空間 | 約 9–18 KBRichard Barry 於 2022 年提供的可用核心設定數據。FreeRTOS 大小討論 ↗ | 約 2–4 MBBootlin 於 2017 年演講中提供的嵌入式核心儲存空間參考。Bootlin 核心大小參考 ↗ |
| 公開範例中的 RAM 用量 | 21,944 位元組 約 22 KB一個 STM32F3 Crane 應用程式的範例,包含堆疊、緩衝區、物件和應用程式資料。2026 年研究 · 表 11 ↗ | 32 MB 以上2022 年針對較實用的小型 Linux 系統提供的參考;極簡系統可能使用更少記憶體。Bootlin RAM 參考指南 ↗ |
記憶體選擇:MCU 韌體、Linux 與配置方式
在 MCU 嵌入式系統中,晶片內建的 SRAM 存放任務堆疊、取樣資料與緩衝區,韌體通常存放於快閃記憶體。具備外部 DRAM 與 MMU 的應用處理器,可以支援 Linux 行程、虛擬記憶體和更完整的驅動程式體系。無論哪一種平台,單靠記憶體容量都無法保證時序。
應在迴圈開始前準備好關鍵工作記憶體。FreeRTOS 支援靜態或動態物件配置 ,但堆疊、佇列與緩衝區的大小仍需由開發者決定。堆積管理指南 介紹了不同的記憶體管理方式。
RTOS 核心內部:任務、中斷與排程如何協作
RTOS 是一種作業系統類別。 FreeRTOS 與 Zephyr 是提供排程及同步機制的具體實作。開發者設定這些機制,並實作自己的應用任務。
為了說明 FreeRTOS 任務排程,本文採用搶先式單核心設定。控制任務等待新資料時,感測與遙測各自擁有執行上下文。
核心將任務狀態保存在**任務控制區塊(TCB)**中。pxTopOfStack 指向已儲存的上下文,uxPriority 決定優先順序,串列項目則將任務連到狀態串列與事件串列。RTOS 上下文切換會從儲存的執行位置恢復任務。
優先順序 3 + 就緒 / 等待串列連結
儲存的 CPU 上下文
允許切換時,排程器會選擇符合條件且優先順序最高的就緒(Ready)任務。若高優先順序任務從不阻塞,低優先順序工作就可能一直沒有執行機會。可參閱 FreeRTOS 任務實作 。
在單核心模型中,就緒串列依優先順序索引。任務因等待佇列而阻塞時,會從就緒集合移除,並登記為等待者;有限逾時也需要管理延遲串列。事件或逾時發生後,任務才重新具備執行資格。核心會保護這些串列更新,避免中斷看到只改到一半的排程結構。部分設定使用針對移植版本最佳化的位元圖查找優先順序,但不是所有晶片都採用同一種演算法。
現在讓感測器觸發資料就緒中斷。下圖呈現完整的交接過程:就緒(Ready)還不等於執行中(Running)。
- 1等待
- 控制
- 阻塞
- CPU
- 遙測任務
控制任務等待新的取樣資料,此時低優先順序的遙測任務可以使用 CPU。
- 2中斷
- 控制
- 阻塞
- CPU
- 感測器 ISR
資料就緒中斷搶先於任務執行,ISR 確認並處理感測器事件。
- 3喚醒
- 控制
- 就緒
- CPU
- 感測器 ISR
可在 ISR 中安全呼叫的核心操作喚醒控制任務。任務已可執行,但 ISR 仍在執行。
- 4切換
- 控制
- 就緒
- CPU
- PendSV / 上下文切換
當高優先順序例外允許切換時,移植版本會儲存原任務的上下文,並還原所選任務。
- 5執行
- 控制
- 執行
- CPU
- 控制任務
例外返回後恢復控制任務,它便可讀取取樣資料並計算關節修正量。
在 Cortex-M4F 移植版本上,切換要求可以將低優先順序例外 PendSV 設為待處理。硬體先儲存例外框架,再由移植版本保存其餘任務上下文、選擇另一個 TCB,並還原該任務。行程堆疊指標(PSP)指向任務堆疊,處理常式程式碼則使用主堆疊指標(MSP)。
R0–R3 · R12 · LR · PC · xPSRR4–R11 · EXC_RETURN- 儲存PendSV 將其餘暫存器儲存到切出任務的堆疊中。
- 選擇
vTaskSwitchContext()在核心保護下選擇下一個可執行任務。 - 還原載入下一個 TCB 的堆疊指標,還原移植版本儲存的暫存器。
- 返回例外返回時還原硬體框架,從儲存的 PC 位置繼續執行。
- PSP
- 任務堆疊指標
- MSP
- 處理常式堆疊指標
- BASEPRI
- 中斷優先順序遮罩門檻
選擇下一個任務時,移植版本會提高 BASEPRI,遮罩可能存取核心資料的中斷優先順序。更緊急的中斷可以維持啟用,但不得呼叫相關 FreeRTOS API。PendSV 處於待處理狀態,並不代表它能強行打斷執行中的更高優先順序處理常式來切換任務。這裡專指 Cortex-M4F 移植版本
,並非 ESP32 的 Xtensa 或 RISC-V 組合語言實作。
搶先式排程可以在兩個節拍之間回應事件。時間片輪替則在節拍到來時,讓相同優先順序的就緒任務輪流執行。兩者使用獨立的 FreeRTOS 設定開關 。
上下文切換內部:暫存器、堆疊與其他排程器
Cortex-M 例外會儲存部分 CPU 上下文。移植版本保存其餘任務上下文與堆疊指標,例外返回時恢復所選任務的指令執行。Memfault 的說明 涵蓋 PSP/MSP、例外框架、BASEPRI 遮罩與浮點上下文。
ISR 必須使用適當的 ISR 安全核心操作,並在 API 或移植版本要求時提出切換要求,不必等到下一個節拍。在適用的 Cortex-M 移植版本上,優先順序高於 API 呼叫許可門檻的中斷,不得呼叫 FreeRTOS API。
FreeRTOS 任務管理範例 進一步介紹單核心模型。Zephyr 排程 則提供不同的就緒佇列實作,以及協作式與搶先式執行緒類別。
佇列、號誌與互斥鎖如何協調任務和共享資源
這裡的 RTOS 任務同步有兩項工作:傳遞感測器取樣資料,以及喚醒等待中的控制任務。應依照跨越任務邊界的內容,選擇適合的核心物件。
| 核心物件 | 承載內容 | 機器人中的用途 |
|---|---|---|
| 佇列 | 資料緩衝的訊息 | 含時間戳記的感測器取樣資料 |
| 二元號誌 | 0 或 1一個可用許可 | 傳輸完成訊號 重複事件可能合併 |
| 計數號誌 | 0 … N多個許可 | 計算可用緩衝區槽位 |
| 互斥鎖 | 所有權資源獨占存取 | 保護任務層級的匯流排存取 基本優先順序繼承 |
取樣資料可用後,等待接收的任務可以從阻塞(Blocked)轉為就緒(Ready),接著才是取得 CPU 執行權。號誌傳遞的是可用狀態,而非取樣資料本身;互斥鎖還包含所有權與基本的優先順序繼承。
FreeRTOS 的佇列由環形資料緩衝區、元素計數,以及等待傳送或接收的任務串列組成。傳送時會複製指定元素大小的位元組,並可能喚醒等待中的接收任務。號誌使用大小為零的資料元素,重複使用佇列機制;關鍵是計數與等待串列,而非資料緩衝區。互斥鎖還會追蹤持有者,讓核心能暫時提高該任務的優先順序。佇列實作 具體呈現了這些關係。
佇列資料新鮮度、事件計數與所有權
二元號誌最多保留一個許可,因此重複事件可能合併。計數號誌追蹤多個可用許可。FreeRTOS 也提供任務通知;若語意符合事件需求,它很適合只有一個接收任務的情境。
應決定控制佇列已滿時,要拒絕新資料、覆寫舊資料,還是回報溢位。累積的舊資料可能不如最新的一筆完整取樣有用。透過指標傳遞訊息時,也必須明確定義緩衝區所有權。可參閱佇列範例 與佇列/號誌共用實作 。
3. 為什麼關鍵修正仍可能延遲
已就緒的控制任務,為什麼不一定能立即執行
高優先順序任務可能已具備執行資格,卻仍無法接手 CPU;也可能還在等待某項相依條件。只提高任務優先順序,無法自動消除這兩種等待。
CPU 正在執行受保護操作或中斷處理,任務必須等待排程。
所需取樣資料、資源或逾時條件尚未滿足。
臨界區、中斷遮罩、排程器暫停與 ISR 執行,都可能延後任務的排程執行,FreeRTOS 也不例外。受保護操作並沒有特殊的「最高任務優先順序」,而是暫時限制可以切換任務的時機。
| 機制 | CPU 或核心的行為 | 控制任務在等什麼 |
|---|---|---|
| 非 RT Linux 自旋鎖 | spin_lock() 會禁止本機任務搶先;IRQ 可能仍保持啟用。 | 受保護區間結束,隨後允許重新排程。 |
| 中斷遮罩 | 被遮罩的中斷來源暫時無法進入處理常式。 | 解除遮罩、處理事件以及隨後的排程執行。 |
| ISR 執行 | 處理常式上下文占用 CPU,不參與一般任務選擇。 | 可以進行例外返回或上下文切換的時機。 |
| 排程器暫停 | vTaskSuspendAll() 會延後任務切換,但本身不會遮罩中斷。 | 排程器恢復以及延後的管理處理。 |
| 互斥鎖相依關係 | 任務因等待另一任務持有的資源而阻塞。 | 持有者繼續執行並釋放資源;優先順序繼承可減少其他任務的干擾。 |
假設未啟用 PREEMPT_RT 的 Linux 中,某個驅動程式持有 spinlock_t。已啟用的中斷可以喚醒更高優先順序的控制執行緒,並提出重新排程要求。但中斷返回後,CPU 仍可能必須先完成驅動程式的受保護區間,才能切換。控制執行緒雖已就緒,剩餘的受保護操作仍需計入它的回應時間預算。
FreeRTOS 的 vTaskSuspendAll() 與中斷遮罩不同:ISR 仍可執行,但任務切換必須等排程器恢復,並處理延後的工作。Cortex-M 臨界區則使用移植版本特有的中斷遮罩。提高任務優先順序,無法取消其中任何一種機制。Linux 鎖定規則
說明了相關自旋鎖與 IRQ 的差異。
數值越大,優先順序越高
- 中 · 2執行日誌記錄
- 低 · 1完成 + 解鎖
- 高 · 3取得互斥鎖 + 控制
- 低 · 1 → 3完成 + 解鎖
- 高 · 3取得互斥鎖 + 控制
- 中 · 2稍後執行日誌記錄
對於支援優先順序繼承的互斥鎖,持有者會暫時繼承等待它的高優先順序任務之優先順序,幫助它完成工作並釋放資源。但這不會消除臨界操作、解決死結,也無法替永遠不回應的裝置設定有效的等待上限。
核心保護、中斷優先順序與多核心鎖
在非 PREEMPT_RT 的 Linux 設定中,取得一般自旋鎖會禁止該 CPU 上的任務搶先。停用 IRQ 的變體還會加上本機中斷遮罩。Linux 鎖定規則 區分了這些機制。
任務優先順序與硬體中斷優先順序是兩回事。移植版本的遮罩門檻,決定哪些中斷可以呼叫核心。在多核心系統中,只靠本機保護,未必能保護其他 CPU 也可存取的資源。
應限制持有資源的時間,並分析鎖定鏈。FreeRTOS 資源管理章節 說明互斥鎖所有權與基本優先順序繼承。
FreeRTOS 與桌面 Linux 有何不同,PREEMPT_RT 又改變了什麼
比較 RTOS 與 Linux 時,必須考量完整回應路徑。兩種核心都會管理任務狀態、優先順序、搶先式排程與中斷;差異在於設定後的系統如何控制整條路徑中的干擾。
- TCB + 依優先順序組織的就緒串列
- 選擇符合條件的最高優先順序任務
- ISR 安全 API 喚醒任務
- 仍存在的延遲: 臨界區可能延後切換
SCHED_FIFO / SCHED_RR可用- 硬中斷處理可能延後排程
spinlock_t禁止本機任務搶先- 仍存在的延遲: 受保護路徑會延後切換
- 大部分 IRQ 工作在執行緒中執行
spinlock_t使用以 RT 互斥鎖為基礎的優先順序繼承- 更多核心路徑變得可搶先
- 仍存在的延遲: raw 鎖和底層路徑仍受保護
PREEMPT_RT 是 Linux 的一種設定,不是 FreeRTOS 功能。 它透過執行緒化中斷,以及支援優先順序繼承的可睡眠鎖,將更多核心工作納入排程器控制。
典型的執行緒化 IRQ 路徑保留一小段硬中斷入口處理,確認或遮罩中斷來源後,再喚醒 IRQ 執行緒。該執行緒依排程策略與優先順序競爭執行機會。PREEMPT_RT 將一般 spinlock_t 改成以 RT 互斥鎖為基礎的實作:競爭者可以睡眠,優先順序繼承則協助持有者繼續執行。raw_spinlock_t、底層入口路徑與其他明確保護的區間,仍無法被搶先。詳見 RT 核心的差異
。
刻度:0–1,500 µs · 虛線:1,000 µs 截止時間
在設定合宜的 PC 上,即時 Linux 可以執行機器人控制。不能直接假設一般 Ubuntu 符合嚴格時限,也不能對未經驗證的 FreeRTOS 系統做出相同假設。開源授權與這項時序問題無關。
即使排程已允許執行,記憶體仍可能增加延遲。使用虛擬記憶體時,指令可能因頁面需要配置、寫入時複製,或讀取檔案/交換區而觸發分頁錯誤;只有部分分頁錯誤會涉及儲存裝置。典型的 MCU FreeRTOS 系統使用常駐記憶體,不採用隨需分頁,但配置、快閃記憶體/快取存取、匯流排與裝置仍可能造成停頓。
- 已預留 RAM
- 重複使用任務堆疊與緩衝區
- 沒有隨需分頁引起的分頁錯誤步驟
Linux 控制執行緒應在迴圈開始前,準備關鍵緩衝區與堆疊頁面,預先存取所需映射以觸發必要的分頁處理,並在檢查錯誤與限制的前提下使用適當的記憶體鎖定。mlockall() 不會讓未來的配置或寫入時複製變得毫無影響。PREEMPT_RT 本身也不會消除分頁錯誤;記憶體鎖定手冊
說明了這些限制。
Linux 優先順序、分頁錯誤與 PREEMPT_RT 的取捨
Linux 提供一般應用程式排程策略,也提供 SCHED_FIFO、SCHED_RR 等即時策略。nice 值不能取代這些策略的設定。排程手冊 定義了相關介面。
位址可使用之前,分頁錯誤可能先帶來額外工作。應預先配置關鍵記憶體、預先存取頁面,並在確認失敗情況與限制後,使用適當的記憶體鎖定。mlockall() 有助於讓記憶體維持常駐,但無法解決 CPU、鎖、快取或裝置延遲。
執行緒化工作與不同的鎖定方式,可能在某些負載下增加額外負擔或降低吞吐量。優先順序、中斷分配、電源管理、CPU 分配與驅動程式都需妥善處理。成本取決於工作負載,並非固定百分比。可參閱 RT 理論 、核心差異 與硬體限制 。
現在為整個修正過程設定同一份時間預算,分別對感測、干擾、計算、傳輸與輸出生效設定上限,並納入打斷計算的高優先順序工作。
固定階段 480 µs + 等待 120 µs = 合計 600 µs
在 1,000 µs 截止時間內 · 餘裕 400 µs
固定階段 480 µs + 等待 800 µs = 合計 1,280 µs
超過 1,000 µs 截止時間 · 逾時 280 µs
取樣 + 等待/干擾 + 計算 + 傳輸 + 套用輸出 ≤ 截止時間。固定階段合計 480 µs。 兩個範例只改變等待時間額度。
等待 120 µs 時,範例總耗時為 600 µs,距離 1,000 µs 截止時間還有 400 µs。等待 800 µs 時,固定工作相同,但總耗時變為 1,280 µs,也就是逾時 280 µs。這些是教學範例數值,不是板卡實測結果。
- 0 µs取得取樣資料感測器時間戳記
- 70 µs進入 ISRGPIO / 追蹤標記
- 190 µs控制開始任務標記
- 390 µs計算結束驅動程式呼叫邊界
- 510 µs傳輸完成匯流排擷取
- 600 µs輸出生效驅動器 / 輸出標記
應量測實際輸出生效的邊界。只看排程延遲,無法知道驅動器何時套用指令;單次執行觀察到的最大延遲,也不能證明最壞情況的上限。
在硬體上驗證完整路徑
為感測器擷取、ISR 入口、任務開始、計算結束、傳輸完成與輸出生效分別記錄時間戳記。GPIO 標記與邏輯分析儀可以協助量測,但標記必須對應同一事件,並明確識別時鐘域。也應對相互競爭的通訊、儲存與中斷施加負載。
Canonical 的 cyclictest 指南 量測的是路徑中與排程相關的部分。Linux 即時應用程式監視器 有助於在支援的核心上診斷分頁錯誤與等待模式。ROS 2 即時背景說明 、PREEMPT_RT 內部機制 與 Zephyr 互斥鎖文件 提供更深入的說明。
4. 從本機控制到完整機器人
建立控制韌體,並透過自訂 SDK 對外提供功能
選擇 FreeRTOS 或 Linux,應從負責感測與動作的硬體出發。RAM、CPU 架構、周邊驅動程式與時序需求,共同決定哪些軟體能勝任。以下針對支援的目標平台,各列出兩個選項範例。
| 晶片 / 開發板 | 兩種軟體選擇 | 適用原因 | 機器人角色與硬體依據 |
|---|---|---|---|
| ESP32 / S3 / C3無線 MCU 晶片內建 SRAM 為數百 KB,容量依晶片而異。 | 精簡的任務核心為 堆疊與無線緩衝區保留空間。IDF 整合晶片驅動程式與服務。 | 無線感測 / 機器人 I/O。 無線模組交換資料,計時器與 GPIO 處理本機訊號。 | |
| RP2040 / RP2350Pico / Pico 2 MCU 264 KB / 520 KB SRAM ↗ | 裸機程式碼避免了核心任務額外負擔;FreeRTOS 在 SRAM 內提供 排程與同步 功能。 | 編碼器 / 脈衝產生。 PIO、計時器和 DMA 可擷取或產生訊號,無須 CPU 處理每個邊緣。 | |
| STM32 F4 / F7 / H7Cortex-M MCU 系列 快閃記憶體與 SRAM 容量依型號而異。 | 可設定的 MCU 核心無須完整的 Linux 行程環境,即可組織 控制、感測與通訊 任務。 | 馬達 / 關節控制器。 ADC、計時器、DMA 和匯流排將回授取樣與致動器指令連接起來。 | |
| Nordic nRF52840無線 Cortex-M4 MCU 256 KB RAM · 1 MB 快閃記憶體 ↗ | Zephyr 整合無線服務;獨立驅動程式適用於 較簡單的周邊裝置韌體。兩者都需要規劃 RAM 用量。 | 電池供電感測器。 無線與睡眠模式適合間歇取樣;裸機 nrfx 本身並不是 Bluetooth 協定堆疊。 | |
| STM32F765Pixhawk 4 飛行控制器 512 KB RAM · 2 MB 快閃記憶體 ↗ | 針對特定板卡的飛行韌體將 RTOS 與 感測器驅動程式、任務堆疊與緩衝區結合使用。 | 無人機姿態穩定。 IMU 取樣、估測與控制共同產生及時的 ESC 指令。 | |
| BCM2712Raspberry Pi 5 應用 SoC GB 級外部 DRAM ↗ | MMU 與外部 DRAM 支援 行程、虛擬記憶體、檔案系統和 Linux 驅動程式。 | ROS 2 / 攝影機 / 閘道器。 多核心運算和攝影機/網路 I/O 支援主機的並行工作負載。 | |
| NVIDIA OrinJetson CPU / GPU 模組 GB 級 DRAM,容量取決於模組。 | Linux 提供 GPU 和裝置服務;在支援的版本中,RT 核心會改變 CPU 排程與中斷處理 機制。 | 視覺 / AI 推論。 GPU 處理影格和張量;CPU 即時調校並不能約束所有 GPU 操作的時限。 | |
| Intel / AMDPC 應用處理器 外部 DRAM + MMU。 | 廣泛的行程與驅動程式平台承載大型應用程式;RT 設定減少 核心造成的等待。 | 開發 / 規劃 / 經驗證的控制。 CPU 能力支援複雜工作負載;直接控制仍需合適的 I/O 和時序驗證。 |
為感測與回授控制指定明確的喚醒條件、優先順序、執行時間上限,並提供足夠的堆疊。不要讓解析、網路通訊、日誌與儲存工作持續占用關鍵迴圈需要的資源。
核心提供排程與同步,韌體提供控制行為和驅動程式,自訂 SDK 則對外提供指令與實測狀態。
前面的中斷交接過程,可以用以下簡短的 FreeRTOS 模式表示。單一元素佇列保留最新的完整取樣資料。應先建立佇列與任務,再啟用中斷,並透過耗時有上限的硬體路徑取得取樣。
void sample_isr(void) {
BaseType_t wake = pdFALSE;
Sample s = read_ready_sample();
xQueueOverwriteFromISR(
sample_q, &s, &wake);
portYIELD_FROM_ISR(wake);
}複製一筆已完成的取樣資料;高優先順序任務被喚醒時要求切換。
void control_task(void *arg) {
Sample s;
for (;;) {
xQueueReceive(sample_q, &s,
portMAX_DELAY);
Target t = target_snapshot();
Command u =
control_step(s, t);
actuator_write(u);
}
}取樣間隔內阻塞等待,使用一致的目標值與耗時有上限的輸出路徑。
ISR 複製一筆已完成的取樣資料,並在需要時提出切換要求。任務等待時不耗用 CPU,接著讀取一致的目標快照、計算下一次輸出,再呼叫驅動程式。多欄位目標值應透過訊息傳遞,或耗時有上限的任務層級鎖,複製成一致的版本;不要在緩慢的 I/O 期間一直持有這把鎖。
週期迴圈應使用適當的計時器或 xTaskDelayUntil(),避免反覆使用相對延遲,讓工作耗時不斷累積。節拍解析度必須符合週期;短於一個節拍的需求,需要合適的硬體計時來源。
在既有核心設定中,指定 configUSE_PREEMPTION、優先順序範圍、配置選項與堆疊大小,再實作任務及其同步。通常是設定與移植排程器,而非自行撰寫就緒串列的選擇邏輯。在支援的雙核心 ESP-IDF 設定中執行 ESP32 上的 FreeRTOS 時,排程器還會考量核心親和性。把任務固定到某個核心,無法隔離共享記憶體或匯流排;本機中斷遮罩也不會停止另一個核心。共享資料需要使用目標平台支援的跨核心同步機制。
- 關節
- joint_3
- position_rad
- 0.15
- sequence
- 42
- 有效期限
- 定義的有效時間範圍
- 實測位置
- 弧度
- 取樣時間戳記
- 宣告的時鐘域
- 已套用的序號
- 使用了哪一筆指令
- 狀態
- 新鮮 / 過期 / 故障
定義單位、接受範圍、時間戳記、序號、確認回應、新鮮度與逾時行為。收到指令,並不等於已執行物理動作。
在通訊邊界上,應明確定義序列化方式,包括欄位寬度、位元組順序、訊框格式及必要的完整性檢查。不要直接傳送原始 C 結構,因為主機端的填補布局可能不同。控制器驗證封包、發布完整目標值,並回報實際套用的序號。逾時後可選擇適合機構的預定義保持、漸降或故障回應。SDK 應呈現這個狀態,不能把接收成功當成動作成功。
開發客製化機器人時,應將這些介面與感測、致動器整合一併界定範圍。VoicePing 的客製化機器人開發 從任務及其運作環境出發。
ESP-IDF、上游 FreeRTOS 與多核心選擇
ESP-IDF 整合自己的 FreeRTOS 實作、驅動程式與啟動路徑。支援的多核心目標還需考量親和性與共享資源。上游 FreeRTOS 也支援 SMP,因此不必手動實作所有多核心排程。
應遵循對應目標與版本的 IDF 文件 。核心綁定可以減少部分競爭,但無法隔離共享匯流排、記憶體或中斷的影響。定義時鐘同步,明確說明時間戳記代表擷取時刻或傳送時刻,再驗證設定後的系統。
核心如何成為產品平台。 客製化可以在核心移植版本、應用韌體或外部 SDK 邊界進行。企業不必重寫排程器,也能打造自己的控制器。
FreeRTOS↓目標移植版本 + SMP 整合 + 硬體驅動程式↓應用任務 + 網路 / 周邊裝置服務開發者客製化的內容任務優先順序、親和性、緩衝區、 同步與應用程式行為。
FreeRTOS 任務↓感測器就緒 → 估測器 → 控制器 → 馬達輸出↓設定值、參數、日誌 + 板級支援開發者客製化的內容控制演算法與驅動程式、 平台設定與應用模組。
rt/lowcmd → 機器人qdqkpkdtau⇅rt/lowstate → 應用程式開發者客製化的內容主機控制邏輯使用 馬達目標值與實測狀態。 SDK 並未說明關節控制器使用的 OS。
Espressif 公開說明了針對其硬體的 FreeRTOS 實作與整合。Bitcraze 的 Crazyflie 展現另一種常見做法:使用 FreeRTOS 任務,再加上感測器 → 估測器 → 控制器 → 馬達的處理流程。穩定控制文件 與韌體原始碼 呈現了這個應用層。
Unitree 則是公開介面層的例子。SDK2 Go2 範例 發布低階馬達指令並訂閱狀態,Python SDK 文件說明了 Cyclone DDS 的使用 。這能證明機器人介面可擴充,卻不能證明內部未公開的關節控制器使用 FreeRTOS。應區分有文件依據的 SDK 行為,以及對內部韌體的推測。
在四足機器人與無人機中,連接本機 RTOS 控制與 ROS 2
現在把控制器放進整台機器人的架構。主機規劃運動,本機控制器閉合回授迴路,關節驅動器則調節電流。每個迴圈都應配置在能驗證其時序的位置。

ROS 2 是中介軟體,RTOS 是作業系統核心或平台。 兩者職責不同,也經常搭配使用。選定的迴圈同樣可以在適當的 Linux/PREEMPT_RT 主機上執行;ROS 2 即時設計討論 說明了應用層的限制。
Linux 提供行程、攝影機/網路驅動程式、機器人函式庫與部署工具,因此適合擔任主機。PREEMPT_RT 保留這個平台,同時改善核心回應能力。ROS 2 回呼仍需要合適的執行器/執行緒策略、耗時有上限的工作,以及預先準備的記憶體;RT 核心不會自動讓每個回呼都具備即時性。FreeRTOS 則為本機韌體提供較小的執行環境,無法直接接手主機整套 Linux 軟體堆疊。
先決定時序需求,再選核心。 視覺或建圖主機可能需要吞吐量與廣泛的驅動程式支援,快速迴路則交給獨立 MCU。若 Linux 主機直接負責嚴格的控制時限,就需要適當的即時設定及端到端驗證。PC 可以執行 PREEMPT_RT,但一般桌面工作負載往往不需要那麼嚴格的延遲目標。
| 成本或要求 | 產生原因 | 應用決策 |
|---|---|---|
| 可能降低吞吐量 | IRQ 執行緒排程和優先順序繼承鎖的管理會增加工作量。 | 量測真實工作負載;不存在通用的額外負擔百分比。 |
| 更多設定工作 | 任務/IRQ 優先順序、親和性與共享資源相互影響。 | 在網路、儲存與系統維護工作同時執行時驗證控制。 |
| 低優先順序任務飢餓風險 | 持續可執行的 RT 執行緒可能使低優先順序工作無法執行。 | 約束執行與阻塞時間。未啟用 PREEMPT_RT 時也存在此風險。 |
| 能耗取捨 | 某些延遲調校會限制深度閒置狀態或頻率變化。 | 平衡功耗與散熱;僅啟用 PREEMPT_RT 並不代表必須進行這些調校。 |
| 驅動程式假設 | 一般自旋鎖和中斷執行上下文會改變。 | 檢查那些假設自旋鎖一律停用搶先的自訂驅動程式。 |
這些成本取決於工作負載。IRQ 執行緒與優先順序繼承鎖會增加管理工作,CPU 分配及驅動程式的假設也需要檢查。停用深度睡眠或頻率變動,可能以能源效率換取較短的回應時間;這是調校選擇,不是 PREEMPT_RT 自動帶來的效果。Canonical 延遲指南 介紹了這些實務取捨。即使使用非 RT 核心,持續占用 CPU 的即時執行緒也可能使其他工作陷入飢餓。
這種並存也出現在開發者調查中。下方兩個類別涵蓋不同的硬體角色,兩者都不是基準測試,也不是對特定 MCU 的推薦。
- Linux/Raspbian45%
- FreeRTOS32%
- 裸機21%
- Zephyr RTOS17%
- ThreadX17%
- ROS 27%
- Contiki / Contiki-NG5%
- Huawei LiteOS5%
- Linux/Raspbian62%
- Android23%
- Windows19%
- 裸機12%
- ThreadX10%
- Zephyr9%
「資源受限」應相對於應用可用的 RAM、快閃記憶體、CPU、電力與 I/O 預算來理解。ESP32 等級的控制器與 Linux 邊緣電腦,可能面臨不同限制。調查中廣泛的 Linux 使用結果,不能證明桌面 Linux 適合 ESP32。仍需針對實際板卡,核對記憶體容量、MMU 支援、驅動程式及實測迴圈時序。
- IMU量測運動
- 估測器估測姿態
- 控制器計算修正量
- ESC驅動馬達各相
- 馬達改變推力
相同模式也支援無人機姿態穩定。在支援的飛控板上,PX4 通常使用 NuttX;ArduPilot 則在許多 STM32 目標上使用 ChibiOS。可參閱 PX4 飛行軟體堆疊概述 、系統架構 與 ArduPilot 移植指南 。
回到四足機器人
現在,我們能一路追蹤不平整階梯引發的修正,直到指令抵達關節。核心組織執行,而完整的感測、控制與致動路徑,決定修正是否來得及。
設計下一款控制器時,請追蹤一個感測器事件,直到產生物理輸出。明確訂出截止時間,計入每段等待,並在硬體上驗證輸出生效的邊界。
若要將控制器用於實際應用,可以了解 VoicePing 的機器人工程方法 ,共同定義硬體、控制介面與驗收標準。


