# 開發紀錄 ## 背景 在嵌入式系統中,RTOS 常用於管理多個任務之間的協作。 本專案建立一個基於 STM32 的 RTOS 系統,包含: - Sensor Task(Producer):透過 I2C 讀取感測器資料 - Logger Task(Consumer):透過 UART 輸出資料 - 使用 message queue 作為任務間通訊機制 此架構是嵌入式系統中常見的 producer-consumer 模型。 ## 動機 在實際嵌入式系統中,任務之間的速率不匹配(rate mismatch)是一個常見問題, 可能導致: - queue 堆積(backlog) - latency 增加 - 資料丟失(drop) - 系統不穩定 然而,這類問題往往難以觀察與量化。 因此,本專案的目標是: - 建立一個可量測的 RTOS benchmark 系統 - 分析 producer-consumer 架構下的系統行為 - 找出 latency 與 bottleneck 的來源 - 設計機制改善系統穩定性 ## Future Work 目前系統仍有以下待改善項目: - 將 I2C driver 由 polling 改為 interrupt-driven(non-blocking) - 解決 busy wait 導致 CPU 無法讓出 scheduler 的問題 - 加入 mutex 保護 I2C peripheral(確保 thread safety) - 完善 error handling(BERR / ARLO / OVR) - 加入完整 timeout 機制(避免 deadlock) ## 00. Initial Architecture (RTOS Bring-up) [cb71881](https://github.com/rain20010126/stm32-rtos-benchmark/commit/cb718810ae2da2a208d25faed96e1854c5fb971e) ### System Setup 本專案起始於 STM32CubeIDE 產生的基本 RTOS 架構, 使用 CMSIS-RTOS v2(FreeRTOS)作為系統核心。 初始系統包含: - RTOS scheduler - 基本 thread(default task) - Message queue 機制 在此基礎上,逐步建立應用層架構。 ### Architecture Design 系統採用 producer-consumer 架構,將資料取得與輸出解耦: - **Sensor Task(Producer)** - 透過 I2C 讀取感測器資料 - 週期性產生資料(固定 rate) - **Logger Task(Consumer)** - 從 message queue 取出資料 - 透過 UART 輸出 - **Message Queue** - 作為 task 間通訊機制 - decouple producer 與 consumer 的執行速率 ### Data Flow Sensor Task → Queue → Logger Task → UART ### Design Rationale 此設計的目的為: - 避免 I/O blocking 影響系統整體運作 - 將資料取得與處理解耦(decoupling) - 提供可觀察系統行為的基礎架構(benchmark-ready) 此架構也成為後續效能分析與控制策略實驗的基礎。 ## 01. Benchmark (Overloaded System) [c42fe26](https://github.com/rain20010126/stm32-rtos-benchmark/commit/c42fe26261161339167cfaa9b7b129e9bd7ba397) ### Benchmark 系統主要量測以下指標: - **Throughput** - 每秒處理的資料數(msg/sec) - **Latency** - 定義為 enqueue → processing 完成(end-to-end latency) - **Queue Depth** - queue 中資料數量(觀察 backlog) - **Drop Rate** - 因 queue 滿載而丟失的資料數 - **CPU Usage** - 使用 idle-based estimation(透過 idle counter 計算) 測量方法如下: - 使用 timestamp(HAL_GetTick 或 cycle counter)記錄時間 - 在 enqueue 時記錄 T0 - 在 dequeue 時量測 queue latency - 在 processing 完成時量測 total latency - processing latency = total - queue ### 實驗設定 Producer rate:10 Hz(osDelay(100)) Producer workload:50000 loop Consumer workload:300000 loop Queue size:10 Queue 模式:non-blocking(timeout = 0) Latency 定義:enqueue → processing 完成(end-to-end latency) CPU 計算方式:idle-based estimation ### 實驗結果 Throughput:約 4 msg/sec CPU usage:約 70% ~ 87% Max queue depth:10(持續滿) Drop rate:約 2 ~ 3 msg/sec Latency:約 300 ~ 310 ms  ### 問題觀察(Problem Observation) 在 baseline 實驗中觀察到以下現象: - Throughput 僅約 4 msg/sec(遠低於 10 Hz 輸入) - Queue 長時間維持滿載(maxQ = 10) - 持續發生資料丟失(drop 約 2~3/sec) - Latency 約 300 ms,明顯偏高 - CPU 使用率約 70%~87% 雖然觀察到系統效能不佳,但僅從「總 latency」無法判斷: - latency 是來自 queue 等待? - 還是來自 processing 過慢? 無法明確定位 bottleneck 推測系統 bottleneck 可能在: 1. Consumer processing 過慢(CPU-bound) 2. Queue backlog 導致等待時間增加 ### 解決方法(Approach) 為了定位問題來源,將 latency 拆解為兩部分: 1. **Queue latency** - enqueue → dequeue - 代表資料在 queue 中等待時間 2. **Processing latency** - dequeue → processing 完成 - 代表資料處理時間 ### 實驗設計(Experiment Design) 在 LoggerTask 中加入兩段量測: - dequeue 當下量測 queue latency - processing 結束後量測 total latency - processing latency = total - queue ## 02. Bottleneck Analysis (Latency Decomposition) [0fc0e7e](https://github.com/rain20010126/stm32-rtos-benchmark/commit/0fc0e7e0e76fb0b38efe0d4b042877f1a4301b2f) ### 實驗結果 透過 latency 拆解後,觀察到以下數據: - queue latency:約 250~300 ms - processing latency:約 27~30 ms - total latency:約 300~312 ms  ### 結果分析 1. queue latency 明顯大於 processing latency - 約為 9 倍以上 - 表示大部分延遲來自資料等待時間 2. processing latency 相對穩定 - 約 25~30 ms - 與 busy loop 設定一致 3. total latency ≈ queue + processing - 驗證量測方法正確 ### 結論 系統 bottleneck 位於: - [x] Queue backlog(主要原因) - [ ] Processing(次要) 整體延遲主要來自資料在 queue 中等待,而非計算本身。 ### 發現 - 系統瓶頸來自「處理能力 < 輸入速率」,導致 queue 堆積 - 優化方向應優先考慮: - 提升 consumer throughput - 或降低 producer rate - 單純優化 processing 速度未必能解決 latency 問題 將 LoggerTask 的 workload 由 300000 逐步降低至: - 200000 - 100000 | workload | tp | queue latency | processing | drop | CPU | |---------|----|--------------|------------|------|-----| | 200000 | ~5 | ~180 ms | ~18 ms | 有 | ~100% | | 100000 | ~11 | ≈ 0 | ~7 ms | 無 | ~70% |  實驗結果驗證: - 系統 bottleneck 並非單純 processing 慢,而是 processing 能力不足以應付輸入速率 - 當 processing rate ≥ input rate 時,queue backlog 消失,系統進入穩定狀態 - latency 的主要來源為 queue 等待時間,而非計算時間 ### 系統背景 在一個基於 STM32 的 RTOS 系統中,系統包含兩個主要任務: - Sensor Task(Producer):透過 I2C 讀取感測器資料,並將資料送入 message queue - Logger Task(Consumer):從 queue 取出資料,透過 UART 輸出 系統透過 RTOS queue 作為兩個 task 之間的資料傳遞機制。 ### 問題描述 在實驗中發現: 當 Producer 產生資料的速率高於 Consumer 處理能力 時 queue 會逐漸累積(queue buildup)導致: - latency 增加 - queue overflow - 系統行為變得不穩定 本質問題為: Producer 與 Consumer 之間速率不匹配(rate mismatch) ### 設計目標 本系統希望達成: - 維持 queue depth 在合理範圍(避免爆滿或過空) - 降低 latency 並維持穩定性 - 系統可以根據負載自動調整,而非使用固定參數 **不同負載下都能維持穩定** ## 03. Rate Control (PI Controller) [5503d44](https://github.com/rain20010126/stm32-rtos-benchmark/commit/5503d44c648cf3a5e767f2f4a8b41b0ba4da155c) ### 解法 為了解決 rate mismatch 問題,將系統建模為一個feedback control system,使用 PI 控制: - queue depth 作為系統狀態(feedback) - 根據目前 queue 狀態,動態調整 Producer 的速率 ### 實驗結果 P Control 問題(限制) 觀察實驗結果: - target = 5 - 實際 queue depth ≈ 6~7 **steady-state error(穩態誤差)** 為了解決 steady-state error,引入 integral term: 避免 integral 無限制累積: ```c if (integral > limit) integral = limit; if (integral < -limit) integral = -limit; ```  | 指標 | Baseline(無控制) | PI Control | |------|------------------|-----------| | Queue Depth | 滿載(maxQ=10) | 穩定於 target(≈5) | | Latency | ~270000 us | ~106000 us | | Drop | 有(7~8 / s) | 0 | | 穩定性 | 不穩定 | 穩定 | | 系統狀態 | 發散(divergent) | 收斂(steady state) | 在未加入控制器時,系統因 throughput mismatch 導致 queue 堆積、latency 上升與資料丟失。 導入 PI control 後: - 系統成功達到穩定狀態 - queue depth 收斂至目標值 - latency 大幅下降 - 完全避免資料丟失 顯示: > PI control 能有效解決 producer-consumer 不平衡問題,並顯著提升系統效能與穩定性。 ## 04. Driver Integration (I2C under RTOS) [259231d](https://github.com/rain20010126/stm32-rtos-benchmark/commit/259231dce980fa48285dcecfdb17f27bc4203b7e) ### 目的 將自製 register-level I2C driver 整合至 RTOS 系統中, 驗證其在 multi-task 環境下的正確性與穩定性, 並取代 HAL I2C API。 - 使用 register-level 操作(非 HAL) - 支援: - START / STOP condition - ACK / NACK control - repeated start - 加入 timeout 機制避免 deadlock ### 問題 #### Timeout 不完整 (未處理) i2c_read_byte 沒加 timeout #### Error handling 不完整 (未處理) - BERR(bus error) - ARLO(arbitration lost) - OVR(overrun) #### blocking (未處理) I2C driver 採用 polling(busy wait)方式: - while (!TXE) - while (!RXNE) 在 RTOS 環境下: - 會佔用 CPU - 無法讓出 scheduler 觀察 sensor_read() 需等待 I2C transaction 完成, 包含: - start condition - address phase - data transfer #### Thread safety(未處理) I2C peripheral 為 shared resource 即使在單核心 RTOS 系統中, task scheduling 仍可能導致: - transaction interleaving - bus corruption 目前 driver 未使用 mutex 保護 I2C access ## 05. Benchmark Architecture (Non-intrusive Measurement) [bb72452](https://github.com/rain20010126/stm32-rtos-benchmark/commit/bb72452fd411e22ed4def9cce9587b4768b39342) ### 實驗設計 建立一個無額外計算負載(no synthetic workload)的 baseline,用於觀察 RTOS 架構本身(polling + blocking queue)的行為。設定如下: - 固定 producer rate(osDelay(50)) - 關閉 PI controller - 使用 polling-based producer - 使用 blocking consumer 建立穩定基準,用於後續比較 - PI control vs no control - Polling vs Event-driven ### 實驗設定 - Producer rate:50 Hz(osDelay(50)) - Producer workload:0 loop (無額外計算負載) - Consumer workload:0 loop(or current)(無額外計算負載) - Queue size:10 - Queue mode:blocking - Benchmark:non-intrusive ### 實驗結果  | 指標 | 數值 | |------|------| | Throughput | 10 msg/sec | | CPU usage | ~52% | | Max queue depth | 1 | | Drop rate | 0 | | Latency | ~12 us | - 系統達到穩定狀態(steady state) - Producer 與 Consumer 速率匹配 - Queue 無 backlog(maxQ ≈ 1) - 無資料丟失(drop = 0) - Latency 極低,主要為 processing 時間 CPU usage 約為 52%,主要來自 polling-based producer 持續喚醒與系統基本運作開銷,顯示在無 workload 情況下,polling 本身仍具有固定成本 ## h2 ### 架構比較 #### blocking ```c i2c_read_reg() { start wait SB send addr wait ADDR write reg wait TXE repeated start wait SB read data wait RXNE } ``` #### interrupt 版本 ```c i2c_read_reg_async() { set state = START enable interrupt trigger START return // CPU 立刻回來 } ```
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.