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:
|Internal RAM||Internal 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 Flash||Internal flash is used for program code for the application, the TouchGFX library, and other libraries used.|
|External RAM||External RAM is typically used for framebuffers and maybe a bitmap cache.|
|External Flash||External flash is used to store images, fonts and texts.|
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.
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
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.
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 TouchGFXDesigner generates.
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.
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:
After opening the project in IAR, we check in the properties that IAR generates a .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:
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: " section) adds 12.728 bytes of code to the application (and 4.286 bytes of constant data).
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 . 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 CubeMX. 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:
The objects required for the user interface occupies 0x240 bytes = 576 bytes.
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):
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:
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.
The external flash is the "P3" region (starting at address 0x90000000). Here is the content of that region:
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.
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.
|Internal RAM||42.731 bytes|
|TouchGFX Screen objects||576 bytes|
|Internal Flash||45605 bytes|
|TouchGFX Framework||12.728 bytes code|
|External RAM||786.360 bytes|
|External Flash||82.028 bytes|
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:
|Internal RAM||51.387 bytes|
|TouchGFX Screen objects||10.772 bytes|
|Internal Flash||187.768 bytes|
|TouchGFX Framework Code||85.174 bytes code|
|External RAM||786.360 bytes|
|External Flash||5.281.812 bytes|