女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

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

完善資料讓更多小伙伴認(rèn)識你,還能領(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ì)列的阻塞訪問
  • 5.2 隊(duì)列函數(shù)
    • 5.2.1 創(chuàng)建
    • 5.2.2 復(fù)位
    • 5.2.3 刪除
    • 5.2.4 寫隊(duì)列
    • 5.2.5 讀隊(duì)列
    • 5.2.6 查詢
    • 5.2.7 覆蓋/偷看
  • 5.3 示例8: 隊(duì)列的基本使用
  • 5.4 示例9: 分辨數(shù)據(jù)源
  • 5.5 示例10: 傳輸大塊數(shù)據(jù)
  • 5.6 示例11: 郵箱(Mailbox)

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

系列教程總目錄

本教程連載中,篇章會比較多,為方便同學(xué)們閱讀,點(diǎn)擊這里可以查看文章的 目錄列表,目錄列表頁面地址: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ì)列上阻塞是什么意思
  • 怎么在多個隊(duì)列上阻塞
  • 讀寫隊(duì)列時(shí)如何影響任務(wù)的優(yōu)先級

5.1 隊(duì)列的特性

5.1.1 常規(guī)操作

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

  • 隊(duì)列可以包含若干個數(shù)據(jù):隊(duì)列中有若干項(xiàng),這被稱為"長度"(length)
  • 每個數(shù)據(jù)大小固定
  • 創(chuàng)建隊(duì)列時(shí)就要指定長度、數(shù)據(jù)大小
  • 數(shù)據(jù)的操作采用先進(jìn)先出的方法(FIFO,F(xiàn)irst In First Out):寫數(shù)據(jù)時(shí)放到尾部,讀數(shù)據(jù)時(shí)從頭部讀
  • 也可以強(qiáng)制寫隊(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使用拷貝值的方法,這更簡單:

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

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

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

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

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

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

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

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

只要知道隊(duì)列的句柄,誰都可以讀、寫該隊(duì)列。任務(wù)、ISR都可讀、寫隊(duì)列。可以多個任務(wù)讀寫隊(duì)列。

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

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

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

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

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

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

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

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

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

5.2.1 創(chuàng)建

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

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

函數(shù)原型如下:

QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );
參數(shù) 說明
uxQueueLength 隊(duì)列長度,最多能存放多少個數(shù)據(jù)(item)
uxItemSize 每個數(shù)據(jù)(item)的大小:以字節(jié)為單位
返回值 非0:成功,返回句柄,以后使用句柄來操作隊(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ù) 說明
uxQueueLength 隊(duì)列長度,最多能存放多少個數(shù)據(jù)(item)
uxItemSize 每個數(shù)據(jù)(item)的大小:以字節(jié)為單位
pucQueueStorageBuffer 如果uxItemSize非0,pucQueueStorageBuffer必須指向一個uint8_t數(shù)組,
此數(shù)組大小至少為"uxQueueLength * uxItemSize"
pxQueueBuffer 必須執(zhí)行一個StaticQueue_t結(jié)構(gòu)體,用來保存隊(duì)列的數(shù)據(jù)結(jié)構(gòu)
返回值 非0:成功,返回句柄,以后使用句柄來操作隊(duì)列
NULL:失敗,因?yàn)閜xQueueBuffer為NULL

示例代碼:

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

5.2.2 復(fù)位

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

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

5.2.3 刪除

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

void vQueueDelete( QueueHandle_t xQueue );

5.2.4 寫隊(duì)列

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

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

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


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

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

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

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

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

5.2.5 讀隊(duì)列

使用xQueueReceive()函數(shù)讀隊(duì)列,讀到一個數(shù)據(jù)后,隊(duì)列中該數(shù)據(jù)會被移除。這個函數(shù)有兩個版本:在任務(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ù)說明如下:

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

5.2.6 查詢

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

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

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

5.2.7 覆蓋/偷看

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

/* 覆蓋隊(duì)列
 * xQueue: 寫哪個隊(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ù)供多方讀取,也就是說讀取時(shí)不要移除數(shù)據(jù),要留給后來人。那么可以使用"窺視",也就是xQueuePeek()xQueuePeekFromISR()。這些函數(shù)會從隊(duì)列中復(fù)制出數(shù)據(jù),但是不移除數(shù)據(jù)。這也意味著,如果隊(duì)列中沒有數(shù)據(jù),那么"偷看"時(shí)會導(dǎo)致阻塞;一旦隊(duì)列中有數(shù)據(jù),以后每次"偷看"都會成功。
函數(shù)原型如下:

/* 偷看隊(duì)列
 * xQueue: 偷看哪個隊(duì)列
 * pvItemToQueue: 數(shù)據(jù)地址, 用來保存復(fù)制出來的數(shù)據(jù)
 * xTicksToWait: 沒有數(shù)據(jù)的話阻塞一會
 * 返回值: 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

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

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

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

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

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

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

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

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

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

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

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

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

	/* 無限循環(huán) */
	for( ;; )
	{
		/* 寫隊(duì)列
		 * xQueue: 寫哪個隊(duì)列
		 * &lValueToSend: 寫什么數(shù)據(jù)? 傳入數(shù)據(jù)的地址, 會從這個地址把數(shù)據(jù)復(fù)制進(jìn)隊(duì)列
		 * 0: 不阻塞, 如果隊(duì)列滿的話, 寫入失敗, 立刻返回
		 */
		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í), 用這個變量來存放數(shù)據(jù) */
	int32_t lReceivedValue;
	BaseType_t xStatus;
	const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );

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

		if( xStatus == pdPASS )
		{
			/* 讀到了數(shù)據(jù) */
			printf( "Received = %d\r\n", lReceivedValue );
		}
		else
		{
			/* 沒讀到數(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)有多個發(fā)送任務(wù),通過同一個隊(duì)列發(fā)出數(shù)據(jù),接收任務(wù)如何分辨數(shù)據(jù)來源?數(shù)據(jù)本身帶有"來源"信息,比如寫入隊(duì)列的數(shù)據(jù)是一個結(jié)構(gòu)體,結(jié)構(gòu)體中的lDataSouceID用來表示數(shù)據(jù)來源:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	/* 無限循環(huán) */
	for( ;; )
	{
		/* 寫隊(duì)列
		 * xQueue: 寫哪個隊(duì)列
		 * pvParameters: 寫什么數(shù)據(jù)? 傳入數(shù)據(jù)的地址, 會從這個地址把數(shù)據(jù)復(fù)制進(jìn)隊(duì)列
		 * xTicksToWait: 如果隊(duì)列滿的話, 阻塞一會
		 */
		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í), 用這個變量來存放數(shù)據(jù) */
	Data_t xReceivedStructure;
	BaseType_t xStatus;

	/* 無限循環(huán) */
	for( ;; )
	{
		/* 讀隊(duì)列
		 * xQueue: 讀哪個隊(duì)列
		 * &xReceivedStructure: 讀到的數(shù)據(jù)復(fù)制到這個地址
		 * 0: 沒有數(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
		{
			/* 沒讀到數(shù)據(jù) */
			printf( "Could not receive from the queue.\r\n" );
		}
	}
}

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

在這里插入圖片描述

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

  • t1:HMI是最后創(chuàng)建的最高優(yōu)先級任務(wù),它先執(zhí)行,一下子向隊(duì)列寫入5個數(shù)據(jù),把隊(duì)列都寫滿了
  • t2:隊(duì)列已經(jīng)滿了,HMI任務(wù)再發(fā)起第6次寫操作時(shí),進(jìn)入阻塞狀態(tài)。這時(shí)CAN任務(wù)是最高優(yōu)先級的就緒態(tài)任務(wù),它開始執(zhí)行
  • t3:CAN任務(wù)發(fā)現(xiàn)隊(duì)列已經(jīng)滿了,進(jìn)入阻塞狀態(tài);接收任務(wù)變?yōu)樽罡邇?yōu)先級的就緒態(tài)任務(wù),它開始運(yùn)行
  • t4:現(xiàn)在,HMI任務(wù)、CAN任務(wù)的優(yōu)先級都比接收任務(wù)高,它們都在等待隊(duì)列有空閑的空間;一旦接收任務(wù)讀出1個數(shù)據(jù),會馬上被搶占。被誰搶占?誰等待最久?HMI任務(wù)!所以在t4時(shí)刻,切換到HMI任務(wù)。
  • t5:HMI任務(wù)向隊(duì)列寫入第6個數(shù)據(jù),然后再次阻塞,這是CAN任務(wù)已經(jīng)阻塞很久了。接收任務(wù)變?yōu)樽罡邇?yōu)先級的就緒態(tài)任務(wù),開始執(zhí)行。
  • t6:現(xiàn)在,HMI任務(wù)、CAN任務(wù)的優(yōu)先級都比接收任務(wù)高,它們都在等待隊(duì)列有空閑的空間;一旦接收任務(wù)讀出1個數(shù)據(jù),會馬上被搶占。被誰搶占?誰等待最久?CAN任務(wù)!所以在t6時(shí)刻,切換到CAN任務(wù)。
  • t7:CAN任務(wù)向隊(duì)列寫入數(shù)據(jù),因?yàn)閮H僅有一個空間供寫入,所以它馬上再次進(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ì)列;要傳輸一個8字節(jié)的結(jié)構(gòu)體時(shí),把8字節(jié)的數(shù)據(jù)拷貝進(jìn)隊(duì)列。

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		if( xStatus == pdPASS )
		{
			/* 讀到了數(shù)據(jù) */
			printf("Get: %s", buffer);
		}
		else
		{
			/* 沒讀到數(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不一樣,這里的郵箱稱為"櫥窗"也許更恰當(dāng):

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

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

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

代碼如下:

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

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

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

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

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

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

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

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

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

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

    關(guān)注

    5133

    文章

    19501

    瀏覽量

    314281
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11446

    瀏覽量

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

    關(guān)注

    3

    文章

    4367

    瀏覽量

    64057
  • RTOS
    +關(guān)注

    關(guān)注

    24

    文章

    838

    瀏覽量

    120689
  • FreeRTOS
    +關(guān)注

    關(guān)注

    12

    文章

    485

    瀏覽量

    63669
收藏 人收藏

    評論

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

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

    文章目錄 系列教程總目錄 概述 6.1 信號量的特性 6.1.1 信號量的常規(guī)操作 6.1.2 信號量跟隊(duì)列的對比 6.1.3 兩種信號量的對比 6.2 信號量函數(shù) 6.2.1 創(chuàng)建 6.2.2
    的頭像 發(fā)表于 12-13 14:35 ?5427次閱讀
    <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>信號量(6)

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

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

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

    文章目錄前言Queue 隊(duì)列semaphore 信號量Mutex 互斥量微信公眾號前言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系列教程:入門文檔教程+進(jìn)階視頻教程

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

    消息隊(duì)列可以和中斷 人物間發(fā)送和接受不定長的消息,在消息隊(duì)列中會使任務(wù)進(jìn)入阻塞。 可以在調(diào)度器開始前,創(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>和二值信號量 xQueue / xSemaphore

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

    文章目錄前言Queue 隊(duì)列semaphore 信號量Mutex 互斥量微信公眾號前言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> 信號量 互斥量

    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ì)等等。下面就來詳細(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)先級隊(duì)列PriorityQueue。
    的頭像 發(fā)表于 08-19 10:24 ?6125次閱讀
    <b class='flag-5'>隊(duì)列</b><b class='flag-5'>Queue</b>的常用方法有哪些

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

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

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

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