日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

学习《FreeRTOS源码详解与应用开发》笔记

發(fā)布時(shí)間:2025/4/16 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 学习《FreeRTOS源码详解与应用开发》笔记 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1、注意:任務(wù)函數(shù)內(nèi)部定義局部變量的內(nèi)存大小不能大于此任務(wù)堆棧內(nèi)存的大小。

2、FreeRTOS定義任務(wù)優(yōu)先級(jí)時(shí),0優(yōu)先級(jí)(空閑中斷占用)和最高優(yōu)先級(jí)31級(jí)(定時(shí)器占用)不能用。

3、用start_task創(chuàng)建任務(wù)task1和task2時(shí),start_task只創(chuàng)建一次就行,不用多次創(chuàng)建,所以創(chuàng)建完start_task后,就可以把start_task任務(wù)刪除,用vTaskDelete()函數(shù)刪除,要?jiǎng)h除那個(gè)任務(wù),只需把那個(gè)函數(shù)的任務(wù)句柄放在vTaskDelete后面的括號(hào)里面即可,或者直接在括號(hào)里面用一個(gè)NULL也可以。

4、vTaskList()函數(shù)可查詢?nèi)蝿?wù)的名稱、任務(wù)運(yùn)行狀態(tài)(就緒態(tài)、運(yùn)行態(tài)、阻塞態(tài)和刪除態(tài)等)、優(yōu)先級(jí)、任務(wù)運(yùn)行后剩余的堆棧余量等,是一個(gè)重量級(jí)的函數(shù)。注意,當(dāng)定義一個(gè)數(shù)組變量去接收vTaskList()函數(shù)返回的指針值時(shí),這個(gè)數(shù)組變量緩存要大些,因?yàn)槿蝿?wù)多,占用堆棧內(nèi)存大。且這個(gè)數(shù)組變量最好定義成全局變量,如果定義成函數(shù)局部變量,那內(nèi)存是從定義這個(gè)數(shù)組變量的函數(shù)開始調(diào)用這個(gè)數(shù)組變量,就需要把這個(gè)任務(wù)函數(shù)的堆棧改大,否則程序會(huì)出錯(cuò)。

5、vTaskGetRunTimeStatus()函數(shù),這個(gè)函數(shù)可查詢當(dāng)前運(yùn)行的任務(wù)中哪個(gè)任務(wù)比較耗時(shí),可把這個(gè)任務(wù)拆分成小的任務(wù)。減小任務(wù)耗時(shí)。

6、時(shí)序要求嚴(yán)格的時(shí)鐘通信協(xié)議中,如在I2C、SPI正在讀取數(shù)據(jù),高優(yōu)先級(jí)的任務(wù)到來(lái)時(shí),高優(yōu)先級(jí)就搶占CPU,導(dǎo)致I2C或SPI無(wú)法讀取正確的數(shù)據(jù),可用臨界任務(wù)保護(hù)函數(shù),在I2C\SPI讀取數(shù)據(jù)時(shí),禁止高優(yōu)先級(jí)搶占CPU,使I2C和SPI讀到正確的數(shù)據(jù)。可調(diào)用taskENTER_CRITICAL()函數(shù)進(jìn)入任務(wù)保護(hù),調(diào)用taskEXIT_CRITICAL()函數(shù)退出任務(wù)保護(hù)。可進(jìn)行多次嵌套臨界段代碼保護(hù)。注意,在使用臨界區(qū)保護(hù)函數(shù)時(shí),要快進(jìn)快出,避免一些緊急的事件任務(wù)需要處理時(shí),臨界區(qū)保護(hù)的任務(wù)還未完成,那緊急任務(wù)事件得不到實(shí)時(shí)處理,會(huì)出現(xiàn)問(wèn)題的。如在電力系統(tǒng)和醫(yī)療急救中,緊急事件任務(wù)得不到處理,會(huì)出現(xiàn)大問(wèn)題。

7、函數(shù)askENTER_CRITCAL_FROM_ISR()和函數(shù)taskEXIT_CRITCAL_FROM_ISR()是中斷級(jí)臨界區(qū)代碼段保護(hù)函數(shù),用在中斷服務(wù)函數(shù)中,而且這個(gè)中斷的優(yōu)先級(jí)一定要低于configMAX_SYSCALL_INTERRUPT_PRIORITY(高于這個(gè)宏定義定義的中斷優(yōu)先級(jí),不可調(diào)用FreeRTOS系統(tǒng)的API)。

8、在使用taskENTER_CRITCAL_FROM_ISR()時(shí),先定義一個(gè)變量讀取這個(gè)函數(shù)返回的值,等退出臨界保護(hù)時(shí),把這個(gè)變量作為實(shí)參傳遞給taskEXIT_CRITCAL_FROM_ISR()來(lái)退出臨界保護(hù)。
用法如下:
uint32_t ?taskISR_Value;
taskENTER_CRITCAL_FROM_ISR();
被保護(hù)代碼段
taskEXIT_CRITCAL_FROM_ISR(taskISR_Value);

9、延時(shí)函數(shù):vTaskDelay()相對(duì)延時(shí)函數(shù)和vTaskDelayUntil()絕對(duì)延時(shí)函數(shù)。

10、隊(duì)列是用于任務(wù)與任務(wù)、任務(wù)與中斷之間的通信。可在任務(wù)與任務(wù)、任務(wù)與中斷之間傳遞信息,因此隊(duì)列也叫做消息隊(duì)列。隊(duì)列可存儲(chǔ)有限的、大小固定的數(shù)據(jù)項(xiàng)目。任務(wù)與任務(wù)、任務(wù)與中斷之間要交流的數(shù)據(jù)保存在隊(duì)列中,叫隊(duì)列項(xiàng)目。隊(duì)列能保存的最大數(shù)據(jù)項(xiàng)目數(shù)量叫隊(duì)列的長(zhǎng)度。創(chuàng)建隊(duì)列的時(shí)候需指定數(shù)據(jù)項(xiàng)目的大小和隊(duì)列的長(zhǎng)度。注:信號(hào)量也是依據(jù)隊(duì)列來(lái)實(shí)現(xiàn)的。

11、平時(shí)不用操作系統(tǒng)時(shí),用串口中斷接收一幀數(shù)據(jù),但不知道這幀數(shù)據(jù)什么時(shí)候到來(lái),通常我們會(huì)定義一個(gè)接收數(shù)據(jù)標(biāo)志的全局變量來(lái)確定一幀數(shù)據(jù)是否接收完成,在main函數(shù)里面不停輪詢判斷這個(gè)接收標(biāo)志位是否等于1,如果等于1,則確定接收到了新的幀數(shù)據(jù)并在main函數(shù)或其它子函數(shù)進(jìn)行數(shù)據(jù)處理,這種方式效率低且耗費(fèi)CPU。此時(shí)可用操作系統(tǒng)做信號(hào)量的任務(wù)同步,當(dāng)串口中斷服務(wù)函數(shù)/定時(shí)器確定接收到一幀數(shù)據(jù),可發(fā)出一個(gè)信號(hào)量。在程序應(yīng)用中創(chuàng)建一個(gè)任務(wù)去請(qǐng)求獲取接收串口中斷服務(wù)函數(shù)/定時(shí)器發(fā)出的信號(hào)量信息的信號(hào)量,當(dāng)這個(gè)信號(hào)量無(wú)效時(shí),任務(wù)會(huì)進(jìn)入阻塞態(tài),把CPU讓給其他任務(wù)去執(zhí)行;當(dāng)信號(hào)量有效時(shí),這個(gè)任務(wù)接著執(zhí)行處理串口接收到的數(shù)據(jù)。這個(gè)信號(hào)量可實(shí)現(xiàn)任務(wù)與任務(wù)之間的同步,也可實(shí)現(xiàn)中斷(串口中斷/定時(shí)器中斷/外部中斷等)和任務(wù)之間的同步。


12、二值信號(hào)量適合用于同步,如任務(wù)與任務(wù)之間的同步,任務(wù)和中斷之間的同步。互斥信號(hào)量適合用于簡(jiǎn)單的互斥訪問(wèn)。

13、在使用二值信號(hào)量時(shí),會(huì)產(chǎn)生任務(wù)優(yōu)先級(jí)翻轉(zhuǎn)。解決任務(wù)優(yōu)先級(jí)翻轉(zhuǎn)可以使用互斥信號(hào)量。

14、互斥信號(hào)量使用的API操作函數(shù)和二值信號(hào)量使用的API操作函數(shù)是相同的。所以互斥信號(hào)量也可設(shè)置阻塞時(shí)間,與二值信號(hào)量不同的是,互斥信號(hào)量具有優(yōu)先級(jí)繼承的特性。當(dāng)一個(gè)互斥信號(hào)量正在被一個(gè)低優(yōu)先級(jí)的任務(wù)使用,而此時(shí)有個(gè)高優(yōu)先級(jí)的任務(wù)也嘗試獲取這個(gè)互斥信號(hào)量的話就會(huì)被阻塞。不過(guò)這個(gè)高優(yōu)先級(jí)的任務(wù)會(huì)將低優(yōu)先級(jí)任務(wù)的優(yōu)先級(jí)提升到與自己相同的優(yōu)先級(jí),這個(gè)過(guò)程就是優(yōu)先級(jí)繼承。優(yōu)先級(jí)繼承盡可能地降低了高優(yōu)先級(jí)任務(wù)處于阻塞時(shí)間,并且將已經(jīng)出現(xiàn)的“優(yōu)先級(jí)翻轉(zhuǎn)”的影響降到最低。如,現(xiàn)有三個(gè)依次為低、中、高的三個(gè)任務(wù),中高優(yōu)先級(jí)任務(wù)處于就緒掛起態(tài),低優(yōu)先級(jí)任務(wù)在運(yùn)行,此時(shí)低優(yōu)先級(jí)任務(wù)想要訪問(wèn)共享資源,則需要獲取該資源的信號(hào)量。低優(yōu)先級(jí)任務(wù)獲取信號(hào)量后并開始訪問(wèn)共享資源,此時(shí),高優(yōu)先級(jí)任務(wù)開始運(yùn)行,也想訪問(wèn)低優(yōu)先級(jí)任務(wù)正在使用的共享資源,但是該共享資源的信號(hào)量還在被低優(yōu)先級(jí)任務(wù)占用著,高優(yōu)先級(jí)任務(wù)只能進(jìn)入掛起態(tài),默默的等待低優(yōu)先級(jí)任務(wù)釋放該共享資源的信號(hào)量。就在高優(yōu)先級(jí)任務(wù)默默等待看著低優(yōu)先級(jí)任務(wù)什么時(shí)候釋放共享資源的信號(hào)量時(shí),中優(yōu)先級(jí)任務(wù)等待的事件發(fā)生后,中級(jí)優(yōu)先級(jí)任務(wù)也開始運(yùn)行了,由于中優(yōu)先級(jí)任務(wù)的優(yōu)先級(jí)高于低優(yōu)先級(jí)任務(wù)的優(yōu)先級(jí),所以就搶占了CPU的使用權(quán)。一直等到中優(yōu)先級(jí)任務(wù)把自己的事件處理完成后,才把CPU使用權(quán)給低優(yōu)先級(jí)任務(wù),低優(yōu)先級(jí)任務(wù)繼續(xù)使用CPU去訪問(wèn)共享資源,待低優(yōu)先級(jí)任務(wù)訪問(wèn)共享資源完成了,低優(yōu)先級(jí)任務(wù)釋放共享資源的信號(hào)量,最后高優(yōu)先級(jí)任務(wù)才獲取低優(yōu)先級(jí)任務(wù)釋放的信號(hào)量去訪問(wèn)共享資源。這種現(xiàn)象看起來(lái)就是中優(yōu)先級(jí)任務(wù)的優(yōu)先級(jí)要比高優(yōu)先級(jí)任務(wù)的優(yōu)先級(jí)高。此時(shí)高優(yōu)先級(jí)任務(wù)可以使用互斥信號(hào)量,把低優(yōu)先級(jí)任務(wù)的優(yōu)先級(jí)提高到與自己優(yōu)先級(jí)一樣,在低優(yōu)先級(jí)在使用信號(hào)量時(shí),高優(yōu)先級(jí)任務(wù)進(jìn)入掛起態(tài),中優(yōu)先級(jí)任務(wù)事件發(fā)生后想要獲取CPU的使用權(quán),但由于高優(yōu)先級(jí)任務(wù)把低優(yōu)先級(jí)任務(wù)的優(yōu)先級(jí)提高了,中優(yōu)先級(jí)任務(wù)只好等待這兩個(gè)高優(yōu)先級(jí)任務(wù)運(yùn)行完后,才可獲得CPU使用權(quán)。而原先的高優(yōu)先級(jí)任務(wù)等到原低優(yōu)先級(jí)任務(wù)釋放信號(hào)量以后,就可以獲取信號(hào)量去訪問(wèn)原低優(yōu)先級(jí)任務(wù)訪問(wèn)的共享資源。

15、互斥信號(hào)量不能用于中斷服務(wù)器中。原因有兩個(gè):一、互斥信號(hào)量有優(yōu)先級(jí)繼承機(jī)制,只能應(yīng)用在任務(wù)中,不能用于中斷服務(wù)函數(shù)。二、中斷服務(wù)函數(shù)中不能因?yàn)橐却コ庑盘?hào)量二設(shè)置阻塞時(shí)間進(jìn)入阻塞態(tài)。

16、遞歸信號(hào)量與互斥信號(hào)量一樣,不能用在中服務(wù)函數(shù)中。

17、創(chuàng)建的軟件定時(shí)器是休眠狀態(tài)的,要調(diào)用開啟軟件定時(shí)器的函數(shù)開啟定時(shí)器。

18、任務(wù)通知可完成消息隊(duì)列、信號(hào)量、事件標(biāo)志組的功能,不過(guò)任務(wù)通知是只能實(shí)現(xiàn)一對(duì)一的,也就是一個(gè)任務(wù)對(duì)一個(gè)任務(wù)。

19、接收任務(wù)可以因?yàn)榻邮杖蝿?wù)通知而進(jìn)入阻塞態(tài),但是發(fā)送任務(wù)不會(huì)因?yàn)槿蝿?wù)通知發(fā)送失敗而阻塞。但是隊(duì)列就有入隊(duì)阻塞和出對(duì)阻塞,信號(hào)量是根據(jù)隊(duì)列來(lái)實(shí)現(xiàn)的,信號(hào)量也會(huì)出現(xiàn)跟隊(duì)列一樣的情況。

20、雖然任務(wù)通知可以模擬二值信號(hào)量,但任務(wù)通知不能用在資源管理上,只有二值信號(hào)量能用。

21、降低系統(tǒng)主頻可以降低CPU的功耗。

22、內(nèi)存管理,heap1特點(diǎn)如下:
(1)適用于那些一旦創(chuàng)建好任務(wù)、信號(hào)量和隊(duì)列就再也不會(huì)刪除的應(yīng)用,實(shí)際上大多數(shù)的FreeRTOS 應(yīng)用都是這樣的。
(2)具有可確定性(執(zhí)行所花費(fèi)的時(shí)間大多數(shù)都是一樣的),而且不會(huì)導(dǎo)致內(nèi)存碎片。
(3)代碼實(shí)現(xiàn)和內(nèi)存分配過(guò)程都非常簡(jiǎn)單,內(nèi)存是從一個(gè)靜態(tài)數(shù)組中分配到的,也就是適合于那些不需要?jiǎng)討B(tài)內(nèi)存分配的應(yīng)用。

22、內(nèi)存管理,heap2能申請(qǐng)內(nèi)存特點(diǎn)如下:
(1)可以使用在那些可能會(huì)重復(fù)的刪除任務(wù)、隊(duì)列、信號(hào)量等的應(yīng)用中,要注意有內(nèi)存碎片產(chǎn)生!
(2)如果分配和釋放的內(nèi)存 n 大小是隨機(jī)的,那么就要慎重使用了,比如下面的示例:

=》如果一個(gè)應(yīng)用動(dòng)態(tài)的創(chuàng)建和刪除任務(wù),而且任務(wù)需要分配的堆棧大小都是一樣的,那么 heap_2 就非常合適。如果任務(wù)所需的堆棧大小每次都是不同,那么 heap_2 就不適合了,因?yàn)檫@樣會(huì)導(dǎo)致內(nèi)存碎片產(chǎn)生,最終導(dǎo)致任務(wù)分配不到合適的堆棧!不過(guò) heap_4 就很適合這種場(chǎng)景了。

=》如果一個(gè)應(yīng)用中所使用的隊(duì)列存儲(chǔ)區(qū)域每次都不同,那么 heap_2 就不適合了,和上面一樣,此時(shí)可以使用 heap_4。
=》應(yīng)用需要調(diào)用 pvPortMalloc()和 pvPortFree()來(lái)申請(qǐng)和釋放內(nèi)存,而不是通過(guò)其他FreeRTOS 的其他 API 函數(shù)來(lái)間接的調(diào)用,這種情況下 heap_2 不適合。
(3)如果應(yīng)用中的任務(wù)、隊(duì)列、信號(hào)量和互斥信號(hào)量具有不可預(yù)料性(如所需的內(nèi)存大小不能確定,每次所需的內(nèi)存都不相同,? 或者說(shuō)大多數(shù)情況下所需的內(nèi)存都是不同的)的話可能會(huì)導(dǎo)致內(nèi)存碎片。雖然這是小概率事件,但是還是要引起我們的注意!
(4)具有不可確定性,但是也遠(yuǎn)比標(biāo)準(zhǔn) C 中的 mallo()和 free()效率高!heap_2 基本上可以適用于大多數(shù)的需要?jiǎng)討B(tài)分配內(nèi)的工程中,而 heap_4 更是具有將內(nèi)存碎片合并成一個(gè)大的空閑內(nèi)存塊(就是內(nèi)存碎片回收)的功能。

23、內(nèi)存管理,heap3內(nèi)存分配方法是對(duì)標(biāo)準(zhǔn)C中的函數(shù)malloc()和free()的簡(jiǎn)單封裝,FreeRTOS對(duì)這兩函數(shù)做了線程保護(hù)。特點(diǎn)如下:

(1)需要編譯器提供一個(gè)內(nèi)存堆,編譯器庫(kù)要提供 malloc()和 free()函數(shù)。若使用STM32的話可以通過(guò)修改啟動(dòng)文件中的Heap_Size 來(lái)修改內(nèi)存堆的大小。
(2)具有不確定性。
(3)可能會(huì)增加代碼量。

24、內(nèi)存管理,heap4提供了一個(gè)最優(yōu)的匹配算法,不像heap2,heap4會(huì)將內(nèi)存碎片合成一個(gè)大的可用內(nèi)存塊。它提供了內(nèi)存合并算法。
特點(diǎn)如下:
(1)可以用在那些需要重復(fù)創(chuàng)建和刪除任務(wù)、隊(duì)列、信號(hào)量和互斥信號(hào)量等的應(yīng)用中。
(2)不會(huì)像 heap_2 那樣產(chǎn)生嚴(yán)重的內(nèi)存碎片,即使分配的內(nèi)存大小是隨機(jī)的。
(3)具有不確定性,但是遠(yuǎn)比 C 標(biāo)準(zhǔn)庫(kù)中的 malloc()和 free()效率高。heap_4 非常適合于那些需要直接調(diào)用函數(shù)pvPortMalloc()和 vPortFree()來(lái)申請(qǐng)和釋放內(nèi)存的應(yīng)用,注意,我們移植 FreeRTOS 的時(shí)候就選擇的 heap_4!heap_4也使用鏈表結(jié)構(gòu)來(lái)管理空閑內(nèi)存塊,鏈表結(jié)構(gòu)體與 heap_2 一樣。 heap_4 也定義了兩個(gè)局部靜態(tài)變量 pxStart 和 pxEnd來(lái)表示鏈表頭和尾,其中 pxEnd是指向 BlockLink_t 的指針。


25、內(nèi)存管理,heap_5 基本上和 heap_4 一樣,只是 heap_5 支持內(nèi)存堆使用不連續(xù)的內(nèi)存塊。?heap_5 允許內(nèi)存堆跨越多個(gè)不連續(xù)的內(nèi)存段。比如 STM32 的內(nèi)部 RAM 可以作為內(nèi)存堆,但是 STM32 內(nèi)部 RAM 比較小,遇到那些需要大容量 RAM 的應(yīng)用就不行了,如音視頻處理。不過(guò) STM32 可以外接 SRAM 甚至大容量的 SDRAM,如果使用 heap_4 的話你就只能在內(nèi)部 RAM 和外部SRAM 或 SDRAM 之間二選一了,使用 heap_5 的話就不存在這個(gè)問(wèn)題,兩個(gè)都可以一起作為內(nèi)存堆來(lái)用。

26、用pvPortMalloc()申請(qǐng)內(nèi)存、pvPortFree()釋放內(nèi)存,也可查看內(nèi)存使用剩余量。可用一個(gè)指針變量如uint8_t buffer去接收申請(qǐng)到的內(nèi)存。釋放內(nèi)存以后需要將 buffer 設(shè)置為 NULL,函數(shù) pvPortFree()釋放內(nèi)存以后并不會(huì)將 buffer清零,此時(shí) buffer 還是上次申請(qǐng)到的內(nèi)存地址,如果此時(shí)再調(diào)用指針 buffer 的話你會(huì)發(fā)現(xiàn)還是可以使用的!感覺(jué)好像沒(méi)有釋放內(nèi)存,所以需要將 buffer 清零。內(nèi)存申請(qǐng)、內(nèi)存釋放、查看內(nèi)存使用剩余量如下:
uint8_t *buffer,times = 0;
uint32_t freemem;

申請(qǐng)內(nèi)存
buffer = pvPortMalloc(20); //申請(qǐng)內(nèi)存,20個(gè)字節(jié)?
printf("申請(qǐng)到的內(nèi)存地址為:%#x\r\n",(int)buffer);

釋放內(nèi)存
if(buffer!=NULL){
? ?vPortFree(buffer); //釋放內(nèi)存
}
buffer = NULL;

使用內(nèi)存
if(buffer!=NULL) //buffer 可用,使用 buffer (5)
{
? ?times++;
? ?sprintf((char*)buffer,"User %d Times",times);//向buffer中填寫一些數(shù)據(jù)
? ?printf("%s\r\n",buffer); ? ? ? ? ? ? ? ? ? ? //把剛剛寫進(jìn)去的數(shù)據(jù)打印出來(lái)
}

查看內(nèi)存剩余大小
freemem = xPortGetFreeHeapSize(); //獲取剩余內(nèi)存大小
注意:我們申請(qǐng)20字節(jié)的內(nèi)存大小,但實(shí)際申請(qǐng)到的內(nèi)存大小要比20字節(jié)大,為什么會(huì)這樣?因?yàn)樵谏暾?qǐng)內(nèi)存的時(shí)候,會(huì)自動(dòng)進(jìn)行內(nèi)存堆的開始地址對(duì)齊,申請(qǐng)的內(nèi)存地址也需要進(jìn)行字節(jié)對(duì)齊。所以我們申請(qǐng)的是20字節(jié),但是經(jīng)過(guò)字節(jié)對(duì)齊后計(jì)算,實(shí)際會(huì)分配大于20字節(jié)的內(nèi)存給我們。
?

?

?

?

總結(jié)

以上是生活随笔為你收集整理的学习《FreeRTOS源码详解与应用开发》笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。