太原seo網(wǎng)站排名網(wǎng)站優(yōu)化包括
資料來源于硬件家園:資料匯總 - FreeRTOS實時操作系統(tǒng)課程(多任務(wù)管理)
目錄
一、動態(tài)內(nèi)存管理介紹
1、heap_1
2、heap_2
3、heap_3
4、heap_4
5、heap_5
二、動態(tài)內(nèi)存總結(jié)與應(yīng)用
1、heap_1
2、heap_4
3、heap_5
三、內(nèi)存管理編程測試
1、heap_4
2、heap_1
3、heap_5
一、動態(tài)內(nèi)存管理介紹
動態(tài)內(nèi)存管理是 FreeRTOS 非常重要的一項功能,前面章節(jié)講解的任務(wù)創(chuàng)建、信號量、消息隊列、事件標(biāo)志組、互斥信號量、軟件定時器組等需要的 RAM 空間都是通過動態(tài)內(nèi)存管理從 FreeRTOSConfig.h 文件定義的 heap 空間中申請的。
FreeRTOS 支持 5 種動態(tài)內(nèi)存管理方案,分別通過文件 heap_1,heap_2,heap_3,heap_4 和 heap_5實現(xiàn)。
1、heap_1
heap_1 動態(tài)內(nèi)存管理方式是五種動態(tài)內(nèi)存管理方式中最簡單的,這種方式的動態(tài)內(nèi)存管理一旦申請了相應(yīng)內(nèi)存后,是不允許被釋放的。
盡管如此,這種方式的動態(tài)內(nèi)存管理還是滿足大部分嵌入式應(yīng)用的,因為這種嵌入式應(yīng)用在系統(tǒng)啟動階段就完成了任務(wù)創(chuàng)建、事件標(biāo)志組、信號量、消息隊列等資源的創(chuàng)建,而且這些資源是整個嵌入式應(yīng)用過程中一直要使用的,所以也就不需要刪除,不需要釋放內(nèi)存。
2、heap_2
與 heap_1 動態(tài)內(nèi)存管理方式不同,heap_2 動態(tài)內(nèi)存管理利用了最適應(yīng)算法,并且支持內(nèi)存釋放。但是 heap_2 不支持內(nèi)存碎片整理,動態(tài)內(nèi)存管理方式heap_4 支持內(nèi)存碎片整理。
3、heap_3
這種方式實現(xiàn)的動態(tài)內(nèi)存管理是對編譯器提供的 malloc 和 free 函數(shù)進行了封裝,保證是線程安全的。
4、heap_4
與 heap_2 動態(tài)內(nèi)存管理方式不同,heap_4 動態(tài)內(nèi)存管理利用了最適應(yīng)算法,且支持內(nèi)存碎片的回收并將其整理為一個大的內(nèi)存塊。
5、heap_5
有時候我們希望 FreeRTOSConfig.h 文件中定義的 heap 空間可以采用不連續(xù)的內(nèi)存區(qū),比如我們希望可以將其定義在內(nèi)部 SRAM 一部分,外部 SRAM 一部分,此時我們就可以采用 heap_5 動態(tài)內(nèi)存管理方式。另外,heap_5 動態(tài)內(nèi)存管理是在 heap_4 的基礎(chǔ)上實現(xiàn)的。
二、動態(tài)內(nèi)存總結(jié)與應(yīng)用
五種動態(tài)內(nèi)存管理方式簡單總結(jié)如下,實際項目中,用戶根據(jù)需要選擇合適的:
heap_1:五種方式里面最簡單的,但是申請的內(nèi)存不允許釋放
heap_2:支持動態(tài)內(nèi)存的申請和釋放,但是不支持內(nèi)存碎片的處理
heap_3:將編譯器自帶的 malloc 和 free 函數(shù)進行簡單的封裝
heap_4:支持動態(tài)內(nèi)存的申請和釋放,支持內(nèi)存碎片處理
heap_5:在 heap_4 的基礎(chǔ)上支持將動態(tài)內(nèi)存設(shè)置在不連續(xù)的區(qū)域上
1、heap_1
FreeRTOS 的動態(tài)內(nèi)存大小在 FreeRTOSConfig.h 文件中進行了定義:
#define configTOTAL_HEAP_SIZE??( ( size_t ) ( 17 * 1024 ) ) //單位字節(jié)
用戶通過函數(shù) xPortGetFreeHeapSize 就能獲得 FreeRTOS 動態(tài)內(nèi)存的剩余,進而可以根據(jù)剩余情況優(yōu)化動態(tài)內(nèi)存的大小。
heap_1 方式的動態(tài)內(nèi)存管理有以下特點:
①?項目應(yīng)用不需要刪除任務(wù)、信號量、消息隊列等已經(jīng)創(chuàng)建的資源。
②?具有時間確定性,即申請動態(tài)內(nèi)存的時間是固定的并且不會產(chǎn)生內(nèi)存碎片。
③?確切的說這是一種靜態(tài)內(nèi)存分配,因為申請的內(nèi)存是不允許被釋放掉的。
2、heap_4
FreeRTOS 的動態(tài)內(nèi)存大小在 FreeRTOSConfig.h 文件中進行了定義:
#define configTOTAL_HEAP_SIZE??( ( size_t ) ( 17 * 1024?) ) //單位字節(jié)
用戶通過函數(shù) xPortGetFreeHeapSize 就能獲得 FreeRTOS 動態(tài)內(nèi)存的剩余,但是不提供動態(tài)內(nèi)存是如何被分配成各個小內(nèi)存塊的信息。使用函數(shù) xPortGetMinimumEverFreeHeapSize 能夠獲取從系統(tǒng)啟動到當(dāng)前時刻的動態(tài)內(nèi)存最小剩余,從而用戶就可以根據(jù)剩余情況優(yōu)化動態(tài)內(nèi)存的大小。
heap_4 方式的動態(tài)內(nèi)存管理有以下特點:
①?可以用于需要重復(fù)的創(chuàng)建和刪任務(wù)、信號量、事件標(biāo)志組、軟件定時器等內(nèi)部資源的場合。
②?隨機的調(diào)用?pvPortMalloc() 和 vPortFree(),且每次申請的大小都不同,也不會像 heap_2 那樣產(chǎn)生很多的內(nèi)存碎片。
③?不具有時間確定性,即申請動態(tài)內(nèi)存的時間不是確定的
3、heap_5
heap_5 動態(tài)內(nèi)存管理是通過函數(shù) vPortDefineHeapRegions 進行初始化的,也就是說用戶在創(chuàng)建任務(wù) FreeRTOS 的內(nèi)部資源前要優(yōu)先級調(diào)用這個函數(shù) vPortDefineHeapRegions,否則是無法通過函數(shù)pvPortMalloc 申請到動態(tài)內(nèi)存的。
函數(shù) vPortDefineHeapRegions 定義不同段的內(nèi)存空間采用了下面這種結(jié)構(gòu)體:
定義的時候要注意兩個問題,一個是內(nèi)存段結(jié)束時要定義 NULL。另一個是內(nèi)存段的地址是從低地址到高地址排列。
用戶通過函數(shù) xPortGetFreeHeapSize 就能獲得 FreeRTOS 動態(tài)內(nèi)存的剩余,但是不提供動態(tài)內(nèi)存是如何被分配成各個小內(nèi)存塊的信息。使用函數(shù) xPortGetMinimumEverFreeHeapSize 能夠獲取從系統(tǒng)啟動到當(dāng)前時刻的動態(tài)內(nèi)存最小剩余,從而用戶就可以根據(jù)剩余情況優(yōu)化動態(tài)內(nèi)存的大小。
三、內(nèi)存管理編程測試
分別測試heap_4,heap_1與heap_5。
1、heap_4
if(KeyCode==KEY0){sprintf(buff,"當(dāng)前剩余動態(tài)內(nèi)存大小 %u Bytes\r\n",xPortGetFreeHeapSize());HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);sprintf(buff,"系統(tǒng)啟動至當(dāng)前時刻的動態(tài)內(nèi)存最小剩余 %u Bytes\r\n",xPortGetMinimumEverFreeHeapSize());HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);}
輸出內(nèi)存信息:
2、heap_1
if(KeyCode==KEY0){sprintf(buff,"當(dāng)前剩余動態(tài)內(nèi)存大小 %u Bytes\r\n",xPortGetFreeHeapSize());HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);//sprintf(buff,"系統(tǒng)啟動至當(dāng)前時刻的動態(tài)內(nèi)存最小剩余 %u Bytes\r\n",xPortGetMinimumEverFreeHeapSize());//HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);}
?
如果調(diào)用vPortFree()函數(shù)釋放內(nèi)存,系統(tǒng)會死機,heap_1內(nèi)存管理方案不支持內(nèi)存釋放,導(dǎo)致死機,
3、heap_5
定義內(nèi)存區(qū)域:
/* USER CODE BEGIN Init */HeapRegion_t xHeapRegions[]={{(uint8_t*)0x2000B000UL,0x1400},//5K{(uint8_t*)0x2000D800UL,0x2800},//10K{NULL,0}};vPortDefineHeapRegions(xHeapRegions);/* USER CODE END Init */
if(KeyCode==KEY0){sprintf(buff,"當(dāng)前剩余動態(tài)內(nèi)存大小 %u Bytes\r\n",xPortGetFreeHeapSize());HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);sprintf(buff,"系統(tǒng)啟動至當(dāng)前時刻的動態(tài)內(nèi)存最小剩余 %u Bytes\r\n",xPortGetMinimumEverFreeHeapSize());HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);}
輸出內(nèi)存信息: