cancel
Showing results for 
Search instead for 
Did you mean: 

I have a problem with VSYNC and TouchGFX since a recent update of the toolchain. model::tick is called too often.

WSchr.1
Associate II

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.

20 REPLIES 20
AWeng.2
Associate II

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

WSchr.1
Associate II

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.

AWeng.2
Associate II

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.

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().

AWeng.2
Associate II

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.

Martin KJELDSEN
Chief III

​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.

Could you clarify how the timing has changed for the OS scenario with OSWrappers::signalVSync() and OSWrappers::waitForVSync()? It no longer seems to block.

Mayank1
Associate II

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();

  }

}

AWeng.2
Associate II

@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.

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.