色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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

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

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

基于RT-Thread的RoboMaster電控框架(六)

冬至子 ? 來源:螺絲松掉的人 ? 作者:螺絲松掉的人 ? 2023-10-30 17:41 ? 次閱讀

背景

使用的開發(fā)板為大疆RoboMaster-C 型開發(fā)板,基礎(chǔ)工程為 rt-thread>bsp>stm32f407-robomaster-c

MSG模塊開發(fā)

MSG 模塊主要應(yīng)用于應(yīng)用層線程間通訊,實現(xiàn)一種發(fā)布者發(fā)布話題,訂閱者訂閱話題的通訊方式。接下來主要討論開發(fā) MSG 模塊的初衷,以及與其他線程間通訊方式的對比。

開發(fā)的初衷是受 ROS 及其他學(xué)校的如吉林大學(xué)的軟總線中心,湖南大學(xué)的消息中心模塊的啟發(fā),(主要還是苦全局變量久矣),開發(fā)一套簡單易用、線程安全、模塊解耦、邏輯清晰的線程間通訊機(jī)制顯得尤為重要。

但是 RTOS 中不是已經(jīng)提供了諸如:郵箱,消息隊列、信號(軟中斷,這里不具體討論)的線程間通信機(jī)制,為什么不直接用呢?接下來就對各個通信方式進(jìn)行對比分析:

郵箱:郵箱中的每一封郵件只能容納固定的 4 字節(jié)內(nèi)容,當(dāng)需要傳輸更大的數(shù)據(jù)時,可以將指針作為郵件的內(nèi)容進(jìn)行傳輸。但使用郵箱有一個問題:接收郵件,就會將郵件取出,也就是說,發(fā)出去的信只有一份,被一個線程接收后,其他的線程就收不到這封信了,因此面對多個消費者的情況時就會出現(xiàn)問題。而且郵箱的機(jī)制是必須要現(xiàn)有生產(chǎn)者發(fā)出一封郵件,對應(yīng)的消費者才有郵件可讀,也就是說,每次讀取其實是阻塞性質(zhì)的,生產(chǎn)者的郵件發(fā)出之前,消費者是讀不到數(shù)據(jù)的,也不能讀取使用上一次的歷史數(shù)據(jù),因此只要生成者發(fā)送郵件不及時就容易出現(xiàn)問題。

但是在機(jī)器人的開發(fā)中,經(jīng)常會面對多個消費者,以及當(dāng)數(shù)據(jù)更新不及時但為了維持控制頻率就先延用上一次數(shù)據(jù)的情況(當(dāng)然,長時間數(shù)據(jù)未更新的情況下沿用歷史數(shù)據(jù)是絕對不行的!輕則抖動,重則失控!例如遙控器、電機(jī)離線等,對于這些情況也有相應(yīng)的離線檢測和處理機(jī)制)。

消息隊列:消息隊列是郵箱的擴(kuò)展,傳輸?shù)臄?shù)據(jù)就包括指向消息的指針和消息的長度,便于數(shù)據(jù)解析獲取。但上述郵箱通訊方式的弊端依舊存在。

全局變量:全局變量讀寫直接快速,使用簡單,但其如果在 RTOS 中濫用,其危害性就很恐怖了,我們應(yīng)該盡量避免使用全局變量,具體的影響和危害就不展開講了。

MSG模塊:msg 模塊主要解決的就是上述郵箱及消息隊列面對多個消費者等問題,以及避免全局變量滿天飛的情況。msg 模塊較為輕量化,是對 ROS 通訊機(jī)制的拙略模仿,模仿其話題、發(fā)布者、訂閱者之間的通訊機(jī)制。訂閱者讀取話題,并不會取出及改動話題的數(shù)據(jù),不會影響到其他訂閱者對話題的讀取。并且訂閱者讀取話題時不是阻塞的,不需要發(fā)布者先更新話題,訂閱者和發(fā)布者之間并沒有先后順序。而且其是線程安全的,使用信號量進(jìn)行保護(hù),不過讀寫速度肯定不如直接使用全局變量快,但基本可以忽略,利遠(yuǎn)大于弊。

代碼實現(xiàn)

這是對話題、訂閱者、發(fā)布者這幾個重要對象的定義。話題對象包含名字(訂閱和發(fā)布的話題主要就通過名字判斷和聯(lián)系起來)、指向數(shù)據(jù)的指針、提供安全性的信號量;發(fā)布者和訂閱者包含話題名稱、指向話題的指針、消息的長度。這里需要注意,話題中 msg 示例的數(shù)據(jù)格式,需要發(fā)布者和訂閱者都知道才能正確解析,和 ROS 中的 msg 類似。

/**

  • @brief 話題類型

/
typedef struct topic
{
char name[MSG_NAME_MAX];
void msg; // 指向msg實例的指針
rt_sem_t sem;
} topic_t;
/

@brief 訂閱者類型.每個發(fā)布者擁有發(fā)布者實例,并且可以通過鏈表訪問所有訂閱了自己發(fā)布的話題的訂閱者

*/
typedef struct sublisher
{
const char topic_name;
topic_t tp; // 話題的指針
uint8_t len; // 消息類型長度
} subscriber_t;
/

@brief 發(fā)布者類型.每個發(fā)布者擁有發(fā)布者實例,并且可以通過鏈表訪問所有訂閱了自己發(fā)布的話題的訂閱者

*/
typedef struct publisher
{
const char *topic_name;
topic_t *tp; // 話題的指針
uint8_t len; // 消息類型長度
} publisher_t;

以下是訂閱者和發(fā)布者注冊的函數(shù),其注冊不需要分先后順序:

/**

@brief 注冊成為消息發(fā)布者

@param name 發(fā)布者發(fā)布的話題名稱(話題)
@param len 消息類型長度,通過sizeof()獲取
@return publisher_t* 返回發(fā)布者實例
*/
publisher_t *pub_register(char *name, uint8_t len){
uint8_t check_num = check_topic_name(name);
publisher_t *pub = (publisher_t *)rt_malloc(sizeof(publisher_t));
if(!check_num){ // 如果不存在重名的話題實例
topic_obj[idx] = (topic_t )rt_malloc(sizeof(topic_t));
rt_memset(topic_obj[idx], 0, sizeof(topic_t));
if(topic_obj[idx] == NULL){
LOG_E("malloc failed!");
return NULL;
}
topic_obj[idx]->msg = (void )rt_malloc(len);
if(topic_obj[idx]->msg == NULL){
LOG_E("malloc failed!");
return NULL;
}
topic_obj[idx]->sem = rt_sem_create(name, 1, RT_IPC_FLAG_PRIO);
rt_strcpy(topic_obj[idx]->name, name);
pub->tp = topic_obj[idx];
pub->topic_name = topic_obj[idx]->name;
pub->len = len;
idx++;
}
else{
pub->tp = topic_obj[check_num - 1];
pub->topic_name = topic_obj[check_num - 1]->name;
pub->len = len;
}
return pub;
}
/

@brief 訂閱name的話題消息

@param name 話題名稱

@param data 消息長度,通過sizeof()獲取
@return subscriber_t* 返回訂閱者實例
*/
subscriber_t *sub_register(char *name, uint8_t len){
// 和發(fā)布者同樣的流程,直接調(diào)用發(fā)布者的注冊函數(shù)
subscriber_t *sub = (subscriber_t *)pub_register(name, len);
return sub;
}

注冊時通過傳入的話題名稱和消息長度創(chuàng)建對應(yīng)的話題,會先檢查目前已有的話題中是否有同樣名稱的話題,如有則返回已有的話題地址,如果沒有那就創(chuàng)建新的話題。

因此,話題的名稱很重要,如果訂閱者和發(fā)布者創(chuàng)建時名稱差了一個字符就會對不上,推薦話題的名稱直接使用宏定義進(jìn)行管理,避免出錯 (否則出錯了很難查的)

以下是訂閱者和發(fā)布者處理話題的簡單實現(xiàn):

/**

  • @brief 發(fā)布消息
  • @param pub 發(fā)布者實例指針
  • @param data 數(shù)據(jù)指針,將要發(fā)布的消息放到此處
  • @return uint8_t 返回值為0說明發(fā)布失敗,為1說明發(fā)布成功
    */
    uint8_t pub_push_msg(publisher_t pub, void data){
    if(rt_sem_take(pub->tp->sem, RT_WAITING_NO)){
    LOG_W("take sem failed!");
    return 0;
    }
    rt_memcpy(pub->tp->msg, data, pub->len);
    rt_sem_release(pub->tp->sem);
    return 1;
    }
    /

    @brief 獲取消息

@param sub 訂閱者實例指針
@param data 數(shù)據(jù)指針,接收的消息將會放到此處
@return uint8_t 返回值為1說明獲取到了新的消息
*/
uint8_t sub_get_msg(subscriber_t *sub, void *data){
rt_memcpy(data, sub->tp->msg, sub->len);
return 1;
}

可以看出目前是十分簡陋的(輕量化(不是),只有在發(fā)布者更新話題時使用信號量進(jìn)行了保護(hù),從而保證寫入的完整性。但訂閱者獲取消息是沒有保護(hù)的,因為只要保證了發(fā)布者更新數(shù)據(jù)的完整性,訂閱讀取話題是沒有問題的。

但其也是還有許多需要完善的地方,魯棒性仍需加強(qiáng),例如 rt_memcpy 并不保證原子性。這里主要就是提供一個解決思路,拋磚引玉。

使用示例
/* 首先需要在.h文件中定義話題的數(shù)據(jù)格式 /
struct msg_test{
uint8_t id;
uint8_t data[5];
}
/
在發(fā)布者的.c文件中 */
publisher_t pub;
stuct msg_test msg_p;
pub = pub_register("msg_test", sizeof(struct msg_test));
msg_p.id = 1;
for(uint8_t i = 0, i < 5, i++){
msg_p.data[0] = i;
}
pub_push_msg(pub, &msg_p);
/
在訂閱者的.c文件中 */
subscriber_t *sub;
stuct msg_test msg_s;
sub = sub_register("msg_test", sizeof(struct msg_test));
sub_get_msg(sub, &msg_s);

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

    關(guān)注

    211

    文章

    28611

    瀏覽量

    207891
  • RTOS
    +關(guān)注

    關(guān)注

    22

    文章

    819

    瀏覽量

    119799
  • STM32F407
    +關(guān)注

    關(guān)注

    15

    文章

    188

    瀏覽量

    29584
  • RT-Thread
    +關(guān)注

    關(guān)注

    31

    文章

    1304

    瀏覽量

    40294
  • ROS
    ROS
    +關(guān)注

    關(guān)注

    1

    文章

    279

    瀏覽量

    17046
收藏 人收藏

    評論

    相關(guān)推薦

    基于RT-ThreadRoboMaster電控框架設(shè)計

    由于 RT-Thread 穩(wěn)定高效的內(nèi)核,豐富的文檔教程,積極活躍的社區(qū)氛圍,以及設(shè)備驅(qū)動框架、Kconfig、Scons、日志系統(tǒng)、海量的軟件包……很難不選擇 RT-Thread 進(jìn)行項目開發(fā)。
    發(fā)表于 09-06 15:21 ?736次閱讀

    RT-Thread編程指南

    RT-Thread編程指南——RT-Thread開發(fā)組(2015-03-31)。RT-Thread做為國內(nèi)有較大影響力的開源實時操作系統(tǒng),本文是RT-Thread實時操作系統(tǒng)的編程指南
    發(fā)表于 11-26 16:06 ?0次下載

    RT-Thread全球技術(shù)大會:RT-Thread上的單元測試框架與運行測試用例

    RT-Thread全球技術(shù)大會:RT-Thread上的單元測試框架與運行測試用例 ? ? ? ? ? ? ? ? 審核編輯:彭靜
    的頭像 發(fā)表于 05-27 16:21 ?1648次閱讀
    <b class='flag-5'>RT-Thread</b>全球技術(shù)大會:<b class='flag-5'>RT-Thread</b>上的單元測試<b class='flag-5'>框架</b>與運行測試用例

    RT-Thread設(shè)備模型框架及創(chuàng)建注冊設(shè)備的實現(xiàn)

    RT-Thread設(shè)備模型框架及創(chuàng)建注冊設(shè)備的實現(xiàn)方式介紹如下:
    的頭像 發(fā)表于 05-28 10:38 ?2218次閱讀
    <b class='flag-5'>RT-Thread</b>設(shè)備模型<b class='flag-5'>框架</b>及創(chuàng)建注冊設(shè)備的實現(xiàn)

    RT-Thread文檔_RT-Thread 簡介

    RT-Thread文檔_RT-Thread 簡介
    發(fā)表于 02-22 18:22 ?5次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> 簡介

    RT-Thread文檔_RT-Thread SMP 介紹與移植

    RT-Thread文檔_RT-Thread SMP 介紹與移植
    發(fā)表于 02-22 18:31 ?9次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> SMP 介紹與移植

    RT-Thread文檔_utest 測試框架

    RT-Thread文檔_utest 測試框架
    發(fā)表于 02-22 18:43 ?2次下載
    <b class='flag-5'>RT-Thread</b>文檔_utest 測試<b class='flag-5'>框架</b>

    淺析RT-Thread設(shè)備驅(qū)動框架

    RT-Thread 設(shè)備框架屬于組件和服務(wù)層,是基于 RT-Thread 內(nèi)核之上的上層軟件。設(shè)備框架是針對某一類外設(shè),抽象出來的一套統(tǒng)一的操作方法及接入標(biāo)準(zhǔn),可以屏蔽硬件差異,為應(yīng)用
    的頭像 發(fā)表于 08-07 15:39 ?2041次閱讀

    基于 RT-ThreadRoboMaster 電控框架(一)

    。但也正是因為這些優(yōu)點的覆蓋面較廣,很多初學(xué)者會覺得無從下手,但只要步入 RT-Thread 的大門,你就發(fā)現(xiàn)她的美好。這系列文檔將作為本人基于 RT-Thread 開發(fā) RoboMaster
    的頭像 發(fā)表于 09-19 19:55 ?806次閱讀

    基于RT-ThreadRoboMaster電控框架(二)

    由于 RT-Thread 穩(wěn)定高效的內(nèi)核,豐富的文檔教程,積極活躍的社區(qū)氛圍,以及設(shè)備驅(qū)動框架、Kconfig、Scons、日志系統(tǒng)、海量的軟件包
    的頭像 發(fā)表于 09-20 15:16 ?787次閱讀

    基于RT-ThreadRoboMaster電控框架(三)

    使用的開發(fā)板為大疆的 RoboMaster-C 型開發(fā)板,基礎(chǔ)工程為 rt-thread>bsp>stm32f407-robomaster-c
    的頭像 發(fā)表于 09-20 15:21 ?912次閱讀

    基于RT-ThreadRoboMaster電控框架(四)

    使用的開發(fā)板為大疆的 RoboMaster-C 型開發(fā)板,基礎(chǔ)工程為 rt-thread>bsp>stm32f407-robomaster-c
    的頭像 發(fā)表于 09-20 15:28 ?768次閱讀

    RT-Thread框架下的SMP支持

    使其支持 RT-Thread 框架下的 SMP,最近就一直在研究 SMP,并在 Raspberry-Pico 上做了一些實驗。
    的頭像 發(fā)表于 10-11 10:34 ?1184次閱讀
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>框架</b>下的SMP支持

    基于rt-thread的socket通信設(shè)計

    最近再研究 rt-thread 的通信 ,想設(shè)計出 eps8266(多個) rt-thread(作為中控) 服務(wù)器的通信框架,使用的開發(fā)板是 潘多拉
    的頭像 發(fā)表于 10-13 15:02 ?1403次閱讀
    基于<b class='flag-5'>rt-thread</b>的socket通信設(shè)計

    基于RT-ThreadRoboMaster電控框架(五)

    使用的開發(fā)板為大疆的 RoboMaster-C 型開發(fā)板,基礎(chǔ)工程為 rt-thread>bsp>stm32f407-robomaster-c
    的頭像 發(fā)表于 10-30 17:10 ?1260次閱讀
    主站蜘蛛池模板: 成人无码精品一区二区在线观看 | 亚洲一区免费在线观看| 黄色三级三级三级免费看| 这里只有精品在线视频| 嫩小幼处在线| 国产精品私人玩物在线观看 | ebc5恐怖5a26房间| 无套内射在线观看THEPORN| 久久久久久久尹人综合网亚洲| JIZJIZJIZ 日本老师水多| 同时和两老师双飞| 久久中文字幕亚洲| 国产69精品久久久熟女| 欲插爽乱浪伦骨| 视频一区视频二区在线观看| 久久vs国产| 国产高清视频免费最新在线| 在线观看a视频| 色婷婷AV99XX| 久久免费精品视频| 国产成人精品视频播放| 在线亚洲免费| 无码一区国产欧美在线资源| 免费在线视频a| 精品国产手机视频在在线| 成人免费小视频| 6080YYY午夜理论片在线观看| 无码专区久久综合久综合字幕| 毛片网站网址| 黄 色 网 站 免 费 涩涩屋| 大胆国模一区二区三区伊人| 最新国自产拍天天更新| 亚洲精品久久久午夜福利电影网 | 伸进同桌奶罩里摸她胸作文| 狼人射综合| 国产精品亚洲在钱视频 | 在线观看国产亚洲| 无限资源日本2019版| 男生互捏jiji的故事| 久久极品视频| 精品第一国产综合精品蜜芽|