Skip to main content

Memory Usage

Introduction

In this section we will discuss the memory usage of a TouchGFX application. A typical TouchGFX application uses 4 types of memory, but this will depend on the hardware used:

Memory TypeUsage
Internal RAMInternal RAM is used for configuration data like coordinates and colors of all the Widgets. A few objects for the current screen is allocated here.
The operating system memory including the runtime stack of the UI task is also in internal RAM. All data for other software components like filesystems and display drivers is also placed in internal RAM.
Internal FlashInternal flash is used for program code for the application, the TouchGFX library, and other libraries used.
External RAMExternal RAM is typically used for framebuffers and maybe a bitmap cache.
External FlashExternal flash is used to store images, fonts and texts.

Static Memory Allocation

TouchGFX only uses static memory allocation. This means that all memory is preallocated. No memory is allocated by TouchGFX at runtime. This ensures that you will never run out of memory, if the application could fit into memory at start.

Screens and Widgets

In TouchGFX the user interface is created by developing a number of C++ classes. The classes are created by TouchGFX Designer when you design the screens. For each screen designed in TouchGFX Designer you automatically get a number of classes (the MVP architecture). When you show a screen on the display objects of the classes is automatically allocated by TouchGFX in internal RAM.

When you change from one screen to another screen, the objects allocated for the previous screen are not used anymore, only the objects for the new screen. Therefore the new objects are allocated in the place in internal RAM where old objects were allocated (the old objects are overwritten). The internal RAM only holds objects for one screen at one point in time.

Based on the classes defined it is possible for the C++ compiler to calculate the size of the largest screen classes, and reserve memory for those classes.

The memory usage in internal RAM thus does not depend on the number of screens in the application, but on the size of the largest screen.

The memory set aside for these objects is called the FrontendHeap.

TouchGFX

Application code

The application code is normally placed in the internal flash. The application code consists of the program code you write, the code generated by TouchGFX Designer, code from the TouchGFX library and other libraries you use.

The amount of application code will of course increase when you write more code and add more screens to your application. The amount of code taken from libraries increases the first time you use a feature. For example, the first time you add a Button to a screen, the Button code from the TouchGFX library is included in your application which therefore grows. The second time you add a Button to the same or another screen, no additional code is taken from the TouchGFX library, and the application only grows by the amount of code you write or TouchGFX Designer generates.

Assets

Assets like images, texts, and fonts are converted to c++ files and linked into your application. The data for the assets are normally put in the external flash, but can also be put in internal flash. This is controlled by the linker script.

When you add an image, the application size will grow proportionally to the size of the image.

When you add texts the application will grow two bytes for each character in the text. If you use the same string of character twice it is only included once.

Only the characters used by the application are taken from the font files. This means that if you only use the upper case letters A-Z in your application, the lower case letters a-z in the font are not included in your application. If you later add texts that use these letters, the font data in your application will grow in size.

The size of the characters in flash depends on the selected font size. In you increase the font size, the application size will increase.

Checking memory usage

Memory usage of a specific application can be found by examining the map file generated by the linker.

Here we examine a map file generated by the IAR Embedded Workbench. Other compilers produce similar map files.

We start by creating an empty project in TouchGFX Designer for the STM32F746Discovery evaluation kit:

STM32F746 project with a Box and a Button

After opening the project in IAR, we check in the properties that IAR generates a .MAP file:

Generate a linker map file

After compilation in IAR we can check the linker map file, STM32F746G_DISCO.map, found in the EWARM/STM32F746G_DISCO/List folder.

The IAR linker map files contain a nice summary. Look for MODULE SUMMARY:

*******************************************************************************
*** 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

This table has three columns of numbers. ro code and ro data is read-only and is placed in flash. rw data is non-const read-write variables and which are placed in RAM.

The rows in the table are divided into 7 blocks. The first block is all the .cpp files in the project. The next six blocks are the libraries used in the project (.a files). The last one is the TouchGFX library.

We can see that the TouchGFX library (the "touchgfx_core.a: [7]" section) adds 12,728 bytes of code to the application (and 4,286 bytes of constant data).

Internal RAM

To find the total internal RAM usage we look in the Grand Total row in the bottom of the Module Summary table. The third column is the internal RAM. This means that the project uses 42,731 bytes of internal RAM. Looking at the total for the TouchGFX library we see that 256 bytes are used by the TouchGFX library [7]. 32,792 bytes are used by heap_4.o. This is the dynamic memory heap reserved for FREERTOS. 32Kb is the default value, but the heap size can be configured in STM32CubeMX. A typical TouchGFX program uses a few Kb from this heap, mainly to allocate a stack for the user interface task.

By searching for the FrontendHeap, we can find the size of the screen objects:

FrontendHeap::getInstance()::instance
0x2000'95d0 0x240 Data Gb TouchGFXConfiguration.o [1]

The objects required for the user interface occupies 0x240 bytes = 576 bytes.

Internal Flash

We see from the Grand Total row that this application uses 38,676 bytes code + 88,973 bytes data. Only some of this is the internal flash. At least the two images for the Button is in external flash.

To find out how much code and data that is going into the internal flash we start by checking the PLACEMENT SUMMARY (a few details removed):

*******************************************************************************
*** 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 };

The internal flash is starting at address 0x08000000. It is covered by the two regions "A0" and "P1".

Looking a bit further in the map file we can see what is placed in these regions:

  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

This means that 0x1c8 bytes = 456 bytes are used by "A0", and 0xb05d bytes = 45,149 bytes by "P1". The total usage of the internal flash is thus 45,605 bytes.

External Flash

The external flash is the "P3" region (starting at address 0x90000000). Here is the content of that region:

"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

We see that the total usage of the external flash is 0x14076 bytes = 82,038 bytes. The majority of that is used by the two images for the Button (two times 0x9f60 bytes = 40,800 bytes). The rest of the data is for 3 fonts. They don't use much space in this example as they only contain the '?' character, because we do not use any texts in this example.

Summary

The only thing placed in external RAM is the framebuffers. These cannot be found in the linker script as they are not defined as variables in the application. The resolution is 480x272 pixels in 24 bit. We have two framebuffers to the total usage is 480 * 272 * 3 * 2 = 786,360 bytes.

Memory TypeUsage
Internal RAM42,731 bytes
TouchGFX Screen objects576 bytes
Internal Flash45605 bytes
TouchGFX Framework12,728 bytes code
External RAM786,360 bytes
External Flash82,028 bytes

Demo 1

To give another example here are the numbers for the TouchGFX Demo1 which can be found in TouchGFX Designer. It contains 5 screens and more than 100 images:

STM32F746 Demo 1

Summary

Memory TypeUsage
Internal RAM51,387 bytes
TouchGFX Screen objects10,772 bytes
Internal Flash187,768 bytes
TouchGFX Framework Code85,174 bytes code
External RAM786,360 bytes
External Flash5,281,812 bytes