記憶體使用
前言
在本節中,我們將討論TouchGFX應用的存儲空間使用量。 典型的TouchGFX應用使用4類記憶體,但這取決於使用的硬體:
記憶體類型 | 使用 |
---|---|
內部RAM | 內部RAM用於存儲配置資料,如所有Widget的座標和色彩。 這裡存儲了當前螢幕的幾個物件。 包含UI任務執行時間stack的作業系統記憶體也位於內部RAM中。 其他軟體元件的所有資料(如檔案系統和顯示器驅動)同樣位於內部RAM中。 |
內部快閃記憶體 | 內部快閃記憶體用於存儲應用程式碼、TouchGFX庫和使用的其他庫。 |
外部RAM | 外部RAM通常用於提供影像緩衝,也可以是點陣圖快取。 |
外部Flash | 外部快閃記憶體用於存儲圖像、字體和文字。 |
靜態存儲分配
TouchGFX只使用靜態存儲分配。 這意味著所有存儲空間都是預先分配的。 TouchGFX在執行時間中不進行存儲空間分配。 如果應用可以一開始就嵌入記憶體,則可確保永遠不會無存儲空間可用。
Screen和Widget
在TouchGFX中,通過開發許多C++類來創建使用者介面。 TouchGFX Designer在您設計介面時創建類。 對於在TouchGFX Designer中設計的每個介面,您會自動獲得許多類(MVP架構)。 在顯示器上顯示介面時,TouchGFX會在內部RAM中自動分配類的物件。
當從一個介面切換到另一個介面時,不再使用為上一個介面分配的物件,而只使用新介面的物件。 因此,將在內部RAM中舊物件所在的位置分配新物件(舊物件被覆蓋)。 內部RAM僅在一個時間點保存一個顯示器的物件。
根據定義的類,C++編譯器能夠計算最大介面類的大小,並為這些類預留存儲空間。
因此,內部RAM中的存儲空間使用量不取決於應用中介面的數量,而是取決於最大介面的大小。
為這些物件留出的存儲空間稱為FrontendHeap。
TouchGFX
應用程式程式碼
應用程式程式碼通常存儲在內部快閃記憶體中。 應用程式程式碼包括您編寫的程式碼、TouchGFX Designer生成的程式碼、來自TouchGFX Designer庫和您使用的其他庫的程式碼。
隨著您編寫的程式碼和添加到應用的介面越來越多,應用程式碼的數量必然增加。 在您首次使用某項特性時,從函式庫中取出的程式碼的量隨之增加。 例如,在您首次將Button添加到介面時,TouchGFX庫中的Button程式碼就會包含在您的應用中,導致程式碼量增加。 在您第二次為同一個或另一個介面添加Button時,不會再次從TouchGFX庫獲取程式碼,應用中增加的只有您編寫的或TouchGFX Designer生成的程式碼。
資產
諸如圖像、字串和字體之類的資產會被轉換為C++檔並連結到應用中。 資產的資料通常儲存在外部快閃記憶體中,但也可儲存在內部快閃記憶體中。 這是通過連結器腳本來控制的。
在添加圖像時,應用的大小與圖像大小成正比。
在添加文字時,文字中的每個字元會導致應用的大小增加兩個位元組。 如果同一個字串使用了兩次,應用大小只增加一次。
只從字體檔中獲取應用使用的字元。 這意味著如果應用中只使用大寫字母A-Z,則應用中不包含字體中的小寫字母a-z。 如果日後添加使用這些字母的文字,則應用中字體的資料量會增加。
快閃記憶體中字元的大小取決於選擇的字體大小。 如果字體增大,應用大小也會增加。
檢查存儲空間使用量
通過檢查連結器生成的映射檔,可以找到特定應用的存儲空間使用量。
下面我們來檢查IAR Embedded Workbench生成的映射檔。 其他編譯器也會生成類似的映射文件。
首先在TouchGFX Designer中為STM32F746Discovery評估套件創建一個空專案:
在IAR中打開專案後,查看關於IAR生成.MAP檔的屬性:
在IAR中進行編譯後,可以檢查連結器映射檔STM32F746G_DISCO.map,該文件位於EWARM/STM32F746G_DISCO/List資料夾。
IAR連結器映射檔包含一個極佳的總結。 查找“模組總結”:
*******************************************************************************
*** MODULE SUMMARY
***
Module ro code ro data rw data
------ ------- ------- -------
command line/config:
------------------------------------------------------------------
Total:
C:\TouchGFXProjectsDocumentation\STM32F746MemoryUsage\EWARM\STM32F746G_DISCO\Obj: [1]
ApplicationFontProvider.o 20
BitmapDatabase.o 12 40
Blue_Buttons_Round_Edge_small.o 40'800
Blue_Buttons_Round_Edge_small_pressed.o 40'800
Font_verdana_10_4bpp_0.o 24
Font_verdana_20_4bpp_0.o 72
Font_verdana_40_4bpp_0.o 280
FrontendApplication.o 46 60
FrontendApplicationBase.o 706 816
GeneratedFont.o 84 84
Kerning_verdana_10_4bpp.o 4
Kerning_verdana_20_4bpp.o 4
Kerning_verdana_40_4bpp.o 4
Model.o 10
OSWrappers.o 156 1 9
STM32DMA.o 898 176
STM32TouchController.o 162 24 4
...
heap_4.o 444 32'792
...
touchgfx_core.a: [7]
AbstractButton.o 136
AbstractPartition.o 8
Application.o 2'218 290 28
Bitmap.o 1'064 604 36
Box.o 108 104
Button.o 276 308
ConstFont.o 62
Container.o 510 396
DMA.o 558 252
DisplayTransformation.o 192
Drawable.o 418
FontManager.o 12 4
Gestures.o 364 60
HAL.o 1'758 544 18
LCD24bpp.o 2'732 1'604 80
Screen.o 1'924 124
TouchCalibration.o 252 76
TypedText.o 14
------------------------------------------------------------------
Total: 12'728 4'286 256
Gaps 4 3
Linker created 36 2'560
----------------------------------------------------------------------
Grand Total: 38'676 88'973 42'731
此表包含三列數字, 其中的ro程式碼和ro資料為唯讀,位於快閃記憶體中, rw資料為非常量讀寫變數,位於RAM中。
表中的行劃分為7塊。 第一塊為專案中的所有.cpp文件。 後面的六塊為專案中使用的函式庫(.a文件)。 最後一個是TouchGFX庫。
我們可以看到TouchGFX庫(「touchgfx_core.a:[7]」部分)為應用程式增加了12,728位元組的程式碼(和4,286位元組的常數資料)。
內部RAM
為了找到內部RAM的總使用量,我們來看模組總結表底部的“總計”一行。 第三列是內部RAM。 這表示專案使用了內部RAM的42,731位元組空間。 我們來看TouchGFX庫的總值,可以看到TouchGFX庫[7] 使用了256位元組。 heap_4.o使用了32,792位元組。 這是為FREERTOS預留的動態記憶體堆。 32Kb是預設值,但堆的大小可在STM32CubeMX中配置。 典型的TouchGFX程式使用此堆中幾Kb的空間,主要用來為使用者介面任務分配棧。
通過搜索FrontendHeap,我們可以找到介面物件的大小:
FrontendHeap::getInstance()::instance
0x2000'95d0 0x240 Data Gb TouchGFXConfiguration.o [1]
使用者介面所需的物件佔用了0x240位元組 = 576位元組的空間。
內部快閃記憶體
從總計一列中可以看到,此應用程式使用了38,676位元組程式碼 + 88,973位元組資料。 其中只有一部分是內部快閃記憶體。 至少兩張Button圖像位於外部快閃記憶體中。
為了找出會有多少程式碼和資料存儲在內部快閃記憶體中,我們首先檢查“存儲總結”(刪除了一些細節):
*******************************************************************************
*** PLACEMENT SUMMARY
***
"A0": place at address 0x800'0000 { ro section .intvec };
"P1": place in [from 0x800'0000 to 0x80f'ffff] { ro };
"P2": place in [from 0x2000'0000 to 0x2004'ffff] { rw };
"P3": place in [from 0x9000'0000 to 0x90ff'ffff] {
section ExtFlashSection, section FontFlashSection,
section TextFlashSection };
內部快閃記憶體的起始位址為0x08000000。 它被兩個區域“A0”和”P1”覆蓋。
繼續看映射檔,可以看到這些區域中的內容:
Section Kind Address Size Object
------- ---- ------- ---- ------
"A0": 0x1c8
.intvec ro code 0x800'0000 0x1c8 startup_stm32f746xx.o [1]
- 0x800'01c8 0x1c8
"P1": 0xb05d
.text ro code 0x800'01c8 0x9b8 main.o [1]
.text ro code 0x800'0b80 0x14 memset.o [5]
...
.text ro code 0x800'b17a 0x2 AbstractButton.o [7]
.rodata const 0x800'b17c 0x1 unwind_debug.o [6]
.rodata const 0x800'b17d 0x0 zero_init3.o [5]
.rodata const 0x800'b17d 0x0 lz77_init_single.o [5]
Initializer bytes const 0x800'b17d 0xa8 <for P2-1>
- 0x800'b225 0xb05d
這表示「A0」使用了0x1c8位元組 = 456位元組,「P1」使用了0xb05d位元組 = 45,149位元組。 內部快閃記憶體的總使用量為45,605位元組。
外部Flash
外部快閃記憶體為”P3”區域(起始位址為0x90000000)。 下面是該區域的內容:
"P3": 0x1'4076
ExtFlashSection const 0x9000'0000 0x9f60 Blue_Buttons_Round_Edge_small.o [1]
ExtFlashSection const 0x9000'9f60 0x9f60 Blue_Buttons_Round_Edge_small_pressed.o [1]
FontFlashSection const 0x9001'3ec0 0x118 Font_verdana_40_4bpp_0.o [1]
FontFlashSection const 0x9001'3fd8 0x48 Font_verdana_20_4bpp_0.o [1]
FontFlashSection const 0x9001'4020 0x18 Font_verdana_10_4bpp_0.o [1]
FontFlashSection const 0x9001'4038 0x10 Table_verdana_10_4bpp.o [1]
FontFlashSection const 0x9001'4048 0x10 Table_verdana_20_4bpp.o [1]
FontFlashSection const 0x9001'4058 0x10 Table_verdana_40_4bpp.o [1]
FontFlashSection const 0x9001'4068 0x4 Kerning_verdana_10_4bpp.o [1]
FontFlashSection const 0x9001'406c 0x4 Kerning_verdana_20_4bpp.o [1]
FontFlashSection const 0x9001'4070 0x4 Kerning_verdana_40_4bpp.o [1]
TextFlashSection const 0x9001'4074 0x2 Texts.o [1]
- 0x9001'4076 0x1'4076
可以看到外部快閃記憶體的總使用量為0x14076位元組 = 82,038位元組。 兩張「按鈕」圖像(2 x 0x9f60位元組 = 40,800位元組)使用了大部分。 其餘資料屬於3種字體。 在本例中,由於不使用任何文字,只包含“?”字元,因此它們用不了多少空間。
總結
外部RAM中只有影像緩衝。 由於它們未被定義為應用中的變數,因此在連結器腳本中找不到它們。 解析度為480x272像素(24位元)。 有兩個影像緩衝區,總使用量為480 * 272 * 3 * 2 = 786,360位元組。
記憶體類型 | 使用 |
---|---|
內部RAM | 42,731位元組 |
TouchGFX介面物件 | 576 位元組 |
內部快閃記憶體 | 45605 位元組 |
TouchGFX框架 | 12,728位元組程式碼 |
外部RAM | 786,360位元組 |
外部Flash | 82,028位元組 |
Demo 1
以下是另一個範例:TouchGFX Designer中可以找到的TouchGFX Demo1的資料量。 它包含5個介面和100多張圖像:
總結
記憶體類型 | 使用 |
---|---|
內部RAM | 51,387位元組 |
TouchGFX介面物件 | 10,772位元組 |
內部快閃記憶體 | 187,768位元組 |
TouchGFX框架程式碼 | 85,174位元組程式碼 |
外部RAM | 786,360位元組 |
外部Flash | 5,281,812位元組 |