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

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

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

freeRTOS中的消息郵箱

汽車電子技術(shù) ? 來源:嵌入式之入坑筆記 ? 作者:嵌入式之入坑筆記 ? 2023-02-10 11:05 ? 次閱讀

**1、freeRTOS中的消息郵箱 **

freeRTOS實(shí)現(xiàn)的消息郵箱是基于任務(wù)通知方式而實(shí)現(xiàn)的。

采用這種方式有什么優(yōu)勢呢?

從官方給出的測試報(bào)告中有說明到,喚醒由于信號量和事件標(biāo)志組而處于阻塞態(tài)的任務(wù),消息郵箱的速度會提升大約 45%,而且這種方式需要的 RAM 空間更小。

freeRTOS中的消息郵箱使用是比較靈活的,它可以實(shí)現(xiàn)二值信號量、計(jì)數(shù)信號量、事件標(biāo)志組、消息隊(duì)列等通知方式。

但用這種 方式實(shí)現(xiàn)信號量和事件標(biāo)志組也有它的局限性,主要表現(xiàn)在以下兩個(gè)方面:

1)任務(wù)通知方式僅可以用在只有一個(gè)任務(wù)等待信號量,消息郵箱或者事件標(biāo)志組的情況。

2)如果使用任務(wù)通知方式實(shí)現(xiàn)消息郵箱替代消息隊(duì)列時(shí),發(fā)送消息的任務(wù)是不支持超時(shí)等待的。在消息隊(duì)列中,當(dāng)數(shù)據(jù)已經(jīng)滿時(shí),是可以等待消息隊(duì)列有空間才存新的數(shù)據(jù)的,但是任務(wù)通知方式實(shí)現(xiàn)的消 息郵箱就不支持超時(shí)等待。

2、有關(guān)freeRTOS中的任務(wù)控制塊

freeRTOS中的每一個(gè)任務(wù)都有一個(gè)任務(wù)控制塊,而任務(wù)控制塊本質(zhì)就是一個(gè)結(jié)構(gòu)體變量,用于記錄任務(wù)的相關(guān)的消息。

而在結(jié)構(gòu)體變量中有一個(gè)32位的變量成員ulNotifiedValue是可以專門用于任務(wù)通知的。這個(gè)變量可以實(shí)現(xiàn)計(jì)數(shù)信號量,二值信號量,事件標(biāo)志組和消息郵箱(消息郵箱就是消息隊(duì) 列長度為 1 的情況)。

ulNotifiedValue 實(shí)現(xiàn)的:

1)設(shè)置接收任務(wù)控制塊中的變量 ulNotifiedValue 可以實(shí)現(xiàn)消息郵箱。

2)如果接收任務(wù)控制塊中的變量 ulNotifiedValue 還沒有被其接收到,也可以用新數(shù)據(jù)覆蓋原有數(shù)據(jù) ,這就是 覆蓋方式的消息郵箱 。

3)設(shè)置接收任務(wù)控制塊中的變量 ulNotifiedValue 的 bit0-bit31 數(shù)值可以實(shí)現(xiàn)事件標(biāo)志組。

4)設(shè)置接收任務(wù)控制塊中的變量 ulNotifiedValue 數(shù)值進(jìn)行加一或者減一操作可以實(shí)現(xiàn)計(jì)數(shù)信號量和二 值信號量。

3、freeRTOS中消息郵箱的管理API函數(shù)

消息郵箱實(shí)現(xiàn)的相關(guān)API函數(shù):

3.1、消息郵箱的創(chuàng)建

freeRTOS中的消息郵箱是用于任務(wù)之間的一種通知方式,它的使用是不需要像信號量這樣要專門創(chuàng)建的。是直接發(fā)送通知的。

3.2、消息郵箱的發(fā)送

1)在任務(wù)函數(shù)中發(fā)送

函數(shù)原型:

BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, /* 任務(wù)句柄 */
                     uint32_t ulValue,           /* 更新任務(wù)控制塊中的變量 ulNotifiedValue */
                       eNotifyAction eAction );    /* 任務(wù)通知模式設(shè)置 */

函數(shù)描述:

第 1 個(gè)參數(shù)是任務(wù)句柄。

第 2 個(gè)參數(shù)是用來更新任務(wù)控制塊中的 32 位變量 ulNotifiedValue。

第 3 個(gè)參數(shù)是任務(wù)通知模式設(shè)置,支持以下 5 個(gè)參數(shù):

圖片

返回值,根據(jù)上面第3個(gè)參數(shù)的說明,將其設(shè)置為 :

eSetValueWithoutOverwrite ,有可能返回 pdFALSE,其余所有情況都返回值 pdPASS。

使用這個(gè)函數(shù)要注意以下問題:

1)任務(wù)創(chuàng)建后,任務(wù)控制塊中的變量 ulNotifiedValue 初始計(jì)數(shù)值是 0。

2)默認(rèn)配置此函數(shù)可以使用的的宏定義已經(jīng)在 FreeRTOS.h 文件中使能:

#define configUSE_TASK_NOTIFICATIONS  1

當(dāng)然,如果不需要使用任務(wù)通知功能相關(guān)的函數(shù),可以在 FreeRTOSConfig.h 文件中配置此宏定 義為 0 來禁止,這樣創(chuàng)建的每個(gè)任務(wù)可以節(jié)省 8 個(gè)字節(jié)的需求。

3)此函數(shù)是用于任務(wù)代碼中調(diào)用的,故不可以在中斷服務(wù)程序中調(diào)用此函數(shù),中斷服務(wù)程序中使用的是 xTaskNotifyFromISR。

4)根據(jù) FreeRTOS 的建議,實(shí)現(xiàn)二值信號量和計(jì)數(shù)信號量時(shí)使用函數(shù) xTaskNotifyGive()替代此函數(shù) xTaskNotify()。

2)在中斷中發(fā)送

函數(shù)原型:

BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, /* 任務(wù)句柄 */
                    uint32_t ulValue,       /* 更新任務(wù)控制塊中的變量 ulNotifiedValue */
                        eNotifyAction eAction,     /* 任務(wù)通知模式設(shè)置 */
                    BaseType_t *pxHigherPriorityTaskWoken ); /* 高優(yōu)先級任務(wù)是否被喚醒的狀態(tài)保存 */

函數(shù)描述:

函數(shù) xTaskNotifyFromISR 通過設(shè)置任務(wù)控制塊中的變量 ulNotifiedValue 可以在中斷服務(wù)程序中實(shí)現(xiàn)任 務(wù)事件標(biāo)志組,任務(wù)計(jì)數(shù)信號量,任務(wù)消息郵箱和任務(wù)二值信號量四種方式的消息通知。

第 1 個(gè)參數(shù)是任務(wù)句柄。

第 2 個(gè)參數(shù)是用來更新任務(wù)控制塊中的 32 位變量 ulNotifiedValue。

第 3 個(gè)參數(shù)是任務(wù)通知模式設(shè)置,支持以下 5 個(gè)參數(shù):

圖片

圖片

第4個(gè)參數(shù)用于保存是否有高優(yōu)先級任務(wù)準(zhǔn)備就緒。如果函數(shù)執(zhí)行完畢后,此參數(shù)的數(shù)值是 pdTRUE , 說明有高優(yōu)先級任務(wù)要執(zhí)行,否則沒有。

返回值,根據(jù)上面第 3 個(gè)參數(shù)的說明,將其設(shè)置為:

eSetValueWithoutOverwrite ,有可能返回 pdFALSE ,其余所有情況都返回值 pdPASS 。

使用這個(gè)函數(shù)要注意以下問題:

  1. 任務(wù)創(chuàng)建后,任務(wù)控制塊中的變量** ulNotifiedValue **初始計(jì)數(shù)值是 0。
  2. 默認(rèn)配置此函數(shù)可以使用的的宏定義已經(jīng)在 FreeRTOS.h 文件中使能:
#define  configUSE_TASK_NOTIFICATIONS   1

當(dāng)然,如果用戶不需要使用任務(wù)通知功能相關(guān)的函數(shù),可以在 FreeRTOSConfig.h 文件中配置此宏定 義為 0 來禁止,這樣創(chuàng)建的每個(gè)任務(wù)可以節(jié)省 8 個(gè)字節(jié)的需求。

3)此函數(shù)是用于中斷服務(wù)程序中調(diào)用的,故不可以在任務(wù)代碼中調(diào)用此函數(shù),任務(wù)代碼中使用的是 xTaskNotify。

4)FreeRTOS 的建議,實(shí)現(xiàn)二值信號量和計(jì)數(shù)信號量時(shí)使用函數(shù) vTaskNotifyGiveFromISR ()替代 此函數(shù) xTaskNotifyFromISR ()。

3.3、等待消息郵箱

(1)等待消息郵箱

函數(shù)原型:

BaseType_t xTaskNotifyWait(
          /* 設(shè)置函數(shù)執(zhí)行前清零任務(wù)控制塊中變量 ulNotifiedValue 那些位 */
            uint32_t ulBitsToClearOnEntry,
          /*設(shè)置函數(shù)退出前清零任務(wù)控制塊中變量 ulNotifiedValue 那些位 */
            uint32_t ulBitsToClearOnExit,
          /* 保存任務(wù)控制塊中的變量 ulNotifiedValue 到指針變量 pulNotifiedValue 所指向的存儲單元 */
            uint32_t *pulNotificationValue,
          /* 等待消息通知的最大等待時(shí)間 */
            TickType_t xTicksToWait
              );

函數(shù)描述:

函數(shù) xTaskNotifyWait 可以在任務(wù)代碼中實(shí)現(xiàn)任務(wù)事件標(biāo)志組,任務(wù)計(jì)數(shù)信號量,任務(wù)消息郵箱和任務(wù)二 值信號量四種方式的消息獲取。

第 1 個(gè)參數(shù) ulBitsToClearOnEntry 用于函數(shù)執(zhí)行之前,將任務(wù)控制塊中的變量 ulNotifiedValue 進(jìn) 行如下操作 :

ulNotifiedValue &= ~ulBitsToClearOnEntry

簡單的說就是參數(shù) ulBitsToClearOnEntry 哪個(gè)位是 1,那么變量 ulNotifiedValue 的那個(gè)位就會被 清零。比如 ulBitsToClearOnEntry = 0x01 表示將變量 ulNotifiedValue 的 bit0 清零,又比如 ulBitsToClearOnEntry = 0xffffffff 表示將變量 ulNotifiedValue 的所有位清零。

第 2 個(gè)參數(shù) ulBitsToClearOnExit 用于函數(shù)退出前,將任務(wù)控制塊中的變量 ulNotifiedValue 進(jìn)行如 下操作 :

ulNotifiedValue &= ~ ulBitsToClearOnExit

簡單的說就是參數(shù) ulBitsToClearOnExit 哪個(gè)位是 1,那么變量 ulNotifiedValue 的那個(gè)位就會被清 零。比如 ulBitsToClearOnExit= 0x01 表示將變量 ulNotifiedValue 的 bit0 清零,又比如 ulBitsToClearOnExit= 0xffffffff 表示將變量 ulNotifiedValue 的所有位清零。

第 3 個(gè)參數(shù)用于將任務(wù)控制塊中的變量 ulNotifiedValue 保存到此參數(shù)指針?biāo)赶虻拇鎯卧?。如?此參數(shù)沒有用上,可以將其設(shè)置為 NULL。

第 4 個(gè)參數(shù)是沒有消息時(shí),等待消息的最大等待時(shí)間,單位系統(tǒng)時(shí)鐘節(jié)拍。

返回值,如果成功接收到消息返回 pdTRUE,否則返回 pdFALSE,比如在設(shè)置的超時(shí)時(shí)間內(nèi)沒有收 到消息。

使用這個(gè)函數(shù)要注意以下問題:

1)任務(wù)創(chuàng)建后,任務(wù)控制塊中的變量 ulNotifiedValue 初始計(jì)數(shù)值是 0。

2)默認(rèn)配置此函數(shù)可以使用的的宏定義已經(jīng)在 FreeRTOS.h 文件中使能:

#define configUSE_TASK_NOTIFICATIONS  1

當(dāng)然,如果用戶不需要使用任務(wù)通知功能相關(guān)的函數(shù),可以在 FreeRTOSConfig.h 文件中配置此宏定 義為 0 來禁止,這樣創(chuàng)建的每個(gè)任務(wù)可以節(jié)省 8 個(gè)字節(jié)的需求。

3)如果用戶將 FreeRTOSConfig.h 文件中的宏定義 INCLUDE_vTaskSuspend 配置為 1 且第 2 個(gè)參數(shù)配 置為:

portMAX_DELAY ,那么此函數(shù)會永久等待直到消息可用。

4)根據(jù) FreeRTOS 的建議,實(shí)現(xiàn)二值信號量和計(jì)數(shù)信號量時(shí)使用函數(shù) ulTaskNotifyTake ()替代此函數(shù) xTaskNotifyWait ()。

4、消息郵箱的應(yīng)用示例

為了更好的說明freeRTOS中的消息郵箱的使用。下面給出了一個(gè)簡單的示例。

代碼思路如下:

創(chuàng)建3個(gè)任務(wù):start_task,led0_task,led2_task。start_task任務(wù)用于創(chuàng)建led0_task和led2_task任務(wù),led0_task任務(wù)判斷按鍵的情況,然后根據(jù)按鍵按下,消息郵箱發(fā)送不同的消息到任務(wù)led2_task,在這個(gè)任務(wù)中改變LED2和LED3的狀態(tài)。代碼示例如下:

void start_task(void *pvParameters)
{
    pvParameters =  pvParameters;
    taskENTER_CRITICAL();  //進(jìn)入臨界區(qū)

    xTaskCreate((TaskFunction_t)  led0_task,
                 (const char*)    "led0_task",
                  (uint16_t)      TASK_STK_LED0_SIZE,
                  (void*)         NULL,
                  (UBaseType_t)   TASK_LED0_PRIO,
                  (TaskHandle_t*) &LED0_Handler );

    xTaskCreate((TaskFunction_t)  led2_task,
                 (const char*)    "led2_task",
                  (uint16_t)      TASK_STK_LED2_SIZE,
                  (void*)         NULL,
                  (UBaseType_t)   TASK_LED2_PRIO,
                  (TaskHandle_t*) &LED2_Handler );
    vTaskDelete(StartTask_Handler);   //刪除開始任務(wù)
    taskEXIT_CRITICAL();   //退出臨界區(qū)
}


void led0_task(void *pvParameters)
{
  //pvParameters =  pvParameters;
  BaseType_t err = pdFALSE;
  uint32_t MboxValue=0;
  for(;;)
  {
     if(gd_eval_key_state_get(KEY_WAKEUP) == RESET)
     {
       MboxValue = 10;
       err = xTaskNotify((TaskHandle_t )  LED2_Handler, //任務(wù)句柄,指明往哪個(gè)任務(wù)發(fā)送消息,很重要
                         (uint32_t )      MboxValue,    //發(fā)送的消息
                         (eNotifyAction)  eSetValueWithOverwrite //消息發(fā)送方式
                        );
     }
     else if(gd_eval_key_state_get(KEY_TAMPER) == RESET)
     {
       MboxValue = 50;
       err = xTaskNotify((TaskHandle_t )  LED2_Handler, //任務(wù)句柄
                         (uint32_t )     MboxValue,     //發(fā)送的消息
                         (eNotifyAction) eSetValueWithOverwrite //消息發(fā)送方式
                        );
     }
     else{}
     gd_eval_led_toggle(LED4);
     vTaskDelay(200);
  }
}


void led2_task(void *pvParameters)
{
  //pvParameters = pvParameters;
  uint32_t notifyValue = 0;
  BaseType_t err;
  for(;;)
  {
     err = xTaskNotifyWait((uint32_t )  0x00,         //進(jìn)入函數(shù)時(shí)不清楚bit
                           (uint32_t)   0xffffffff,   //退出函數(shù)時(shí)清除所有的bit
                           (uint32_t*)  ¬ifyValue, //保存消息的內(nèi)容
                           (TickType_t) portMAX_DELAY //阻塞時(shí)間
                          );
    if(err == pdTRUE)
    {
       switch(notifyValue)
       {
         case 10:
           gd_eval_led_toggle(LED2);
           break;
         case 50:
           gd_eval_led_toggle(LED3);
           break;
         default:
           break;
       }
    }
    vTaskDelay(100);
  }
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • FreeRTOS
    +關(guān)注

    關(guān)注

    12

    文章

    484

    瀏覽量

    62271
  • 信號量
    +關(guān)注

    關(guān)注

    0

    文章

    53

    瀏覽量

    8362
  • 消息隊(duì)列
    +關(guān)注

    關(guān)注

    0

    文章

    33

    瀏覽量

    3010
收藏 人收藏

    評論

    相關(guān)推薦

    QQ郵箱手機(jī)上如何配置POP/IMAP?

    QQ郵箱手機(jī)上如何配置POP/IMAP? 以Nokia E71為例     1.在QQ郵箱啟用P
    發(fā)表于 02-25 09:53 ?1.2w次閱讀

    FreeRTOS的任務(wù)管理

    任務(wù)是 FreeRTOS 中最基本的調(diào)度單元,它是一段可執(zhí)行的代碼,可以獨(dú)立運(yùn)行。FreeRTOS 的任務(wù)是基于優(yōu)先級的搶占式調(diào)度,優(yōu)先級高的任務(wù)可以搶占優(yōu)先級低的任務(wù)的 CPU 資源。任務(wù)的創(chuàng)建、刪除、掛起、恢復(fù)、設(shè)置優(yōu)先級
    的頭像 發(fā)表于 11-27 17:03 ?1046次閱讀

    用的cube生成的freertos工程,串口和任務(wù)通過郵箱通訊,結(jié)果任務(wù)反應(yīng)很慢是怎么回事?

    初學(xué)freertos。用的cube生成的freertos工程,單片機(jī)型號位stm32f103vbt6。 建了三個(gè)人物,一個(gè)是串口任務(wù),一個(gè)是LED每秒翻轉(zhuǎn)一次,一個(gè)是空任務(wù)。 串口接收
    發(fā)表于 05-08 08:13

    STM32CubeMX FreeRTOS學(xué)習(xí)[5] 郵箱隊(duì)列(Lu)

    STM32CubeMX FreeRTOS學(xué)習(xí)[5] 郵箱隊(duì)列(Lu)
    發(fā)表于 09-06 16:36

    轉(zhuǎn):第27章 FreeRTOS任務(wù)消息郵箱

    本章節(jié)為大家講解FreeRTOS消息隊(duì)列(消息隊(duì)列長度固定為1)的另一種實(shí)現(xiàn)方式----基于任務(wù)通知(Task Notifications)的消息隊(duì)列,這里我們將這種方式實(shí)現(xiàn)的消息隊(duì)列(消息隊(duì)列
    發(fā)表于 09-09 07:52

    電子郵箱,電子郵箱是什么意思

    電子郵箱,電子郵箱是什么意思 電子郵箱(E-MAIL BOX)是通過網(wǎng)絡(luò)電子郵局為網(wǎng)絡(luò)客戶提供的網(wǎng)絡(luò)交流電子信息空間。電子郵箱具有存
    發(fā)表于 03-06 15:00 ?2.8w次閱讀

    RT-Thread的郵箱服務(wù),包括郵箱工作機(jī)制、工作管理方式以及應(yīng)用示例

    當(dāng)一個(gè)線程從郵箱接收郵件時(shí),如果郵箱是空的,接收線程可以選擇是否等待掛起直到收到新的郵件而喚醒,或可以設(shè)置超時(shí)時(shí)間。當(dāng)達(dá)到設(shè)置的超時(shí)時(shí)間,郵箱依然未收到郵件時(shí),這個(gè)選擇超時(shí)等待的線程
    的頭像 發(fā)表于 03-28 09:38 ?1.3w次閱讀
    RT-Thread的<b class='flag-5'>郵箱</b>服務(wù),包括<b class='flag-5'>郵箱</b>工作機(jī)制、工作管理方式以及應(yīng)用示例

    STM32斷及FreeRTOS中斷優(yōu)先級配置

    STM32斷,及FreeRTOS中斷優(yōu)先級配置
    的頭像 發(fā)表于 03-04 11:45 ?8957次閱讀
    STM32<b class='flag-5'>中</b>斷及<b class='flag-5'>FreeRTOS</b>中斷優(yōu)先級配置

    FreeRTOS相對延時(shí)與絕對延時(shí)的區(qū)別

    FreeRTOS相對延時(shí)和絕對延時(shí)的區(qū)別
    的頭像 發(fā)表于 03-12 10:32 ?8498次閱讀
    <b class='flag-5'>FreeRTOS</b><b class='flag-5'>中</b>相對延時(shí)與絕對延時(shí)的區(qū)別

    FreeRTOS的API函數(shù)功能分析及調(diào)用方法

    FreeRTOS的API函數(shù)功能分析及調(diào)用方法說明。
    發(fā)表于 03-26 11:50 ?33次下載

    Freertos 的移植 “FreeRTOSConfig.h“ 的配置

    Freertos 的移植 “FreeRTOSConfig.h“ 的配置
    發(fā)表于 12-04 14:06 ?10次下載
    <b class='flag-5'>Freertos</b> 的移植<b class='flag-5'>中</b> “FreeRTOSConfig.h“ 的配置

    基于STM32的FreeRTOS開發(fā)(1)----FreeRTOS簡介

    管理功能,可以讓您在嵌入式系統(tǒng)實(shí)現(xiàn)多任務(wù)環(huán)境,這對于涉及多個(gè)獨(dú)立功能的系統(tǒng)是非常重要的。它還提供了一些高級功能,如事件組、信號量、郵箱等,可用于實(shí)現(xiàn)任務(wù)之間的同步和通信。 FreeRTOS還提供了
    的頭像 發(fā)表于 07-27 09:49 ?1365次閱讀
    基于STM32的<b class='flag-5'>FreeRTOS</b>開發(fā)(1)----<b class='flag-5'>FreeRTOS</b>簡介

    FreeRTOS的空閑任務(wù)是什么

    空閑任務(wù)是 FreeRTOS 必不可少的一個(gè)任務(wù),其他 RTOS 類系統(tǒng)也有空閑任務(wù),比如 uC/OS。看名字就知道,空閑任務(wù)是處理器空閑的時(shí)候去運(yùn)行的一個(gè)任務(wù),當(dāng)系統(tǒng)沒有其他就緒任務(wù)的時(shí)候空閑
    的頭像 發(fā)表于 07-30 10:55 ?1293次閱讀

    uC/OS-II—郵箱介紹

    在uC/OS-II郵箱是線程(任務(wù))通訊的一種,使用郵箱能夠發(fā)送一個(gè)指針,當(dāng)然也可以發(fā)送指針大小的數(shù)據(jù)。
    的頭像 發(fā)表于 09-11 15:35 ?1134次閱讀

    SoC的核間通信機(jī)制硬件郵箱

    小的硬件隊(duì)列,其中包含 VRING ID。 VRING 是共享內(nèi)存的 SW 隊(duì)列,保存兩個(gè) CPU 之間傳遞的實(shí)際消息。當(dāng)收到中斷時(shí),郵箱消息會告知從哪個(gè) VRING 出
    的頭像 發(fā)表于 09-13 17:35 ?1095次閱讀
    SoC的核間通信機(jī)制硬件<b class='flag-5'>郵箱</b>