国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

上海新聞發(fā)布會疫情吉林百度seo公司

上海新聞發(fā)布會疫情,吉林百度seo公司,手機(jī)移動端網(wǎng)站建設(shè)宣傳,網(wǎng)站建設(shè)中怎么編輯圖片提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔 文章目錄 前言一、隊列是什么?而在freertos中,隊列是什么呢?①如果要進(jìn)行中斷、任務(wù)的交流,那我用全局變量行嗎?②…

提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔

文章目錄

  • 前言
  • 一、隊列是什么?
    • 而在freertos中,隊列是什么呢?
      • ①如果要進(jìn)行中斷、任務(wù)的交流,那我用全局變量行嗎?
      • ②那為什么隊列就可以代替全局變量的功能呢?
      • ③看一看在freertos中隊列的結(jié)構(gòu)
      • ④問題:當(dāng)多個任務(wù)寫入消息給一個“滿隊列”時,這些任務(wù)都會進(jìn)入阻塞狀態(tài),也就是說有多個任務(wù) 在等待同一 個隊列的空間。那當(dāng)隊列中有空間時,哪個任務(wù)會進(jìn)入就緒態(tài)?
      • ⑤數(shù)據(jù)寫隊列、讀隊列操作過程![在這里插入圖片描述](https://img-blog.csdnimg.cn/02032663fbd14548b0b9f6e699186440.png)
  • 二、隊列的結(jié)構(gòu)體
    • 1.結(jié)構(gòu)體內(nèi)容
    • 2.結(jié)構(gòu)體示意圖
  • 三、隊列相關(guān)API函數(shù)介紹
    • 1.創(chuàng)建隊列
    • 2.寫消息入隊列
      • (1)前三個函數(shù)
      • (2)后面的函數(shù)
    • 3.從隊列中讀取消息
      • 代碼例子:
  • 四、隊列入隊和出隊操作實(shí)驗(yàn)
    • 1.實(shí)驗(yàn)?zāi)繕?biāo)
    • 2.例程
      • ①main.c
      • ②freertos_demo();
      • ③操作隊列和存儲大數(shù)據(jù)塊
      • ④任務(wù)一:實(shí)現(xiàn)入隊
      • ⑤任務(wù)二:小數(shù)據(jù)出隊
      • ⑥任務(wù)三:大數(shù)據(jù)出隊
    • 3.例程運(yùn)行結(jié)果:
  • 五、隊列相關(guān)API函數(shù)解析
    • 1.隊列的創(chuàng)建API函數(shù):xQueueCreate( )
    • 2.往隊列寫入數(shù)據(jù)API函數(shù)(入隊):xQueueSend( )
    • 3.從隊列讀取數(shù)據(jù)API函數(shù)(出隊): xQueueReceive( )


前言

`本文包括以下內(nèi)容:
在這里插入圖片描述

一、隊列是什么?

綜述:隊列是一種特殊的數(shù)據(jù)結(jié)構(gòu),它遵循先進(jìn)先出(FIFO)的原則。隊列中的元素按照其插入的順序進(jìn)行訪問和處理,新元素被插入到隊列的末尾,而已存在的元素則在隊列的前端進(jìn)行操作和刪除。隊列的操作包括入隊(enqueue)和出隊(dequeue),入隊表示將元素插入到隊列的末尾,而出隊則表示將隊列的前端元素移除并返回。隊列常用于需要按照先后順序處理元素的場景,例如任務(wù)調(diào)度、消息傳遞等。

而在freertos中,隊列是什么呢?

隊列是任務(wù)到任務(wù)、任務(wù)到中斷、中斷到任務(wù)數(shù)據(jù)交流的一種機(jī)制(消息傳遞)
在這里插入圖片描述

①如果要進(jìn)行中斷、任務(wù)的交流,那我用全局變量行嗎?

答:不行。以這個圖為例,比如一個全局變量a=0,兩個任務(wù)里面都有對全局變量a的自增,如果兩個任務(wù)優(yōu)先級不同,當(dāng)運(yùn)行任務(wù)1時a++可能運(yùn)行到讀數(shù)據(jù)-修改數(shù)據(jù),但還沒有寫數(shù)據(jù)時就已經(jīng)被高優(yōu)先級的任務(wù)二打斷,導(dǎo)致a≠1,執(zhí)行任務(wù)二后才=1,這樣的話,執(zhí)行兩次任務(wù)卻讓全局變量a的值是錯誤的。

所以全局變量的弊端:數(shù)據(jù)無保護(hù),導(dǎo)致數(shù)據(jù)不安全,當(dāng)多個任務(wù)同時對該變量操作時,數(shù)據(jù)易受損

②那為什么隊列就可以代替全局變量的功能呢?

首先來看隊列的結(jié)構(gòu):
在這里插入圖片描述
可以看到,任務(wù)A和B是寫隊列操作,寫隊列這個函數(shù)呢,它會進(jìn)入臨界區(qū),完成實(shí)際操作后再退出臨界區(qū),所以:寫隊列時實(shí)際關(guān)閉了系統(tǒng)中斷,使得臨界區(qū)代碼可以完整的運(yùn)行不被打斷,而讀隊列也是同理。

所以,讀寫隊列具有程序保護(hù)功能,防止多任務(wù)同時訪問造成的數(shù)據(jù)沖突。

③看一看在freertos中隊列的結(jié)構(gòu)

在這里插入圖片描述
在隊列中可以存儲數(shù)量有限、大小固定的數(shù)據(jù)。隊列中的每一個數(shù)據(jù)叫做“隊列項目”,隊列能夠存儲“隊列項目”的最大數(shù)量稱為隊列的長度。
所以隊列的核心特征:隊列長度和每個隊列項目大小。需要我們自己創(chuàng)建時設(shè)置。
在Freertos中,隊列的特點(diǎn):
在這里插入圖片描述

(1)FIFO是First-In First-Out的縮寫,意為先進(jìn)先出。在隊列中,新元素被插入到隊列的末尾,而已存在的元素則在隊列的前端進(jìn)行操作和刪除。當(dāng)需要訪問或處理隊列中的元素時,先訪問或處理隊列中最早插入的元素,然后按照插入的先后順序依次訪問或處理其他元素。這種先進(jìn)先出的特性使得隊列成為一種常用的數(shù)據(jù)結(jié)構(gòu),在任務(wù)調(diào)度、緩存管理、消息傳遞等場景中得到廣泛應(yīng)用。

(2)在FreeRTOS中,隊列可以采用實(shí)際值傳遞或者傳遞指針的方式進(jìn)行數(shù)據(jù)傳遞。實(shí)際值傳遞是指將數(shù)據(jù)的副本拷貝到隊列中進(jìn)行傳遞,這樣操作的是數(shù)據(jù)的副本,對原始數(shù)據(jù)沒有影響。而傳遞指針則是將指向?qū)嶋H數(shù)據(jù)的指針放入隊列中,這樣可以避免復(fù)制大量的數(shù)據(jù),但需要注意在使用指針傳遞時,確保不會出現(xiàn)指針指向無效數(shù)據(jù)的情況。
在傳遞較大的數(shù)據(jù)時,采用指針傳遞可以避免頻繁的數(shù)據(jù)復(fù)制,提高效率。但需要注意在使用指針傳遞時,要確保數(shù)據(jù)的有效性,即確保指針指向的數(shù)據(jù)在傳遞過程中不會被修改或釋放,以免導(dǎo)致數(shù)據(jù)錯誤或懸掛指針的情況。

(3)隊列在FreeRTOS中是一種通用的機(jī)制,可以被任何任務(wù)或中斷使用來發(fā)送和讀取消息。這是因?yàn)殛犃惺且环N共享的數(shù)據(jù)結(jié)構(gòu),用于在不同的任務(wù)或中斷之間傳遞數(shù)據(jù)。任何任務(wù)或中斷都可以使用隊列的API函數(shù)來發(fā)送消息到隊列或從隊列中讀取消息,無論它們屬于哪個任務(wù)。
這種靈活性使得隊列成為一種常用的通信機(jī)制,在多任務(wù)或多中斷的系統(tǒng)中,可以方便地進(jìn)行任務(wù)間的數(shù)據(jù)傳遞和同步。通過隊列,任務(wù)和中斷可以安全地共享數(shù)據(jù),避免競爭條件和數(shù)據(jù)沖突的問題。同時,任務(wù)和中斷可以根據(jù)需要進(jìn)行阻塞或喚醒,以實(shí)現(xiàn)有效的同步和通信。

(4)當(dāng)任務(wù)向一個隊列發(fā)送消息時,可以通過指定一個阻塞時間來控制任務(wù)的行為。
如果隊列已滿,無法將消息入隊,任務(wù)可以選擇以下幾種行為
①阻塞等待:任務(wù)可以指定一個阻塞時間,如果隊列已滿,則任務(wù)會在隊列有空閑位置之前被阻塞。任務(wù)將等待,直到隊列有空閑位置并成功將消息入隊,或者等待的超時時間到達(dá)
②非阻塞立即返回:任務(wù)可以選擇在隊列已滿時立即返回,而不進(jìn)行阻塞等待。任務(wù)可以根據(jù)返回的結(jié)果來判斷是否消息成功發(fā)送到隊列中。
在這里插入圖片描述

④問題:當(dāng)多個任務(wù)寫入消息給一個“滿隊列”時,這些任務(wù)都會進(jìn)入阻塞狀態(tài),也就是說有多個任務(wù) 在等待同一 個隊列的空間。那當(dāng)隊列中有空間時,哪個任務(wù)會進(jìn)入就緒態(tài)?

在這里插入圖片描述

⑤數(shù)據(jù)寫隊列、讀隊列操作過程在這里插入圖片描述

二、隊列的結(jié)構(gòu)體

1.結(jié)構(gòu)體內(nèi)容

如下:

typedef struct QueueDefinition 
{int8_t * pcHead					/* 存儲區(qū)域的起始地址 */int8_t * pcWriteTo;        				/* 下一個寫入的位置 */union{QueuePointers_t     xQueue; SemaphoreData_t  xSemaphore; } u ;List_t xTasksWaitingToSend; 			/* 等待發(fā)送列表 */List_t xTasksWaitingToReceive;			/* 等待接收列表 */volatile UBaseType_t uxMessagesWaiting; 	/* 非空閑隊列項目的數(shù)量 */UBaseType_t uxLength;			/* 隊列長度 */UBaseType_t uxItemSize;                 		/* 隊列項目的大小 */volatile int8_t cRxLock; 				/* 讀取上鎖計數(shù)器 */volatile int8_t cTxLock;			/* 寫入上鎖計數(shù)器 *//* 其他的一些條件編譯 */
} xQUEUE;

這段代碼是一個隊列的定義,具體的結(jié)構(gòu)體成員解釋如下:

int8_t * pcHead: 存儲區(qū)域的起始地址,即隊列的存儲空間的首地址。

int8_t * pcWriteTo: 下一個寫入位置的指針,用于指示下一個要寫入數(shù)據(jù)的位置。

union { QueuePointers_t xQueue; SemaphoreData_t xSemaphore; } u: 一個聯(lián)合體,用于保存隊列指針或信號量數(shù)據(jù)。

List_t xTasksWaitingToSend: 等待發(fā)送列表,用于存儲等待向隊列發(fā)送消息的任務(wù)。

List_t xTasksWaitingToReceive: 等待接收列表,用于存儲等待從隊列接收消息的任務(wù)。

volatile UBaseType_t uxMessagesWaiting: 非空閑隊列項目的數(shù)量,用于記錄當(dāng)前隊列中等待接收的消息數(shù)量。

UBaseType_t uxLength: 隊列長度,表示隊列可以容納的最大項目數(shù)量。

UBaseType_t uxItemSize: 隊列項目的大小,表示每個項目占用的字節(jié)數(shù)。

volatile int8_t cRxLock: 讀取上鎖計數(shù)器,用于記錄當(dāng)前隊列被讀取操作鎖定的次數(shù)。

volatile int8_t cTxLock: 寫入上鎖計數(shù)器,用于記錄當(dāng)前隊列被寫入操作鎖定的次數(shù)。

2.結(jié)構(gòu)體示意圖

在這里插入圖片描述

三、隊列相關(guān)API函數(shù)介紹

使用隊列的主要流程:創(chuàng)建隊列 ->寫隊列 -> 讀隊列。主要包括創(chuàng)建隊列、寫隊列、讀隊列三個部分。

1.創(chuàng)建隊列

在這里插入圖片描述
參數(shù)說明:

uxQueueLength:隊列的長度,即隊列可以容納的最大項目數(shù)量。
uxItemSize:隊列中每個項目的大小,即每個項目占用的字節(jié)數(shù)。
返回值:

成功創(chuàng)建隊列時,返回一個有效的隊列句柄(QueueHandle_t)。
創(chuàng)建隊列失敗時,返回 NULL。
在這里插入圖片描述
示例用法:

#include "FreeRTOS.h"
#include "queue.h"// 創(chuàng)建一個長度為10,每個項目大小為4字節(jié)的隊列
QueueHandle_t xQueue = xQueueCreate(10, sizeof(int));
if (xQueue != NULL) {// 隊列創(chuàng)建成功
} else {// 隊列創(chuàng)建失敗
}

xQueueCreate() 函數(shù)用于在運(yùn)行時動態(tài)創(chuàng)建一個隊列,并返回一個隊列句柄,該句柄可用于后續(xù)對隊列進(jìn)行操作,如發(fā)送消息和接收消息。注意,在使用完隊列后,需要使用 vQueueDelete() 函數(shù)來刪除隊列,以釋放相關(guān)的資源。

2.寫消息入隊列

在這里插入圖片描述
寫消息到隊列里,只能往隊列頭部、隊列尾部、覆寫方式寫入隊列這三種方法,覆寫只有在隊列的隊列長度為 1 時,才能夠使用

(1)前三個函數(shù)

xQueueSend()、xQueueSendToBack() 和 xQueueSendToFront() 函數(shù)都是用于向隊列中寫入消息的函數(shù),它們的作用類似,但有一些細(xì)微的差別。

這些函數(shù)的函數(shù)原型如下:

BaseType_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait);BaseType_t xQueueSendToBack(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait);BaseType_t xQueueSendToFront(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait);

參數(shù)說明:
xQueue:要寫入的隊列的句柄。
pvItemToQueue:指向要寫入隊列的消息的指針。
xTicksToWait:寫入操作的超時時間,如果隊列已滿,則等待一段時間再嘗試寫入??梢允褂?portMAX_DELAY 來表示無限等待。

返回值:
如果成功寫入消息到隊列,則返回 pdPASS。
如果寫入消息失敗(如隊列已滿),并且在指定的超時時間內(nèi)未能成功寫入,則返回 errQUEUE_FULL。

示例用法:

#include "FreeRTOS.h"
#include "queue.h"// 創(chuàng)建一個長度為10,每個項目大小為4字節(jié)的隊列
QueueHandle_t xQueue = xQueueCreate(10, sizeof(int));int message = 42;// 向隊列尾部寫入消息
if (xQueueSend(xQueue, &message, portMAX_DELAY) == pdPASS) {// 消息寫入成功
} else {// 消息寫入失敗
}// 向隊列尾部寫入消息(與 xQueueSend() 等效)
if (xQueueSendToBack(xQueue, &message, portMAX_DELAY) == pdPASS) {// 消息寫入成功
} else {// 消息寫入失敗
}// 向隊列頭部寫入消息
if (xQueueSendToFront(xQueue, &message, portMAX_DELAY) == pdPASS) {// 消息寫入成功
} else {// 消息寫入失敗
}

這些函數(shù)用于將消息寫入隊列中,xQueueSend() 和 xQueueSendToBack() 將消息寫入隊列的尾部,而 xQueueSendToFront() 將消息寫入隊列的頭部。如果隊列已滿,則寫入操作將會阻塞,直到隊列有可用空間或超時。

(2)后面的函數(shù)

xQueueOverwrite() 和 xQueueOverwriteFromISR() 函數(shù)用于覆寫隊列中的消息,僅適用于隊列長度為1的情況。

這些函數(shù)的函數(shù)原型如下:

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

參數(shù)說明:

xQueue:要操作的隊列的句柄。
pvItemToQueue:指向要寫入隊列的消息的指針。
pxHigherPriorityTaskWoken:一個指向 BaseType_t 類型變量的指針,用于指示是否有更高優(yōu)先級的任務(wù)需要喚醒。在 xQueueOverwriteFromISR() 中使用,可以設(shè)置為 NULL。
返回值:

如果成功覆寫隊列中的消息,則返回 pdPASS。
如果隊列為空或隊列長度不為1,則返回 errQUEUE_FULL。
示例用法:

#include "FreeRTOS.h"
#include "queue.h"// 創(chuàng)建一個長度為1,每個項目大小為4字節(jié)的隊列
QueueHandle_t xQueue = xQueueCreate(1, sizeof(int));int message = 42;// 覆寫隊列中的消息
if (xQueueOverwrite(xQueue, &message) == pdPASS) {// 消息覆寫成功
} else {// 消息覆寫失敗
}// 在中斷中覆寫隊列中的消息
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (xQueueOverwriteFromISR(xQueue, &message, &xHigherPriorityTaskWoken) == pdPASS) {// 消息覆寫成功
} else {// 消息覆寫失敗
}

xQueueOverwrite() 和 xQueueOverwriteFromISR() 函數(shù)用于覆寫隊列中的消息。在隊列長度為1的情況下,可以使用這些函數(shù)來覆蓋隊列中的現(xiàn)有消息,而不需要等待或創(chuàng)建新的消息。請注意,這些函數(shù)只適用于隊列長度為1的情況。

在中斷處理程序中使用 xQueueOverwriteFromISR() 函數(shù)時,需要將 pxHigherPriorityTaskWoken 參數(shù)設(shè)置為非空指針,并且根據(jù)實(shí)際情況判斷是否需要喚醒更高優(yōu)先級的任務(wù)。

3.從隊列中讀取消息

在這里插入圖片描述

xQueueReceive()
從隊列頭部讀取消息,并將消息從隊列中刪除。
如果隊列為空,任務(wù)將進(jìn)入阻塞狀態(tài),直到隊列中有消息可讀取。
返回pdPASS表示成功讀取到消息,返回errQUEUE_EMPTY表示隊列為空。

xQueuePeek()
從隊列頭部讀取消息,但不刪除消息。
如果隊列為空,任務(wù)將進(jìn)入阻塞狀態(tài),直到隊列中有消息可讀取。
返回pdPASS表示成功讀取到消息,返回errQUEUE_EMPTY表示隊列為空。

xQueueReceiveFromISR()
在中斷中從隊列頭部讀取消息,并將消息從隊列中刪除。
與xQueueReceive()函數(shù)類似,但是特別適用于在中斷服務(wù)例程(ISR)中使用。
返回pdPASS表示成功讀取到消息,返回errQUEUE_EMPTY表示隊列為空。

xQueuePeekFromISR()
在中斷中從隊列頭部讀取消息,但不刪除消息。
與xQueuePeek()函數(shù)類似,但是特別適用于在中斷服務(wù)例程(ISR)中使用。
返回pdPASS表示成功讀取到消息,返回errQUEUE_EMPTY表示隊列為空。

這些函數(shù)都是用于讀取隊列中的消息,并根據(jù)需要刪除消息或者保留消息。其中,xQueueReceiveFromISR()和xQueuePeekFromISR()函數(shù)專門用于在中斷服務(wù)例程中使用。這些函數(shù)將任務(wù)或中斷服務(wù)例程阻塞直到隊列中有消息可讀取。如果隊列為空,任務(wù)或中斷服務(wù)例程將進(jìn)入阻塞狀態(tài),直到隊列中有消息可讀取。返回值用于指示讀取操作是否成功。

代碼例子:

下面是一個簡單的示例代碼,展示了如何使用xQueueReceive()和xQueuePeek()函數(shù)從隊列中讀取消息:

#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"// 定義一個全局隊列
QueueHandle_t queue;// 任務(wù)函數(shù)1,向隊列中發(fā)送消息
void task1(void *pvParameters) {int msg = 100;while(1) {// 發(fā)送消息到隊列中xQueueSend(queue, &msg, 0);// 任務(wù)延時1秒vTaskDelay(pdMS_TO_TICKS(1000));}
}// 任務(wù)函數(shù)2,從隊列中讀取消息并刪除
void task2(void *pvParameters) {int receivedMsg;while(1) {// 從隊列中讀取并刪除消息if(xQueueReceive(queue, &receivedMsg, portMAX_DELAY) == pdPASS) {printf("Received message: %d\n", receivedMsg);}// 任務(wù)延時500毫秒vTaskDelay(pdMS_TO_TICKS(500));}
}int main() {// 創(chuàng)建隊列queue = xQueueCreate(5, sizeof(int));// 創(chuàng)建任務(wù)1xTaskCreate(task1, "Task 1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);// 創(chuàng)建任務(wù)2xTaskCreate(task2, "Task 2", configMINIMAL_STACK_SIZE, NULL, 2, NULL);// 啟動調(diào)度器vTaskStartScheduler();// 如果調(diào)度器啟動失敗,則打印錯誤信息printf("Failed to start FreeRTOS scheduler!\n");return 0;
}

在這個示例中,我們創(chuàng)建了一個全局隊列queue,然后創(chuàng)建了兩個任務(wù)task1和task2。task1任務(wù)通過xQueueSend()函數(shù)將消息發(fā)送到隊列中,而task2任務(wù)使用xQueueReceive()函數(shù)從隊列中讀取并刪除消息。每個任務(wù)都使用vTaskDelay()函數(shù)延時一定的時間,以模擬任務(wù)執(zhí)行的過程。

當(dāng)task2任務(wù)成功從隊列中讀取到消息時,將打印消息內(nèi)容。這里使用了portMAX_DELAY作為阻塞時間參數(shù),表示如果隊列為空,任務(wù)將一直阻塞,直到有消息可讀取。

這個示例展示了如何使用xQueueReceive()函數(shù)從隊列中讀取消息并刪除,以及如何使用xQueueSend()函數(shù)向隊列中發(fā)送消息。實(shí)際應(yīng)用中,可以根據(jù)需要在任務(wù)中使用這些函數(shù)來實(shí)現(xiàn)消息傳遞和同步。

四、隊列入隊和出隊操作實(shí)驗(yàn)

1.實(shí)驗(yàn)?zāi)繕?biāo)

在這里插入圖片描述
這次例程我會進(jìn)行一個非常細(xì)致的講解:

2.例程

①main.c

int main(void)
{HAL_Init();                                 /* 初始化HAL庫 */sys_stm32_clock_init(360, 25, 2, 8);        /* 設(shè)置時鐘,180Mhz */delay_init(180);                            /* 延時初始化 */usart_init(115200);                         /* 串口初始化為115200 */led_init();                                 /* 初始化LED */key_init();                                 /* 初始化按鍵 */sdram_init();                               /* SRAM初始化 */lcd_init();                                 /* 初始化LCD */my_mem_init(SRAMIN);                        /* 初始化內(nèi)部內(nèi)存池 */my_mem_init(SRAMEX);                        /* 初始化外部內(nèi)存池 */my_mem_init(SRAMCCM);                       /* 初始化CCM內(nèi)存池 */freertos_demo();
}

除了那些裸機(jī)也用到的函數(shù)外,還有這些內(nèi)存初始化設(shè)置:
sdram_init():用于初始化SRAM(靜態(tài)隨機(jī)存取存儲器)。SRAM是一種高速的存儲器,通常用于存儲數(shù)據(jù)、變量或者代碼。

my_mem_init(SRAMIN):用于初始化內(nèi)部內(nèi)存池。內(nèi)部內(nèi)存池是指在芯片內(nèi)部的一塊存儲空間,用于存儲數(shù)據(jù)、變量或者代碼。

my_mem_init(SRAMEX):用于初始化外部內(nèi)存池。外部內(nèi)存池是指連接在芯片外部的一塊存儲空間,通常是使用外部存儲器(如SDRAM、NOR Flash)擴(kuò)展的存儲器。

my_mem_init(SRAMCCM):用于初始化CCM(Core-Coupled Memory)內(nèi)存池。CCM內(nèi)存是一種與CPU核心緊密耦合的存儲器,它具有低延遲和高帶寬的特點(diǎn),適用于存儲關(guān)鍵數(shù)據(jù)和代碼。

最重要的當(dāng)然就是freertos_demo();函數(shù)了。

②freertos_demo();


/*** @brief       FreeRTOS例程入口函數(shù)* @param       無* @retval      無*/
void freertos_demo(void)
{    /* 隊列的創(chuàng)建 */key_queue = xQueueCreate( 2, sizeof(uint8_t) );if(key_queue != NULL){printf("key_queue隊列創(chuàng)建成功!!\r\n");}else printf("key_queue隊列創(chuàng)建失敗!!\r\n");big_date_queue = xQueueCreate( 1, sizeof(char *) );if(big_date_queue != NULL){printf("big_date_queue隊列創(chuàng)建成功!!\r\n");}else printf("big_date_queue隊列創(chuàng)建失敗!!\r\n");xTaskCreate((TaskFunction_t         )   start_task,(char *                 )   "start_task",(configSTACK_DEPTH_TYPE )   START_TASK_STACK_SIZE,(void *                 )   NULL,(UBaseType_t            )   START_TASK_PRIO,(TaskHandle_t *         )   &start_task_handler );vTaskStartScheduler();
}

這是一個名為freertos_demo()的函數(shù),用于演示FreeRTOS中隊列的創(chuàng)建和任務(wù)的創(chuàng)建與調(diào)度。

key_queue = xQueueCreate(2, sizeof(uint8_t)):創(chuàng)建一個容量為2,元素大小為uint8_t的隊列,用于存儲按鍵值。如果隊列創(chuàng)建成功,會打印"key_queue隊列創(chuàng)建成功!!“,否則打印"key_queue隊列創(chuàng)建失敗!!”。

big_date_queue = xQueueCreate(1, sizeof(char *)):創(chuàng)建一個容量為1,元素大小為char指針的隊列,用于存儲大數(shù)據(jù)塊。如果隊列創(chuàng)建成功,會打印"big_date_queue隊列創(chuàng)建成功!!“,否則打印"big_date_queue隊列創(chuàng)建失敗!!”.

xTaskCreate(start_task, “start_task”, START_TASK_STACK_SIZE, NULL, START_TASK_PRIO, &start_task_handler):創(chuàng)建一個名為"start_task"的任務(wù),使用start_task()函數(shù)作為任務(wù)函數(shù)。該任務(wù)的堆棧大小為START_TASK_STACK_SIZE,優(yōu)先級為START_TASK_PRIO。任務(wù)句柄start_task_handler用于后續(xù)操作。
vTaskStartScheduler():啟動FreeRTOS調(diào)度器,開始執(zhí)行任務(wù)。

③操作隊列和存儲大數(shù)據(jù)塊

QueueHandle_t key_queue;        /* 小數(shù)據(jù)句柄 */
QueueHandle_t big_date_queue;   /* 大數(shù)據(jù)句柄 */
char buff[100] = {"我是一個大數(shù)組,大大的數(shù)組 124214 uhsidhaksjhdklsadhsaklj"};

key_queue和big_date_queue是隊列的句柄(或稱為隊列的指針),用于在程序中引用這兩個隊列。key_queue是一個指向小數(shù)據(jù)隊列的句柄,big_date_queue是一個指向大數(shù)據(jù)隊列的句柄。

另外,還定義了一個名為buff的字符數(shù)組,長度為100,用于存儲大數(shù)據(jù)塊。該數(shù)組中包含了一個字符串,表示一個大數(shù)據(jù)塊的內(nèi)容。

④任務(wù)一:實(shí)現(xiàn)入隊

在這里插入圖片描述

/* 任務(wù)一,實(shí)現(xiàn)入隊 */
void task1( void * pvParameters )
{uint8_t key = 0;char * buf;BaseType_t   err = 0;buf = &buff[0]; /* buf = &buff[0] */while(1) {key = key_scan(0);if(key == KEY0_PRES || key == KEY1_PRES){err = xQueueSend( key_queue, &key, portMAX_DELAY );if(err != pdTRUE){printf("key_queue隊列發(fā)送失敗\r\n");}}else if(key == WKUP_PRES){err = xQueueSend( big_date_queue, &buf, portMAX_DELAY );if(err != pdTRUE){printf("key_queue隊列發(fā)送失敗\r\n");}}vTaskDelay(10);}
}

在任務(wù)函數(shù)開始時,定義了一個key變量和一個buf指針變量。buf指針指向了之前提到的buff數(shù)組的第一個元素。

在任務(wù)的主循環(huán)中,首先調(diào)用key_scan(0)函數(shù)來獲取按鍵值,并將其賦值給key變量。然后通過條件判斷,判斷按鍵值是否為KEY0_PRES或KEY1_PRES,如果是,則將key值發(fā)送到key_queue隊列中,使用xQueueSend()函數(shù)來實(shí)現(xiàn)。如果發(fā)送失敗,則打印"key_queue隊列發(fā)送失敗"。

另外,如果按鍵值為WKUP_PRES,則將buf指針發(fā)送到big_date_queue隊列中,同樣使用xQueueSend()函數(shù)來實(shí)現(xiàn)。如果發(fā)送失敗,則打印"key_queue隊列發(fā)送失敗"。

最后,通過vTaskDelay(10)函數(shù)來延時10個系統(tǒng)時鐘周期,然后繼續(xù)下一次循環(huán)。

這個任務(wù)函數(shù)的功能是根據(jù)按鍵值將數(shù)據(jù)發(fā)送到不同的隊列中,實(shí)現(xiàn)了數(shù)據(jù)入隊的操作。

⑤任務(wù)二:小數(shù)據(jù)出隊

在這里插入圖片描述


/* 任務(wù)二,小數(shù)據(jù)出隊 */
void task2( void * pvParameters )
{uint8_t key = 0;BaseType_t err = 0;while(1){err = xQueueReceive( key_queue,&key,portMAX_DELAY);if(err != pdTRUE){printf("key_queue隊列讀取失敗\r\n");}else {printf("key_queue讀取隊列成功,數(shù)據(jù):%d\r\n",key);}}
}

在任務(wù)函數(shù)開始時,定義了一個key變量和一個err變量。

在任務(wù)的主循環(huán)中,調(diào)用xQueueReceive()函數(shù)從key_queue隊列中接收數(shù)據(jù),并將接收到的數(shù)據(jù)保存在key變量中。使用portMAX_DELAY作為阻塞時間,表示如果隊列為空,任務(wù)將一直阻塞直到有數(shù)據(jù)可用。

接收數(shù)據(jù)后,通過條件判斷,判斷數(shù)據(jù)接收是否成功。如果接收失敗,則打印"key_queue隊列讀取失敗"。如果接收成功,則打印"key_queue讀取隊列成功,數(shù)據(jù):"并打印出接收到的key值。

這個任務(wù)函數(shù)的功能是從key_queue隊列中接收數(shù)據(jù)并進(jìn)行處理

⑥任務(wù)三:大數(shù)據(jù)出隊

在這里插入圖片描述

/* 任務(wù)三,大數(shù)據(jù)出隊 */
void task3( void * pvParameters )
{char * buf;BaseType_t err = 0;while(1){err = xQueueReceive( big_date_queue,&buf,portMAX_DELAY);if(err != pdTRUE){printf("big_date_queue隊列讀取失敗\r\n");}else {printf("數(shù)據(jù):%s\r\n",buf);}}
}

根據(jù)你提供的代碼,這是一個名為task3()的任務(wù)函數(shù),用于實(shí)現(xiàn)大數(shù)據(jù)出隊操作。

在任務(wù)函數(shù)開始時,定義了一個buf指針變量和一個err變量。

在任務(wù)的主循環(huán)中,調(diào)用xQueueReceive()函數(shù)從big_date_queue隊列中接收數(shù)據(jù),并將接收到的數(shù)據(jù)保存在buf指針變量中。使用portMAX_DELAY作為阻塞時間,表示如果隊列為空,任務(wù)將一直阻塞直到有數(shù)據(jù)可用。

接收數(shù)據(jù)后,通過條件判斷,判斷數(shù)據(jù)接收是否成功。如果接收失敗,則打印"big_date_queue隊列讀取失敗"。如果接收成功,則打印"數(shù)據(jù):"并打印出接收到的字符串?dāng)?shù)據(jù)。

這個任務(wù)函數(shù)的功能是從big_date_queue隊列中接收大數(shù)據(jù)塊,并進(jìn)行處理。

3.例程運(yùn)行結(jié)果:

在這里插入圖片描述

五、隊列相關(guān)API函數(shù)解析

1.隊列的創(chuàng)建API函數(shù):xQueueCreate( )

xQueueCreate()函數(shù)是一個FreeRTOS中用于創(chuàng)建隊列的API函數(shù)。它的內(nèi)部實(shí)現(xiàn)過程如下:

首先,函數(shù)會檢查傳入的隊列長度和隊列元素大小是否合法。如果不合法,函數(shù)會返回NULL,表示隊列創(chuàng)建失敗。

接著,函數(shù)會為隊列分配內(nèi)存空間,包括隊列控制塊和隊列存儲區(qū)。隊列控制塊是一個結(jié)構(gòu)體,用于管理隊列的各種屬性和狀態(tài)信息;隊列存儲區(qū)是一個連續(xù)的內(nèi)存塊,用于存儲隊列中的元素。

然后,函數(shù)會初始化隊列控制塊的各個字段。例如,設(shè)置隊列的長度、元素大小、存儲區(qū)的起始地址等。

接下來,函數(shù)會初始化隊列的信號量,用于實(shí)現(xiàn)隊列的同步和互斥訪問。這個信號量用于控制任務(wù)對隊列的讀取和寫入操作,確保只有一個任務(wù)在訪問隊列的時候。

最后,函數(shù)會返回創(chuàng)建的隊列的指針。如果隊列創(chuàng)建失敗,函數(shù)將返回NULL。

需要注意的是,xQueueCreate()函數(shù)只是創(chuàng)建了隊列的數(shù)據(jù)結(jié)構(gòu),并沒有分配隊列存儲區(qū)的內(nèi)存空間。實(shí)際的內(nèi)存分配是在調(diào)用xQueueSend()和xQueueReceive()等函數(shù)時進(jìn)行的。這是因?yàn)殛犃械拇鎯^(qū)大小是根據(jù)隊列長度和元素大小動態(tài)計算的,所以需要在運(yùn)行時動態(tài)分配內(nèi)存空間。

2.往隊列寫入數(shù)據(jù)API函數(shù)(入隊):xQueueSend( )

xQueueSend()函數(shù)是一個FreeRTOS中用于往隊列寫入數(shù)據(jù)的API函數(shù),也被稱為入隊操作。它的內(nèi)部實(shí)現(xiàn)過程如下:

首先,函數(shù)會檢查傳入的隊列指針和待寫入的數(shù)據(jù)指針是否合法。如果隊列指針或數(shù)據(jù)指針為空,函數(shù)會返回一個錯誤碼,表示寫入操作失敗。

接著,函數(shù)會嘗試獲取隊列的信號量。這是為了確保只有一個任務(wù)在訪問隊列的時候,避免多個任務(wù)同時寫入隊列導(dǎo)致數(shù)據(jù)混亂。

如果成功獲取到隊列的信號量,函數(shù)會將待寫入的數(shù)據(jù)復(fù)制到隊列的存儲區(qū)中。具體的復(fù)制方式取決于隊列的類型。例如,如果是一個字節(jié)隊列,直接將數(shù)據(jù)復(fù)制到存儲區(qū)即可;如果是一個結(jié)構(gòu)體隊列,需要按照結(jié)構(gòu)體的大小逐個成員進(jìn)行復(fù)制。

寫入數(shù)據(jù)后,函數(shù)會更新隊列的相關(guān)屬性,例如隊列中的元素數(shù)量、讀取和寫入指針等。

最后,函數(shù)會釋放隊列的信號量,表示寫入操作完成。

需要注意的是,xQueueSend()函數(shù)在寫入數(shù)據(jù)時,有兩種寫入模式可以選擇:阻塞模式和非阻塞模式。在阻塞模式下,如果隊列已滿,寫入操作將會阻塞當(dāng)前任務(wù),直到隊列有空閑位置可寫入;在非阻塞模式下,如果隊列已滿,寫入操作將會立即返回一個錯誤碼,表示寫入操作失敗。這種模式由函數(shù)調(diào)用時傳入的阻塞時間參數(shù)決定。

3.從隊列讀取數(shù)據(jù)API函數(shù)(出隊): xQueueReceive( )

xQueueReceive()函數(shù)是一個FreeRTOS中用于從隊列讀取數(shù)據(jù)的API函數(shù),也被稱為出隊操作。它的內(nèi)部實(shí)現(xiàn)過程如下:

首先,函數(shù)會檢查傳入的隊列指針和接收數(shù)據(jù)的指針是否合法。如果隊列指針或接收數(shù)據(jù)的指針為空,函數(shù)會返回一個錯誤碼,表示讀取操作失敗。

接著,函數(shù)會嘗試獲取隊列的信號量。這是為了確保只有一個任務(wù)在訪問隊列的時候,避免多個任務(wù)同時讀取隊列導(dǎo)致數(shù)據(jù)混亂。

如果成功獲取到隊列的信號量,函數(shù)會從隊列的存儲區(qū)中讀取數(shù)據(jù),并將讀取到的數(shù)據(jù)復(fù)制到接收數(shù)據(jù)的指針中。具體的復(fù)制方式取決于隊列的類型。例如,如果是一個字節(jié)隊列,直接從存儲區(qū)中讀取數(shù)據(jù)即可;如果是一個結(jié)構(gòu)體隊列,需要按照結(jié)構(gòu)體的大小逐個成員進(jìn)行復(fù)制。

讀取數(shù)據(jù)后,函數(shù)會更新隊列的相關(guān)屬性,例如隊列中的元素數(shù)量、讀取和寫入指針等。

最后,函數(shù)會釋放隊列的信號量,表示讀取操作完成。

需要注意的是,xQueueReceive()函數(shù)在讀取數(shù)據(jù)時,有兩種讀取模式可以選擇:阻塞模式和非阻塞模式。在阻塞模式下,如果隊列為空,讀取操作將會阻塞當(dāng)前任務(wù),直到隊列有數(shù)據(jù)可讀取;在非阻塞模式下,如果隊列為空,讀取操作將會立即返回一個錯誤碼,表示讀取操作失敗。這種模式由函數(shù)調(diào)用時傳入的阻塞時間參數(shù)決定。

http://m.aloenet.com.cn/news/33609.html

相關(guān)文章:

  • 介紹好的電影網(wǎng)站模板下載什么是seo關(guān)鍵詞
  • 網(wǎng)站建設(shè)目標(biāo)是什么意思需要優(yōu)化的網(wǎng)站有哪些?
  • 網(wǎng)站建設(shè)教程實(shí)訓(xùn)心得創(chuàng)建網(wǎng)站免費(fèi)注冊
  • 網(wǎng)站開發(fā)多少錢電子商務(wù)網(wǎng)站設(shè)計方案
  • 廣東一站式網(wǎng)站建設(shè)報價百度網(wǎng)址大全舊版安裝
  • 焦點(diǎn)網(wǎng)站設(shè)計seo交互論壇
  • 黨建專欄 文字說明 網(wǎng)站建設(shè)福州seo網(wǎng)站排名
  • 凡科建站是什么推廣如何做網(wǎng)上引流
  • web前端開發(fā)工程師面試自我介紹seo關(guān)鍵詞排名優(yōu)化如何
  • 網(wǎng)站建設(shè) 資質(zhì)榮譽(yù)互聯(lián)網(wǎng)推廣引流公司
  • 做百度網(wǎng)站圖片怎么做百度網(wǎng)站排名seo
  • 杭州網(wǎng)站推廣怎樣做長沙網(wǎng)站搭建關(guān)鍵詞排名
  • asp.net 網(wǎng)站壓縮b站推廣入口2023mmm無病毒
  • 上海浦東新區(qū)網(wǎng)站百度網(wǎng)址瀏覽大全
  • 做視頻直播網(wǎng)站需要多少資金百度官方電話號碼
  • 網(wǎng)站做cnzz流量統(tǒng)計關(guān)鍵詞優(yōu)化排名的步驟
  • 如何做網(wǎng)站數(shù)據(jù)分析網(wǎng)絡(luò)營銷包括
  • 門戶網(wǎng)站平臺建設(shè)情況網(wǎng)絡(luò)優(yōu)化seo
  • 如何手機(jī)創(chuàng)建網(wǎng)站百度收錄網(wǎng)站要多久
  • 東莞振安保安公司網(wǎng)絡(luò)推廣優(yōu)化seo
  • 株洲網(wǎng)站seo優(yōu)化價格鄭州高端網(wǎng)站建設(shè)哪家好
  • 公司網(wǎng)站seo優(yōu)化的線上營銷推廣方式
  • 騰訊云 wordpress教程視頻seo外鏈推廣
  • wordpress+技術(shù)類模板網(wǎng)站seo優(yōu)化有哪些方面
  • 在什么網(wǎng)站可以接活做梅州網(wǎng)絡(luò)推廣
  • 布料市場做哪個網(wǎng)站好代寫軟文
  • 動漫網(wǎng)站設(shè)計方案華為手機(jī)軟文范文300
  • 網(wǎng)站群如何做網(wǎng)站seo快速優(yōu)化軟件
  • 單位網(wǎng)站中文域名到期續(xù)費(fèi)seo的培訓(xùn)班
  • 梧州網(wǎng)站建設(shè)設(shè)計百度服務(wù)電話在線人工