RT-Thread之郵箱使用示例
郵箱(Mailbox)是RT-Thread中高效的線程間通信機制,其核心特點是:
- 傳輸固定尺寸數據:每條消息為4字節(32位系統),可傳遞整型或指針
- 輕量級通信:比消息隊列更節省內存,適用于小數據量場景
- 優先級傳遞:支持緊急消息優先處理
典型應用場景: 在硬件中斷服務中,通過rt_mb_send快速傳遞傳感器狀態字,消費線程解析后觸發相應動作,避免中斷長時間占用CPU資源。
一、郵箱API函數
1、郵箱的創建
- 動態創建郵箱(推薦靈活場景)
rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag)
- 靜態創建郵箱
rt_err_t rt_mb_init(rt_mailbox_t mb,
const char *name,
void *msgpool,
rt_size_t size,
rt_uint8_t flag)
2、郵箱的發送
線程或者中斷服務程序都可以通過往郵箱里寫入郵件。發送的郵件,可以是32位的任意格式數據,可以是一個整型值或者一個指向某塊內存的指針
- 直接發送郵件:只有在郵箱有可用的空閑空間時,才能成功發送消息,否則返回錯誤。
rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value)
- 等待發送郵件:如果郵箱沒有可用的空閑空間,會根據timeout參數等待,超時后才返回錯誤。
rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
rt_ubase_t value,
rt_int32_t timeout)
- 緊急發送郵件:只有在郵箱有可用的空閑空間,它才會把郵件插在郵件隊首,以便這個郵件能被第1時間讀取。
rt_err_t rt_mb_urgent(rt_mailbox_t mb, rt_ubase_t value)
3、消息的接收
當郵箱有郵件時,使用收郵件函數,可以從郵箱接收郵件。如果沒有郵件,根據指定的timeout參數等待,直到超時結束。
rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout)
4、郵箱的脫離/刪除
刪除或者脫離郵箱時,如果有線程在等待該郵箱,則內核先喚醒這些線程(線程返回值是RT_ERROR),然后再釋放郵箱使用的內存,最后刪除郵箱對象。
- 刪除使用 rt_mb_create()創建的隊列
rt_err_t rt_mb_delete(rt_mailbox_t mb)
- 脫離使用 rt_mb_init()初始化的隊列
rt_err_t rt_mb_detach(rt_mailbox_t mb)
二、創建郵箱示例
1、創建郵箱
struct rt_mailbox mb_static; /* 郵箱句柄 */
uint8_t msgpool[48]; /* 郵箱靜態內存池 */
/* 靜態創建一個郵箱 */
rt_mb_init(
&mb_static, /* 郵箱對象的句柄 */
"mb_static_test", /* 郵箱對象名稱 */
msgpool, /* 內存池指向 */
sizeof(msgpool) / 4, /* 郵箱中能容納的郵件數量,每封郵件占四字節 */
RT_IPC_FLAG_FIFO /* 如果有多個線程等待,按照先來先得到的方法分配 */
);
rt_mailbox_t mb_dynamic; /* 郵箱句柄指針 */
/* 動態創建一個郵箱 */
mb_dynamic = rt_mb_create(
"mb_dynamic_test", /* 郵箱對象名稱 */
12, /* 郵箱中能容納的郵件數量,每封郵件占四字節 */
RT_IPC_FLAG_FIFO /* 如果有多個線程等待,按照先來先得到的方法分配 */
);
2、接收與發送消息
#include "thread_task.h"
#include "main.h"
#include <stdio.h>
#include "rtthread.h"
#include <rthw.h>
/******************************************** 線程 1 ******************************************************/
#define THREAD_1_PRIORITY 4 /* 進程優先級 */
#define THREAD_1_STACK_SIZE 512 /* 進程棧空間大小 */
#define THREAD_1_TIMESLICE 10 /* 進程執行時間片個數 */
static struct rt_thread *thread_1_handle; /* 進程句柄 */
/******************************************** 線程 2 ******************************************************/
#define THREAD_2_PRIORITY 5 /* 進程優先級 */
#define THREAD_2_STACK_SIZE 512 /* 進程棧空間大小 */
#define THREAD_2_TIMESLICE 10 /* 進程執行時間片個數 */
static struct rt_thread *thread_2_handle; /* 進程句柄 */
rt_mailbox_t mb_dynamic; /* 郵箱句柄指針 */
/**
* @brief 線程1入口函數
* @param 無
* @retval 無
*/
void thread_1_entry(void* param)
{
uint32_t value = 0;
while(1)
{
rt_thread_delay(4000); /* 精準延時4000時間片 */
rt_mb_recv(mb_dynamic, &value, 0xffffffff);
HAL_GPIO_TogglePin(GPIOC, LED1_Pin);
}
}
/**
* @brief 線程2入口函數
* @param 無
* @retval 無
*/
void thread_2_entry(void* param)
{
while(1)
{
rt_mb_send_wait(mb_dynamic, (uint32_t)0x01, 0xffffffff);
HAL_GPIO_TogglePin(GPIOC, LED2_Pin);
rt_thread_delay(200);
}
}
/**
* @brief 動態創建線程任務并啟動
* @param 無
* @retval 無
*/
void ThreadStart(void)
{
rt_base_t level = rt_hw_interrupt_disable();
/* 動態創建線程 */
thread_1_handle = rt_thread_create(
"thread_1", /* 線程句柄名稱*/
thread_1_entry, /* 函數入口 */
RT_NULL, /* 入口函數參數 */
THREAD_1_STACK_SIZE, /* 線程棧大小 */
THREAD_1_PRIORITY, /* 線程優先級 */
THREAD_1_TIMESLICE /* 線程時間片大小 */
);
rt_thread_startup(thread_1_handle); /* 啟動線程 */
thread_2_handle = rt_thread_create(
"thread_2", /* 線程句柄名稱*/
thread_2_entry, /* 函數入口 */
RT_NULL, /* 入口函數參數 */
THREAD_2_STACK_SIZE, /* 線程棧大小 */
THREAD_2_PRIORITY, /* 線程優先級 */
THREAD_2_TIMESLICE /* 線程時間片大小 */
);
rt_thread_startup(thread_2_handle); /* 啟動線程 */
/* 動態創建郵箱 */
mb_dynamic = rt_mb_create(
"mb_dynamic_test",
12,
RT_IPC_FLAG_FIFO
);
rt_hw_interrupt_enable(level);
}
執行流程如下:
(1)初始階段
- 線程1立即阻塞等待消息(郵箱空)
- 線程2開始高頻發送(每200 ticks發送1次)
(2)郵箱填滿階段
-
線程2發送12條消息后郵箱滿 →
rt_mb_send_wait()開始阻塞 -
系統進入雙阻塞狀態(線程1和2均掛起)
(3)恢復同步階段
-
線程1的rt_thread_delay(4000)到期后:
-
消費1條消息 → 釋放1個郵箱槽位
-
喚醒線程2繼續發送
-
-
穩定狀態:每4000 ticks消費1條,線程2每200 ticks補充1條


郵箱(Mailbox)是RT-Thread中高效的線程間通信機制。
浙公網安備 33010602011771號