日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

RT_thread邮箱的使用

發(fā)布時(shí)間:2023/12/8 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RT_thread邮箱的使用 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、郵箱工作機(jī)制

RT_thread操作系統(tǒng)中的郵箱用于線程間通信,特點(diǎn)是開銷較小,效率比較高。郵箱中的每一封郵件只能容納固定的4字節(jié)內(nèi)容(針對32位處理系統(tǒng)。指針的大小即為4字節(jié),所以一封郵件恰好能容納一個(gè)指針)

線程或中斷服務(wù)例程把一封4字節(jié)長度的郵件發(fā)到郵箱中,而其他需要的線程可以通過郵箱中接收這些郵件并處理。

郵箱控制塊:

RT-Thread中使用郵箱實(shí)現(xiàn)線程異步通信工作,具有如下特性:

郵件支持先進(jìn)先出方式排隊(duì)與優(yōu)先級排隊(duì)方式,支持異步讀寫工作方式。 發(fā)送與接收郵件均支持超時(shí)機(jī)制。 一個(gè)線程能夠從任意一個(gè)消息隊(duì)列接收和發(fā)送郵件。 多個(gè)線程能夠向同一個(gè)郵箱發(fā)送郵件和從中接收郵件。 郵箱中的每一封郵件只能容納固定的4字節(jié)內(nèi)容(可以存放地址)。 當(dāng)隊(duì)列使用結(jié)束后,需要通過刪除郵箱以釋放內(nèi)存。

郵箱與消息隊(duì)列很相似,消息隊(duì)列中消息的長度是可以由用戶配置的,但郵箱中郵件的大小卻只能是固定容納4字節(jié)的內(nèi)容,所以,使用郵箱的開銷是很小的,因?yàn)閭鬟f的只能是4字節(jié)以內(nèi)的內(nèi)容,那么其效率會(huì)更高。

運(yùn)作機(jī)制
創(chuàng)建郵箱對象時(shí)會(huì)先創(chuàng)建一個(gè)郵箱對象控制塊,然后給郵箱分配一塊內(nèi)存空間用來存放郵件,這塊內(nèi)存的大小等于郵件大小(4字節(jié))與郵箱容量的乘積,接著初始化接收郵件和發(fā)送郵件在郵箱中的偏移量,接著再初始化消息隊(duì)列,此時(shí)消息隊(duì)列為空。

線程或者中斷服務(wù)程序都可以給郵箱發(fā)送郵件,非阻塞方式的郵件發(fā)送過程能夠安全的應(yīng)用于中斷服務(wù)中,中斷服務(wù)函數(shù)、定時(shí)器向線程發(fā)送消息的有效手段,而阻塞方式的郵件發(fā)送只能應(yīng)用于線程中。當(dāng)發(fā)送郵件時(shí),當(dāng)且僅當(dāng)郵箱還沒滿郵件的時(shí)候才能進(jìn)行發(fā)送,如果郵箱已滿,可以根據(jù)用戶設(shè)定的等待時(shí)間進(jìn)行等待,當(dāng)郵箱中的郵件被收取而空出空間來時(shí),等待掛起的發(fā)送線程將被喚醒繼續(xù)發(fā)送的過程,當(dāng)?shù)却龝r(shí)間到了還未完成發(fā)送郵件,或者未設(shè)置等待時(shí)間,此時(shí)發(fā)送郵件失敗,發(fā)送郵件的線程或者中斷程序會(huì)收到一個(gè)錯(cuò)誤碼(-RT_EFULL)。線程發(fā)送郵件可以帶阻塞,但在中斷中不能采用任何帶阻塞的方式發(fā)送郵件。

二、郵箱的操作

1、RT-Thread 創(chuàng)建一個(gè)郵箱有兩種方式:動(dòng)態(tài)創(chuàng)建、靜態(tài)初始化。

動(dòng)態(tài)創(chuàng)建一個(gè)郵箱的系統(tǒng)函數(shù)如下,調(diào)用這個(gè)函數(shù)創(chuàng)建一個(gè)郵箱時(shí),內(nèi)核會(huì)先從對象管理器中分配一個(gè)郵箱對象,然后創(chuàng)建一個(gè)郵箱控制塊,接著對郵箱控制塊進(jìn)行初始化,包括郵箱緩沖區(qū)地址、郵件數(shù)目、發(fā)送郵件在郵箱中的偏移等。

rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag);

(1)入口參數(shù):

name:郵箱名稱。
size:郵箱容量。
flag:郵箱標(biāo)志,它可以取如下數(shù)值:RT_IPC_FLAG_FIFO 或RT_IPC_FLAG_PRIO。

(2)返回值:

RT_NULL:創(chuàng)建失敗。
郵箱對象的句柄:創(chuàng)建成功。

2.刪除動(dòng)態(tài)郵箱函數(shù):當(dāng)用 rt_mb_create() 創(chuàng)建的郵箱不再被使用時(shí),應(yīng)該刪除它來釋放相應(yīng)的系統(tǒng)資源,一旦操作完成,郵箱將被永久性的刪除。刪除郵箱時(shí),如果有線程被掛起在該郵箱對象上,內(nèi)核先喚醒掛起在該郵箱上的所有線程(線程返回值是 RT_ERROR),然后再釋放郵箱使用的內(nèi)存,最后刪除郵箱對象。刪除郵箱的函數(shù)接口如下:

rt_err_t rt_mb_delete (rt_mailbox_t mb);

(1)入口參數(shù):

mb:要?jiǎng)h除的郵箱對象的句柄。

(2)返回值:

RT_EOK:成功。

3、創(chuàng)建靜態(tài)郵箱函數(shù):
這里所說的創(chuàng)建靜態(tài)郵箱和《RT-Thread編程指南》所講的初始化郵箱是一樣的,跟動(dòng)態(tài)創(chuàng)建郵箱類似,只是初始化郵箱用于靜態(tài)郵箱對象的初始化。與創(chuàng)建郵箱不同的是,靜態(tài)郵箱對象的內(nèi)存是在系統(tǒng)編譯時(shí)由編譯器分配的,一般放于讀寫數(shù)據(jù)段或未初始化數(shù)據(jù)段中,其余的初始化工作與創(chuàng)建郵箱時(shí)相同。初始化郵箱時(shí),該函數(shù)接口需要獲得用戶已經(jīng)申請獲得的郵箱對象控制塊,緩沖區(qū)的指針,以及郵箱名稱和郵箱容量(能夠存儲(chǔ)的郵件數(shù))。函數(shù)接口如下:

rt_err_t rt_mb_init(rt_mailbox_t mb,const char *name,void *msgpool,rt_size_t size,rt_uint8_t flag);

1)入口參數(shù):

mb:郵箱對象的句柄。
name:郵箱名稱。
msgpool:緩沖區(qū)指針。
size:郵箱容量。
flag:郵箱標(biāo)志,它可以取如下數(shù)值:RT_IPC_FLAG_FIFO 或 RT_IPC_FLAG_PRIO。

(2)返回值:

RT_EOK:成功。

注意:這里的 size 參數(shù)指定的是郵箱的容量,即如果 msgpool 指向的緩沖區(qū)的字節(jié)數(shù)是 N,那么郵箱容量應(yīng)該是 N/4。

4、刪除靜態(tài)郵箱函數(shù):這里所說的刪除靜態(tài)郵箱和《RT-Thread編程指南》所講的脫離郵箱是一樣的,脫離郵箱將把靜態(tài)初始化的郵箱對象從內(nèi)核對象管理器中脫離,內(nèi)核先喚醒所有掛在該郵箱上的線程(線程獲得返回值是 RT_ERROR),然后將該郵箱對象從內(nèi)核對象管理器中脫離。脫離郵箱使用下面的接口:

rt_err_t rt_mb_detach(rt_mailbox_t mb);

(1)入口參數(shù):

mb:郵箱對象的句柄。

(2)返回值:

RT_EOK:成功。

5、發(fā)送郵件函數(shù):線程或者中斷服務(wù)程序可以通過郵箱給其他線程發(fā)送郵件,發(fā)送的郵件可以是 32 位任意格式的數(shù)據(jù),一個(gè)整型值或者一個(gè)指向緩沖區(qū)的指針。當(dāng)郵箱中的郵件已經(jīng)滿時(shí),發(fā)送郵件的線程或者中斷程序會(huì)收到 RT_EFULL 的返回值。函數(shù)接口如下:

rt_err_t rt_mb_send (rt_mailbox_t mb, rt_uint32_t value);

(1)入口參數(shù):

mb:郵箱對象的句柄。
value:郵件內(nèi)容。

(2)返回值:

RT_EOK:發(fā)送成功。
RT_EFULL:郵箱已經(jīng)滿了。

6、等待方式發(fā)送郵件函數(shù):用戶也可以通過如下的函數(shù)接口向指定郵箱發(fā)送郵件:

rt_err_t rt_mb_send_wait(rt_mailbox_t mb,rt_uint32_t value,rt_int32_t timeout);

rt_mb_send_wait() 與 rt_mb_send() 的區(qū)別在于有等待時(shí)間,如果郵箱已經(jīng)滿了,那么發(fā)送線程將根據(jù)設(shè)定的 timeout 參數(shù)等待郵箱中因?yàn)槭杖∴]件而空出空間。如果設(shè)置的超時(shí)時(shí)間到達(dá)依然沒有空出空間,這時(shí)發(fā)送線程將被喚醒并返回錯(cuò)誤碼。

(1)入口參數(shù):

mb:郵箱對象的句柄。
value:郵件內(nèi)容。
timeout:超時(shí)時(shí)間。

(2)返回值:

RT_EOK:發(fā)送成功。
RT_ETIMEOUT:超時(shí)。
RT_ERROR:失敗,返回錯(cuò)誤。

7、接收郵件函數(shù):接收郵件時(shí),接收者需指定接收郵件的郵箱句柄,并指定接收到的郵件存放位置以及最多能夠等待的超時(shí)時(shí)間。接收郵件函數(shù)接口如下:

rt_err_t rt_mb_recv (rt_mailbox_t mb, rt_uint32_t* value, rt_int32_t timeout);

(1)入口參數(shù):

mb:郵箱對象的句柄。
value:郵件內(nèi)容。
timeout:超時(shí)時(shí)間。

(2)返回值:

RT_EOK:發(fā)送成功。
RT_ETIMEOUT:超時(shí)。
RT_ERROR:失敗,返回錯(cuò)誤。

三、基于STM32的郵箱示例

采用RTT&正點(diǎn)原子聯(lián)合出品潘多拉開發(fā)板,基于STM32。創(chuàng)建一個(gè)郵箱,兩個(gè)線程,其中一個(gè)線程用于發(fā)送郵件,另外一個(gè)線程由于接收郵件。通過按下不同按鍵發(fā)送不同的郵件內(nèi)容,根據(jù)讀取到右郵件內(nèi)容執(zhí)行不同操作。當(dāng)讀取到內(nèi)容為KEY0按下時(shí)點(diǎn)亮RGB紅燈,其他熄滅,當(dāng)讀取到內(nèi)容為KEY1按下時(shí)點(diǎn)亮RGB藍(lán)燈,其他熄滅,當(dāng)讀取到內(nèi)容為KEY0按下時(shí)點(diǎn)亮RGB綠燈,其他熄滅。

#include "rtthread.h" #include "string.h" #include "mailbox_app.h" #include "led.h" #include "key.h"/* 線程句柄 */ static rt_thread_t thread1 = RT_NULL; static rt_thread_t thread2 = RT_NULL;/* 郵箱句柄 */ static rt_mailbox_t mailbox1 = RT_NULL;char mailbox_msg_key0_press[] = "mailbox_msg_key0_press"; char mailbox_msg_key1_press[] = "mailbox_msg_key1_press"; char mailbox_msg_key2_press[] = "mailbox_msg_key2_press";/************************************************************** 函數(shù)名稱 : thread1_recv_mailbox_msg 函數(shù)功能 : 線程1入口函數(shù),用于接收郵件 輸入?yún)?shù) : parameter:入口參數(shù) 返回值 : 無 備注 : 無 **************************************************************/ void thread1_recv_mailbox_msg(void *parameter) {char *mb_msg;while(1){if(rt_mb_recv(mailbox1, (rt_uint32_t *)&mb_msg, RT_WAITING_FOREVER) == RT_EOK){rt_kprintf("recv mb_msg:%s\r\n", mb_msg);if(0 == strcmp(mb_msg, "mailbox_msg_key0_press")){LED_R(0);LED_B(1);LED_G(1);}else if(0 == strcmp(mb_msg, "mailbox_msg_key1_press")){LED_R(1);LED_B(0);LED_G(1);}else if(0 == strcmp(mb_msg, "mailbox_msg_key2_press")){LED_R(1);LED_B(1);LED_G(0);}}rt_thread_mdelay(1);} }/************************************************************** 函數(shù)名稱 : thread2_send_mailbox_msg 函數(shù)功能 : 線程2入口函數(shù),用于發(fā)送郵件 輸入?yún)?shù) : parameter:入口參數(shù) 返回值 : 無 備注 : 無 **************************************************************/ void thread2_send_mailbox_msg(void *parameter) {u8 key;while(1){key = key_scan(0);if(key== KEY0_PRES){rt_mb_send(mailbox1, (rt_uint32_t)&mailbox_msg_key0_press);}else if(key== KEY1_PRES){rt_mb_send(mailbox1, (rt_uint32_t)&mailbox_msg_key1_press);}else if(key== KEY2_PRES){rt_mb_send(mailbox1, (rt_uint32_t)&mailbox_msg_key2_press);}rt_thread_mdelay(1);} }void rtthread_mailbox_test(void) {mailbox1 = rt_mb_create("mailbox1", 12, RT_IPC_FLAG_FIFO); /* FIFO模式 */if(mailbox1 != RT_NULL){rt_kprintf("RT-Thread create mailbox successful\r\n");}else{rt_kprintf("RT-Thread create mailbox failed\r\n");return;}thread1 = rt_thread_create("thread1",thread1_recv_mailbox_msg,NULL,512,3,20);if(thread1 != RT_NULL){rt_thread_startup(thread1);;}else{rt_kprintf("create thread1 failed\r\n");return;}thread2 = rt_thread_create("thread2",thread2_send_mailbox_msg,NULL,1024,2,20);if(thread2 != RT_NULL){rt_thread_startup(thread2);;}else{rt_kprintf("create thread2 failed\r\n");return;} }

四、郵箱的使用場合及技巧

郵箱是一種簡單的線程間消息傳遞方式,特點(diǎn)是開銷比較低,效率較高。在 RT-Thread 操作系統(tǒng)的實(shí)現(xiàn)中能夠一次傳遞一個(gè) 4 字節(jié)大小的郵件,并且郵箱具備一定的存儲(chǔ)功能,能夠緩存一定數(shù)量的郵件數(shù) (郵件數(shù)由創(chuàng)建、初始化郵箱時(shí)指定的容量決定)。郵箱中一封郵件的最大長度是 4 字節(jié),所以郵箱能夠用于不超過 4 字節(jié)的消息傳遞。
由于在 32 系統(tǒng)上 4 字節(jié)的內(nèi)容恰好可以放置一個(gè)指針,因此當(dāng)需要在線程間傳遞比較大的消息時(shí),可以把指向一個(gè)緩沖區(qū)的指針作為郵件發(fā)送到郵箱中,即郵箱也可以傳遞指針,例如:

struct msg {rt_uint8_t *data_ptr;rt_uint32_t data_size; };

對于這樣一個(gè)消息結(jié)構(gòu)體,其中包含了指向數(shù)據(jù)的指針 data_ptr 和數(shù)據(jù)塊長度的變量 data_size。當(dāng)一個(gè)線程需要把這個(gè)消息發(fā)送給另外一個(gè)線程時(shí),可以采用如下的操作:

struct msg* msg_ptr;msg_ptr = (struct msg*)rt_malloc(sizeof(struct msg)); msg_ptr->data_ptr = ...; /* 指 向 相 應(yīng) 的 數(shù) 據(jù) 塊 地 址 */ msg_ptr->data_size = len; /* 數(shù) 據(jù) 塊 的 長 度 *//* 發(fā) 送 這 個(gè) 消 息 指 針 給 mb 郵 箱 */ rt_mb_send(mb, (rt_uint32_t)msg_ptr);

申請結(jié)構(gòu)體大小的內(nèi)存空間,返回的指針指向了結(jié)構(gòu)體,當(dāng)結(jié)構(gòu)體中的信息處理完,那么可以將指向結(jié)構(gòu)體的指針作為郵件發(fā)送到郵箱中,而在接收郵件的線程中完成對結(jié)構(gòu)體信息的讀取操作,在完成操作后應(yīng)當(dāng)釋放內(nèi)存,因?yàn)槭杖∵^來的是指針,而 msg_ptr 是一個(gè)新分配出來的內(nèi)存塊,所以在接收線程處理完畢后,需要釋放相應(yīng)的內(nèi)存塊:

struct msg* msg_ptr;if (rt_mb_recv(mb, (rt_uint32_t*)&msg_ptr) == RT_EOK) {/* 在 接 收 線 程 處 理 完 畢 后, 需 要 釋 放 相 應(yīng) 的 內(nèi) 存 塊 */rt_free(msg_ptr); }

總結(jié)

以上是生活随笔為你收集整理的RT_thread邮箱的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。