文章目錄
- 前言
- 一、郵箱的特性
- 二、郵箱操作函數
- 2.1 創建郵箱
- 創建動態郵箱
- 創建靜態郵箱
- 2.2 刪除郵箱
- 2.3 發郵件
- 2.4 取郵件
- 三、示例代碼
- 總結
前言
RT-Thread是一個開源的實時嵌入式操作系統,廣泛應用于各種嵌入式系統和物聯網設備。在RT-Thread中,郵箱是一種常用的線程間通信機制,用于實現不同線程之間的消息傳遞。本教程將介紹如何在RT-Thread中使用郵箱,以便開發者更好地利用這一功能。
一、郵箱的特性
郵箱的本質是環形緩沖區:
郵箱中的每一封郵件,只能容納 4 字節內容(對于 32 位系統,指針大小剛好為 4 字節);
- 郵件的發送通常是非阻塞的,線程、中斷都可以發送郵件;也可使用阻塞方式發送;
- 郵件的接收通常是阻塞的,取決于郵箱中是否有郵件;
- 當一個線程向郵箱發送郵件時:
- 如果郵箱沒滿,就把數值寫入郵箱中
- 如果郵箱滿了:
- 發送線程可以直接返回RT_EFULL
- 也可以掛起一段時間,在掛起的期間,別的線程或中斷服務程序讀了郵箱,會喚醒掛起的線程。
- 當一個線程從郵箱接收郵件時:
- 如果郵箱不為空,就讀取郵箱中的數值
- 如果郵箱為空:
- 接收線可以直接返回RT_ETIMOUT
- 也可以掛起一段時間,在掛起的期間,別的線程或中斷服務程序寫了郵箱,會喚醒掛起的線程。
二、郵箱操作函數
郵箱由郵箱控制塊管理,由結構體 rt_mailbox 表示。
使用郵箱的流程:創建/初始化郵箱、發送郵件、接收郵件、刪除/脫離郵箱
2.1 創建郵箱
創建動態郵箱
我們可以使用下面這個函數創建動態郵箱:
rt_mailbox_t rt_mb_create (const char* name, rt_size_t size, rt_uint8_t flag);
參數說明:
name 郵箱名稱
size 郵箱容量
flag 郵箱采用的等待方式: RT_IPC_FLAG_FIFO 或 RT_IPC_FLAG_PRIO
返回值 郵箱對象的句柄:成功,返回句柄,以后使用句柄來操作郵箱,RT_NULL:失敗
創建靜態郵箱
我們可以使用下面這個函數創建靜態郵箱:
rt_err_t rt_mb_init(rt_mailbox_t mb,const char* name,void* msgpool,rt_size_t size,rt_uint8_t flag);
參數說明:
mb 郵箱對象的句柄
name 郵箱的名字
msgpool 緩沖區指針
size 郵箱容量
flag 郵箱采用的等待方式: RT_IPC_FLAG_FIFO 或 RT_IPC_FLAG_PRIO
返回值 RT_EOK:成功
2.2 刪除郵箱
我們可以使用下面這個函數刪除rt_mb_create
函數創建的郵箱:
rt_err_t rt_mb_delete (rt_mailbox_t mb);
參數為郵箱的handle
我們可以使用下面這個函數刪除rt_mb_init
創建的郵箱:
rt_err_t rt_mb_detach(rt_mailbox_t mb);
參數為郵箱的handle
他們的返回值為RT_ERROR
時,表示出錯了
2.3 發郵件
- 我們可以使用下面這個函數來發送郵件:
rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value);
參數1為郵箱的handle
參數2為要發送的值
- 我們可以使用下面這個函數來發送郵件,并等待一定的tick:
rt_err_t rt_mb_send_wait(rt_mailbox_t mb,rt_ubase_t value,rt_int32_t timeout);
參數1為郵箱的handle
參數2為要發送的值
參數3為等待的tick
- 我們可以使用下面這個函數來發送緊急郵件:
rt_err_t rt_mb_urgent (rt_mailbox_t mb, rt_ubase_t value);
參數1為郵箱的handle
參數2為要發送的值
2.4 取郵件
我們可以使用下面這個函數來收郵件:
rt_err_t rt_mb_recv (rt_mailbox_t mb, rt_uint32_t* value, rt_int32_t timeout);
參數1為郵箱的handle
參數2為存儲的地址
參數3為等待時間
三、示例代碼
#include <rtthread.h>// 定義一個郵箱句柄
static rt_mailbox_t mailbox;// 定義一個線程1
static void thread1_entry(void *parameter)
{rt_uint32_t message = 123;// 發送消息到郵箱rt_mb_send(mailbox, &message, sizeof(message));// 等待一段時間,模擬其他操作rt_thread_delay(50);
}// 定義一個線程2
static void thread2_entry(void *parameter)
{rt_uint32_t message;// 從郵箱接收消息rt_mb_recv(mailbox, &message, RT_WAITING_FOREVER);// 處理接收到的消息rt_kprintf("Received message: %d\n", message);
}int mailbox_example(void)
{// 創建郵箱,設置郵箱大小為5,每個消息大小為4字節mailbox = rt_mb_create("mbox", 5, RT_IPC_FLAG_FIFO);if (mailbox == RT_NULL){rt_kprintf("Failed to create mailbox!\n");return -1;}// 創建線程1rt_thread_t thread1 = rt_thread_create("t1", thread1_entry, RT_NULL, 512, 10, 10);if (thread1 != RT_NULL){rt_thread_startup(thread1);}// 創建線程2rt_thread_t thread2 = rt_thread_create("t2", thread2_entry, RT_NULL, 512, 11, 10);if (thread2 != RT_NULL){rt_thread_startup(thread2);}// 等待線程執行完成rt_thread_mdelay(100);// 刪除郵箱rt_mb_delete(mailbox);return 0;
}// 在RT-Thread的初始化中調用示例函數
INIT_APP_EXPORT(mailbox_example);
總結
通過本教程,我們深入了解了在RT-Thread中如何有效地使用郵箱進行線程間通信。郵箱作為一種輕量級的消息傳遞機制,為開發者提供了一種靈活而高效的方式來實現不同線程之間的數據傳遞。通過合理地利用郵箱,我們能夠在嵌入式系統和物聯網設備中構建更為可靠和響應的應用程序。希望本教程能夠幫助開發者更好地利用RT-Thread的功能,提升嵌入式系統的開發效率和性能。