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