使用freertos如何確定分配堆棧空間大小

運行freertos系統的大部分都是資源有限的MCU,所以對於ram我們都要考慮儘量的節省,避免資源浪費,從而也可以針對項目選擇性價比更好的mcu。

首先要配置freertos的堆(heap)空間,創建任務我們還需要爲每個任務分配棧(stack)空間,那麼針對freertos的堆棧空間到底該如何確定?

freertos從V9版本以後同時支持靜態內存和動態內存分配方式。靜態內存分配在編譯時候就會對freertos的內核對象分配ram空間。動態分配都是在程序運行起來以後從堆空間上分配的。這裏我們也只討論動態內存分配,動態內存分配的好處是可以在刪除對象的時候釋放掉內存的空間。從而保證ram的可持續利用!

先看下圖弄清楚freertos的heap空間和任務棧空間的不同與聯繫。

使用freertos如何確定分配堆棧空間大小

假設在freertos的配置選項中已經配置使用動態內存分配方式。如上圖所示,其他比如任務或者隊列或者用戶使用 pvPortMalloc() 分配的空間都從heap堆上面劃分。所以我相信你不會做把任務棧分配的比heap堆還大的傻事!

好了,這個關係搞清楚,那麼又該如何定heap的空間大小呢,可以先進行一個粗略的計算,假設任務1分配2kbytes棧,任務2分配3kbytes棧,隊列大概佔1k,用戶malloc大概2k,這麼算一共就是8k。那麼在資源有限的情況下可以先把heap空間分個15k。

因爲程序運行起來實際佔用heap的空間不好計算那麼準,那麼我們可以藉助freertos的API來準確的得出空閒的heap空間和用的最對時候的空閒值。這兩個API如下:

xPortGetFreeHeapSize()

這個函數可以獲取調用時堆中空閒內存的大小,以字節爲單位。使用它可以優化堆的大小。需要注意,當使用heap_3時是不能調用這個函數的。

xPortGetMinimumEverFreeHeapSize()

此函數返回FreeRTOS應用程序開始運行之後曾經存在的最小的未被分配的存儲空間的字節數。它的返回值指示了應用程序離將要耗盡堆空間的接近程度。需要注意xPortGetMinimumEverFreeHeapSize()只在使用heap_4或者heap_5時生效。

在隨便一個任務運行過程中,我們可以把這兩個函數的返回值打印出來,比如分別爲4200和3000,那麼我們就清晰的知道了heap在分配出去最多的時候還剩餘3000bytes空閒的,那麼我們就可以把heap空間優化減小3000bytes。但是實際過程中請大方一點,不要算的那麼死,給freertos留下一點喘息的的機會。

堆空間的大小還容易估算一點,但是任務棧空間具體佔用多少想計算出來可是複雜很多的。比如任務運行過程中函數調用的圧棧,局部變量等都存在任務的棧空間上,所以我們一開始也只能儘量分配個大一點的值,之後再來調整。那麼得出任務棧空間具體還有多少剩餘也是有API可以調用的:

uxTaskGetStackHighWaterMark()

但是該API使用是有配置開關的,在freertosConfig.h中把 INCLUDE_uxTaskGetStackHighWaterMark 配置爲1打開開關

比如我們在一個任務中如下調用:

printf(" the min free stack size is %d \r\n",(int32_t)uxTaskGetStackHighWaterMark(NULL));

就可以打印出來該任務自啓動起來最小剩餘棧空間大小。然後我們就可以計算出最大使用的大小,一般可以再乘以1.5左右作爲最終分配的值。需要注意的是該函數不像前面兩個返回的是bytes,而返回的以字爲單位,真實的bytes需要乘以4.

所以總體的原則就是:先分大再調小最終把它確定好。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章