Skip to main content

STM32 RTOS 系列教學 - 第五篇:RTOS 訊號量(Semaphore)與資源同步應用

🎯 教學目標

  • 理解 RTOS 中 Semaphore 的概念與分類(Binary / Counting)
  • 學會在多任務間使用 Semaphore 實現資源同步
  • 實作一個防止資源衝突的共享範例

🔐 Semaphore 是什麼?

Semaphore(訊號量)是 RTOS 中用來控制任務間共享資源的一種同步工具,避免同時存取導致資源衝突。

📌 種類

  • Binary Semaphore:僅有 0 和 1,用於任務間同步(類似旗標)
  • Counting Semaphore:允許多個資源存取計數(像計數器),適用於多個資源管理

🛠 STM32CubeMX 設定 Semaphore

Step 1:新增 Semaphore

  • 開啟 Middleware > FreeRTOS > CMSIS RTOS v2
  • 新增 Semaphore,命名為 myBinarySem01
  • 類型選擇 Binary

Step 2:取得 Handle 並初始化

  • main.c 中取得 handle:
osSemaphoreId_t myBinarySem01Handle;
  • 在初始化階段建立 semaphore:
const osSemaphoreAttr_t myBinarySem01_attributes = {
  .name = "myBinarySem01"
};
myBinarySem01Handle = osSemaphoreNew(1, 0, &myBinarySem01_attributes);

✋ 任務同步範例:Button Trigger

範例說明:

  • 任務 A 持續等待 semaphore(類似被 block)
  • 中斷服務程式 (EXTI) 發生時觸發 osSemaphoreRelease()

EXTI 中斷觸發:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(GPIO_Pin == GPIO_PIN_13)
  {
    osSemaphoreRelease(myBinarySem01Handle);
  }
}

任務中等待觸發:

void StartDefaultTask(void *argument)
{
  for(;;)
  {
    if(osSemaphoreAcquire(myBinarySem01Handle, osWaitForever) == osOK)
    {
      HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    }
  }
}

🧠 常見應用場景

  • Button / IRQ 中斷喚醒任務
  • 任務間事件同步(生產者-消費者)
  • 控制一次只允許一個任務進入共享區(Critical Section)

✅ 成功條件檢查

  • 按下按鈕,LED 能夠閃爍一次,且不會重複觸發
  • 任務能穩定接收中斷產生的 semaphore
  • 無資源衝突或 crash 現象

🧩 下一篇預告

第 6 篇:RTOS Queue 任務間資料傳輸實作