chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

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

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

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

韋東山freeRTOS系列教程之隊(duì)列(queue)(5)

嵌入式Linux那些事 ? 2021-12-13 14:33 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

文章目錄

  • 系列教程總目錄
  • 概述
  • 5.1 隊(duì)列的特性
    • 5.1.1 常規(guī)操作
    • 5.1.2 傳輸數(shù)據(jù)的兩種方法
    • 5.1.3 隊(duì)列的阻塞訪問(wèn)
  • 5.2 隊(duì)列函數(shù)
    • 5.2.1 創(chuàng)建
    • 5.2.2 復(fù)位
    • 5.2.3 刪除
    • 5.2.4 寫(xiě)隊(duì)列
    • 5.2.5 讀隊(duì)列
    • 5.2.6 查詢(xún)
    • 5.2.7 覆蓋/偷看
  • 5.3 示例8: 隊(duì)列的基本使用
  • 5.4 示例9: 分辨數(shù)據(jù)源
  • 5.5 示例10: 傳輸大塊數(shù)據(jù)
  • 5.6 示例11: 郵箱(Mailbox)

需要獲取更好閱讀體驗(yàn)的同學(xué),請(qǐng)?jiān)L問(wèn)我專(zhuān)門(mén)設(shè)立的站點(diǎn)查看,地址:http://rtos.100ask.net/

系列教程總目錄

本教程連載中,篇章會(huì)比較多,為方便同學(xué)們閱讀,點(diǎn)擊這里可以查看文章的 目錄列表,目錄列表頁(yè)面地址:https://blog.csdn.net/thisway_diy/article/details/121399484

概述

隊(duì)列(queue)可以用于"任務(wù)到任務(wù)"、“任務(wù)到中斷”、"中斷到任務(wù)"直接傳輸信息。

本章涉及如下內(nèi)容:

  • 怎么創(chuàng)建、清除、刪除隊(duì)列
  • 隊(duì)列中消息如何保存
  • 怎么向隊(duì)列發(fā)送數(shù)據(jù)、怎么從隊(duì)列讀取數(shù)據(jù)、怎么覆蓋隊(duì)列的數(shù)據(jù)
  • 在隊(duì)列上阻塞是什么意思
  • 怎么在多個(gè)隊(duì)列上阻塞
  • 讀寫(xiě)隊(duì)列時(shí)如何影響任務(wù)的優(yōu)先級(jí)

5.1 隊(duì)列的特性

5.1.1 常規(guī)操作

隊(duì)列的簡(jiǎn)化操如入下圖所示,從此圖可知:

  • 隊(duì)列可以包含若干個(gè)數(shù)據(jù):隊(duì)列中有若干項(xiàng),這被稱(chēng)為"長(zhǎng)度"(length)
  • 每個(gè)數(shù)據(jù)大小固定
  • 創(chuàng)建隊(duì)列時(shí)就要指定長(zhǎng)度、數(shù)據(jù)大小
  • 數(shù)據(jù)的操作采用先進(jìn)先出的方法(FIFO,F(xiàn)irst In First Out):寫(xiě)數(shù)據(jù)時(shí)放到尾部,讀數(shù)據(jù)時(shí)從頭部讀
  • 也可以強(qiáng)制寫(xiě)隊(duì)列頭部:覆蓋頭部數(shù)據(jù)
在這里插入圖片描述

更詳細(xì)的操作入下圖所示:

在這里插入圖片描述

5.1.2 傳輸數(shù)據(jù)的兩種方法

使用隊(duì)列傳輸數(shù)據(jù)時(shí)有兩種方法:

  • 拷貝:把數(shù)據(jù)、把變量的值復(fù)制進(jìn)隊(duì)列里
  • 引用:把數(shù)據(jù)、把變量的地址復(fù)制進(jìn)隊(duì)列里

FreeRTOS使用拷貝值的方法,這更簡(jiǎn)單:

局部變量的值可以發(fā)送到隊(duì)列中,后續(xù)即使函數(shù)退出、局部變量被回收,也不會(huì)影響隊(duì)列中的數(shù)據(jù)

無(wú)需分配buffer來(lái)保存數(shù)據(jù),隊(duì)列中有buffer

局部變量可以馬上再次使用

發(fā)送任務(wù)、接收任務(wù)解耦:接收任務(wù)不需要知道這數(shù)據(jù)是誰(shuí)的、也不需要發(fā)送任務(wù)來(lái)釋放數(shù)據(jù)

如果數(shù)據(jù)實(shí)在太大,你還是可以使用隊(duì)列傳輸它的地址

隊(duì)列的空間有FreeRTOS內(nèi)核分配,無(wú)需任務(wù)操心

對(duì)于有內(nèi)存保護(hù)功能的系統(tǒng),如果隊(duì)列使用引用方法,也就是使用地址,必須確保雙方任務(wù)對(duì)這個(gè)地址都有訪問(wèn)權(quán)限。使用拷貝方法時(shí),則無(wú)此限制:內(nèi)核有足夠的權(quán)限,把數(shù)據(jù)復(fù)制進(jìn)隊(duì)列、再把數(shù)據(jù)復(fù)制出隊(duì)列。

5.1.3 隊(duì)列的阻塞訪問(wèn)

只要知道隊(duì)列的句柄,誰(shuí)都可以讀、寫(xiě)該隊(duì)列。任務(wù)、ISR都可讀、寫(xiě)隊(duì)列??梢远鄠€(gè)任務(wù)讀寫(xiě)隊(duì)列。

任務(wù)讀寫(xiě)隊(duì)列時(shí),簡(jiǎn)單地說(shuō):如果讀寫(xiě)不成功,則阻塞;可以指定超時(shí)時(shí)間。口語(yǔ)化地說(shuō),就是可以定個(gè)鬧鐘:如果能讀寫(xiě)了就馬上進(jìn)入就緒態(tài),否則就阻塞直到超時(shí)。

某個(gè)任務(wù)讀隊(duì)列時(shí),如果隊(duì)列沒(méi)有數(shù)據(jù),則該任務(wù)可以進(jìn)入阻塞狀態(tài):還可以指定阻塞的時(shí)間。如果隊(duì)列有數(shù)據(jù)了,則該阻塞的任務(wù)會(huì)變?yōu)榫途w態(tài)。如果一直都沒(méi)有數(shù)據(jù),則時(shí)間到之后它也會(huì)進(jìn)入就緒態(tài)。

既然讀取隊(duì)列的任務(wù)個(gè)數(shù)沒(méi)有限制,那么當(dāng)多個(gè)任務(wù)讀取空隊(duì)列時(shí),這些任務(wù)都會(huì)進(jìn)入阻塞狀態(tài):有多個(gè)任務(wù)在等待同一個(gè)隊(duì)列的數(shù)據(jù)。當(dāng)隊(duì)列中有數(shù)據(jù)時(shí),哪個(gè)任務(wù)會(huì)進(jìn)入就緒態(tài)?

  • 優(yōu)先級(jí)最高的任務(wù)
  • 如果大家的優(yōu)先級(jí)相同,那等待時(shí)間最久的任務(wù)會(huì)進(jìn)入就緒態(tài)

跟讀隊(duì)列類(lèi)似,一個(gè)任務(wù)要寫(xiě)隊(duì)列時(shí),如果隊(duì)列滿了,該任務(wù)也可以進(jìn)入阻塞狀態(tài):還可以指定阻塞的時(shí)間。如果隊(duì)列有空間了,則該阻塞的任務(wù)會(huì)變?yōu)榫途w態(tài)。如果一直都沒(méi)有空間,則時(shí)間到之后它也會(huì)進(jìn)入就緒態(tài)。

既然寫(xiě)隊(duì)列的任務(wù)個(gè)數(shù)沒(méi)有限制,那么當(dāng)多個(gè)任務(wù)寫(xiě)"滿隊(duì)列"時(shí),這些任務(wù)都會(huì)進(jìn)入阻塞狀態(tài):有多個(gè)任務(wù)在等待同一個(gè)隊(duì)列的空間。當(dāng)隊(duì)列中有空間時(shí),哪個(gè)任務(wù)會(huì)進(jìn)入就緒態(tài)?

  • 優(yōu)先級(jí)最高的任務(wù)
  • 如果大家的優(yōu)先級(jí)相同,那等待時(shí)間最久的任務(wù)會(huì)進(jìn)入就緒態(tài)

5.2 隊(duì)列函數(shù)

使用隊(duì)列的流程:創(chuàng)建隊(duì)列、寫(xiě)隊(duì)列、讀隊(duì)列、刪除隊(duì)列。

5.2.1 創(chuàng)建

隊(duì)列的創(chuàng)建有兩種方法:動(dòng)態(tài)分配內(nèi)存、靜態(tài)分配內(nèi)存,

  • 動(dòng)態(tài)分配內(nèi)存:xQueueCreate,隊(duì)列的內(nèi)存在函數(shù)內(nèi)部動(dòng)態(tài)分配

函數(shù)原型如下:

QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );
參數(shù) 說(shuō)明
uxQueueLength 隊(duì)列長(zhǎng)度,最多能存放多少個(gè)數(shù)據(jù)(item)
uxItemSize 每個(gè)數(shù)據(jù)(item)的大?。阂宰止?jié)為單位
返回值 非0:成功,返回句柄,以后使用句柄來(lái)操作隊(duì)列
NULL:失敗,因?yàn)閮?nèi)存不足
  • 靜態(tài)分配內(nèi)存:xQueueCreateStatic,隊(duì)列的內(nèi)存要事先分配好

函數(shù)原型如下:

QueueHandle_t xQueueCreateStatic(
                           UBaseType_t uxQueueLength,
                           UBaseType_t uxItemSize,
                           uint8_t *pucQueueStorageBuffer,
                           StaticQueue_t *pxQueueBuffer
                       );
參數(shù) 說(shuō)明
uxQueueLength 隊(duì)列長(zhǎng)度,最多能存放多少個(gè)數(shù)據(jù)(item)
uxItemSize 每個(gè)數(shù)據(jù)(item)的大?。阂宰止?jié)為單位
pucQueueStorageBuffer 如果uxItemSize非0,pucQueueStorageBuffer必須指向一個(gè)uint8_t數(shù)組,
此數(shù)組大小至少為"uxQueueLength * uxItemSize"
pxQueueBuffer 必須執(zhí)行一個(gè)StaticQueue_t結(jié)構(gòu)體,用來(lái)保存隊(duì)列的數(shù)據(jù)結(jié)構(gòu)
返回值 非0:成功,返回句柄,以后使用句柄來(lái)操作隊(duì)列
NULL:失敗,因?yàn)閜xQueueBuffer為NULL

示例代碼:

// 示例代碼
 #define QUEUE_LENGTH 10
 #define ITEM_SIZE sizeof( uint32_t )
 
 // xQueueBuffer用來(lái)保存隊(duì)列結(jié)構(gòu)體
 StaticQueue_t xQueueBuffer;
 
 // ucQueueStorage 用來(lái)保存隊(duì)列的數(shù)據(jù)
 // 大小為:隊(duì)列長(zhǎng)度 * 數(shù)據(jù)大小
 uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];
 
 void vATask( void *pvParameters )
 {
	QueueHandle_t xQueue1;
 
	// 創(chuàng)建隊(duì)列: 可以容納QUEUE_LENGTH個(gè)數(shù)據(jù),每個(gè)數(shù)據(jù)大小是ITEM_SIZE
	xQueue1 = xQueueCreateStatic( QUEUE_LENGTH,
						  ITEM_SIZE,
						  ucQueueStorage,
						  &xQueueBuffer ); 
 }

5.2.2 復(fù)位

隊(duì)列剛被創(chuàng)建時(shí),里面沒(méi)有數(shù)據(jù);使用過(guò)程中可以調(diào)用xQueueReset()把隊(duì)列恢復(fù)為初始狀態(tài),此函數(shù)原型為:

/* pxQueue : 復(fù)位哪個(gè)隊(duì)列;
 * 返回值: pdPASS(必定成功)
 */
BaseType_t xQueueReset( QueueHandle_t pxQueue);

5.2.3 刪除

刪除隊(duì)列的函數(shù)為vQueueDelete(),只能刪除使用動(dòng)態(tài)方法創(chuàng)建的隊(duì)列,它會(huì)釋放內(nèi)存。原型如下:

void vQueueDelete( QueueHandle_t xQueue );

5.2.4 寫(xiě)隊(duì)列

可以把數(shù)據(jù)寫(xiě)到隊(duì)列頭部,也可以寫(xiě)到尾部,這些函數(shù)有兩個(gè)版本:在任務(wù)中使用、在ISR中使用。函數(shù)原型如下:

/* 等同于xQueueSendToBack
 * 往隊(duì)列尾部寫(xiě)入數(shù)據(jù),如果沒(méi)有空間,阻塞時(shí)間為xTicksToWait
 */
BaseType_t xQueueSend(
                                QueueHandle_t    xQueue,
                                const void       *pvItemToQueue,
                                TickType_t       xTicksToWait
                            );

/* 
 * 往隊(duì)列尾部寫(xiě)入數(shù)據(jù),如果沒(méi)有空間,阻塞時(shí)間為xTicksToWait
 */
BaseType_t xQueueSendToBack(
                                QueueHandle_t    xQueue,
                                const void       *pvItemToQueue,
                                TickType_t       xTicksToWait
                            );


/* 
 * 往隊(duì)列尾部寫(xiě)入數(shù)據(jù),此函數(shù)可以在中斷函數(shù)中使用,不可阻塞
 */
BaseType_t xQueueSendToBackFromISR(
                                      QueueHandle_t xQueue,
                                      const void *pvItemToQueue,
                                      BaseType_t *pxHigherPriorityTaskWoken
                                   );

/* 
 * 往隊(duì)列頭部寫(xiě)入數(shù)據(jù),如果沒(méi)有空間,阻塞時(shí)間為xTicksToWait
 */
BaseType_t xQueueSendToFront(
                                QueueHandle_t    xQueue,
                                const void       *pvItemToQueue,
                                TickType_t       xTicksToWait
                            );

/* 
 * 往隊(duì)列頭部寫(xiě)入數(shù)據(jù),此函數(shù)可以在中斷函數(shù)中使用,不可阻塞
 */
BaseType_t xQueueSendToFrontFromISR(
                                      QueueHandle_t xQueue,
                                      const void *pvItemToQueue,
                                      BaseType_t *pxHigherPriorityTaskWoken
                                   );

這些函數(shù)用到的參數(shù)是類(lèi)似的,統(tǒng)一說(shuō)明如下:

參數(shù) 說(shuō)明
xQueue 隊(duì)列句柄,要寫(xiě)哪個(gè)隊(duì)列
pvItemToQueue 數(shù)據(jù)指針,這個(gè)數(shù)據(jù)的值會(huì)被復(fù)制進(jìn)隊(duì)列,
復(fù)制多大的數(shù)據(jù)?在創(chuàng)建隊(duì)列時(shí)已經(jīng)指定了數(shù)據(jù)大小
xTicksToWait 如果隊(duì)列滿則無(wú)法寫(xiě)入新數(shù)據(jù),可以讓任務(wù)進(jìn)入阻塞狀態(tài),
xTicksToWait表示阻塞的最大時(shí)間(Tick Count)。
如果被設(shè)為0,無(wú)法寫(xiě)入數(shù)據(jù)時(shí)函數(shù)會(huì)立刻返回;
如果被設(shè)為portMAX_DELAY,則會(huì)一直阻塞直到有空間可寫(xiě)
返回值 pdPASS:數(shù)據(jù)成功寫(xiě)入了隊(duì)列
errQUEUE_FULL:寫(xiě)入失敗,因?yàn)殛?duì)列滿了。

5.2.5 讀隊(duì)列

使用xQueueReceive()函數(shù)讀隊(duì)列,讀到一個(gè)數(shù)據(jù)后,隊(duì)列中該數(shù)據(jù)會(huì)被移除。這個(gè)函數(shù)有兩個(gè)版本:在任務(wù)中使用、在ISR中使用。函數(shù)原型如下:

BaseType_t xQueueReceive( QueueHandle_t xQueue,
                          void * const pvBuffer,
                          TickType_t xTicksToWait );

BaseType_t xQueueReceiveFromISR(
                                    QueueHandle_t    xQueue,
                                    void             *pvBuffer,
                                    BaseType_t       *pxTaskWoken
                                );

參數(shù)說(shuō)明如下:

參數(shù) 說(shuō)明
xQueue 隊(duì)列句柄,要讀哪個(gè)隊(duì)列
pvBuffer bufer指針,隊(duì)列的數(shù)據(jù)會(huì)被復(fù)制到這個(gè)buffer
復(fù)制多大的數(shù)據(jù)?在創(chuàng)建隊(duì)列時(shí)已經(jīng)指定了數(shù)據(jù)大小
xTicksToWait 果隊(duì)列空則無(wú)法讀出數(shù)據(jù),可以讓任務(wù)進(jìn)入阻塞狀態(tài),
xTicksToWait表示阻塞的最大時(shí)間(Tick Count)。
如果被設(shè)為0,無(wú)法讀出數(shù)據(jù)時(shí)函數(shù)會(huì)立刻返回;
如果被設(shè)為portMAX_DELAY,則會(huì)一直阻塞直到有數(shù)據(jù)可寫(xiě)
返回值 pdPASS:從隊(duì)列讀出數(shù)據(jù)入
errQUEUE_EMPTY:讀取失敗,因?yàn)殛?duì)列空了。

5.2.6 查詢(xún)

可以查詢(xún)隊(duì)列中有多少個(gè)數(shù)據(jù)、有多少空余空間。函數(shù)原型如下:

/*
 * 返回隊(duì)列中可用數(shù)據(jù)的個(gè)數(shù)
 */
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );

/*
 * 返回隊(duì)列中可用空間的個(gè)數(shù)
 */
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );

5.2.7 覆蓋/偷看

當(dāng)隊(duì)列長(zhǎng)度為1時(shí),可以使用xQueueOverwrite()xQueueOverwriteFromISR()來(lái)覆蓋數(shù)據(jù)。
注意,隊(duì)列長(zhǎng)度必須為1。當(dāng)隊(duì)列滿時(shí),這些函數(shù)會(huì)覆蓋里面的數(shù)據(jù),這也以為著這些函數(shù)不會(huì)被阻塞。
函數(shù)原型如下:

/* 覆蓋隊(duì)列
 * xQueue: 寫(xiě)哪個(gè)隊(duì)列
 * pvItemToQueue: 數(shù)據(jù)地址
 * 返回值: pdTRUE表示成功, pdFALSE表示失敗
 */
BaseType_t xQueueOverwrite(
                           QueueHandle_t xQueue,
                           const void * pvItemToQueue
                      );

BaseType_t xQueueOverwriteFromISR(
                           QueueHandle_t xQueue,
                           const void * pvItemToQueue,
                           BaseType_t *pxHigherPriorityTaskWoken
                      );

如果想讓隊(duì)列中的數(shù)據(jù)供多方讀取,也就是說(shuō)讀取時(shí)不要移除數(shù)據(jù),要留給后來(lái)人。那么可以使用"窺視",也就是xQueuePeek()xQueuePeekFromISR()。這些函數(shù)會(huì)從隊(duì)列中復(fù)制出數(shù)據(jù),但是不移除數(shù)據(jù)。這也意味著,如果隊(duì)列中沒(méi)有數(shù)據(jù),那么"偷看"時(shí)會(huì)導(dǎo)致阻塞;一旦隊(duì)列中有數(shù)據(jù),以后每次"偷看"都會(huì)成功。
函數(shù)原型如下:

/* 偷看隊(duì)列
 * xQueue: 偷看哪個(gè)隊(duì)列
 * pvItemToQueue: 數(shù)據(jù)地址, 用來(lái)保存復(fù)制出來(lái)的數(shù)據(jù)
 * xTicksToWait: 沒(méi)有數(shù)據(jù)的話阻塞一會(huì)
 * 返回值: pdTRUE表示成功, pdFALSE表示失敗
 */
BaseType_t xQueuePeek(
                          QueueHandle_t xQueue,
                          void * const pvBuffer,
                          TickType_t xTicksToWait
                      );

BaseType_t xQueuePeekFromISR(
                                 QueueHandle_t xQueue,
                                 void *pvBuffer,
                             );

5.3 示例8: 隊(duì)列的基本使用

本節(jié)代碼為:FreeRTOS_08_queue。

本程序會(huì)創(chuàng)建一個(gè)隊(duì)列,然后創(chuàng)建2個(gè)發(fā)送任務(wù)、1個(gè)接收任務(wù):

  • 發(fā)送任務(wù)優(yōu)先級(jí)為1,分別往隊(duì)列中寫(xiě)入100、200
  • 接收任務(wù)優(yōu)先級(jí)為2,讀隊(duì)列、打印數(shù)值

main函數(shù)中創(chuàng)建的隊(duì)列、創(chuàng)建了發(fā)送任務(wù)、接收任務(wù),代碼如下:

/* 隊(duì)列句柄, 創(chuàng)建隊(duì)列時(shí)會(huì)設(shè)置這個(gè)變量 */
QueueHandle_t xQueue;

int main( void )
{
	prvSetupHardware();
	
    /* 創(chuàng)建隊(duì)列: 長(zhǎng)度為5,數(shù)據(jù)大小為4字節(jié)(存放一個(gè)整數(shù)) */
    xQueue = xQueueCreate( 5, sizeof( int32_t ) );

	if( xQueue != NULL )
	{
		/* 創(chuàng)建2個(gè)任務(wù)用于寫(xiě)隊(duì)列, 傳入的參數(shù)分別是100、200
		 * 任務(wù)函數(shù)會(huì)連續(xù)執(zhí)行,向隊(duì)列發(fā)送數(shù)值100、200
		 * 優(yōu)先級(jí)為1
		 */
		xTaskCreate( vSenderTask, "Sender1", 1000, ( void * ) 100, 1, NULL );
		xTaskCreate( vSenderTask, "Sender2", 1000, ( void * ) 200, 1, NULL );

		/* 創(chuàng)建1個(gè)任務(wù)用于讀隊(duì)列
		 * 優(yōu)先級(jí)為2, 高于上面的兩個(gè)任務(wù)
		 * 這意味著隊(duì)列一有數(shù)據(jù)就會(huì)被讀走
		 */
		xTaskCreate( vReceiverTask, "Receiver", 1000, NULL, 2, NULL );

		/* 啟動(dòng)調(diào)度器 */
		vTaskStartScheduler();
	}
	else
	{
		/* 無(wú)法創(chuàng)建隊(duì)列 */
	}

	/* 如果程序運(yùn)行到了這里就表示出錯(cuò)了, 一般是內(nèi)存不足 */
	return 0;
}

發(fā)送任務(wù)的函數(shù)中,不斷往隊(duì)列中寫(xiě)入數(shù)值,代碼如下:

static void vSenderTask( void *pvParameters )
{
	int32_t lValueToSend;
	BaseType_t xStatus;

	/* 我們會(huì)使用這個(gè)函數(shù)創(chuàng)建2個(gè)任務(wù)
	 * 這些任務(wù)的pvParameters不一樣
 	 */
	lValueToSend = ( int32_t ) pvParameters;

	/* 無(wú)限循環(huán) */
	for( ;; )
	{
		/* 寫(xiě)隊(duì)列
		 * xQueue: 寫(xiě)哪個(gè)隊(duì)列
		 * &lValueToSend: 寫(xiě)什么數(shù)據(jù)? 傳入數(shù)據(jù)的地址, 會(huì)從這個(gè)地址把數(shù)據(jù)復(fù)制進(jìn)隊(duì)列
		 * 0: 不阻塞, 如果隊(duì)列滿的話, 寫(xiě)入失敗, 立刻返回
		 */
		xStatus = xQueueSendToBack( xQueue, &lValueToSend, 0 );

		if( xStatus != pdPASS )
		{
			printf( "Could not send to the queue.\r\n" );
		}
	}
}

接收任務(wù)的函數(shù)中,讀取隊(duì)列、判斷返回值、打印,代碼如下:

static void vReceiverTask( void *pvParameters )
{
	/* 讀取隊(duì)列時(shí), 用這個(gè)變量來(lái)存放數(shù)據(jù) */
	int32_t lReceivedValue;
	BaseType_t xStatus;
	const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );

	/* 無(wú)限循環(huán) */
	for( ;; )
	{
		/* 讀隊(duì)列
		 * xQueue: 讀哪個(gè)隊(duì)列
		 * &lReceivedValue: 讀到的數(shù)據(jù)復(fù)制到這個(gè)地址
		 * xTicksToWait: 如果隊(duì)列為空, 阻塞一會(huì)
		 */
		xStatus = xQueueReceive( xQueue, &lReceivedValue, xTicksToWait );

		if( xStatus == pdPASS )
		{
			/* 讀到了數(shù)據(jù) */
			printf( "Received = %d\r\n", lReceivedValue );
		}
		else
		{
			/* 沒(méi)讀到數(shù)據(jù) */
			printf( "Could not receive from the queue.\r\n" );
		}
	}
}

程序運(yùn)行結(jié)果如下:

在這里插入圖片描述


任務(wù)調(diào)度情況如下圖所示:

在這里插入圖片描述

5.4 示例9: 分辨數(shù)據(jù)源

本節(jié)代碼為:FreeRTOS_09_queue_datasource。

當(dāng)有多個(gè)發(fā)送任務(wù),通過(guò)同一個(gè)隊(duì)列發(fā)出數(shù)據(jù),接收任務(wù)如何分辨數(shù)據(jù)來(lái)源?數(shù)據(jù)本身帶有"來(lái)源"信息,比如寫(xiě)入隊(duì)列的數(shù)據(jù)是一個(gè)結(jié)構(gòu)體,結(jié)構(gòu)體中的lDataSouceID用來(lái)表示數(shù)據(jù)來(lái)源:

typedef struct {
    ID_t eDataID;
    int32_t lDataValue;
}Data_t;

不同的發(fā)送任務(wù),先構(gòu)造好結(jié)構(gòu)體,填入自己的eDataID,再寫(xiě)隊(duì)列;接收任務(wù)讀出數(shù)據(jù)后,根據(jù)eDataID就可以知道數(shù)據(jù)來(lái)源了,如下圖所示:

  • CAN任務(wù)發(fā)送的數(shù)據(jù):eDataID=eMotorSpeed
  • HMI任務(wù)發(fā)送的數(shù)據(jù):eDataID=eSpeedSetPoint
在這里插入圖片描述

FreeRTOS_09_queue_datasource程序會(huì)創(chuàng)建一個(gè)隊(duì)列,然后創(chuàng)建2個(gè)發(fā)送任務(wù)、1個(gè)接收任務(wù):

  • 創(chuàng)建的隊(duì)列,用來(lái)發(fā)送結(jié)構(gòu)體:數(shù)據(jù)大小是結(jié)構(gòu)體的大小
  • 發(fā)送任務(wù)優(yōu)先級(jí)為2,分別往隊(duì)列中寫(xiě)入自己的結(jié)構(gòu)體,結(jié)構(gòu)體中會(huì)標(biāo)明數(shù)據(jù)來(lái)源
  • 接收任務(wù)優(yōu)先級(jí)為1,讀隊(duì)列、根據(jù)數(shù)據(jù)來(lái)源打印信息

main函數(shù)中創(chuàng)建了隊(duì)列、創(chuàng)建了發(fā)送任務(wù)、接收任務(wù),代碼如下:

/* 定義2種數(shù)據(jù)來(lái)源(ID) */
typedef enum
{
	eMotorSpeed,
	eSpeedSetPoint
} ID_t;

/* 定義在隊(duì)列中傳輸?shù)臄?shù)據(jù)的格式 */
typedef struct {
    ID_t eDataID;
    int32_t lDataValue;
}Data_t;

/* 定義2個(gè)結(jié)構(gòu)體 */
static const Data_t xStructsToSend[ 2 ] =
{
	{ eMotorSpeed,    10 }, /* CAN任務(wù)發(fā)送的數(shù)據(jù) */
	{ eSpeedSetPoint, 5 }   /* HMI任務(wù)發(fā)送的數(shù)據(jù) */
};

/* vSenderTask被用來(lái)創(chuàng)建2個(gè)任務(wù),用于寫(xiě)隊(duì)列
 * vReceiverTask被用來(lái)創(chuàng)建1個(gè)任務(wù),用于讀隊(duì)列
 */
static void vSenderTask( void *pvParameters );
static void vReceiverTask( void *pvParameters );

/*-----------------------------------------------------------*/

/* 隊(duì)列句柄, 創(chuàng)建隊(duì)列時(shí)會(huì)設(shè)置這個(gè)變量 */
QueueHandle_t xQueue;

int main( void )
{
	prvSetupHardware();
	
    /* 創(chuàng)建隊(duì)列: 長(zhǎng)度為5,數(shù)據(jù)大小為4字節(jié)(存放一個(gè)整數(shù)) */
    xQueue = xQueueCreate( 5, sizeof( Data_t ) );

	if( xQueue != NULL )
	{
		/* 創(chuàng)建2個(gè)任務(wù)用于寫(xiě)隊(duì)列, 傳入的參數(shù)是不同的結(jié)構(gòu)體地址
		 * 任務(wù)函數(shù)會(huì)連續(xù)執(zhí)行,向隊(duì)列發(fā)送結(jié)構(gòu)體
		 * 優(yōu)先級(jí)為2
		 */
		xTaskCreate(vSenderTask, "CAN Task", 1000, (void *) &(xStructsToSend[0]), 2, NULL);
		xTaskCreate(vSenderTask, "HMI Task", 1000, (void *) &( xStructsToSend[1]), 2, NULL);

		/* 創(chuàng)建1個(gè)任務(wù)用于讀隊(duì)列
		 * 優(yōu)先級(jí)為1, 低于上面的兩個(gè)任務(wù)
		 * 這意味著發(fā)送任務(wù)優(yōu)先寫(xiě)隊(duì)列,隊(duì)列常常是滿的狀態(tài)
		 */
		xTaskCreate( vReceiverTask, "Receiver", 1000, NULL, 1, NULL );

		/* 啟動(dòng)調(diào)度器 */
		vTaskStartScheduler();
	}
	else
	{
		/* 無(wú)法創(chuàng)建隊(duì)列 */
	}

	/* 如果程序運(yùn)行到了這里就表示出錯(cuò)了, 一般是內(nèi)存不足 */
	return 0;
}

發(fā)送任務(wù)的函數(shù)中,不斷往隊(duì)列中寫(xiě)入數(shù)值,代碼如下:

static void vSenderTask( void *pvParameters )
{
	BaseType_t xStatus;
	const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );

	/* 無(wú)限循環(huán) */
	for( ;; )
	{
		/* 寫(xiě)隊(duì)列
		 * xQueue: 寫(xiě)哪個(gè)隊(duì)列
		 * pvParameters: 寫(xiě)什么數(shù)據(jù)? 傳入數(shù)據(jù)的地址, 會(huì)從這個(gè)地址把數(shù)據(jù)復(fù)制進(jìn)隊(duì)列
		 * xTicksToWait: 如果隊(duì)列滿的話, 阻塞一會(huì)
		 */
		xStatus = xQueueSendToBack( xQueue, pvParameters, xTicksToWait );

		if( xStatus != pdPASS )
		{
			printf( "Could not send to the queue.\r\n" );
		}
	}
}

接收任務(wù)的函數(shù)中,讀取隊(duì)列、判斷返回值、打印,代碼如下:

static void vReceiverTask( void *pvParameters )
{
	/* 讀取隊(duì)列時(shí), 用這個(gè)變量來(lái)存放數(shù)據(jù) */
	Data_t xReceivedStructure;
	BaseType_t xStatus;

	/* 無(wú)限循環(huán) */
	for( ;; )
	{
		/* 讀隊(duì)列
		 * xQueue: 讀哪個(gè)隊(duì)列
		 * &xReceivedStructure: 讀到的數(shù)據(jù)復(fù)制到這個(gè)地址
		 * 0: 沒(méi)有數(shù)據(jù)就即刻返回,不阻塞
		 */
		xStatus = xQueueReceive( xQueue, &xReceivedStructure, 0 );

		if( xStatus == pdPASS )
		{
			/* 讀到了數(shù)據(jù) */
			if( xReceivedStructure.eDataID == eMotorSpeed )
			{
				printf( "From CAN, MotorSpeed = %d\r\n", xReceivedStructure.lDataValue );
			}
			else if( xReceivedStructure.eDataID == eSpeedSetPoint )
			{
				printf( "From HMI, SpeedSetPoint = %d\r\n", xReceivedStructure.lDataValue );
			}
		}
		else
		{
			/* 沒(méi)讀到數(shù)據(jù) */
			printf( "Could not receive from the queue.\r\n" );
		}
	}
}

運(yùn)行結(jié)果如下:

在這里插入圖片描述

任務(wù)調(diào)度情況如下圖所示:

  • t1:HMI是最后創(chuàng)建的最高優(yōu)先級(jí)任務(wù),它先執(zhí)行,一下子向隊(duì)列寫(xiě)入5個(gè)數(shù)據(jù),把隊(duì)列都寫(xiě)滿了
  • t2:隊(duì)列已經(jīng)滿了,HMI任務(wù)再發(fā)起第6次寫(xiě)操作時(shí),進(jìn)入阻塞狀態(tài)。這時(shí)CAN任務(wù)是最高優(yōu)先級(jí)的就緒態(tài)任務(wù),它開(kāi)始執(zhí)行
  • t3:CAN任務(wù)發(fā)現(xiàn)隊(duì)列已經(jīng)滿了,進(jìn)入阻塞狀態(tài);接收任務(wù)變?yōu)樽罡邇?yōu)先級(jí)的就緒態(tài)任務(wù),它開(kāi)始運(yùn)行
  • t4:現(xiàn)在,HMI任務(wù)、CAN任務(wù)的優(yōu)先級(jí)都比接收任務(wù)高,它們都在等待隊(duì)列有空閑的空間;一旦接收任務(wù)讀出1個(gè)數(shù)據(jù),會(huì)馬上被搶占。被誰(shuí)搶占?誰(shuí)等待最久?HMI任務(wù)!所以在t4時(shí)刻,切換到HMI任務(wù)。
  • t5:HMI任務(wù)向隊(duì)列寫(xiě)入第6個(gè)數(shù)據(jù),然后再次阻塞,這是CAN任務(wù)已經(jīng)阻塞很久了。接收任務(wù)變?yōu)樽罡邇?yōu)先級(jí)的就緒態(tài)任務(wù),開(kāi)始執(zhí)行。
  • t6:現(xiàn)在,HMI任務(wù)、CAN任務(wù)的優(yōu)先級(jí)都比接收任務(wù)高,它們都在等待隊(duì)列有空閑的空間;一旦接收任務(wù)讀出1個(gè)數(shù)據(jù),會(huì)馬上被搶占。被誰(shuí)搶占?誰(shuí)等待最久?CAN任務(wù)!所以在t6時(shí)刻,切換到CAN任務(wù)。
  • t7:CAN任務(wù)向隊(duì)列寫(xiě)入數(shù)據(jù),因?yàn)閮H僅有一個(gè)空間供寫(xiě)入,所以它馬上再次進(jìn)入阻塞狀態(tài)。這時(shí)HMI任務(wù)、CAN任務(wù)都在等待空閑空間,只有接收任務(wù)可以繼續(xù)執(zhí)行。
在這里插入圖片描述

5.5 示例10: 傳輸大塊數(shù)據(jù)

本節(jié)代碼為:FreeRTOS_10_queue_bigtransfer。

FreeRTOS的隊(duì)列使用拷貝傳輸,也就是要傳輸uint32_t時(shí),把4字節(jié)的數(shù)據(jù)拷貝進(jìn)隊(duì)列;要傳輸一個(gè)8字節(jié)的結(jié)構(gòu)體時(shí),把8字節(jié)的數(shù)據(jù)拷貝進(jìn)隊(duì)列。

如果要傳輸1000字節(jié)的結(jié)構(gòu)體呢?寫(xiě)隊(duì)列時(shí)拷貝1000字節(jié),讀隊(duì)列時(shí)再拷貝1000字節(jié)?不建議這么做,影響效率!

這時(shí)候,我們要傳輸?shù)氖沁@個(gè)巨大結(jié)構(gòu)體的地址:把它的地址寫(xiě)入隊(duì)列,對(duì)方從隊(duì)列得到這個(gè)地址,使用地址去訪問(wèn)那1000字節(jié)的數(shù)據(jù)。

使用地址來(lái)間接傳輸數(shù)據(jù)時(shí),這些數(shù)據(jù)放在RAM里,對(duì)于這塊RAM,要保證這幾點(diǎn):

  • RAM的所有者、操作者,必須清晰明了
    這塊內(nèi)存,就被稱(chēng)為"共享內(nèi)存"。要確保不能同時(shí)修改RAM。比如,在寫(xiě)隊(duì)列之前只有由發(fā)送者修改這塊RAM,在讀隊(duì)列之后只能由接收者訪問(wèn)這塊RAM。
  • RAM要保持可用
    這塊RAM應(yīng)該是全局變量,或者是動(dòng)態(tài)分配的內(nèi)存。對(duì)于動(dòng)然分配的內(nèi)存,要確保它不能提前釋放:要等到接收者用完后再釋放。另外,不能是局部變量。

FreeRTOS_10_queue_bigtransfer程序會(huì)創(chuàng)建一個(gè)隊(duì)列,然后創(chuàng)建1個(gè)發(fā)送任務(wù)、1個(gè)接收任務(wù):

  • 創(chuàng)建的隊(duì)列:長(zhǎng)度為1,用來(lái)傳輸"char *"指針
  • 發(fā)送任務(wù)優(yōu)先級(jí)為1,在字符數(shù)組中寫(xiě)好數(shù)據(jù)后,把它的地址寫(xiě)入隊(duì)列
  • 接收任務(wù)優(yōu)先級(jí)為2,讀隊(duì)列得到"char *"值,把它打印出來(lái)

這個(gè)程序故意設(shè)置接收任務(wù)的優(yōu)先級(jí)更高,在它訪問(wèn)數(shù)組的過(guò)程中,接收任務(wù)無(wú)法執(zhí)行、無(wú)法寫(xiě)這個(gè)數(shù)組。

main函數(shù)中創(chuàng)建了隊(duì)列、創(chuàng)建了發(fā)送任務(wù)、接收任務(wù),代碼如下:

/* 定義一個(gè)字符數(shù)組 */
static char pcBuffer[100];


/* vSenderTask被用來(lái)創(chuàng)建2個(gè)任務(wù),用于寫(xiě)隊(duì)列
 * vReceiverTask被用來(lái)創(chuàng)建1個(gè)任務(wù),用于讀隊(duì)列
 */
static void vSenderTask( void *pvParameters );
static void vReceiverTask( void *pvParameters );

/*-----------------------------------------------------------*/

/* 隊(duì)列句柄, 創(chuàng)建隊(duì)列時(shí)會(huì)設(shè)置這個(gè)變量 */
QueueHandle_t xQueue;

int main( void )
{
	prvSetupHardware();
	
    /* 創(chuàng)建隊(duì)列: 長(zhǎng)度為1,數(shù)據(jù)大小為4字節(jié)(存放一個(gè)char指針) */
    xQueue = xQueueCreate( 1, sizeof(char *) );

	if( xQueue != NULL )
	{
		/* 創(chuàng)建1個(gè)任務(wù)用于寫(xiě)隊(duì)列
		 * 任務(wù)函數(shù)會(huì)連續(xù)執(zhí)行,構(gòu)造buffer數(shù)據(jù),把buffer地址寫(xiě)入隊(duì)列
		 * 優(yōu)先級(jí)為1
		 */
		xTaskCreate( vSenderTask, "Sender", 1000, NULL, 1, NULL );

		/* 創(chuàng)建1個(gè)任務(wù)用于讀隊(duì)列
		 * 優(yōu)先級(jí)為2, 高于上面的兩個(gè)任務(wù)
		 * 這意味著讀隊(duì)列得到buffer地址后,本任務(wù)使用buffer時(shí)不會(huì)被打斷
		 */
		xTaskCreate( vReceiverTask, "Receiver", 1000, NULL, 2, NULL );

		/* 啟動(dòng)調(diào)度器 */
		vTaskStartScheduler();
	}
	else
	{
		/* 無(wú)法創(chuàng)建隊(duì)列 */
	}

	/* 如果程序運(yùn)行到了這里就表示出錯(cuò)了, 一般是內(nèi)存不足 */
	return 0;
}

發(fā)送任務(wù)的函數(shù)中,現(xiàn)在全局大數(shù)組pcBuffer中構(gòu)造數(shù)據(jù),然后把它的地址寫(xiě)入隊(duì)列,代碼如下:

static void vSenderTask( void *pvParameters )
{
	BaseType_t xStatus;
	static int cnt = 0;
	
	char *buffer;

	/* 無(wú)限循環(huán) */
	for( ;; )
	{
		sprintf(pcBuffer, "www.100ask.net Msg %d\r\n", cnt++);
		buffer = pcBuffer; // buffer變量等于數(shù)組的地址, 下面要把這個(gè)地址寫(xiě)入隊(duì)列
		
		/* 寫(xiě)隊(duì)列
		 * xQueue: 寫(xiě)哪個(gè)隊(duì)列
		 * pvParameters: 寫(xiě)什么數(shù)據(jù)? 傳入數(shù)據(jù)的地址, 會(huì)從這個(gè)地址把數(shù)據(jù)復(fù)制進(jìn)隊(duì)列
		 * 0: 如果隊(duì)列滿的話, 即刻返回
		 */
		xStatus = xQueueSendToBack( xQueue, &buffer, 0 ); /* 只需要寫(xiě)入4字節(jié), 無(wú)需寫(xiě)入整個(gè)buffer */

		if( xStatus != pdPASS )
		{
			printf( "Could not send to the queue.\r\n" );
		}
	}
}

接收任務(wù)的函數(shù)中,讀取隊(duì)列、得到buffer的地址、打印,代碼如下:

static void vReceiverTask( void *pvParameters )
{
	/* 讀取隊(duì)列時(shí), 用這個(gè)變量來(lái)存放數(shù)據(jù) */
	char *buffer;
	const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );	
	BaseType_t xStatus;

	/* 無(wú)限循環(huán) */
	for( ;; )
	{
		/* 讀隊(duì)列
		 * xQueue: 讀哪個(gè)隊(duì)列
		 * &xReceivedStructure: 讀到的數(shù)據(jù)復(fù)制到這個(gè)地址
		 * xTicksToWait: 沒(méi)有數(shù)據(jù)就阻塞一會(huì)
		 */
		xStatus = xQueueReceive( xQueue, &buffer, xTicksToWait); /* 得到buffer地址,只是4字節(jié) */

		if( xStatus == pdPASS )
		{
			/* 讀到了數(shù)據(jù) */
			printf("Get: %s", buffer);
		}
		else
		{
			/* 沒(méi)讀到數(shù)據(jù) */
			printf( "Could not receive from the queue.\r\n" );
		}
	}
}

運(yùn)行結(jié)果如下圖所示:

在這里插入圖片描述

5.6 示例11: 郵箱(Mailbox)

本節(jié)代碼為:FreeRTOS_11_queue_mailbox。

FreeRTOS的郵箱概念跟別的RTOS不一樣,這里的郵箱稱(chēng)為"櫥窗"也許更恰當(dāng):

  • 它是一個(gè)隊(duì)列,隊(duì)列長(zhǎng)度只有1
  • 寫(xiě)郵箱:新數(shù)據(jù)覆蓋舊數(shù)據(jù),在任務(wù)中使用xQueueOverwrite(),在中斷中使用xQueueOverwriteFromISR()
    既然是覆蓋,那么無(wú)論郵箱中是否有數(shù)據(jù),這些函數(shù)總能成功寫(xiě)入數(shù)據(jù)。
  • 讀郵箱:讀數(shù)據(jù)時(shí),數(shù)據(jù)不會(huì)被移除;在任務(wù)中使用xQueuePeek(),在中斷中使用xQueuePeekFromISR()。
    這意味著,第一次調(diào)用時(shí)會(huì)因?yàn)闊o(wú)數(shù)據(jù)而阻塞,一旦曾經(jīng)寫(xiě)入數(shù)據(jù),以后讀郵箱時(shí)總能成功。

main函數(shù)中創(chuàng)建了隊(duì)列(隊(duì)列長(zhǎng)度為1)、創(chuàng)建了發(fā)送任務(wù)、接收任務(wù):

  • 發(fā)送任務(wù)的優(yōu)先級(jí)為2,它先執(zhí)行
  • 接收任務(wù)的優(yōu)先級(jí)為1

代碼如下:

/* 隊(duì)列句柄, 創(chuàng)建隊(duì)列時(shí)會(huì)設(shè)置這個(gè)變量 */
QueueHandle_t xQueue;

int main( void )
{
	prvSetupHardware();
	
    /* 創(chuàng)建隊(duì)列: 長(zhǎng)度為1,數(shù)據(jù)大小為4字節(jié)(存放一個(gè)char指針) */
    xQueue = xQueueCreate( 1, sizeof(uint32_t) );

	if( xQueue != NULL )
	{
		/* 創(chuàng)建1個(gè)任務(wù)用于寫(xiě)隊(duì)列
		 * 任務(wù)函數(shù)會(huì)連續(xù)執(zhí)行,構(gòu)造buffer數(shù)據(jù),把buffer地址寫(xiě)入隊(duì)列
		 * 優(yōu)先級(jí)為2
		 */
		xTaskCreate( vSenderTask, "Sender", 1000, NULL, 2, NULL );

		/* 創(chuàng)建1個(gè)任務(wù)用于讀隊(duì)列
		 * 優(yōu)先級(jí)為1
		 */
		xTaskCreate( vReceiverTask, "Receiver", 1000, NULL, 1, NULL );

		/* 啟動(dòng)調(diào)度器 */
		vTaskStartScheduler();
	}
	else
	{
		/* 無(wú)法創(chuàng)建隊(duì)列 */
	}

	/* 如果程序運(yùn)行到了這里就表示出錯(cuò)了, 一般是內(nèi)存不足 */
	return 0;
}

發(fā)送任務(wù)、接收任務(wù)的代碼和執(zhí)行流程如下:

  • A:發(fā)送任務(wù)先執(zhí)行,馬上阻塞
  • BC:接收任務(wù)執(zhí)行,這是郵箱無(wú)數(shù)據(jù),打印"Could not …"。在發(fā)送任務(wù)阻塞過(guò)程中,接收任務(wù)多次執(zhí)行、多次打印。
  • D:發(fā)送任務(wù)從阻塞狀態(tài)退出,立刻執(zhí)行、寫(xiě)隊(duì)列
  • E:發(fā)送任務(wù)再次阻塞
  • FG、HI、……:接收任務(wù)不斷"偷看"郵箱,得到同一個(gè)數(shù)據(jù),打印出多個(gè)"Get: 0"
  • J:發(fā)送任務(wù)從阻塞狀態(tài)退出,立刻執(zhí)行、覆蓋隊(duì)列,寫(xiě)入1
  • K:發(fā)送任務(wù)再次阻塞
  • LM、……:接收任務(wù)不斷"偷看"郵箱,得到同一個(gè)數(shù)據(jù),打印出多個(gè)"Get: 1"
在這里插入圖片描述

運(yùn)行結(jié)果如下圖所示:

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

    關(guān)注

    5149

    文章

    19657

    瀏覽量

    317340
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11509

    瀏覽量

    213701
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4379

    瀏覽量

    64824
  • RTOS
    +關(guān)注

    關(guān)注

    24

    文章

    851

    瀏覽量

    121143
  • FreeRTOS
    +關(guān)注

    關(guān)注

    12

    文章

    493

    瀏覽量

    64299
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    東山freeRTOS系列程之信號(hào)量(6)

    文章目錄 系列教程總目錄 概述 6.1 信號(hào)量的特性 6.1.1 信號(hào)量的常規(guī)操作 6.1.2 信號(hào)量跟隊(duì)列的對(duì)比 6.1.3 兩種信號(hào)量的對(duì)比 6.2 信號(hào)量函數(shù) 6.2.1 創(chuàng)建 6.2.2
    的頭像 發(fā)表于 12-13 14:35 ?5612次閱讀
    <b class='flag-5'>韋</b><b class='flag-5'>東山</b><b class='flag-5'>freeRTOS</b><b class='flag-5'>系列</b>教<b class='flag-5'>程之</b>信號(hào)量(6)

    FreeRTOS發(fā)送消息隊(duì)列失敗的解決辦法?

    剛?cè)腴T(mén)FreeRTOS,正在學(xué)習(xí)發(fā)送消息隊(duì)列。程序參考原子哥的例子寫(xiě)的。在執(zhí)行 err = xQueueSend(SI24R1Rx_Queue,&RxBuff,100);這一句的時(shí)候??偸菚?huì)
    發(fā)表于 06-14 09:01

    Queue隊(duì)列的作用是什么

    文章目錄前言Queue 隊(duì)列semaphore 信號(hào)量Mutex 互斥量微信公眾號(hào)前言FreeRTOS STM32CubeMX配置 內(nèi)存管理 任務(wù)管理上節(jié)介紹了用STM32CubeMX生成帶
    發(fā)表于 02-14 06:57

    消息隊(duì)列Queue相關(guān)資料推薦

    消息隊(duì)列QueueAPItx_queue_createtx_queue_deletex_queue_flushtx_queue_front_sendtx_queue_receivetx_queue_send_notifyAPItx_queue_createtx_queue_del
    發(fā)表于 02-22 06:53

    東山freeRTOS系列教程:入門(mén)文檔教程+進(jìn)階視頻教程

    文章目錄 學(xué)前知識(shí)普及 初級(jí)文檔教程 進(jìn)階視頻教程 進(jìn)階一:FreeRTOS的內(nèi)部機(jī)制 進(jìn)階二:深入理解FreeRTOS隊(duì)列隊(duì)列實(shí)戰(zhàn) 進(jìn)階三:RTOS商業(yè)產(chǎn)品案例源碼講解 學(xué)前知識(shí)普
    發(fā)表于 11-29 16:36 ?2606次閱讀
    <b class='flag-5'>韋</b><b class='flag-5'>東山</b><b class='flag-5'>freeRTOS</b><b class='flag-5'>系列</b>教程:入門(mén)文檔教程+進(jìn)階視頻教程

    東山freeRTOS程之FreeRTOS概述與體驗(yàn)(1)

    文章目錄 教程目錄 1.1 FreeRTOS目錄結(jié)構(gòu) 1.1 FreeRTOS目錄結(jié)構(gòu) 1.2 核心文件 1.3 移植時(shí)涉及的文件 1.4 頭文件相關(guān) 1.4.1 頭文件目錄 1.4.2 頭文件
    發(fā)表于 11-29 16:56 ?2452次閱讀
    <b class='flag-5'>韋</b><b class='flag-5'>東山</b><b class='flag-5'>freeRTOS</b>教<b class='flag-5'>程之</b><b class='flag-5'>FreeRTOS</b>概述與體驗(yàn)(1)

    東山freeRTOS系列程之內(nèi)存管理(2)

    文章目錄 教程目錄 2.1 為什么要自己實(shí)現(xiàn)內(nèi)存管理 2.2 FreeRTOS5種內(nèi)存管理方法 2.2.1 Heap_1 2.2.2 Heap_2 2.2.3 Heap_3 2.2.4
    發(fā)表于 11-29 16:58 ?1240次閱讀
    <b class='flag-5'>韋</b><b class='flag-5'>東山</b><b class='flag-5'>freeRTOS</b><b class='flag-5'>系列</b>教<b class='flag-5'>程之</b>內(nèi)存管理(2)

    FreeRTOS消息隊(duì)列 & ESP32使用

    FreeRTOS消息隊(duì)列 & ESP32實(shí)戰(zhàn)FreeRTOS消息隊(duì)列FreeRTOS的消息隊(duì)列
    發(fā)表于 12-03 17:51 ?1次下載
    <b class='flag-5'>FreeRTOS</b>消息<b class='flag-5'>隊(duì)列</b> & ESP32使用

    FreeRTOS學(xué)習(xí)(五)消息隊(duì)列和二值信號(hào)量 xQueue / xSemaphore

    消息隊(duì)列可以和中斷 人物間發(fā)送和接受不定長(zhǎng)的消息,在消息隊(duì)列中會(huì)使任務(wù)進(jìn)入阻塞。 可以在調(diào)度器開(kāi)始前,創(chuàng)建消息隊(duì)列。#include "FreeRTOS.h"#include
    發(fā)表于 12-04 20:06 ?7次下載
    <b class='flag-5'>FreeRTOS</b>學(xué)習(xí)(五)消息<b class='flag-5'>隊(duì)列</b>和二值信號(hào)量 xQueue / xSemaphore

    FreeRTOS 隊(duì)列 信號(hào)量 互斥量

    文章目錄前言Queue 隊(duì)列semaphore 信號(hào)量Mutex 互斥量微信公眾號(hào)前言FreeRTOS STM32CubeMX配置 內(nèi)存管理 任務(wù)管理上節(jié)介紹了用STM32CubeMX生成帶
    發(fā)表于 12-09 09:51 ?0次下載
    <b class='flag-5'>FreeRTOS</b> <b class='flag-5'>隊(duì)列</b> 信號(hào)量 互斥量

    ThreadX(九)------消息隊(duì)列Queue

    消息隊(duì)列QueueAPItx_queue_createtx_queue_deletex_queue_flushtx_queue_front_sendtx_queue_receivetx_queue_send_notifyAPItx_queue_createtx_queue_del
    發(fā)表于 12-28 19:35 ?2次下載
    ThreadX(九)------消息<b class='flag-5'>隊(duì)列</b><b class='flag-5'>Queue</b>

    FreeRTOS系列第18篇---FreeRTOS隊(duì)列API函數(shù)

    FreeRTOS為操作隊(duì)列提供了非常豐富的API函數(shù),包括隊(duì)列的創(chuàng)建、刪除,靈活的入隊(duì)和出隊(duì)方式、帶中斷保護(hù)的入隊(duì)和出隊(duì)等等。下面就來(lái)詳細(xì)...
    發(fā)表于 01-26 17:44 ?12次下載
    <b class='flag-5'>FreeRTOS</b><b class='flag-5'>系列</b>第18篇---<b class='flag-5'>FreeRTOS</b><b class='flag-5'>隊(duì)列</b>API函數(shù)

    隊(duì)列Queue的常用方法有哪些

    FIFO(先入先出)隊(duì)列Queue,LIFO(后入先出)隊(duì)列LifoQueue,和優(yōu)先級(jí)隊(duì)列PriorityQueue。
    的頭像 發(fā)表于 08-19 10:24 ?6265次閱讀
    <b class='flag-5'>隊(duì)列</b><b class='flag-5'>Queue</b>的常用方法有哪些

    STM32G0開(kāi)發(fā)筆記:使用FreeRTOS系統(tǒng)的隊(duì)列Queue

    使用Platformio平臺(tái)的libopencm3開(kāi)發(fā)框架來(lái)開(kāi)發(fā)STM32G0,下面為使用FreeRTOS系統(tǒng)的隊(duì)列Queue。
    的頭像 發(fā)表于 01-16 14:50 ?1845次閱讀

    FreeRTOS消息隊(duì)列結(jié)構(gòu)體

    有一個(gè)結(jié)構(gòu)體用于描述隊(duì)列,叫做 Queue_t,這個(gè)結(jié)構(gòu)體在文件 queue.c 中定義。 3、隊(duì)列創(chuàng)建 在使用隊(duì)列之前必須先創(chuàng)建
    的頭像 發(fā)表于 07-06 17:03 ?1455次閱讀
    <b class='flag-5'>FreeRTOS</b>消息<b class='flag-5'>隊(duì)列</b>結(jié)構(gòu)體