0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

FreeRTOS信號(hào)量的使用與實(shí)例

CHANBAEK ? 來源:FunIO ? 作者:FunIO ? 2023-12-12 15:25 ? 次閱讀

嵌入式系統(tǒng)中,任務(wù)管理是一個(gè)重要的部分,它涉及到任務(wù)之間的通信和同步,信號(hào)量,隊(duì)列,互斥鎖和事件標(biāo)志組等概念。本文將以 FreeRTOS 為例,詳細(xì)講解這些內(nèi)容。

1. 任務(wù)間通信與同步概述

在 FreeRTOS 中,任務(wù)是由一個(gè)或多個(gè)函數(shù)組成的獨(dú)立的執(zhí)行流,它們可以獨(dú)立的運(yùn)行和調(diào)度。任務(wù)之間的通信和同步是任務(wù)管理的核心內(nèi)容之一。任務(wù)間的通信是指一個(gè)任務(wù)向另一個(gè)任務(wù)傳遞信息,而同步則是指多個(gè)任務(wù)按照一定的順序執(zhí)行。FreeRTOS 提供了多種任務(wù)間通信和同步的機(jī)制,包括信號(hào)量,隊(duì)列,互斥鎖和事件標(biāo)志組等。

2. 信號(hào)量的使用與實(shí)例

信號(hào)量(Semaphore)是 FreeRTOS 中一種常用的同步機(jī)制,主要用于任務(wù)間和中斷服務(wù)例程(ISR)間的通信。它們被用來保護(hù)共享資源,使得只有一個(gè)任務(wù)或者中斷服務(wù)例程可以訪問共享資源,避免了資源沖突的問題。

FreeRTOS 中的信號(hào)量主要有兩種類型:計(jì)數(shù)信號(hào)量和二值信號(hào)量。

  1. 計(jì)數(shù)信號(hào)量(Counting Semaphore):是一種可以持有多個(gè)“計(jì)數(shù)”或者“票”的信號(hào)量。例如,如果你有一些共享資源,每個(gè)資源都需要獨(dú)立的訪問控制,你就可以使用一個(gè)初始計(jì)數(shù)等于資源數(shù)量的計(jì)數(shù)信號(hào)量。當(dāng)一個(gè)任務(wù)需要訪問一個(gè)資源時(shí),它會(huì)嘗試“獲取”一個(gè)信號(hào)量。如果信號(hào)量計(jì)數(shù)大于 0,那么信號(hào)量計(jì)數(shù)減 1,任務(wù)繼續(xù)執(zhí)行。如果計(jì)數(shù)為 0,那么任務(wù)就會(huì)阻塞,直到信號(hào)量計(jì)數(shù)大于 0。當(dāng)任務(wù)不再需要訪問資源時(shí),它應(yīng)該“釋放”信號(hào)量,信號(hào)量計(jì)數(shù)加 1。
  2. 二值信號(hào)量(Binary Semaphore):是一種只有兩個(gè)值(01)的特殊信號(hào)量。它通常被用作任務(wù)之間或者任務(wù)與中斷服務(wù)例程之間的同步機(jī)制。當(dāng)信號(hào)量的值為1時(shí),任務(wù)可以獲取信號(hào)量并繼續(xù)執(zhí)行。當(dāng)信號(hào)量的值為0時(shí),任務(wù)嘗試獲取信號(hào)量會(huì)被阻塞,直到信號(hào)量的值變?yōu)?code>1。二值信號(hào)量也可以被用作互斥量(Mutex),用于保護(hù)共享資源的訪問。

在 FreeRTOS 中,信號(hào)量的操作主要有創(chuàng)建(xSemaphoreCreateBinary, xSemaphoreCreateCounting等函數(shù))、獲取(xSemaphoreTake函數(shù))和釋放(xSemaphoreGive函數(shù))。在中斷服務(wù)例程中,獲取和釋放信號(hào)量的函數(shù)有所不同,分別為xSemaphoreTakeFromISRxSemaphoreGiveFromISR。

示例

計(jì)數(shù)信號(hào)量

假設(shè)有兩個(gè)任務(wù) TaskA 和 TaskB,TaskA 負(fù)責(zé)發(fā)送數(shù)據(jù),TaskB 負(fù)責(zé)接收數(shù)據(jù)。我們使用計(jì)數(shù)信號(hào)量來實(shí)現(xiàn) TaskA 和 TaskB 之間的同步。

首先,在 FreeRTOS 中創(chuàng)建一個(gè)計(jì)數(shù)信號(hào)量:

SemaphoreHandle_t xSemaphore;
xSemaphore = xSemaphoreCreateCounting(10, 0); // 創(chuàng)建一個(gè)計(jì)數(shù)信號(hào)量,初始計(jì)數(shù)值為0,最大計(jì)數(shù)值為10

接下來,在 TaskA 中發(fā)送數(shù)據(jù)時(shí)獲取計(jì)數(shù)信號(hào)量:

void TaskA(void *pvParameters) {
    while (1) {
        // 發(fā)送數(shù)據(jù)
        ...

        // 獲取計(jì)數(shù)信號(hào)量,如果計(jì)數(shù)值為0,則任務(wù)被阻塞
        xSemaphoreTake(xSemaphore, portMAX_DELAY);
    }
}

在 TaskB 中接收數(shù)據(jù)時(shí)釋放計(jì)數(shù)信號(hào)量:

void TaskB(void *pvParameters) {
    while (1) {
        // 接收數(shù)據(jù)
        ...

        // 釋放計(jì)數(shù)信號(hào)量,增加計(jì)數(shù)值
        xSemaphoreGive(xSemaphore);
    }
}

在上述代碼中,當(dāng) TaskA 發(fā)送數(shù)據(jù)時(shí),它會(huì)獲取計(jì)數(shù)信號(hào)量,如果計(jì)數(shù)值為 0,則 TaskA 會(huì)被阻塞,直到 TaskB 接收數(shù)據(jù)并釋放計(jì)數(shù)信號(hào)量為止。當(dāng) TaskB 釋放計(jì)數(shù)信號(hào)量后,計(jì)數(shù)值增加,TaskA 可以繼續(xù)執(zhí)行發(fā)送數(shù)據(jù)的操作。

這樣,使用計(jì)數(shù)信號(hào)量可以實(shí)現(xiàn) TaskA 和 TaskB 之間的同步,保證 TaskA 在 TaskB 完成接收數(shù)據(jù)后才進(jìn)行發(fā)送數(shù)據(jù)的操作,避免了數(shù)據(jù)的丟失和沖突。

二值信號(hào)量

二值信號(hào)量(Binary Semaphore)是一種用于任務(wù)間同步和互斥的機(jī)制。它只有兩個(gè)狀態(tài),可以是空閑或者被占用,類似于互斥鎖。

下面是一個(gè)使用二值信號(hào)量的示例:

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

// 創(chuàng)建一個(gè)二值信號(hào)量
SemaphoreHandle_t binarySemaphore;

// 任務(wù)1
void task1(void *pvParameters)
{
    while (1)
    {
        // 等待二值信號(hào)量
        xSemaphoreTake(binarySemaphore, portMAX_DELAY);

        // 執(zhí)行任務(wù)1的操作
        // ...

        // 釋放二值信號(hào)量
        xSemaphoreGive(binarySemaphore);

        // 延時(shí)一段時(shí)間
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

// 任務(wù)2
void task2(void *pvParameters)
{
    while (1)
    {
        // 等待二值信號(hào)量
        xSemaphoreTake(binarySemaphore, portMAX_DELAY);

        // 執(zhí)行任務(wù)2的操作
        // ...

        // 釋放二值信號(hào)量
        xSemaphoreGive(binarySemaphore);

        // 延時(shí)一段時(shí)間
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

int main()
{
    // 創(chuàng)建二值信號(hào)量
    binarySemaphore = xSemaphoreCreateBinary();

    // 創(chuàng)建任務(wù)1
    xTaskCreate(task1, "Task 1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);

    // 創(chuàng)建任務(wù)2
    xTaskCreate(task2, "Task 2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);

    // 啟動(dòng)任務(wù)調(diào)度器
    vTaskStartScheduler();

    return 0;
}

在上面的示例中,首先創(chuàng)建了一個(gè)二值信號(hào)量binarySemaphore,然后創(chuàng)建了兩個(gè)任務(wù)task1task2。這兩個(gè)任務(wù)都會(huì)在一個(gè)無限循環(huán)中執(zhí)行,首先等待二值信號(hào)量,然后執(zhí)行自己的操作,最后釋放二值信號(hào)量。

當(dāng)一個(gè)任務(wù)等待二值信號(hào)量時(shí),如果二值信號(hào)量的狀態(tài)是空閑(未被占用),則任務(wù)可以獲取到該信號(hào)量,繼續(xù)執(zhí)行自己的操作。如果二值信號(hào)量的狀態(tài)是被占用(已經(jīng)有任務(wù)獲取到了信號(hào)量),則任務(wù)會(huì)一直等待,直到信號(hào)量被釋放。

需要注意的是,當(dāng)一個(gè)任務(wù)獲取到二值信號(hào)量后,其他任務(wù)將無法獲取到該信號(hào)量,直到該任務(wù)釋放信號(hào)量。這就保證了任務(wù)之間的互斥性。

通過使用二值信號(hào)量,可以實(shí)現(xiàn)任務(wù)間的同步和互斥操作,確保多個(gè)任務(wù)按照特定的順序執(zhí)行或者避免資源的競(jìng)爭(zhēng)。

3. 隊(duì)列的使用與實(shí)例

隊(duì)列是一種數(shù)據(jù)結(jié)構(gòu),它允許任務(wù)按照先進(jìn)先出(FIFO)的原則將數(shù)據(jù)項(xiàng)插入隊(duì)列和從隊(duì)列中獲取數(shù)據(jù)項(xiàng)。在 FreeRTOS 中,可以使用 xQueueCreate()函數(shù)來創(chuàng)建一個(gè)隊(duì)列。

示例:

QueueHandle_t xQueue;

void vProducerTask(void  pvParameters)
{
    int32_t lValueToSend;
    BaseType_t xStatus;

    lValueToSend = (int32_t) pvParameters;

    for(;;)
    {
        xStatus = xQueueSendToBack(xQueue, &lValueToSend, 0);
        if(xStatus != pdPASS)
        {
            printf("Could not send to the queue.n");
        }
    }
}

在這個(gè)例子中,vProducerTask 任務(wù)將數(shù)據(jù)項(xiàng)發(fā)送到隊(duì)列的尾部。如果發(fā)送成功,xQueueSendToBack()函數(shù)將返回 pdPASS,否則,將返回一個(gè)錯(cuò)誤代碼。

4. 互斥鎖的使用與實(shí)例

互斥鎖是一種用于保護(hù)共享資源的機(jī)制。當(dāng)一個(gè)任務(wù)需要使用一個(gè)共享資源時(shí),它必須首先獲取互斥鎖。如果互斥鎖已經(jīng)被另一個(gè)任務(wù)獲取,那么這個(gè)任務(wù)就需要等待,直到互斥鎖被釋放。在 FreeRTOS 中,可以使用 xSemaphoreCreateMutex()函數(shù)來創(chuàng)建一個(gè)互斥鎖。

示例:

SemaphoreHandle_t xMutex;

void vTask(void  pvParameters)
{
    for(;;)
    {
        if(xSemaphoreTake(xMutex, (TickType_t)10) == pdTRUE)
        {
            // The mutex was successfully taken, so the shared resource can be accessed.
            printf("Task: Mutex taken!n");

            // ...
            // Access the shared resource.
            // ...

            // Release the mutex.
            xSemaphoreGive(xMutex);
        }
        else
        {
            // The mutex could not be taken.
            printf("Task: Mutex not taken!n");
        }
    }
}

在這個(gè)例子中,vTask 任務(wù)嘗試獲取一個(gè)互斥鎖。如果成功,它將訪問一個(gè)共享資源,然后釋放互斥鎖。

5. 事件標(biāo)志組的使用與實(shí)例

事件標(biāo)志組是一種用于表示一組事件發(fā)生狀態(tài)的數(shù)據(jù)結(jié)構(gòu)。每一個(gè)事件都有一個(gè)對(duì)應(yīng)的標(biāo)志,當(dāng)事件發(fā)生時(shí),標(biāo)志被設(shè)置,當(dāng)事件被處理時(shí),標(biāo)志被清除。在 FreeRTOS 中,可以使用 xEventGroupCreate()函數(shù)來創(chuàng)建一個(gè)事件標(biāo)志組。

示例:

EventGroupHandle_t xEventGroup;

void vTask(void  pvParameters)
{
    EventBits_t uxBits;

    for(;;)
    {
        uxBits = xEventGroupWaitBits(
            xEventGroup,   // The event group being tested.
            BIT_0 | BIT_4, // The bits within the event group to wait for.
            pdTRUE,        // BIT_0 & BIT_4 should be cleared before returning.
            pdFALSE,       // Don't wait for both bits, either bit will do.
            portMAX_DELAY  // Wait a maximum for either bit to be set.
        );

        if((uxBits & (BIT_0 | BIT_4)) == (BIT_0 | BIT_4))
        {
            // Both bits were set.
            printf("Task: Both bits were set!n");
        }
        else if((uxBits & BIT_0) != 0)
        {
            // Bit 0 was set.
            printf("Task: Bit 0 was set!n");
        }
        else if((uxBits & BIT_4) != 0)
        {
            // Bit 4 was set.
            printf("Task: Bit 4 was set!n");
        }
        else
        {
            // Neither bit was set.
            printf("Task: Neither bit was set!n");
        }
    }
}

在這個(gè)例子中,vTask 任務(wù)等待事件標(biāo)志組中的任何一個(gè)事件發(fā)生。如果兩個(gè)事件都發(fā)生,它將打印出"Both bits were set!",如果只有一個(gè)事件發(fā)生,它將打印出對(duì)應(yīng)的消息。

6. 信號(hào)量 vs 互斥鎖

信號(hào)量(Semaphore)和互斥鎖(Mutex)都是多任務(wù)環(huán)境下保護(hù)共享資源的一種方法,它們之間存在一些區(qū)別:

  1. 互斥鎖是一種所有權(quán)的概念,即一個(gè)任務(wù)獲取了互斥鎖后,只有它自己可以釋放這個(gè)互斥鎖,其他任務(wù)不能釋放。而信號(hào)量沒有所有權(quán)的概念,任何任務(wù)都可以釋放信號(hào)量。
  2. 在 FreeRTOS 中,互斥鎖有優(yōu)先級(jí)反轉(zhuǎn)的解決機(jī)制,當(dāng)一個(gè)低優(yōu)先級(jí)的任務(wù)獲取了互斥鎖,而高優(yōu)先級(jí)的任務(wù)需要這個(gè)互斥鎖時(shí),低優(yōu)先級(jí)的任務(wù)的優(yōu)先級(jí)會(huì)被提升,以減少優(yōu)先級(jí)反轉(zhuǎn)的問題。而信號(hào)量沒有這個(gè)機(jī)制。
  3. 互斥鎖通常用于保護(hù)共享資源,即在同一時(shí)間只能有一個(gè)任務(wù)訪問某個(gè)資源。信號(hào)量則更多是用于任務(wù)同步,它可以被用來喚醒一個(gè)或多個(gè)等待的任務(wù)。
  4. 在 FreeRTOS 中,信號(hào)量可以有計(jì)數(shù)的概念,即可以被“給”多次,每次“給”都會(huì)增加一個(gè)計(jì)數(shù),而互斥鎖沒有這個(gè)概念,它只有鎖定和解鎖兩種狀態(tài)。
  5. 信號(hào)量可以被用作二元信號(hào)量(即只有兩種狀態(tài),01,類似互斥鎖),而互斥鎖不能被用作計(jì)數(shù)信號(hào)量。

總結(jié)

在 FreeRTOS 中,任務(wù)間的通信和同步是一個(gè)重要的部分,它涉及到信號(hào)量,隊(duì)列,互斥鎖和事件標(biāo)志組等概念。通過理解和掌握這些概念,可以有效地管理和調(diào)度任務(wù),提高系統(tǒng)的效率和穩(wěn)定性。

FreeRTOS 任務(wù)間通信與同步

嵌入式系統(tǒng)中,任務(wù)管理是一個(gè)重要的部分,它涉及到任務(wù)之間的通信和同步,信號(hào)量,隊(duì)列,互斥鎖和事件標(biāo)志組等概念。本文將以 FreeRTOS 為例,詳細(xì)講解這些內(nèi)容。

1. 任務(wù)間通信與同步概述

在 FreeRTOS 中,任務(wù)是由一個(gè)或多個(gè)函數(shù)組成的獨(dú)立的執(zhí)行流,它們可以獨(dú)立的運(yùn)行和調(diào)度。任務(wù)之間的通信和同步是任務(wù)管理的核心內(nèi)容之一。任務(wù)間的通信是指一個(gè)任務(wù)向另一個(gè)任務(wù)傳遞信息,而同步則是指多個(gè)任務(wù)按照一定的順序執(zhí)行。FreeRTOS 提供了多種任務(wù)間通信和同步的機(jī)制,包括信號(hào)量,隊(duì)列,互斥鎖和事件標(biāo)志組等。

2. 信號(hào)量的使用與實(shí)例

信號(hào)量(Semaphore)是 FreeRTOS 中一種常用的同步機(jī)制,主要用于任務(wù)間和中斷服務(wù)例程(ISR)間的通信。它們被用來保護(hù)共享資源,使得只有一個(gè)任務(wù)或者中斷服務(wù)例程可以訪問共享資源,避免了資源沖突的問題。

FreeRTOS 中的信號(hào)量主要有兩種類型:計(jì)數(shù)信號(hào)量和二值信號(hào)量。

  1. 計(jì)數(shù)信號(hào)量(Counting Semaphore):是一種可以持有多個(gè)“計(jì)數(shù)”或者“票”的信號(hào)量。例如,如果你有一些共享資源,每個(gè)資源都需要獨(dú)立的訪問控制,你就可以使用一個(gè)初始計(jì)數(shù)等于資源數(shù)量的計(jì)數(shù)信號(hào)量。當(dāng)一個(gè)任務(wù)需要訪問一個(gè)資源時(shí),它會(huì)嘗試“獲取”一個(gè)信號(hào)量。如果信號(hào)量計(jì)數(shù)大于 0,那么信號(hào)量計(jì)數(shù)減 1,任務(wù)繼續(xù)執(zhí)行。如果計(jì)數(shù)為 0,那么任務(wù)就會(huì)阻塞,直到信號(hào)量計(jì)數(shù)大于 0。當(dāng)任務(wù)不再需要訪問資源時(shí),它應(yīng)該“釋放”信號(hào)量,信號(hào)量計(jì)數(shù)加 1。
  2. 二值信號(hào)量(Binary Semaphore):是一種只有兩個(gè)值(01)的特殊信號(hào)量。它通常被用作任務(wù)之間或者任務(wù)與中斷服務(wù)例程之間的同步機(jī)制。當(dāng)信號(hào)量的值為1時(shí),任務(wù)可以獲取信號(hào)量并繼續(xù)執(zhí)行。當(dāng)信號(hào)量的值為0時(shí),任務(wù)嘗試獲取信號(hào)量會(huì)被阻塞,直到信號(hào)量的值變?yōu)?code>1。二值信號(hào)量也可以被用作互斥量(Mutex),用于保護(hù)共享資源的訪問。

在 FreeRTOS 中,信號(hào)量的操作主要有創(chuàng)建(xSemaphoreCreateBinary, xSemaphoreCreateCounting等函數(shù))、獲?。?code>xSemaphoreTake函數(shù))和釋放(xSemaphoreGive函數(shù))。在中斷服務(wù)例程中,獲取和釋放信號(hào)量的函數(shù)有所不同,分別為xSemaphoreTakeFromISRxSemaphoreGiveFromISR。

示例

計(jì)數(shù)信號(hào)量

假設(shè)有兩個(gè)任務(wù) TaskA 和 TaskB,TaskA 負(fù)責(zé)發(fā)送數(shù)據(jù),TaskB 負(fù)責(zé)接收數(shù)據(jù)。我們使用計(jì)數(shù)信號(hào)量來實(shí)現(xiàn) TaskA 和 TaskB 之間的同步。

首先,在 FreeRTOS 中創(chuàng)建一個(gè)計(jì)數(shù)信號(hào)量:

SemaphoreHandle_t xSemaphore;
xSemaphore = xSemaphoreCreateCounting(10, 0); // 創(chuàng)建一個(gè)計(jì)數(shù)信號(hào)量,初始計(jì)數(shù)值為0,最大計(jì)數(shù)值為10

接下來,在 TaskA 中發(fā)送數(shù)據(jù)時(shí)獲取計(jì)數(shù)信號(hào)量:

void TaskA(void *pvParameters) {
    while (1) {
        // 發(fā)送數(shù)據(jù)
        ...

        // 獲取計(jì)數(shù)信號(hào)量,如果計(jì)數(shù)值為0,則任務(wù)被阻塞
        xSemaphoreTake(xSemaphore, portMAX_DELAY);
    }
}

在 TaskB 中接收數(shù)據(jù)時(shí)釋放計(jì)數(shù)信號(hào)量:

void TaskB(void *pvParameters) {
    while (1) {
        // 接收數(shù)據(jù)
        ...

        // 釋放計(jì)數(shù)信號(hào)量,增加計(jì)數(shù)值
        xSemaphoreGive(xSemaphore);
    }
}

在上述代碼中,當(dāng) TaskA 發(fā)送數(shù)據(jù)時(shí),它會(huì)獲取計(jì)數(shù)信號(hào)量,如果計(jì)數(shù)值為 0,則 TaskA 會(huì)被阻塞,直到 TaskB 接收數(shù)據(jù)并釋放計(jì)數(shù)信號(hào)量為止。當(dāng) TaskB 釋放計(jì)數(shù)信號(hào)量后,計(jì)數(shù)值增加,TaskA 可以繼續(xù)執(zhí)行發(fā)送數(shù)據(jù)的操作。

這樣,使用計(jì)數(shù)信號(hào)量可以實(shí)現(xiàn) TaskA 和 TaskB 之間的同步,保證 TaskA 在 TaskB 完成接收數(shù)據(jù)后才進(jìn)行發(fā)送數(shù)據(jù)的操作,避免了數(shù)據(jù)的丟失和沖突。

二值信號(hào)量

二值信號(hào)量(Binary Semaphore)是一種用于任務(wù)間同步和互斥的機(jī)制。它只有兩個(gè)狀態(tài),可以是空閑或者被占用,類似于互斥鎖。

下面是一個(gè)使用二值信號(hào)量的示例:

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

// 創(chuàng)建一個(gè)二值信號(hào)量
SemaphoreHandle_t binarySemaphore;

// 任務(wù)1
void task1(void *pvParameters)
{
    while (1)
    {
        // 等待二值信號(hào)量
        xSemaphoreTake(binarySemaphore, portMAX_DELAY);

        // 執(zhí)行任務(wù)1的操作
        // ...

        // 釋放二值信號(hào)量
        xSemaphoreGive(binarySemaphore);

        // 延時(shí)一段時(shí)間
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

// 任務(wù)2
void task2(void *pvParameters)
{
    while (1)
    {
        // 等待二值信號(hào)量
        xSemaphoreTake(binarySemaphore, portMAX_DELAY);

        // 執(zhí)行任務(wù)2的操作
        // ...

        // 釋放二值信號(hào)量
        xSemaphoreGive(binarySemaphore);

        // 延時(shí)一段時(shí)間
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

int main()
{
    // 創(chuàng)建二值信號(hào)量
    binarySemaphore = xSemaphoreCreateBinary();

    // 創(chuàng)建任務(wù)1
    xTaskCreate(task1, "Task 1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);

    // 創(chuàng)建任務(wù)2
    xTaskCreate(task2, "Task 2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);

    // 啟動(dòng)任務(wù)調(diào)度器
    vTaskStartScheduler();

    return 0;
}

在上面的示例中,首先創(chuàng)建了一個(gè)二值信號(hào)量binarySemaphore,然后創(chuàng)建了兩個(gè)任務(wù)task1task2。這兩個(gè)任務(wù)都會(huì)在一個(gè)無限循環(huán)中執(zhí)行,首先等待二值信號(hào)量,然后執(zhí)行自己的操作,最后釋放二值信號(hào)量。

當(dāng)一個(gè)任務(wù)等待二值信號(hào)量時(shí),如果二值信號(hào)量的狀態(tài)是空閑(未被占用),則任務(wù)可以獲取到該信號(hào)量,繼續(xù)執(zhí)行自己的操作。如果二值信號(hào)量的狀態(tài)是被占用(已經(jīng)有任務(wù)獲取到了信號(hào)量),則任務(wù)會(huì)一直等待,直到信號(hào)量被釋放。

需要注意的是,當(dāng)一個(gè)任務(wù)獲取到二值信號(hào)量后,其他任務(wù)將無法獲取到該信號(hào)量,直到該任務(wù)釋放信號(hào)量。這就保證了任務(wù)之間的互斥性。

通過使用二值信號(hào)量,可以實(shí)現(xiàn)任務(wù)間的同步和互斥操作,確保多個(gè)任務(wù)按照特定的順序執(zhí)行或者避免資源的競(jìng)爭(zhēng)。

3. 隊(duì)列的使用與實(shí)例

隊(duì)列是一種數(shù)據(jù)結(jié)構(gòu),它允許任務(wù)按照先進(jìn)先出(FIFO)的原則將數(shù)據(jù)項(xiàng)插入隊(duì)列和從隊(duì)列中獲取數(shù)據(jù)項(xiàng)。在 FreeRTOS 中,可以使用 xQueueCreate()函數(shù)來創(chuàng)建一個(gè)隊(duì)列。

示例:

QueueHandle_t xQueue;

void vProducerTask(void  pvParameters)
{
    int32_t lValueToSend;
    BaseType_t xStatus;

    lValueToSend = (int32_t) pvParameters;

    for(;;)
    {
        xStatus = xQueueSendToBack(xQueue, &lValueToSend, 0);
        if(xStatus != pdPASS)
        {
            printf("Could not send to the queue.n");
        }
    }
}

在這個(gè)例子中,vProducerTask 任務(wù)將數(shù)據(jù)項(xiàng)發(fā)送到隊(duì)列的尾部。如果發(fā)送成功,xQueueSendToBack()函數(shù)將返回 pdPASS,否則,將返回一個(gè)錯(cuò)誤代碼。

4. 互斥鎖的使用與實(shí)例

互斥鎖是一種用于保護(hù)共享資源的機(jī)制。當(dāng)一個(gè)任務(wù)需要使用一個(gè)共享資源時(shí),它必須首先獲取互斥鎖。如果互斥鎖已經(jīng)被另一個(gè)任務(wù)獲取,那么這個(gè)任務(wù)就需要等待,直到互斥鎖被釋放。在 FreeRTOS 中,可以使用 xSemaphoreCreateMutex()函數(shù)來創(chuàng)建一個(gè)互斥鎖。

示例:

SemaphoreHandle_t xMutex;

void vTask(void  pvParameters)
{
    for(;;)
    {
        if(xSemaphoreTake(xMutex, (TickType_t)10) == pdTRUE)
        {
            // The mutex was successfully taken, so the shared resource can be accessed.
            printf("Task: Mutex taken!n");

            // ...
            // Access the shared resource.
            // ...

            // Release the mutex.
            xSemaphoreGive(xMutex);
        }
        else
        {
            // The mutex could not be taken.
            printf("Task: Mutex not taken!n");
        }
    }
}

在這個(gè)例子中,vTask 任務(wù)嘗試獲取一個(gè)互斥鎖。如果成功,它將訪問一個(gè)共享資源,然后釋放互斥鎖。

5. 事件標(biāo)志組的使用與實(shí)例

事件標(biāo)志組是一種用于表示一組事件發(fā)生狀態(tài)的數(shù)據(jù)結(jié)構(gòu)。每一個(gè)事件都有一個(gè)對(duì)應(yīng)的標(biāo)志,當(dāng)事件發(fā)生時(shí),標(biāo)志被設(shè)置,當(dāng)事件被處理時(shí),標(biāo)志被清除。在 FreeRTOS 中,可以使用 xEventGroupCreate()函數(shù)來創(chuàng)建一個(gè)事件標(biāo)志組。

示例:

EventGroupHandle_t xEventGroup;

void vTask(void  pvParameters)
{
    EventBits_t uxBits;

    for(;;)
    {
        uxBits = xEventGroupWaitBits(
            xEventGroup,   // The event group being tested.
            BIT_0 | BIT_4, // The bits within the event group to wait for.
            pdTRUE,        // BIT_0 & BIT_4 should be cleared before returning.
            pdFALSE,       // Don't wait for both bits, either bit will do.
            portMAX_DELAY  // Wait a maximum for either bit to be set.
        );

        if((uxBits & (BIT_0 | BIT_4)) == (BIT_0 | BIT_4))
        {
            // Both bits were set.
            printf("Task: Both bits were set!n");
        }
        else if((uxBits & BIT_0) != 0)
        {
            // Bit 0 was set.
            printf("Task: Bit 0 was set!n");
        }
        else if((uxBits & BIT_4) != 0)
        {
            // Bit 4 was set.
            printf("Task: Bit 4 was set!n");
        }
        else
        {
            // Neither bit was set.
            printf("Task: Neither bit was set!n");
        }
    }
}

在這個(gè)例子中,vTask 任務(wù)等待事件標(biāo)志組中的任何一個(gè)事件發(fā)生。如果兩個(gè)事件都發(fā)生,它將打印出"Both bits were set!",如果只有一個(gè)事件發(fā)生,它將打印出對(duì)應(yīng)的消息。

6. 信號(hào)量 vs 互斥鎖

信號(hào)量(Semaphore)和互斥鎖(Mutex)都是多任務(wù)環(huán)境下保護(hù)共享資源的一種方法,它們之間存在一些區(qū)別:

  1. 互斥鎖是一種所有權(quán)的概念,即一個(gè)任務(wù)獲取了互斥鎖后,只有它自己可以釋放這個(gè)互斥鎖,其他任務(wù)不能釋放。而信號(hào)量沒有所有權(quán)的概念,任何任務(wù)都可以釋放信號(hào)量。
  2. 在 FreeRTOS 中,互斥鎖有優(yōu)先級(jí)反轉(zhuǎn)的解決機(jī)制,當(dāng)一個(gè)低優(yōu)先級(jí)的任務(wù)獲取了互斥鎖,而高優(yōu)先級(jí)的任務(wù)需要這個(gè)互斥鎖時(shí),低優(yōu)先級(jí)的任務(wù)的優(yōu)先級(jí)會(huì)被提升,以減少優(yōu)先級(jí)反轉(zhuǎn)的問題。而信號(hào)量沒有這個(gè)機(jī)制。
  3. 互斥鎖通常用于保護(hù)共享資源,即在同一時(shí)間只能有一個(gè)任務(wù)訪問某個(gè)資源。信號(hào)量則更多是用于任務(wù)同步,它可以被用來喚醒一個(gè)或多個(gè)等待的任務(wù)。
  4. 在 FreeRTOS 中,信號(hào)量可以有計(jì)數(shù)的概念,即可以被“給”多次,每次“給”都會(huì)增加一個(gè)計(jì)數(shù),而互斥鎖沒有這個(gè)概念,它只有鎖定和解鎖兩種狀態(tài)。
  5. 信號(hào)量可以被用作二元信號(hào)量(即只有兩種狀態(tài),01,類似互斥鎖),而互斥鎖不能被用作計(jì)數(shù)信號(hào)量。

總結(jié)

在 FreeRTOS 中,任務(wù)間的通信和同步是一個(gè)重要的部分,它涉及到信號(hào)量,隊(duì)列,互斥鎖和事件標(biāo)志組等概念。通過理解和掌握這些概念,可以有效地管理和調(diào)度任務(wù),提高系統(tǒng)的效率和穩(wěn)定性。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 嵌入式系統(tǒng)
    +關(guān)注

    關(guān)注

    40

    文章

    3519

    瀏覽量

    128802
  • 中斷
    +關(guān)注

    關(guān)注

    5

    文章

    889

    瀏覽量

    41219
  • FreeRTOS
    +關(guān)注

    關(guān)注

    12

    文章

    483

    瀏覽量

    61721
  • 信號(hào)量
    +關(guān)注

    關(guān)注

    0

    文章

    53

    瀏覽量

    8282
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    實(shí)時(shí)操作系統(tǒng)FreeRTOS信號(hào)量應(yīng)用

    二值信號(hào)量通常用于互斥訪問或同步,二值信號(hào)量和互斥信號(hào)量非常相似,但還是有細(xì)微差別,互斥信號(hào)量擁有優(yōu)先級(jí)繼承機(jī)制,二值信號(hào)沒有。因此二值信
    的頭像 發(fā)表于 06-08 09:24 ?3559次閱讀
    實(shí)時(shí)操作系統(tǒng)<b class='flag-5'>FreeRTOS</b><b class='flag-5'>信號(hào)量</b>應(yīng)用

    FreeRTOS串口中斷接收不定長(zhǎng)的數(shù)據(jù)與二值信號(hào)量的使用

    FreeRTOS例程,使用串口中斷接收不定長(zhǎng)的數(shù)據(jù),以及二值信號(hào)量的使用
    的頭像 發(fā)表于 09-26 09:02 ?3789次閱讀
    <b class='flag-5'>FreeRTOS</b>串口中斷接收不定長(zhǎng)的數(shù)據(jù)與二值<b class='flag-5'>信號(hào)量</b>的使用

    FreeRTOS信號(hào)量使用教程

    信號(hào)量是操作系統(tǒng)中重要的一部分,信號(hào)量一般用來進(jìn)行資源管理和任務(wù)同步, FreeRTOS信號(hào)量又分為二值信號(hào)量、 計(jì)數(shù)型
    的頭像 發(fā)表于 12-19 09:22 ?2871次閱讀
    <b class='flag-5'>FreeRTOS</b><b class='flag-5'>信號(hào)量</b>使用教程

    轉(zhuǎn):freeRTOS信號(hào)量學(xué)習(xí)

    信號(hào)量同樣是RTOS學(xué)習(xí)中很重要的一節(jié),信號(hào)量可以用在共享資源或者同步任務(wù)中,對(duì)執(zhí)行權(quán)的控制,誰擁有信號(hào)量誰擁有執(zhí)行權(quán),在freeRTOS信號(hào)量
    發(fā)表于 08-12 18:29

    轉(zhuǎn):第21章 FreeRTOS計(jì)數(shù)信號(hào)量

    本章節(jié)開始講解FreeRTOS任務(wù)間的同步和資源共享機(jī)制,計(jì)數(shù)信號(hào)量。FreeRTOS中計(jì)數(shù)信號(hào)量的源碼實(shí)現(xiàn)是基于消息隊(duì)列實(shí)現(xiàn)的。 本章教程配套的例子含Cortex-M3內(nèi)核的STM3
    發(fā)表于 09-05 09:36

    FreeRTOS信號(hào)量介紹

    FreeRTOS信號(hào)量 & ESP32實(shí)戰(zhàn)閱讀建議:有一定操作系統(tǒng)基礎(chǔ)知識(shí)。FreeRTOS信號(hào)量1. 二值信號(hào)量??二值
    發(fā)表于 01-27 07:28

    Linux信號(hào)量(2):POSIX 信號(hào)量

    上一章,講述了 SYSTEM V 信號(hào)量,主要運(yùn)行于進(jìn)程之間,本章主要介紹 POSIX 信號(hào)量:有名信號(hào)量、無名信號(hào)量。 POSIX 信號(hào)量
    的頭像 發(fā)表于 10-29 17:34 ?613次閱讀

    FreeRTOS信號(hào)量 & ESP32實(shí)戰(zhàn)

    FreeRTOS信號(hào)量 & ESP32實(shí)戰(zhàn)閱讀建議:有一定操作系統(tǒng)基礎(chǔ)知識(shí)。FreeRTOS信號(hào)量1. 二值信號(hào)量??二值
    發(fā)表于 12-03 18:06 ?1次下載
    <b class='flag-5'>FreeRTOS</b><b class='flag-5'>信號(hào)量</b> & ESP32實(shí)戰(zhàn)

    FreeRTOS 隊(duì)列 信號(hào)量 互斥

    文章目錄前言Queue 隊(duì)列semaphore 信號(hào)量Mutex 互斥微信公眾號(hào)前言FreeRTOS STM32CubeMX配置 內(nèi)存管理 任務(wù)管理上節(jié)介紹了用STM32CubeMX生成帶
    發(fā)表于 12-09 09:51 ?0次下載
    <b class='flag-5'>FreeRTOS</b> 隊(duì)列 <b class='flag-5'>信號(hào)量</b> 互斥<b class='flag-5'>量</b>

    FreeRTOS高級(jí)篇6---FreeRTOS信號(hào)量分析

    FreeRTOS信號(hào)量包括二進(jìn)制信號(hào)量、計(jì)數(shù)信號(hào)量、互斥信號(hào)量(以后簡(jiǎn)稱互斥)和遞歸互斥
    發(fā)表于 01-26 17:39 ?7次下載
    <b class='flag-5'>FreeRTOS</b>高級(jí)篇6---<b class='flag-5'>FreeRTOS</b><b class='flag-5'>信號(hào)量</b>分析

    FreeRTOS系列第20篇---FreeRTOS信號(hào)量API函數(shù)

    FreeRTOS信號(hào)量包括二進(jìn)制信號(hào)量、計(jì)數(shù)信號(hào)量、互斥信號(hào)量(以后簡(jiǎn)稱互斥)和遞歸互斥
    發(fā)表于 01-26 17:44 ?4次下載
    <b class='flag-5'>FreeRTOS</b>系列第20篇---<b class='flag-5'>FreeRTOS</b><b class='flag-5'>信號(hào)量</b>API函數(shù)

    在Arduino IDE中使用FreeRTOS信號(hào)量

    電子發(fā)燒友網(wǎng)站提供《在Arduino IDE中使用FreeRTOS信號(hào)量.zip》資料免費(fèi)下載
    發(fā)表于 01-04 10:18 ?0次下載
    在Arduino IDE中使用<b class='flag-5'>FreeRTOS</b><b class='flag-5'>信號(hào)量</b>

    freeRTOS中最常用到的信號(hào)量有哪些

    在操作系統(tǒng)系統(tǒng)中,信號(hào)量通常用于控制對(duì)共享資源的訪問和任務(wù)之間進(jìn)行同步,信號(hào)量在操作系統(tǒng)中是很常用的,也是學(xué)習(xí)freeRTOS操作系統(tǒng)必須要掌握的。
    的頭像 發(fā)表于 02-10 11:04 ?1775次閱讀
    <b class='flag-5'>freeRTOS</b>中最常用到的<b class='flag-5'>信號(hào)量</b>有哪些

    FreeRTOS的二值信號(hào)量

    FreeRTOS中的信號(hào)量是一種任務(wù)間通信的方式,信號(hào)量包括:二值信號(hào)量、互斥信號(hào)量、計(jì)數(shù)信號(hào)量
    的頭像 發(fā)表于 02-10 15:07 ?1242次閱讀

    FreeRTOS四種信號(hào)量詳細(xì)介紹

    1、二值信號(hào)量 二值信號(hào)量通常用于互斥訪問或同步,二值信號(hào)量和互斥信號(hào)量非常類似,但是還是有一些細(xì)微的差別,互斥信號(hào)量擁有優(yōu)先級(jí)繼承機(jī)制,二
    的頭像 發(fā)表于 07-06 17:14 ?2254次閱讀