2024-05-27 12:33 AM - edited 2024-05-27 04:00 AM
Running my application in the Simulator, after a few seconds on a screen with a ScrollList I get this assertion. Can anyone tell me what components use excessive amounts of these timer objects, so I can try to work around it?
The same code running on the target runs fine.
The ScrollListItems have several MoveAnimators, but only a few of them are running an animation. Do MoveAnimators use TimerWidgets?
Solved! Go to Solution.
2024-06-13 04:48 AM - edited 2024-06-18 12:08 AM
With great help from @GaetanGodart we sorted this (almost) out. I'm still not sure if this assertion is a bug (more likely) or a feature (timebomb?) inside TouchGFX Simulator framework code, but I can use the ScrollList as planned without getting the assertion. I will explain what parts of my code caused this assertion and how I changed it. Maybe this helps other users, when seeing the same assertion while running the Simulator application.
Contrary to what I first thought, the MoveAnimators did not cause the problem.
I have code that updates the content of all my ScrollList's items every second, because the information shown on the items could have changed (yes I know...:face_with_rolling_eyes:). My function to trigger the item-update-callback for each item of the ScrollList looked like this:
void MyView::updateList(uint16_t size)
{
scrollList.setNumberOfItems(0); //workaround update bug
scrollList.setNumberOfItems(size);
for (int i = 0; i < scrollListListItems.getNumberOfDrawables(); i++) {
scrollList.itemChanged(i);
}
scrollList.invalidate();
}
When calling setNumberOfItems(0) while the ScrollList is not scrolled up to the top item, the "TimerWidget" counter gets incremented and after reaching a count of 255 I get the assertion. I'll explain next why I had the seemingly pointless call to setNumberOfItems(0) before setting the real size.
While developing on the target I had issues with some Items of the ScrollList did not update their content while scrolling through the list (mostly the last ones). I thought it's a bug of TouchGFX and played around with the ScrollList API and found out that setting the size to 0 at first fixed my problem. Now I understand why it helped and what I did wrong until now:
A ScrollList has a fixed number or DrawableListItems (typically number of visible list elements on screen + 2). In my for-loop I iterate over this count and thought itemChanged(i) would tell every DrawableListItem to trigger the item-update-callback. But I mixed the two indices the ScrollList is working with: One is the index of the DrawableListItems and the other one is the index to your list (counting up to whatever "numberofItems" your told the ScrollList to have. And itemChanged(i) expects an index to the later one.
Mixing those caused some of my items to never update. By resizing the ScrollList having it resized to 0 and back to whatever size it has, internally causes a call to the item-update-callback for each item on screen.
Now my update code looks like this:
scrollList.setNumberOfItems(size);
for (int i = 0; i < scrollList.getNumberOfItems(); i++) {
scrollList.itemChanged(i);
}
scrollList.invalidate();
The only disadvantage is when your list is long (like 1000 or so), you iterate over all of your items and TouchGFX filters out the elements currently shown on the screen calling the update-callback for those items.
To only iterate over the currently visible items I would need to know which elements are currently visible (the scroll offset). But unfortunately, the ScrollLists (inherited from ScrollBase) method getOffset() is declared as protected.
It's the same reason that prevents me from creating a scroll bar around the ScrollList - we don't have access to the scrolled position. Hopefully that changes with the next TouchGFX release. :)
2024-05-28 09:01 AM - edited 2024-06-11 12:43 AM
Hello @t.decker ,
I have used fadeAnimator and had the same issue (but if I remember correctly, I was blocked after 20 timers).
To bypass this issue, since my animations were kind of similar, I just used the handleTickEvent function to copy the fade values.
I guess you use your moveAnimator in a custom container that you include in your scrollList.
Maybe the simplest solution is to make your GUI a bit less good looking by simply removing your moveAnimator.
The correct fix is probably to fetch the amount scrolled and to set the x and y position of the element in your scroll list accordingly to never use the moveAnimator.
If this comment answers your question, I invite you to select it as "best answer".
Regards,
2024-06-03 10:54 PM
Hi @GaetanGodart,
I have quite a lot MoveAnimators on this screen, but only one or two of them are animating when the error shows up. I use them with my "TextAreaMarquee" (see https://community.st.com/t5/stm32-mcus-touchgfx-and-gui/share-your-custom-widgets/m-p/678013/highlight/true#M37701) each having a MoveAnimator.
Having a ScrollList and some normally hidden custom containers with edit-functions for the ScrollListItems I may have about 30 MoveAnimators on the screen. No way I can get to the limit of TimerWidgets 255 with this (assuming a MoveAnimator only needs one timer). And the MoveAnimators are not animating most of the time, only when the text of the "TextAreaMarquee" is too long.
So I had situations where I got this error with only one active MoveAnimator. At the moment I don't get this error at all and I don't know why. Maybe there is a bug in the MS Windows implementation of this part of TouchGFX library? Because on the target I never had issues. Not sure how to debug this in more detail...
2024-06-04 02:59 AM
Hello @t.decker ,
It doesn't matter if the moveAnimators are active or not. If you add one (or a widget using one), it will use the timer at all time basically.
How many items does your scrollList have? How many moveAnimator is there per custom widget text slider?
To my knowlege, there can only be 20 timers fors fadeAnimators so there should also be only 20 timers for moveAnimators. I have checked the line 909 and it seems it counts the potential timers that you added to be over 255. Maybe we changed that recently (it didn't make any sense to be limited to 20).
Do you have a for loop where you add timers or something like that?
"At the moment I don't get this error at all and I don't know why."
I don't understand what you mean. You don't have the error anymore? What did you change? Something must have changed.
Regards,
2024-06-04 04:58 AM
Good to know that also inactive MoveAnimators also use/reserve a timer object. My ScrollList has 8 items, each having 3 scroll texts (1 MoveAnimator each). On normally hidden custom containers (used as modal edit popup windows) there are maybe 10 more scroll texts.
So in sum I have ~34 MoveAnimators. I'm not sure when the assertion stopped appearing, because sometimes it took about 5 or even 15 minutes for it to appear and I continued to work on this screen's code. I had the feeling that intensive scrolling my list provoked the assertion to show faster, but I'm not sure about that.
I had maybe 10 MoveAnimators more on the screen but removed them some days ago - maybe I dropped under a magic possible number of custom MoveAnimators. Who knows how many TimerWidget are already used by other TouchGFX stuff.
For now I'm fine with the infos I got. If the assertion appears again, I will try to reduce the MoveAnimator count further.
Thank you
2024-06-04 08:16 AM
I am not sure what is going on there but since you seems satisfied for now, I will stop investigating.
"Who knows how many TimerWidget are already used by other TouchGFX stuff." I am pretty sure no TouchGFX use the timers allocated for the user.
Regards,
2024-06-05 02:52 AM - edited 2024-06-05 04:04 AM
Hi @GaetanGodart,
sorry to bother you again. You said the 255 TimerWidgets are only used by my own code. Because this number is way above the number of MoveAnimators (and I think that's the only thing using timers on that screen. I don't use FadeAnimators), I tried to figure out when the assertion happens.
So what I can say now is:
Both situations showed same content in the ScrollLists. So what's the difference? When scrolling through the elements the ScollListItems get updated. This can cause a MoveAnimator to start or stop an animation. I do calls to:
txtMarquee.startMoveAnimation(...)
txtMarquee.cancelMoveAnimation()
txtMarquee.isMoveAnimationRunning()
I'm not digging into this any deeper. For now I will disable the use of a MoveAnimator for the Simulator build by:
#ifndef SIMULATOR
# define USE_MARQUEE 1
#else
# define USE_MARQUEE 0
#endif
#if USE_MARQUEE
touchgfx::MoveAnimator< touchgfx::TextAreaWithOneWildcard > txtMarquee;
#else
touchgfx::TextAreaWithOneWildcard txtMarquee;
#endif
Regards
Tom
Edit: Ok now it's getting weird. Had the program without the MoveAnimator running during lunch break and had the assertion on the screen afterwards. So where does the extensive use of TimerWidgets come from? I have no clue...
Just upgraded to TouchGFX 4.24.0, no change in behaviour.
2024-06-09 11:45 PM
@GaetanGodartcan you please have a look into this again? I get the TimerWidget-assertions without having any MoveAnimator on the screen. How can I figure out, what's causing the crash?
2024-06-10 01:07 AM - edited 2024-06-14 01:16 AM
Hello @t.decker ,
Sure I can look at it.
Please tell me exactly what you have done to get this assertion.
Did you take your old project (with your scroll list having a bunch of custom animated textArea) and removed everything from it?
What do you have right now?
If you did remove everything, then it should look like a brand new empty project.
What you could do in this case is to create a new empty project with the same setup and use a software to compare files and see the differences.
Other than that, I am quite limited in helping you there if you cannot share your project.
Can you compress you project using 7zip and attach it here?
Regards,
2024-06-13 04:48 AM - edited 2024-06-18 12:08 AM
With great help from @GaetanGodart we sorted this (almost) out. I'm still not sure if this assertion is a bug (more likely) or a feature (timebomb?) inside TouchGFX Simulator framework code, but I can use the ScrollList as planned without getting the assertion. I will explain what parts of my code caused this assertion and how I changed it. Maybe this helps other users, when seeing the same assertion while running the Simulator application.
Contrary to what I first thought, the MoveAnimators did not cause the problem.
I have code that updates the content of all my ScrollList's items every second, because the information shown on the items could have changed (yes I know...:face_with_rolling_eyes:). My function to trigger the item-update-callback for each item of the ScrollList looked like this:
void MyView::updateList(uint16_t size)
{
scrollList.setNumberOfItems(0); //workaround update bug
scrollList.setNumberOfItems(size);
for (int i = 0; i < scrollListListItems.getNumberOfDrawables(); i++) {
scrollList.itemChanged(i);
}
scrollList.invalidate();
}
When calling setNumberOfItems(0) while the ScrollList is not scrolled up to the top item, the "TimerWidget" counter gets incremented and after reaching a count of 255 I get the assertion. I'll explain next why I had the seemingly pointless call to setNumberOfItems(0) before setting the real size.
While developing on the target I had issues with some Items of the ScrollList did not update their content while scrolling through the list (mostly the last ones). I thought it's a bug of TouchGFX and played around with the ScrollList API and found out that setting the size to 0 at first fixed my problem. Now I understand why it helped and what I did wrong until now:
A ScrollList has a fixed number or DrawableListItems (typically number of visible list elements on screen + 2). In my for-loop I iterate over this count and thought itemChanged(i) would tell every DrawableListItem to trigger the item-update-callback. But I mixed the two indices the ScrollList is working with: One is the index of the DrawableListItems and the other one is the index to your list (counting up to whatever "numberofItems" your told the ScrollList to have. And itemChanged(i) expects an index to the later one.
Mixing those caused some of my items to never update. By resizing the ScrollList having it resized to 0 and back to whatever size it has, internally causes a call to the item-update-callback for each item on screen.
Now my update code looks like this:
scrollList.setNumberOfItems(size);
for (int i = 0; i < scrollList.getNumberOfItems(); i++) {
scrollList.itemChanged(i);
}
scrollList.invalidate();
The only disadvantage is when your list is long (like 1000 or so), you iterate over all of your items and TouchGFX filters out the elements currently shown on the screen calling the update-callback for those items.
To only iterate over the currently visible items I would need to know which elements are currently visible (the scroll offset). But unfortunately, the ScrollLists (inherited from ScrollBase) method getOffset() is declared as protected.
It's the same reason that prevents me from creating a scroll bar around the ScrollList - we don't have access to the scrolled position. Hopefully that changes with the next TouchGFX release. :)