這個是全網(wǎng)最詳細的STM32項目教學視頻。
第一篇在這里:
視頻在這里
V3:HAL庫開發(fā)、手把手教學下面功能:PID速度控制、PID循跡、PID跟隨、遙控、避障、PID角度控制、openmv視覺控制、電磁循跡、FreeRTOS、K210視覺智能車(更新中)、K230視覺智能車(更新中)、MSPM0G3507視覺智能車(更新中)
22.3-任務棧大小 和 系統(tǒng)可用堆
我們前面創(chuàng)建任務使用了任務棧的概念,那么我們新建任務的時候,設置多大的任務棧合適那?任務棧又是從哪里來的,那塊空間又如何獲得那?
實際開發(fā)中無法精準計算任務需要的任務棧大小,如果任務中有較大數(shù)組或者變量,一定要設置的比變量更大,如果沒有則可以先按照默認128字設置,然后任務編寫完成后加入uxTaskGetStackHighWaterMark 函數(shù)獲得任務堆棧的“高水位標記”(剩余未使用的堆??臻g的最小值),還要加入xPortGetFreeHeapSize函數(shù)獲得當前系統(tǒng)的可用堆內(nèi)存。
22.3.1-任務棧 和 系統(tǒng)可用堆 知識!!(重點掌握)
任務棧是 FreeRTOS 為每個任務分配的一塊獨立內(nèi)存,用于保存任務運行時的局部變量、函數(shù)調(diào)用上下文、中斷上下文等。將如下的幾個選項簡單的累加就可以得到一個粗略的棧大?。?/p>
1、函數(shù)
① 局部變量
② 函數(shù)形參 (針對函數(shù)嵌套)
③ 函數(shù)返回地址 (針對函數(shù)嵌套)
④ 函數(shù)內(nèi)部的狀態(tài)保存
2、任務切換
3、發(fā)生中斷
實際應用中將這些都加起來是一件非常麻煩的工作,上面這些棧空間加起來的總和只是棧的最小需求,實際分配的棧大小可以在最小棧需求的基礎上乘以一個安全系數(shù),一般取 1.5-2。
上面的計算是我們用戶可以確定的棧大小,項目應用中還存在無法確定的棧大小,比如調(diào)用printf函數(shù)就很難確定實際的棧消耗。又比如通過函數(shù)指針實現(xiàn)函數(shù)的間接調(diào)用,因為函數(shù)指針不是固定的指向一個函數(shù)進行調(diào)用,而是根據(jù)不同的程序設計可以指向不同的函數(shù),使得棧大小的計算變得比較麻煩。
另外還要注意一點,建議不要編寫遞歸代碼(函數(shù)直接或間接地調(diào)用自身),因為我們不知道遞歸的層數(shù),棧的大小也是不好確定的。
通過函數(shù)獲得任務 高水位 線 uxTaskGetStackHighWaterMark 【這里展示使用這個】
通過函數(shù)uxTaskGetStackHighWaterMark 用于獲得一個任務的高水位值,其原型定義如下:
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
如果要查詢?nèi)蝿兆约旱母咚恢?,將參?shù)xTask設置NULL即可。
諾要使用這個函數(shù),必須將參數(shù)宏INCLUDE_uxTaskGetStackHighWaterMark 必須為 1可以在Cubemx里設置。高水位值實際就是任務的??臻g最小可用剩余空間的大小,單位是字(word),這個值越小,表示任務的??臻g越容易溢出。
比如一個任務中增加下面代碼,可以輸出當前任務的棧高水位值
UBaseType_t stackHighWaterMark = uxTaskGetStackHighWaterMark(NULL);// 獲取當前任務的棧高水位值
printf("Stack High Water Mark: %u wordsn", (unsigned int)stackHighWaterMark);
通過函數(shù)分析任務資源vTaskGetRunTimeStats[這里不展開,后面單獨講解]
這個需要功能需要修改一個定時器,這里因為定時器都用完了所以暫時不演示這個功能,如果芯片定時器資源充足可以使用,但是項目開發(fā)完或者發(fā)布量產(chǎn)代碼要去掉這個相關功能。
vTaskGetRunTimeStats()
:適用于獲取任務的 CPU 占用時間 和 運行時間,對于性能調(diào)優(yōu)、任務優(yōu)化和分析系統(tǒng)資源消耗非常有幫助。
需要設置一個定時器,這個定時器的時間基準精度要高于系統(tǒng)時鐘節(jié)拍,達到系統(tǒng)時鐘節(jié)拍的10-20倍,這樣測量的任務信息才能準確。
此測試方法僅限用于調(diào)試,測試,實際發(fā)布項目代碼中不要使用,因為這種測試方式比較消耗資源,影響系統(tǒng)實時性。
FreeRTOS的系統(tǒng)內(nèi)核沒有對計數(shù)時間做出溢出保護,比如定時器周期為50us,最大支持計數(shù)時間是2^32*50us/3600s=59.6分鐘,運行時間超過59.6分鐘就將不準確了。
任務棧使用哪里的空間-如何查看當前系統(tǒng)的可用堆內(nèi)存
(FreeRTOS堆中可用的RAM總量)定義freeRTOS系統(tǒng)堆大小。
configTOTAL_HEAP_SIZE
設置了 FreeRTOS從芯片的RAM分配的堆內(nèi)存的總大小,這個堆內(nèi)存用于FreeRTOS所有動態(tài)內(nèi)存分配,具體將用于FreeRTOS的任務棧的分配,隊列、信號量等資源,內(nèi)存池或動態(tài)內(nèi)存分配。
FreeRTOS 提供了 xPortGetFreeHeapSize()
函數(shù)來監(jiān)控當前堆內(nèi)存的剩余空間。你可以在程序中定期調(diào)用該函數(shù),查看堆內(nèi)存的使用情況,以確保內(nèi)存不會耗盡。
size_t heapRemaining = xPortGetFreeHeapSize();
比如任務加入下面代碼
size_t freeHeapSize = xPortGetFreeHeapSize();// 獲取系統(tǒng)的可用堆空間
printf("Free Heap Size: %u bytesn", (unsigned int)freeHeapSize);