cancel
Showing results for 
Search instead for 
Did you mean: 

TouchGFX custom driver- vsync problem

maciek
Associate II

Hello,

I want to run TouchGFX on STM32F413VGTX MCU. It Doesnt not have LTDC nor DMA2D so I want to make it run using FSMC without graphic accelerator with my ST7529 LCD controller. The problem is I can not make it run.

I created a project with ToucGFX and custom driver:

0693W000001s14uQAA.png

I added MX_TouchGFX_Process() to the default task:

void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  for(;;)
  {
	  MX_TouchGFX_Process();
  }
  /* USER CODE END 5 */ 
}

And I added another task to trigger a vsync signal:

void testTask(void *argument)
{
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  for(;;)
  {
	  TouchGFX_TickHandler();
	  osDelay(1);
  }
  /* USER CODE END 5 */
}

The TouchGFX_TickHandler() is constructed as follows:

extern "C" {
    void TouchGFX_TickHandler(void)
    {
    	if (os_inited)
    	{
        	OSWrappers::signalVSync();
    	}
    }
}

And now, the result is everything is initializing, framebuffer is allocated, all the queues from OSWrappers are created, the TouchGFX process is running and it reaches void OSWrappers::waitForVSync(). It waits for a vsync_queue. When testTask reaches OSWrappers::signalVSync(); message is put into the queue and waitForVSync exits triggering Model::tick() and for example Screen1View::setupScreen(). After that OSWrappers::takeFrameBufferSemaphore() is called but osSemaphoreAcquire(frame_buffer_sem, osWaitForever) never gets a semaphore and it stucks.

The problems are:

  1. Nothing appears to happen with framebuffer. Engine does not draw anything to RAM.
  2. TouchGFX process never enters OSWrappers::waitForVSync() again. It seems like it waits for something.
  3. TouchGFX stucks in takeFrameBufferSemaphore().

What have I forgot about? My LCD does not have a vsync signal so I have to trigger it manually. Should I make it from ISR? Have I forgot about some instructions in TouchGFX_TickHandler()?

Thanks in advance,

Maciek

4 REPLIES 4
maciek
Associate II

Well, I modified my TouchGFX_TickHandler() (found somewhere in examples):

extern "C" {
    void TouchGFX_TickHandler(void)
    {
    	static bool tmp = false;
    	if (os_inited)
    	{
    		if (tmp)
    		{
    			tmp = false;
    			HAL::getInstance()->vSync();
    			OSWrappers::signalVSync();
    			HAL::getInstance()->swapFrameBuffers();
    		} else {
    			tmp = true;
                HAL::getInstance()->frontPorchEntered();
    		}
    	}
    }
}

Dunno if framebuffer semaphore problem happened with or without these additional lines. I managed to fix the problem with adding HAL::getInstance()->unlockFrameBuffer() in TouchGFXHAL::initialize(). This method unblocks the semaphore. Now everything is rolling.

Hi @maciek​,

There was an unfortunate bug in the CMSIS V2 OSWrapper generated by TouchGFX Generator that had an additional aquire() to the framebuffer semaphore. Nice find on your own that you could simply unlock() manually. I've already fixed it for the upcoming release a while back and should probably have mentioned it, but i wasn't seeing many issues here.

/Martin

maciek
Associate II

Hi @Martin KJELDSEN​ ,

Thank you for an answear.

I'd like to ask you if TouchGFX_TickHandler routine is written well according to my settings which are: custom driver (fsmc- data is flushed into LCD when flush routine is called), custom tick source, no DMA, single framebuffer. TouchGFX_TickHandler is copied from some example and I do not really know if it is good.

And how often do I need to call TouchGFX_TickHandler? 60 Hz will be enough?

It seems wasteful to constantly check if os is inited in the interrupt handler.

You may also not need to signal frontporchentered, unless you're using lockDMAToFrontPorch(true) setting.

All you really need to do is signal OSWrappers::signalVsync(); like you're doing. But you're just toggling on a variable (tmp) - You don't really know if you've entered the front porch.

swapFrameBuffers() is already called by the framework.

HAL::getInstance()->vsync() is only to increase a counter that can help you compensate for "missing frames" and skip those if you have performance issues so you don't have laggy animations.

60Hz is everones dream.