0 引言
在嵌入式系統設計中,需要根據系統的功能需求選擇相應的單片機。筆者參與開發的一款中央空調主控制板選用了意法半導體公司的 STM32F407 單片機,這一系列的單片機具有高集成度、高性能、嵌入式存儲器和外設,適合作為主控制板的核心單片機使用。STM32F407 主要特征如下:提供了工作頻率為 168 MHz 的 Cortex-M4 內核(具有浮點單元)的性能,在168MHz 頻率下,從 Flash 存儲器執行時,STM32F407 能夠提供 210 DMIPS/566 CoreMark 性能,并且利用意法半導體的 ART 加速器實現了 Flash 零等待狀態。DSP 指令和浮點單元擴大了產品的應用范圍。
STM32F407產品系列具有 512 KB~1MB Flash 和 192 KBSRAM,采用尺寸小至 10 mm×10mm 的 100~ 176 引腳封裝。在開發該控制板的軟件時發現,由于 STM32F407 的 SRAM 地址不連續,造成動態內存分配存在問題,不能利用全部的片內 192 KB SRAM 資源,有必要深入分析并解決。
筆者在開發該控制板的軟件時,使用IAR公司的EWARM7.40作為 C/C++ 編譯器,該編譯器提供了靜態內存分配與動態內存分配2種不同的內存分配機制。
1.1 簡介
ARM內核可處理4GB 的連續內存,范圍從0x00000000到0xFFFF FFFF。不同類型的物理內存可以放置在上述內存范圍中。典型的應用程序同時具有只讀存儲器(ROM)和隨機存取內存(RAM)。此外,內存范圍的某些部分包含處理器控制寄存器和外圍單元。
在典型的應用程序中,數據可以通過以下3種不同的方式存儲在內存中:
(1)自動變量
除已聲明為靜態變量者外,所有函數的局部變量都存儲在寄存器或堆棧上。這些變量在函數執行時可以使用。當函數返回到其調用者時,內存空間不再有效。
(2)全局變量、模塊靜態變量和聲明為 static的局部變量
在這種情況下,內存的分配是一勞永逸的。在此語境中,“靜態”一詞表示應用程序運行時分配給此類變量的內存數量不會改變。ARM 內核有一個單一的地址空間且編譯器支持完整的內存尋址。
(3)動態分配的數據
應用程序可以在堆上分配數據,此數據一直有效,直到它被應用程序顯式地釋放回系統。對于在應用程序執行之前不知道對象數量的場合,這種類型的內存是有用的。注意:就內存量有限的系統或預期運行很久的系統而言,存在著與使用動態分配的數據相關的潛在風險。
1.2 自動變量和參數的存儲
按照 C 語言標準,函數內定義且未聲明為靜態的變 量被命名為自動變量。其中一些變量被放置在處理器寄存器中,其余的放在堆棧上。從語義的角度來看,這是等價的。與放在堆棧上的變量相比,主要區別在于訪問寄存器更快,并且需要的內存更少。自動變量只能在函數執行時存活;當函數返回時,分配在堆棧上的內存被釋放。
(1)堆棧
堆??梢园何创鎯υ诩拇嫫髦械木植孔兞亢蛥?;表達式的臨時結果;函數的返回值(在寄存器中傳遞的除外);中斷期間的處理器狀態;應在函數返回前恢復的處理器寄存器(被調用者保存的寄存器)。
堆棧是一個固定的內存塊,分為兩部分:第一部分包含為調用當前函數的函數,以及調用該函數的函數所使用而分配的內存;第二部分包含可分配的自由內存。這兩個區域之間的邊界線稱為棧頂,由一個專門的處理器寄存器——堆棧指針來表示。通過移動堆棧指針,內存被分配到堆棧上。
函數絕不應指向包含自由內存的堆棧區域。原因是,如果發生中斷,被調用的中斷函數會分配、修改,當然還有在堆棧上去分配內存。
(2)優點
堆棧的主要優點是:程序不同部分的函數可以使用相同的內存空間存儲其數據。不同于堆,堆棧永遠不會變成碎片或出現內存泄漏。
函數可以直接或間接地調用自己(遞歸函數),每個調用可以在堆棧上存儲自己的數據。
(3)潛在的問題
堆棧的工作方式使得臆想在函數返回后存儲數據變得不可能。以下函數演示了常見的編程錯誤。它返回指向變量 x 的指針,該變量在函數返回后已不存在。
int * MyFunction(){
int x;
/*在此處理一些事情*/
return &.x; /* 不正確*/
}
另一個問題是堆棧耗盡的風險。這個問題在一個函數調用另一個、被調函數繼續調用第3個函數等,每個函數使用堆棧的總和大于堆棧的大小時會發生。當大型數據對象存儲在堆棧上或使用遞歸函數時,風險更高。
1.3 堆上的動態內存
分配在堆上的對象的內存將一直存在,直到對象被顯式釋放。這種類型的內存存儲對于直到運行時才知道數據量的應用程序是非常有用的。
在 C 語言中,使用標準庫函數 malloc或相關函數 calloc 和 realloc 中的一個來分配內存,使用free 來釋放內存。
在 C++ 語言中,一個特殊的關鍵字new 分配內存和運行構造器。通過 new 分配的內存必須使用關鍵字 delete 來釋放。
設計使用堆分配對象的應用程序時必須非常仔細,因為很容易出現無法在堆上分配對象的情形。如果你的應用程序使用過多的內存,堆可能會耗盡。如果不再使用的內存未被釋放,則堆也會用完。
對于每個分配的內存塊,若干字節用于管理目的的數據是必需的。對于分配大量小塊的應用程序,此管理開銷可能很大。
還存在碎片化的問題。這意味著在堆中,一小部分自由內存被分配對象使用的內存所分隔。如果沒有一塊足夠大的自由內存給對象,即使自由內存大小的總和超過對象的大小,還是無法分配一個新的對象。不幸的是,隨著內存的分配和釋放,碎片化往往會增加?;诖?,設計長時間運行的應用程序時應盡量避免使用分配在堆上的內存。
2 問題分析與解決方案
以下介紹的程序實例在編譯器EWARM7.40、Fre-eRTOS 10.0.0 下驗證通過。
2.1 STM32F407 的片內 SRAM
STM32F407 具有192 KB 的片內 SRAM 。片內 SRAM 可以字節、半字(16位)或全字(32位)的形式訪問。讀取和寫人操作以 CPU 速度執行,等待狀態為0。片內 SRAM 最多分為兩個模塊:SRAM1 和 SRAM2 映射地址0x20000000,可以被所有 AHB 主設備存??;CCM(核心耦合存儲器)映射到地址0x10000000, 只能由 CPU 通過 D 總線存取。
STM32F407 的內存映射如圖1所示,應用程序可以使用的系統SRAM 地址為0x20000000~0x2001 FFFF(128KB),CCM地址為0x10000000~0x1000 FFFF(64 KB)。
由于兩塊內存的地址不連續,使用編譯器 EWARM 7.40時,new 運算符只能夠在一片連續的空間分配內存,無法同時使用另外一片連續的空間。換言之,堆的實現只能在128 KB 的 SRAM 內存空間內,另外1/3的片內 SRAM 被白白浪費了,這在應用程序較為復雜時是個嚴重的缺陷,必須設法解決。
圖1 STM32F407 的內存映射
2.2 解決方案
由于編譯器 EWARM7.40 的局限性,堆無法在兩片不連續的內存空間實現。為了解決此問題,筆者聯想到了免費的實時操作系統 FreeRTOS, 該操作系統在2014年8月發布的 V8.1.0中提供了新的內存管理文件 heap_5.c, 允許堆跨越多個不連續的內存區域。后續版本對此功能做了優化與改進。筆者嘗試用此方案解決堆的實現問題,取得了成功。具體方法如下:
①把FreeRTOS源程序包中的heap_5.c添加到軟件工程中。
②在頭文件中定義堆的大小。
#define configTOTAL_HEAP1_SIZE((size_t)(64*1024))
//HEAP164KB
#define configTOTAL_HEAP2_SIZE((size_t)(100*1024))
//HEAP2100KB
說明:HEAP1 使用CCM 的全部 64KB;HEAP2 使用 SRAM 的100 KB, 剩余部分留給操作系統使用。此數值可根據應用程序的需求靈活調整。
③在main.c中定義兩片內存區域:
#pragmalocation=".ccmram"
uint8_tucHeapl[configTOTAL_HEAP1_SIZE];
uint8_tucHeap2[configTOTAL_HEAP2_SIZE];
constHeapRegion_txHeapRegions[]={
/*Startaddress with dummy offsets Size */
{ucHeapl,configTOTAL_HEAP1_SIZE},
{ucHeap2,configTOTAL_HEAP2_SIZE},
{NULL,0}
};
④ 在 main.c 中重載new 和delete:
void *operator new(size_t size){
void *p=0;
p=pvPortMalloc(size); //調用FreeRTOS 的內存分配函數
return p;
void operator delete(void *p){
vPortFree(p); // 調用 FreeRTOS 的內存釋放函數
經過上述改進后,應用程序可以使用的堆的大小為 164KB, 徹底擺脫了編譯器 EWARM7.40 的局限性,滿足了復雜應用程序的需求。
3 結語
本文詳細介紹了使用多塊不連續內存空間實現堆的軟件方法,以及在 STM32F407 單片機上的軟件實現方法。使用該技術可以在多塊不連續內存空間實現堆,更好 地實現了內存的動態分配。使用該軟件的控制器產品至今已在現場穩定運行18個月。
審核編輯:劉清
-
嵌入式系統
+關注
關注
40文章
3442瀏覽量
128342 -
加速器
+關注
關注
2文章
759瀏覽量
36655 -
Flash存儲器
+關注
關注
3文章
104瀏覽量
25542 -
STM32F407
+關注
關注
15文章
187瀏覽量
29056 -
靜態變量
+關注
關注
0文章
13瀏覽量
6623
原文標題:使用多塊不連續空間實現堆的軟件方法
文章出處:【微信號:麥克泰技術,微信公眾號:麥克泰技術】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論