99久久全国免费观看_国产一区二区三区四区五区VM_久久www人成免费看片中文_国产高清在线a视频大全_深夜福利www_日韩一级成人av

小麥大叔
認證:普通會員
所在專題目錄 查看專題
基于CubeIDE快速整合FreeRTOS創建第一個任務
【FreeRTOS學習02】源碼結構/數據類型/命名規則總結
【FreeRTOS學習03】Task Management 任務管理基本概念介紹
【FreeRTOS學習04】Queue Management 消息隊列使用詳解
【FreeRTOS學習05】深度解剖FreeRTOSConfig.h實現對系統的自定義剪裁
【FreeRTOS學習06】深度解剖中斷與任務之間同步的具體使用場景
作者動態 更多
一款輕量級的開源GUI項目——SimpleGUI,可以完美適配單色屏
02-22 09:47
看到這100多個軟硬件開源項目,真是爽爆了
2024-11-30 14:12
推薦一個高效,可靠,安全的串口通訊開源方案
2024-11-27 11:17
推薦一款開源hack硬件平臺工具
2024-11-26 13:58
新手學STM32的話,先學標準庫還是HAL庫?
2024-10-18 15:09

【FreeRTOS學習04】Queue Management 消息隊列使用詳解

1 前言

任務之間的同步(同步就是任務之間做數據交互,或為兩個任務之間的通訊),任務和中斷之間的同步都可以依靠消息隊列,從而實現異步處理,FreeRTOS的隊列采用FIFO(先進先出)緩沖區,具體如下圖所示;

2 xQUEUE

FreeRTOS消息隊列的實現主要是queue.c,需要包含頭文件queue.h,下面先看一下queue.c中的數據類型xQUEUE,源碼如下所示;

typedef struct QueueDefinition
{
	int8_t *pcHead;					/*< Points to the beginning of the queue storage area. */
	int8_t *pcTail;					/*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */
	int8_t *pcWriteTo;				/*< Points to the free next place in the storage area. */

	union							/* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */
	{
		int8_t *pcReadFrom;			/*< Points to the last place that a queued item was read from when the structure is used as a queue. */
		UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */
	} u;

	List_t xTasksWaitingToSend;		/*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */
	List_t xTasksWaitingToReceive;	/*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */

	volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */
	UBaseType_t uxLength;			/*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
	UBaseType_t uxItemSize;			/*< The size of each items that the queue will hold. */

	volatile int8_t cRxLock;		/*< Stores the number of items received from the queue (removed from the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */
	volatile int8_t cTxLock;		/*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */

	#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
		uint8_t ucStaticallyAllocated;	/*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */
	#endif

	#if ( configUSE_QUEUE_SETS == 1 )
		struct QueueDefinition *pxQueueSetContainer;
	#endif

	#if ( configUSE_TRACE_FACILITY == 1 )
		UBaseType_t uxQueueNumber;
		uint8_t ucQueueType;
	#endif

} xQUEUE;

本文暫時不需要深入源碼,在queue.h的接口已經封裝得相當好,無需對細節太過于關注,下面會是對常用接口的使用的總結,如果英文好,直接看源碼中的函數注釋也是很好的選擇。

3 相關概念

3.1 數據結構

隊列可以保存有限個具有確定長度的數據單元。隊列可以保存的最大單元數目被稱為隊列的“深度”。在隊列創建時需要設定其深度和每個單元的大小。通常情況下,隊列被作為 FIFO(先進先出)使用,即數據由隊列尾寫入,從隊列首讀出。當然,由隊列首寫入也是可能的。往隊列寫入數據是通過字節拷貝把數據復制存儲到隊列中;從隊列讀出數據使得把隊列中的數據拷貝刪除。1 如下圖所示;

注意上面提到的數據單元可以是一個charint類型的數,但是相對比較合理的設計是,封裝成一個合理的類,或者稱之為結構體,可以明確當前數據單元的數據類型,數據來源(來自哪個任務)等等,因為一個隊列可以被多個任務進行讀取和發送函數,這樣就避免了傳輸數據出現混淆的情況。通常設計是一個隊列被多個任務寫入數據,然后有一個任務讀取,暫時稱之為多寫一讀,反之,多讀一寫則較少遇到。

3.2 收發數據堵塞

當某個任務試圖讀或者寫一個隊列時,其可以指定一個阻塞超時時間,

  • 讀取:任務讀取數據時,在設置堵塞超時時間內,如果隊列為空,該任務將保持阻塞狀態以等待隊列數據有效。當其它任務或中斷服務例程往其等待的隊列中寫入了數據,該任務將自動由阻塞態轉移為就緒態

  • 寫入:如果隊列被多個任務寫入,那么將導致多個任務堵塞以等待隊列有效,當隊列有效的時候,這些任務中的優先級最高的任務優先進入就緒態。

4 常用函數

FreeRTOS的消息隊列常用接口都封裝在queue.h中,通過宏定義統一將接口函數的命名風格整理得十分統一;具體如下圖所示;

這里有兩種需要注意;

  • 任務與任務之間同步:例如圖中處的API適用于任務間同步;
    • xQueueSendToFront
    • xQueueSendToFront
    • xQueueSend
    • xQueueOverwrite
  • 任務與中斷之間同步:圖中②處的API適用于任務于中斷間同步,xxxISR()后綴的函數都是FreeRTOS中保證了線程安全的;
    • xQueueSendToFrontFromISR
    • xQueueSendToBackFromISR
    • xQueueOverwriteFromISR
    • xQueueSendFromISR

4.1 創建隊列

  • QueueHandle_tQueueHandle_t是一個void類型的指針變量,定義在queue.h中,具體如下;
/**
 * Type by which queues are referenced.  For example, a call to xQueueCreate()
 * returns an QueueHandle_t variable that can then be used as a parameter to
 * xQueueSend(), xQueueReceive(), etc.
 */
typedef void * QueueHandle_t;

基本上每個隊列函數都會使用這個變量,這里我們統一稱為隊列的句柄;

  • xQueueCreate這個函數可以創建一個隊列,創建成功則會返回一個隊列句柄,如果創建失敗則返回NULL,其函數原型是xQueueGenericCreate,具體如下所示;
#define xQueueCreate( uxQueueLength, uxItemSize ) \
xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )

xQueueCreate如下所示;

 QueueHandle_t xQueueCreate(
							  UBaseType_t uxQueueLength,
							  UBaseType_t uxItemSize
						  );

4.2 發送數據

下面都是從任務發送數據到隊列,

  • xQueueSendToFront將數據發送至隊首,函數聲明如下;

 BaseType_t xQueueSendToBack(
								   QueueHandle_t	xQueue,
								   const void		*pvItemToQueue,
								   TickType_t		xTicksToWait
							   ); 
  • xQueueSendToBack將數據發送至隊尾,函數聲明如下;
 BaseType_t xQueueSendToFront(
							  QueueHandle_t xQueue,
							  const void * pvItemToQueue,
							  TickType_t xTicksToWait
						 );
  • xQueueSend與xQueueSendToBack入隊順序相同,函數聲明如下所示;
BaseType_t xQueueSend(
							  QueueHandle_t xQueue,
							  const void * pvItemToQueue,
							  TickType_t xTicksToWait
						 );

具體的參數描述如下:

  • xTicksToWait設為0 ,且隊列已滿,則xQueueSendToFront()與xQueueSendToBack()均會立即返回。阻塞時間是以系統心跳周期為單位的,所以絕對時間取決于系統心跳頻率。常量 portTICK_RATE_MS 可以用來把心跳時間單位轉換為毫秒時間單位
  • xTicksToWait 設置為 portMAX_DELAY , 并且在FreeRTOSConig.h 中設定 INCLUDE_vTaskSuspend 為 1,那么阻塞等待將沒有超時限制。

4.3 接收數據

  • xQueueReceivexQueueReceive()用于從隊列中接收(讀取)數據單元。接收到的單元同時會從隊列中刪除。函數聲明如下;

 BaseType_t xQueueReceive(
								 QueueHandle_t xQueue,
								 void *pvBuffer,
								 TickType_t xTicksToWait
							); 
  • xQueuePeekxQueuePeek()也是從從隊列中接收數據單元,不同的是并不從隊列中刪出接收到的單元。 xQueuePeek()從隊列首接收到數據后,不會修改隊列中的數據,也不會改變數據在隊列中的存儲序順。函數聲明如下;
 BaseType_t xQueuePeek(
							 QueueHandle_t xQueue,
							 void * const pvBuffer,
							 TickType_t xTicksToWait
						 );

具體的參數描述如下:

  • uxQueueSpacesAvailableuxQueueSpacesAvailable()用于查詢隊列中可用的空閑空間數量;函數聲明如下;
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );

  • uxQueueMessagesWaitinguxQueueMessagesWaiting()用于查詢隊列中當前有效數據單元個數;函數聲明如下;
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );

4.4 刪除隊列

  • vQueueDelete用來刪除一個隊列,直接傳入已創建的隊列句柄即可,函數聲明如下;
void vQueueDelete( QueueHandle_t xQueue );

5 舉例

多個任務寫入一個任務讀取的時候應該怎么做呢?如下圖所示2

這里有三個任務,所以為了搞清楚數據來自哪個任務,因此將數據單元封裝起來,使用iMeaning表示數據單元的源頭,當然這里還是比較簡單的應用。

6 總結

本文介紹了FreeRTOS的消息隊列比價常用的方法,當然是相對簡單的,側重在了解概念上,需要實際的應用從而加深理解,更加詳細已經靈活的應用可以參考FreeRTOS作者撰寫的Mastering_the_FreeRTOS_Real_Time_Kernel-A_Hands-On_Tutorial_Guide

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 4
收藏 3
關注 145
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧
主站蜘蛛池模板: 免费看av毛片多人群伦 | 日韩欧美精品在线视频 | 一本大道久久加勒比香蕉 | 一本一道久久a久久综合蜜桃 | 国产吹潮视频在线观看 | 日韩视频一区二区三区在线观看 | 欧美黑人添添高潮a片www | 男人的天堂av社区在线 | 天天宗合 | 中文一二三区 | 草久视频在线 | 成人激情av | 一二三四在线观看免费中文在线观看 | 人妻av资源先锋影音av资源 | 99视频在线无码 | 天天色人人爱 | 国产精品美女WWW爽爽爽视频 | jvid视频在线观看免费 | 中文字幕在线伊人 | 精品国产91九色蝌蚪 | 国产无遮挡色视频免费观看性色 | 无码精品每日更新精品久久久 | 成年女人粗暴毛片免费观看 | 艳妇荡乳豪妇荡乳av精东 | 在线观看最新中文字幕AV | 蜜桃av一区二区三区 | 国产精品无码午夜福利 | 蜜桃传媒一区二区 | 亚洲国产精品综合小说图片区 | 亚洲无吗视频在线 | 欧美在线视频一区二区 | xxx2高清在线观看免费视频 | 久草麻豆 | 日韩午夜高清 | 欧美制服第一页 | 国产精品第一页在线观看 | 久久久www视频| av高清| 红桃视频国产精品 | 野花社区免费观看视频高清 | 99久久夜色精品国产亚洲av卜 |