2021-01-20 08:55 AM
The change in the generated code is in TouchGFXConfiguration.cpp touchgfx_taskEntry().
Before the update it called OSWrappers::waitForVSync();
Now it calls
if (OSWrappers::isVSyncAvailable())
{
hal.backPorchExited();
}
which does not reset vsync_sem in OSWrappers. So the tick is called again and again.
I am not sure if the change came from CubeMX 1.6.10 or TouchGFX 4.15 or STM32H7 1.8.
I am using STM32H743, LTDC with internal framebuffer, a RGB565 Display and no RTOS.
As soon as AZURE RTOS is available, I plan to use it, but until then I have to keep my application running.
I can change the code back to waitForVSync(), but it will be overwritten, when I regenerate the code with CubeMX.
2021-02-24 07:44 AM
@moredatalesscenter after the update the TouchGFX does not wait anymore for VSYNC Interrupts, so it tries to do as many updates as it can. Thats the cause you see the CPU usage increase.
In fact the vsync_sem gets set in in the interrupt, but never reset. So you need to add the function OSWrappers::signalRenderingDone(); somewhere.
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
MX_TouchGFX_Process();
/* USER CODE BEGIN 3 */
OSWrappers::signalRenderingDone();
}
/* USER CODE END 3 */
2021-02-24 07:55 AM
This looks like a pretty good place for the call. At least it does not get overwritten.
But it would be fine if someone who knows about TouchGFX internals could confirm that.
Maybe the call should be different whether double buffering is used or not.
So far this solution works fine for me.
2021-02-24 08:03 AM
If depend on your strategy what should happen if you use to much rendering time. If you call this function as early than possible, then the next refresh will be done direct after the end of the last one and you could maybe stay in sync (if you use ticks() for "exact" timing. But it could generate tearing.
On the other hand, calling it in main.c as latest as possible, guaranties you less tearing but a possible refresh time loss if your rendering time gets to high.
Both ways can not help if you regularly over time the rendering time, so better fix that than worry so much about the best position.
2021-02-24 08:17 AM
My OSWrappers::waitForVSync() is waiting on a semaphore that is set from OSWrappers::signalVSync(), which is called from a timer. Both are still being called. I don't have a body for OSWrappers::signalRenderingDone().
2021-02-24 08:31 AM
but OSWrappers::waitForVSync() will be not more called, touchgfx_taskEntry() now calls isVSyncAvailable() instead.
void touchgfx_taskEntry()
{
/*
* Main event loop will check for VSYNC signal, and then process next frame.
*
* Note This function returns immediately if there is no VSYNC signal.
*/
if (OSWrappers::isVSyncAvailable())
{
hal.backPorchExited();
}
}
Just insert OSWrappers::signalRenderingDone() in your main and it is fixed.
2021-02-24 02:33 PM
Let me try to clarify this tomorrow perhaps, getting a bit late here:
isVsyncAvailable() is used now when you're not running an operating system. It's a mechanism that can give you a bit more control of what you do with your vsyncs, along with signalRenderingDone(). isVsyncAvailable() is a function that can return something rather than busy-waiting in NO OS scenario which usually is not possible.
In the meantime, you can check the G071 AT to see how these functions are used there.
2021-02-24 05:56 PM
Could you clarify how the timing has changed for the OS scenario with OSWrappers::signalVSync() and OSWrappers::waitForVSync()? It no longer seems to block.
2021-02-24 09:05 PM
Hi @WSchr.1
Try Implementing a timer, and write this code in your main.c. In this case TIM6 is implemented
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
{
if (htim->Instance == TIM6)
{
touchgfx_signalVSyncTimer();
}
}
2021-02-25 12:26 AM
@Mayank Why should a timer be a good solution (the other solution work just fine)? The timer solution lacks any synchronisation with TFT vsinc interrupts and therefore it will produce visible artefacts if you have animations.
2021-02-25 12:28 AM
But signalRenderingDone() is not called at any place and then isVsyncAvailable() is always true and TouchGFX renders as fast as it can instead once per VSync Interrupt.