天天看點

基于STM32和FreeRTOS的二值信号量實作任務同步

引言

在嵌入式開發中,隻要你使用實時作業系統,那麼使用信号量可以說必不可少。我們常使用信号量進行同步或互斥。

信号量介紹

信号量(semaphore)是一種用于提供不同程序之間或者一個給定的不同線程間同步手段的原語。信号量多用于任務間的同步與互斥。

信号量在FreeRTOS中分為三種:計數型信号量、二值信号量和互斥信号量。

  1. 同步:處理競争就是同步,安排程序執行的先後順序就是同步,每個程序都有一定的個先後執行順序。
  2. 互斥:互斥通路不可共享的臨界資源,同時會引發兩個新的控制問題(互斥可以說是特殊的同步)。
  3. 競争:當并發程序競争使用同一個資源的時候,我們就稱為競争程序。

二值信号量顧名思義就是信号量取值隻有0和1的信号量,但他與互斥信号量不同,他沒有優先級繼承機制,也不是擷取和釋放均隻能在同一個任務裡進行。在實作任務間同步中,使用的非常廣泛。

準備

硬體

  1. STM32F103開發闆
  2. LED燈

軟體

  1. Keil 5
  2. STM32CubeMX
  3. 序列槽調試助手

功能設計

需求設計

設定兩個任務和一個信号量。

任務1運作時會令LED1閃爍,并序列槽發送01,當運作4次任務1後,任務1會釋放二值信号量。

任務2首先擷取二值信号量,如果擷取失敗任務進行排程。當擷取到信号量時,任務2會執行LED2閃爍,并序列槽發送02。

實作任務1 每運作四次,任務2運作一次。

軟體實作

  1. 信号量定義

    下面的程式目的是建立了一個二值信号量。

#include "Semaphore.h"

SemaphoreHandle_t LED_Semaphore;
void initSemaphore(void)
{
   LED_Semaphore =xSemaphoreCreateBinary();
   configASSERT(LED_Semaphore          != NULL);
}      
  1. 任務1

    任務1主要是每次執行一次閃爍和序列槽發送01,當執行第四次的時候,釋放信号量。

void LED1ToggleTesk(void const * argument)
{
  BaseType_t xReturn=pdTRUE;
  int ledtime1=4;
  for(;;)
  {
    usart_send[0]=0x1;
    ledtime1--;
    if(ledtime1==0){
    xSemaphoreGive(LED_Semaphore);
    ledtime1=4;    
    }
    HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);  
  HAL_UART_Transmit(&huart3,usart_send,1,portMAX_DELAY);
    vTaskDelay(1000);
  }
}      
  1. 任務2

    任務2主要執行的是,當擷取的信号量時,LED2翻轉,并序列槽發送02。

void LED2ToggleTesk(void const *argument)
{
  BaseType_t xReturn=pdTRUE;
  for(;;)
  {
    usart_send[0]=0x2;
    xReturn =xSemaphoreTake(LED_Semaphore,0);
    if(xReturn==pdTRUE)
    {
      HAL_UART_Transmit(&huart3,usart_send,1,portMAX_DELAY);
  HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
    }
    vTaskDelay(1000);
  }
  
}      

現象

實作的現象是LED1始終在翻轉,序列槽始終發送01,當執行四次上述現象的時候。LED2翻轉并序列槽發送02.

後續