在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

FreeRTOS的消息隊列

汽車電子技術 ? 來源:物聯網IoT開發 ? 作者: 杰杰mcu ? 2023-02-14 09:56 ? 次閱讀

問題解答

曾經有人問我,FreeRTOS那么多API,到底怎么記住呢?

我想說,其實API不難記,就是有點難找,因為FreeRTOS的API很多都是帶參宏,所以跳來跳去的比較麻煩,而且注釋也很多,要找還真不是那么容易,不過也沒啥,一般都會有API手冊的,我就告訴大家一下:

FreeRTOS Kernel: Reference Manual

FreeRTOS內核:參考手冊,大家可以在官網下載,也能在后臺得到。

當然書本是英文的,如果英語像我這樣子不咋地的同學,可以用谷歌瀏覽器在官網直接看API手冊,直接翻譯一下就行了。傳送門:https://www.freertos.org/a00018.html

圖片

Reference Manual

圖片

FreeRTOS官網的API

FreeRTOS消息隊列

基于 FreeRTOS 的應用程序由一組獨立的任務構成——每個任務都是具有獨立權限的程序。這些獨立的任務之間的通訊與同步一般都是基于操作系統提供的IPC通訊機制,而FreeRTOS 中所有的通信與同步機制都是基于隊列實現的。

消息隊列是一種常用于任務間通信的數據結構,隊列可以在任務與任務間、中斷和任務間傳送信息,實現了任務接收來自其他任務或中斷的不固定長度的消息。任務能夠從隊列里面讀取消息,當隊列中的消息是空時,掛起讀取任務,用戶還可以指定掛起的任務時間;當隊列中有新消息時,掛起的讀取任務被喚醒并處理新消息,消息隊列是一種異步的通信方式。

隊列特性

1.數據存儲

隊列可以保存有限個具有確定長度的數據單元。隊列可以保存的最大單元數目被稱為隊列的“深度”。在隊列創建時需要設定其深度和每個單元的大小。

通常情況下,隊列被作為 FIFO(先進先出)緩沖區使用,即數據由隊列尾寫入,從隊列首讀出。當然,由隊列首寫入也是可能的。

往隊列寫入數據是通過字節拷貝把數據復制存儲到隊列中;從隊列讀出數據使得把隊列中的數據拷貝刪除。

2.讀阻塞

當某個任務試圖讀一個隊列時,其可以指定一個阻塞超時時間。在這段時間中,如果隊列為空,該任務將保持阻塞狀態以等待隊列數據有效。當其它任務或中斷服務例程往其等待的隊列中寫入了數據,該任務將自動由阻塞態轉移為就緒態。當等待的時間超過了指定的阻塞時間,即使隊列中尚無有效數據,任務也會自動從阻塞態轉移為就緒態。

由于隊列可以被多個任務讀取,所以對單個隊列而言,也可能有多個任務處于阻塞狀態以等待隊列數據有效。這種情況下,一旦隊列數據有效,只會有一個任務會被解除阻塞,這個任務就是所有等待任務中優先級最高的任務。而如果所有等待任務的優先級相同,那么被解除阻塞的任務將是等待最久的任務。

說些題外話,ucos中是具有廣播消息的,當有多個任務阻塞在隊列上,當發送消息的時候可以選擇廣播消息,那么這些阻塞的任務都能被解除阻塞。

3.寫阻塞

與讀阻塞想反,任務也可以在寫隊列時指定一個阻塞超時時間。這個時間是當被寫隊列已滿時,任務進入阻塞態以等待隊列空間有效的最長時間。

由于隊列可以被多個任務寫入,所以對單個隊列而言,也可能有多個任務處于阻塞狀態以等待隊列空間有效。這種情況下,一旦隊列空間有效,只會有一個任務會被解除阻塞,這個任務就是所有等待任務中優先級最高的任務。而如果所有等待任務的優先級相同,那么被解除阻塞的任務將是等待最久的任務。

消息隊列的工作流程

1.發送消息

任務或者中斷服務程序都可以給消息隊列發送消息,當發送消息時,如果隊列未滿或者允許覆蓋入隊, FreeRTOS 會將消息拷貝到消息隊列隊尾,否則,會根據用戶指定的阻塞超時時間進行阻塞,在這段時間中,如果隊列一直不允許入隊,該任務將保持阻塞狀態以等待隊列允許入隊。當其它任務從其等待的隊列中讀取入了數據(隊列未滿),該任務將自動由阻塞態轉為就緒態。當任務等待的時間超過了指定的阻塞時間,即使隊列中還不允許入隊,任務也會自動從阻塞態轉移為就緒態,此時發送消息的任務或者中斷程序會收到一個錯誤碼 errQUEUE_FULL。

發送緊急消息的過程與發送消息幾乎一樣,唯一的不同是,當發送緊急消息時,發送的位置是消息隊列隊頭而非隊尾,這樣,接收者就能夠優先接收到緊急消息,從而及時進行消息處理。

下面是消息隊列的發送API接口,函數中有FromISR則表明在中斷中使用的。

圖片

消息隊列入隊(發送)的API接口

1 /*-----------------------------------------------------------*/
 2 BaseType_t xQueueGenericSend( QueueHandle_t xQueue,        (1) 
 3                               const void * const pvItemToQueue,     (2)
 4                               TickType_t xTicksToWait,        (3)
 5                               const BaseType_t xCopyPosition )    (4)
 6 {
 7     BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired;
 8     TimeOut_t xTimeOut;
 9     Queue_t * const pxQueue = ( Queue_t * ) xQueue;
10 
11     /* 已刪除一些斷言操作 */
12 
13     for ( ;; ) {
14         taskENTER_CRITICAL();                    (5)
15         {
16             /* 隊列未滿 */
17             if ( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
18                  || ( xCopyPosition == queueOVERWRITE ) ) {    (6) 
19                 traceQUEUE_SEND( pxQueue );
20                 xYieldRequired =
21           prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); (7)
22 
23                 /* 已刪除使用隊列集部分代碼 */
24                 /* 如果有任務在等待獲取此消息隊列 */
25       if ( listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive))==pdFALSE){ (8)
26                     /* 將任務從阻塞中恢復 */
27             if ( xTaskRemoveFromEventList(
28                   &( pxQueue->xTasksWaitingToReceive ) )!=pdFALSE) { (9)
29                         /* 如果恢復的任務優先級比當前運行任務優先級還高,
30                         那么需要進行一次任務切換 */
31                         queueYIELD_IF_USING_PREEMPTION();    (10)
32                     } else {
33                         mtCOVERAGE_TEST_MARKER();
34                     }
35                 } else if ( xYieldRequired != pdFALSE ) {
36                     /* 如果沒有等待的任務,拷貝成功也需要任務切換 */
37                     queueYIELD_IF_USING_PREEMPTION();        (11)
38                 } else {
39                     mtCOVERAGE_TEST_MARKER();
40                 }
41 
42                 taskEXIT_CRITICAL();                (12)
43                 return pdPASS;
44             }
45             /* 隊列已滿 */
46             else {                        (13)
47                 if ( xTicksToWait == ( TickType_t ) 0 ) {
48                     /* 如果用戶不指定阻塞超時時間,退出 */
49                     taskEXIT_CRITICAL();            (14)
50                     traceQUEUE_SEND_FAILED( pxQueue );
51                     return errQUEUE_FULL;
52                 } else if ( xEntryTimeSet == pdFALSE ) {    
53                     /* 初始化阻塞超時結構體變量,初始化進入
54                 阻塞的時間xTickCount和溢出次數xNumOfOverflows */
55                     vTaskSetTimeOutState( &xTimeOut );        (15)
56                     xEntryTimeSet = pdTRUE;
57                 } else {
58                     mtCOVERAGE_TEST_MARKER();
59                 }
60             }
61         }
62         taskEXIT_CRITICAL();                    (16)
63         /* 掛起調度器 */
64         vTaskSuspendAll();
65         /* 隊列上鎖 */
66         prvLockQueue( pxQueue );
67 
68         /* 檢查超時時間是否已經過去了 */
69         if (xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait)==pdFALSE){ (17)
70             /* 如果隊列還是滿的 */
71             if ( prvIsQueueFull( pxQueue ) != pdFALSE ) {    (18)    
72                 traceBLOCKING_ON_QUEUE_SEND( pxQueue );    
73                 /* 將當前任務添加到隊列的等待發送列表中
74                    以及阻塞延時列表,延時時間為用戶指定的超時時間xTicksToWait */
75                 vTaskPlaceOnEventList(
76                    &( pxQueue->xTasksWaitingToSend ), xTicksToWait );(19)
77                 /* 隊列解鎖 */
78                 prvUnlockQueue( pxQueue );            (20)
79 
80                 /* 恢復調度器 */
81                 if ( xTaskResumeAll() == pdFALSE ) {
82                     portYIELD_WITHIN_API();
83                 }
84             } else {
85                 /* 隊列有空閑消息空間,允許入隊 */
86                 prvUnlockQueue( pxQueue );            (21)
87                 ( void ) xTaskResumeAll();
88             }
89         } else {
90             /* 超時時間已過,退出 */
91             prvUnlockQueue( pxQueue );                (22)
92             ( void ) xTaskResumeAll();
93 
94             traceQUEUE_SEND_FAILED( pxQueue );
95             return errQUEUE_FULL;
96         }
97     }
98 }
99 /*-----------------------------------------------------------*/

如果阻塞時間不為 0,任務會因為等待入隊而進入阻塞, 在將任務設置為阻塞的過程中, 系統不希望有其它任務和中斷操作這個隊列的 xTasksWaitingToReceive 列表和 xTasksWaitingToSend 列表,因為可能引起其它任務解除阻塞,這可能會發生優先級翻轉。比如任務 A 的優先級低于當前任務,但是在當前任務進入阻塞的過程中,任務 A 卻因為其它原因解除阻塞了,這顯然是要絕對禁止的。因此FreeRTOS 使用掛起調度器禁止其它任務操作隊列,因為掛起調度器意味著任務不能切換并且不準調用可能引起任務切換的 API 函數。但掛起調度器并不會禁止中斷,中斷服務函數仍然可以操作隊列阻塞列表,可能會解除任務阻塞、可能會進行上下文切換,這也是不允許的。于是,FreeRTOS解決辦法是不但掛起調度器,還要給隊列上鎖,禁止任何中斷來操作隊列。

下面來看看流程圖:

圖片

消息隊列發送流程

相比在任務中調用的發送函數,在中斷中調用的函數會更加簡單一些, 沒有任務阻塞操作。

函數 xQueueGenericSend中插入數據后, 會檢查等待接收鏈表是否有任務等待,如果有會恢復就緒。如果恢復的任務優先級比當前任務高, 則會觸發任務切換;但是在中斷中調用的這個函數的做法是返回一個參數標志是否需要觸發任務切換,并不在中斷中切換任務。

在任務中調用的函數中有鎖定和解鎖隊列的操作, 鎖定隊列的時候, 隊列的事件鏈表不能被修改。 而在被中斷中發送消息的處理是: 當遇到隊列被鎖定的時候, 將新數據插入到隊列后, 并不會直接恢復因為等待接收的任務, 而是累加了計數, 當隊列解鎖的時候, 會根據這個計數, 對應恢復幾個任務。

遇到隊列滿的情況, 函數會直接返回, 而不是阻塞等待, 因為在中斷中阻塞是不允許的!?。?/p>

1 BaseType_t xQueueGenericSendFromISR(
 2        QueueHandle_t xQueue,
 3        const void * const pvItemToQueue,
 4        /* 不在中斷函數中觸發任務切換, 而是返回一個標記 */
 5        BaseType_t * const pxHigherPriorityTaskWoken,
 6        const BaseType_t xCopyPosition )
 7{
 8    BaseType_t xReturn;
 9    UBaseType_t uxSavedInterruptStatus;
10    Queue_t * const pxQueue = ( Queue_t * ) xQueue;
11
12    uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
13    {
14        // 判斷隊列是否有空間插入新內容
15        if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
16        {
17            const int8_t cTxLock = pxQueue->cTxLock;
18
19            // 中斷中不能使用互斥鎖, 所以拷貝函數只是拷貝數據,
20            // 沒有任務優先級繼承需要考慮
21            ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
22
23            // 判斷隊列是否被鎖定
24            if( cTxLock == queueUNLOCKED )
25            {
26            #if ( configUSE_QUEUE_SETS == 1 )
27                // 集合相關代碼
28            #else /* configUSE_QUEUE_SETS */
29                {
30                    // 將最高優先級的等待任務恢復到就緒鏈表
31                    if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
32                    {
33                        if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE)
34                        {
35                            // 如果有高優先級的任務被恢復
36                            // 此處不直接觸發任務切換, 而是返回一個標記
37                            if( pxHigherPriorityTaskWoken != NULL )
38                            {
39                                *pxHigherPriorityTaskWoken = pdTRUE;
40                            }
41                        }
42                    }
43                }
44            #endif /* configUSE_QUEUE_SETS */
45            }
46            else
47            {
48                // 隊列被鎖定, 不能修改事件鏈表
49                // 增加計數, 記錄需要接觸幾個任務到就緒
50                // 在解鎖隊列的時候會根據這個計數恢復任務
51                pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 );
52            }
53            xReturn = pdPASS;
54        }
55        else
56        {
57            // 隊列滿 直接返回 不阻塞
58            xReturn = errQUEUE_FULL;
59        }
60    }
61
62    // 恢復中斷的優先級
63    portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
64
65    return xReturn;
66}

消息隊列讀取

圖片

消息讀取

任務調用接收函數收取隊列消息, 函數首先判斷當前隊列是否有未讀消息, 如果沒有, 則會判斷參數 xTicksToWait, 決定直接返回函數還是阻塞等待。

如果隊列中有消息未讀, 首先會把待讀的消息復制到傳進來的指針所指內, 然后判斷函數參數 xJustPeeking == pdFALSE的時候, 符合的話, 說明這個函數讀取了數據, 需要把被讀取的數據做出隊處理, 如果不是, 則只是查看一下(peek),只是返回數據,但是不會把數據清除。

對于正常讀取數據的操作, 清除數據后隊列會空出空位, 所以查看隊列中的等待列表中是否有任務等發送數據而被掛起, 有的話恢復一個任務就緒, 并根據優先級判斷是否需要出進行任務切換。

對于只是查看數據的, 由于沒有清除數據, 所以沒有空間新空出,不需要檢查發送等待鏈表, 但是會檢查接收等待鏈表, 如果有任務掛起會切換其到就緒并判斷是否需要切換。

消息隊列出隊過程分析,其實跟入隊差不多,請看注釋:

1 /*-----------------------------------------------------------*/
 2 BaseType_t xQueueGenericReceive( QueueHandle_t xQueue,        (1) 
 3                                  void * const pvBuffer,        (2)
 4                                  TickType_t xTicksToWait,    (3) 
 5                                  const BaseType_t xJustPeeking )    (4)
 6 {
 7     BaseType_t xEntryTimeSet = pdFALSE;
 8     TimeOut_t xTimeOut;
 9     int8_t *pcOriginalReadPosition;
10     Queue_t * const pxQueue = ( Queue_t * ) xQueue;
11 
12     /* 已刪除一些斷言 */
13     for ( ;; ) {
14         taskENTER_CRITICAL();                    (5)
15         {
16             const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; 
17 
18             /* 看看隊列中有沒有消息 */
19             if ( uxMessagesWaiting > ( UBaseType_t ) 0 ) {    (6) 
20                 /*防止僅僅是讀取消息,而不進行消息出隊操作*/
21                 pcOriginalReadPosition = pxQueue->u.pcReadFrom;    (7)
22                 /* 拷貝消息到用戶指定存放區域pvBuffer */
23                 prvCopyDataFromQueue( pxQueue, pvBuffer );    (8)
24 
25                 if ( xJustPeeking == pdFALSE ) {        (9)
26                     /* 讀取消息并且消息出隊 */
27                     traceQUEUE_RECEIVE( pxQueue );    
28 
29                     /* 獲取了消息,當前消息隊列的消息個數需要減一 */
30                     pxQueue->uxMessagesWaiting = uxMessagesWaiting - 1;  (10)
31                     /* 判斷一下消息隊列中是否有等待發送消息的任務 */
32                     if ( listLIST_IS_EMPTY(            (11)
33                              &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) {
34                         /* 將任務從阻塞中恢復 */
35                         if ( xTaskRemoveFromEventList(        (12)
36                                  &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) {
37                             /* 如果被恢復的任務優先級比當前任務高,會進行一次任務切換 */
38                             queueYIELD_IF_USING_PREEMPTION();    (13)
39                         } else {
40                             mtCOVERAGE_TEST_MARKER();
41                         }
42                     } else {
43                         mtCOVERAGE_TEST_MARKER();
44                     }
45                 } else {                    (14)
46                     /* 任務只是看一下消息(peek),并不出隊 */    
47                     traceQUEUE_PEEK( pxQueue );
48 
49                     /* 因為是只讀消息 所以還要還原讀消息位置指針 */
50                     pxQueue->u.pcReadFrom = pcOriginalReadPosition; (15)
51 
52                     /* 判斷一下消息隊列中是否還有等待獲取消息的任務 */
53                     if ( listLIST_IS_EMPTY(            (16)
54                              &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) {
55                         /* 將任務從阻塞中恢復 */
56                         if ( xTaskRemoveFromEventList(            
57                               &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) {
58                             /* 如果被恢復的任務優先級比當前任務高,會進行一次任務切換 */
59                             queueYIELD_IF_USING_PREEMPTION();    
60                         } else {
61                             mtCOVERAGE_TEST_MARKER();
62                         }
63                     } else {
64                         mtCOVERAGE_TEST_MARKER();
65                     }
66                 }
67 
68                 taskEXIT_CRITICAL();                (17)
69                 return pdPASS;
70             } else {                        (18)
71                 /* 消息隊列中沒有消息可讀 */
72                 if ( xTicksToWait == ( TickType_t ) 0 ) {    (19)    
73                     /* 不等待,直接返回 */
74                     taskEXIT_CRITICAL();
75                     traceQUEUE_RECEIVE_FAILED( pxQueue );
76                     return errQUEUE_EMPTY;
77                 } else if ( xEntryTimeSet == pdFALSE ) {        
78                     /* 初始化阻塞超時結構體變量,初始化進入
79                     阻塞的時間xTickCount和溢出次數xNumOfOverflows */
80                     vTaskSetTimeOutState( &xTimeOut );        (20)
81                     xEntryTimeSet = pdTRUE;
82                 } else {
83                     mtCOVERAGE_TEST_MARKER();
84                 }
85             }
86         }
87         taskEXIT_CRITICAL();                    
88 
89         vTaskSuspendAll();
90         prvLockQueue( pxQueue );                (21)
91 
92         /* 檢查超時時間是否已經過去了*/
93         if ( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) {(22)
94             /* 如果隊列還是空的 */
95             if ( prvIsQueueEmpty( pxQueue ) != pdFALSE ) {
96                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );    (23)    
97                 /* 將當前任務添加到隊列的等待接收列表中
98                    以及阻塞延時列表,阻塞時間為用戶指定的超時時間xTicksToWait */
99                 vTaskPlaceOnEventList(                
100                     &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
101                 prvUnlockQueue( pxQueue );
102                 if ( xTaskResumeAll() == pdFALSE ) {        
103                     /* 如果有任務優先級比當前任務高,會進行一次任務切換 */
104                     portYIELD_WITHIN_API();            
105                 } else {
106                     mtCOVERAGE_TEST_MARKER();
107                 }
108             } else {
109                 /* 如果隊列有消息了,就再試一次獲取消息 */
110                 prvUnlockQueue( pxQueue );            (24)
111                 ( void ) xTaskResumeAll();
112             }
113         } else {
114             /* 超時時間已過,退出 */
115             prvUnlockQueue( pxQueue );                (25)
116             ( void ) xTaskResumeAll();
117 
118             if ( prvIsQueueEmpty( pxQueue ) != pdFALSE ) {
119                 /* 如果隊列還是空的,返回錯誤代碼errQUEUE_EMPTY */
120                 traceQUEUE_RECEIVE_FAILED( pxQueue );
121                 return errQUEUE_EMPTY;                (26)
122             } else {
123                 mtCOVERAGE_TEST_MARKER();
124             }
125         }
126     }
127 }
128 /*-----------------------------------------------------------*/

提示

如果隊列存儲的數據較大時,那最好是利用隊列來傳遞數據的指針而不是數據本身,因為傳遞數據的時候是需要CPU一字節一字節地將數據拷貝進隊列或從隊列拷貝出來。而傳遞指針無論是在處理速度上還是內存空間利用上都更有效。但是,當利用隊列傳遞指針時,一定要十分小心地做到以下兩點:

1.指針指向的內存空間的所有權必須明確

當任務間通過指針共享內存時,應該從根本上保證所不會有任意兩個任務同時修改共享內存中的數據,或是以其它行為方式使得共享內存數據無效或產生一致性問題。原則上,共享內存在其指針發送到隊列之前,其內容只允許被發送任務訪問;共享內存指針從隊列中被讀出之后,其內容亦只允許被接收任務訪問。

2.指針指向的內存空間必須有效

如果指針指向的內存空間是動態分配的,只應該有一個任務負責對其進行內存釋放。當這段內存空間被釋放之后,就不應該有任何一個任務再訪問這段空間。

并且最最最重要的是禁止使用指針訪問任務棧上的空間,也就是局部變量。因為當棧發生改變后,棧上的數據將不再有效。

圖片

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 操作系統
    +關注

    關注

    37

    文章

    6822

    瀏覽量

    123331
  • FreeRTOS
    +關注

    關注

    12

    文章

    484

    瀏覽量

    62172
  • IPC
    IPC
    +關注

    關注

    3

    文章

    347

    瀏覽量

    51916
收藏 人收藏

    評論

    相關推薦

    Freertos隊列項里的字節長度是否可以獲?。?/a>

    最近剛學Freertos, 看到可以獲取Freertos隊列長度,但是隊列項里的字節長度是否可以獲取? 因為項目中隊列中會存放不定長字節,
    發表于 04-29 07:17

    轉:第20章 FreeRTOS消息隊列

    第20章FreeRTOS消息隊列 本章節為大家講解FreeRTOS的一個重要的通信機制----消息隊列,初學者要熟練掌握,因為消息隊列在實際
    發表于 09-04 14:41

    怎么把freeRTOS隊列模塊拿出來單獨使用

    為了彌補uCOSii消息隊列只能傳送指針的問題,請教一下freeRTOS隊列模塊怎么才能拿出來單獨使用,需要砍掉那部分內容才能運行?需要源代碼的留下郵箱。我的郵箱1277185193@qq.com
    發表于 07-14 08:00

    FreeRTOS隊列操作實驗接收的時候第一個字母容易接收到兩次的原因?

    FreeRTOS實驗13-1 FreeRTOS隊列操作實驗原子兄,這個實驗隊列接收的時候第一個字母容易接收到兩次,是什么原因?比如接收“hello”,會接收到“hhello”
    發表于 07-22 02:52

    freertos隊列使用全局變量會出現什么問題?

    freertos隊列章節中,看到如下內容:想搞明白使用全局變量會出現什么問題。串口接收到數據后,要存儲在一個數組中,這個數組不也是全局變量嗎?
    發表于 07-26 08:00

    FreeRTOS消息隊列有何作用

    FreeRTOS消息隊列 & ESP32實戰FreeRTOS消息隊列FreeRTOS的消息隊列
    發表于 01-27 06:53

    FreeRTOS消息隊列和RT-Thread消息隊列的使用注意事項介紹

    一、FreeRTOS消息隊列1.1 創建消息隊列xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, // 隊列
    發表于 05-25 15:32

    關于esp-idf的event是不是基于freeRTOS(隊列)二次開發的事件驅動?

    1.關于esp-idf的event是不是基于freeRTOS(隊列)二次開發的事件驅動?2.工程的主框架是否一般都是以下結構搭建的呢(main函數主要以init為主或者創建各種task呢
    發表于 02-16 08:20

    FreeRTOS隊列創建任務間通信的基本應用程序

    應用程序 : 此代碼是 FreeRTOS 隊列創建任務間通信的基本應用程序 。 BSP 版本: M480系列 BSP CMSIS V3.04.000 硬件: NuMaker-PFM-M487
    發表于 08-22 07:12

    FreeRTOS隊列創建任務間通信的基本應用程序

    應用程序 : 此代碼是 FreeRTOS 隊列創建任務間通信的基本應用程序 。 BSP 版本: M480系列 BSP CMSIS V3.04.000 硬件: NuMaker-PFM-M487
    發表于 08-30 07:56

    FreeRTOS消息隊列 & ESP32使用

    FreeRTOS消息隊列 & ESP32實戰FreeRTOS消息隊列FreeRTOS的消息隊列
    發表于 12-03 17:51 ?1次下載
    <b class='flag-5'>FreeRTOS</b>消息<b class='flag-5'>隊列</b> & ESP32使用

    FreeRTOS消息隊列 傳遞結構體指針和結構體異同

    FreeRTOS消息隊列 傳遞結構體指針和結構體異同
    發表于 12-08 12:06 ?6次下載
    <b class='flag-5'>FreeRTOS</b>消息<b class='flag-5'>隊列</b> 傳遞結構體指針和結構體異同

    FreeRTOS 隊列 信號量 互斥量

    文章目錄前言Queue 隊列semaphore 信號量Mutex 互斥量微信公眾號前言FreeRTOS STM32CubeMX配置 內存管理 任務管理上節介紹了用STM32CubeMX生成帶
    發表于 12-09 09:51 ?0次下載
    <b class='flag-5'>FreeRTOS</b> <b class='flag-5'>隊列</b> 信號量 互斥量

    FreeRTOS消息隊列介紹

    隊列是為了任務與任務、任務與中斷之間的通信而準備的,可以在任務與任務、任務與中斷之間傳遞消息,隊列中可以存儲有限的、大小固定的數據項目。任務與任務、任務與中斷之間要交流的數據保存在隊列中,叫做
    的頭像 發表于 07-06 16:58 ?809次閱讀
    <b class='flag-5'>FreeRTOS</b>消息<b class='flag-5'>隊列</b>介紹

    FreeRTOS消息隊列結構體

    有一個結構體用于描述隊列,叫做 Queue_t,這個結構體在文件 queue.c 中定義。 3、隊列創建 在使用隊列之前必須先創建隊列,有兩種創建
    的頭像 發表于 07-06 17:03 ?1106次閱讀
    <b class='flag-5'>FreeRTOS</b>消息<b class='flag-5'>隊列</b>結構體
    主站蜘蛛池模板: 欧美国产一区二区二区| 就去色综合| 日本污视频网站| 免费能看的黄色网址| 国产香港日本三级在线观看| www.黄色免费| 日本加勒比在线精品视频| 国产精品美女久久久| 亚洲综合一二三区| 一区二区三区伦理| 日本三级黄在线观看| 亚洲国产成人在人网站天堂| 日本最顶级丰满的aⅴ艳星| 久久久精品久久久久久久久久久| 成人网18免费下| 啪啪伊人网| 亚洲免费视频一区| 四虎在线精品| 狠狠色噜噜狠狠狠狠米奇7777| 午夜免费片在线观看不卡| haodiaose在线精品免费观看| 男女免费观看视频| 三级国产在线观看| 国产女人视频| 久久午夜免费视频| 婷婷激情久久| 日韩免费三级电影| 天天爽视频| 又色又爽视频| 色偷偷综合网| www天堂在线| 国产女在线| 天堂bt在线种子网| 国产精品视频第一区二区三区| 女女色综合影院| 亚洲国产成人在线| 夜夜狠操| 中文字幕亚洲一区二区v@在线 | 二区三区在线| 久久澡人人澡狠狠澡| www.av毛片|