Hello @ferro ,
"No, I am not concerned about (running out of) memory. The question is, why it is not recommended as you say next"
You should be concerned about running out of memory :)
It is not recommended because the memory is limited in embedded systems so you can quickly run out of memory.
In case you run out of memory (without protection / checks) your program will crash.
When adding widgets at runtime, if it is different widgets, you don't know how many widgets of type A or type B you will add so you cannot know how much memory you will require, all you can do is expect a worst case scenario. But if you don't have a maximum amount of widget to add it could be infinity.
So you understand that some precautions have to be taken to add elements at runtime, this is why it is not recommended, but also, not prohibited. See below for goo practices.
"Is Gfx Heap memory treated somehow differrent from global C++ runtime static/heap memory ?"
The frontendHeap is just used to store the views, presenters, model and transitions. (It is calculated at compilation, so if the widgets were stored in the frontendHeap, by adding a widget at runtime, the frontendHeap would overflow, but in my example I was able to add 1022 widgets.
So the widgets are stored in the C++ heap.
"At the moment there are two very different statements about this"
Yes, Osman gave a simpler answer, basically "You shouldn't do it" for more beginner level. I answered "It is possible but should be avoided" which is also a simplification because precautions should be taken (c.f. below).
The full answer is : It is possible to add widgets or elements at runtime but due to the limited amount of memory in embedded devices, precautions have to be taken such as allocating a specific memory region for the dynamically added widgets and only adding widgets at runtime in this region plus it is recommended to limit the amount of widget and to reuse the ones that are not visible instead of creating a lot of different widgets.
"STemWin"
Sure, I thought that you said STemWin was able to dynamically allocate memory, create widgets and clear them when they are not visible anymore.
In a way STemWin and TouchGFX work in the same way. You could add widgets at runtime in both but you have to do it smartly.
Are you creating widgets at runtime in your STemWin applications? If you do, what safety measures do you take?
How to properly add widgets at runtime
1) Using new
Create the widget using new.
Add the widget to the screen using add.
Don't forget to clean it in tearDownScreen(), for that you have to store your new widgets in a vector.
This method has no verification so your program can crash.
void Screen2View::handleTickEvent()
{
touchgfx::Box* box2 = new touchgfx::Box();
add(*box2);
box2->invalidate();
}
2) malloc (heap TouchGFX or C++)
Allocate memory for the widget using malloc/calloc.
Verify that the malloc was successful (allocated memory is not 0).
Create the widget using new.
Add the widget to the screen using add.
Don't forget to clean it in tearDownScreen().
This will use up to all the heap available and might block some other processes if they require heap too.
void Screen2View::handleTickEvent()
{
void* memory = malloc(sizeof(touchgfx::Box));
if (memory == 0) return;
touchgfx::Box* box2 = new (memory) touchgfx::Box;
add(*box2);
box2->invalidate();
}
3) FreeRTOS malloc (FreeRTOS heap)
Same as above but use pvPortMalloc() instead.
This will use up to all the heap of the task and may block other processes.
void Screen2View::handleTickEvent()
{
void* memory = pvPortMalloc(sizeof(touchgfx::Box));
if (memory == 0) return;
touchgfx::Box* box2 = new (memory) touchgfx::Box;
add(*box2);
box2->invalidate();
}
4) Allocate a custom heap region (inside another heap)
Create a buffer where you will store your widgets' addresses that will act as a heap.
Add your widget as previously.
This way you won't run out of memory nor use all the available memory.
Also, you don't have to store your widgets in a vector, instead you can just move the heap index to the beginning of the heap.
uint32_t myheap[10000];
uint8_t* heapTop = 0;
uint8_t* heapEnd = 0;
void Screen2View::setupScreen()
{
heapTop = (uint8_t*)myheap;
heapEnd = heapTop + sizeof(myheap);
Screen2ViewBase::setupScreen();
}
void Screen2View::handleTickEvent()
{
void* memory = heapTop;
heapTop += sizeof(touchgfx::Box);
if (heapTop > heapEnd) return;
touchgfx::Box* box2 = new (memory) touchgfx::Box;
add(*box2);
box2->invalidate();
}
Note that the code snippets provided are just here as examples, we tried them earlier but I am not sure they are exactly what we tried.
I hope this clears things up! :smiling_face_with_smiling_eyes:
Regards,