Skip to main content
ebray
Associate III
April 17, 2020
Question

TouchGFX with SPI TFT

  • April 17, 2020
  • 31 replies
  • 9138 views

I've created a simple project to interface a STM32L4R91-DISCO with a TFT using a SPI interface. I've attempted to follow the TouchGFX tutorial but thus far have been unsuccessful in getting the TouchGFX library to render anything.

I have a task that sits in a loop, periodically calling OSWrappers::signalVSync(). This appears to work as the vsync_queue fills up. However, in my separate task which is running the ToughGFX loop, the call to OSWrappers::waitForVsync never returns. This mean the frames don't get rendered and flushed to the display.

Any suggestions for getting this running would be greatly appreciated!

I'm using STM32CubeIDE 1.3.1 with TouchGFX 4.13.0.

This topic has been closed for replies.

31 replies

ebray
ebrayAuthor
Associate III
April 29, 2020

I removed the acquire call in initialize:

void OSWrappers::initialize()
{
 // Create a queue of length 1
 frame_buffer_sem = osSemaphoreNew(1, 1, NULL); // Binary semaphore
 //osSemaphoreAcquire(frame_buffer_sem, osWaitForever); // take the lock
 
 // Create a queue of length 1
 vsync_queue = osMessageQueueNew(1, 4, NULL);
}

Unfortunately, it did not resolve the issue. I'm going to try the hardware timer next and get back to you. Out of curiosity though, is there any advantage to a hardware timer other than being more precise with the timing? It doesn't seem like it should have any impact on the issue I'm encountering.

Thanks!

ebray
ebrayAuthor
Associate III
April 29, 2020

Using a hardware timer also makes no difference. I verified the timer is functioning correctly by toggling an LED in the interrupt handler.

Would it be helpful if I shared my project?

Thanks!

Martin KJELDSEN
Principal III
April 29, 2020

The comment about the VSYNC was unrelated, yeah.

What is the state of the application? Stil doesn't return from waitForVSync()? Can you check the state of the semaphore somehow? To see if your wrapper has properly put something in the queue

/Martin

ebray
ebrayAuthor
Associate III
April 29, 2020

I've verified that the vsync signal is definitely being added to the queue. It also appears that both osMessageQueueGet() calls in waitForVSync() are succeeding. I've confirmed this by adding LED toggles surrounding them. However, after that GUI appears to get stuck at lockFrameBuffer(). I assume this function is implemented in libtouchgfx.a because there is no source available for it.

0693W000000WgQeQAK.jpg

Martin KJELDSEN
Principal III
April 29, 2020

Yes, HAL::lockFrameBuffer(); calls OSWrappers::takeFrameBufferSemaphore(); so you could break in there and see what happens.

/Martin

ebray
ebrayAuthor
Associate III
April 29, 2020

I added breakpoints in OSWrappers::takeFrameBufferSemaphore() (as well as OSWrappers::tryTakeFrameBufferSemaphore() for good measure) but neither of them is reached. It appears that lockFrameBuffer gets hung up before calling them.

Martin KJELDSEN
Principal III
April 29, 2020

The only thing two functions that are called inside `HAL::lockFrameBuffer();` are the following - BUT only if you're NOT using Double Buffering. So if you're not - try enabling double buffering to see if you can skip these functions and see if somehow they cause a crash for you.

dma.isDmaQueueEmpty();
dma.getAllowed();

/Martin

ebray
ebrayAuthor
Associate III
April 29, 2020

I was using single buffering. I changed it to double buffering and now it does indeed make it into OSWrappers::takeFrameBufferSemaphore(). The subsequent call to osSemaphoreAcquire() never returns though.

Since single buffering isn't working, and those two functions you mentioned appear related to DMA, perhaps there's something misconfigured there?

ebray
ebrayAuthor
Associate III
May 22, 2020

Martin,

I've got some more time to spend on this now and wanted to circle back with you. To recap:

Double Buffering: This now seems to work, but only after commenting out the osSemaphoreAcquire() call in OSWrappers::initialize(). Unfortunately, this modification gets reverted every time CubeMX code is generated. It seems like this is bug that needs to be resolved.

Single Buffering: This still does not work. The fix for Double Buffering does not seem to have any impact. The program continues to execute but the GUI task is stuck in HAL::lockFrameBuffer() and never returns. There is no source available for this function but this is what the disassembly shows:

0693W000001pKFRQA2.jpg

Execution stays inside the 3 highlighted lines.

Could you please help me sort out what is going wrong here? Using double buffering isn't really a viable option as it consumes all of the available RAM.

Thanks!

Eric

Martin KJELDSEN
Principal III
May 26, 2020

Hi Ebray,

This is definitely an issue and i just created a branch to fix it - Until then, you need an update so you won't have to revert/fix it every time. I could send it to you, but you can actually fix it yourself temporarily.

Edit the following file - Search for "CMSIS V2" (This is not a problem for V1). Remove the call to `osSemaphoreAcquire(frame_buffer_sem, osWaitForever);`

C:\Users\eric\STM32Cube\Repository\Packs\STMicroelectronics\X-CUBE-TOUCHGFX\4.13.0\CubeMX\templates\Target\OSWrappers_cpp.ftl

 /Martin

ebray
ebrayAuthor
Associate III
May 26, 2020

Martin,

Thank you for pointing me to the template for the temporary fix. I'm able to get the modification to persist and Double Buffering now appears to work as expected.

Do you have any thoughts as to what could be causing the issue for the Single Buffer option? My display is 320x480 so unnecessarily using 2 frame buffers consumes over 90% of the RAM which is very restrictive to my application.

Thanks!

Eric

Richard Lowe
Senior II
February 2, 2021

I can confirm that I have the same behavior. Works with double buffering but fails on unlocking buffer when single buffer is used. Can we get confirmation that this is a bug and if it is or isn't being looked at?

VLau
Associate III
April 26, 2021

Same behavior here. Engine stucks with single buffering strategy option enabled in CubeMX. Only double buffering works.

HAL.hpp
 
virtual void backPorchExited()
{
 swapFrameBuffers();
 tick(); // <- here
}

SMour.1
Associate III
June 1, 2021

I seem to have a very similar problem , even though a simple test like that works

//freeRtos thread 1
while(true)
{
 LL_GPIO_SetOutputPin(LFO1_LED_GPIO_Port,LFO1_LED_Pin) ;
 touchgfx::OSWrappers::signalVSync();
}
//freeRtos thread2
while (true)
{
 touchgfx::OSWrappers::waitForVSync();
 LL_GPIO_ResetOutputPin(LFO1_LED_GPIO_Port,LFO1_LED_Pin) ;
}

replacing the second thread with   

MX_TouchGFX_Process();

Seems to stuck before even calling

flushFrameBuffer

Alexandre RENOUX
Visitor II
January 26, 2022

@Michael K​ @ebray​ @Richard Lowe​ @VLau​ @SMour.1​ 

Hello,

I see that the issue is reproduced by many and to investigate we need more information.

From what I understand (correct me if I'm wrong), it's a problem that happens with STM32L4 and could normally be reproduced with L4R9-DISCO or L496-DISCO.

Do you all use one of these 2 MCUs with DSI and Single buffering ? Does it also happen with other MCUs ?

Have you tried using the latest 4.18.1 TouchGFX version and checking if it is working or not ?

Could you provide the steps you did to reproduce the issue ?

Thank you very much for your help ~

/Alexandre

VLau
Associate III
January 26, 2022

I had a problem with the single buffer option. My setup was random SPI TFT display and NUCLEO board. Solved it with the following answer:

0693W00000JNNbgQAH.png