cancel
Showing results for 
Search instead for 
Did you mean: 

TouchGFX GUI freezes, stuck in OSWrappers::takeFrameBufferSemaphore()

PontusL
Associate III

Hi. I am having issues with my TouchGFX application freezing since the semaphore blocking my UI thread is never returned. The screen freezes after running for roughly 10 minutes, sometimes earlier, sometimes after longer times. Based on what I have read in other posts, it could be DMA2D related (?). 

I am running TouchGFX 4.22 on a custom board using a STM32H750 with DMA2D/ChormeART enabled. Assets are stored in external flash, single framebuffer in SDRAM. System is running FreeRTOS. 480x272 screen running using LTDC.

Not really sure how to tackle this issue or how to solve it. Here is what I have tried so far (without any success)

  • I have tried playing around with the DMA2D interrupt priority, but the issue still remains the regardless of the priority is 5, 9 or 15. This seemed to have some effect here.
  • I have tried guarding the endFrame() function as suggested here. I added this solution in TouchGFXGeneratedHAL::endFrame().
  • I tried changing osSemaphoreWait(frame_buffer_sem, osWaitForever); to osSemaphoreWait(frame_buffer_sem, 50); This only resulted in the application being stuck in touchgfx::LockFreeDMA_Queue::isFull() instead of xQueueSemaphoreTake() at queue.c.
  • I have tried the solutions here. None of the suggestions solved in for me. I put the code changes below.

Suggestion 1:

 

//In STM32DMA.cpp
 
void tearDown()
{
    /* Wait for DMA2D to finish last run */
    while ((READ_REG(DMA2D->CR) & DMA2D_CR_START) != 0U);
    
    /* Clear transfer flags */
    WRITE_REG(DMA2D->IFCR, DMA2D_FLAG_TC|DMA2D_FLAG_CE|DMA2D_FLAG_TE);
}

//changed to 

void tearDown()
{
    /* Wait for DMA2D to finish last run */
    while ((READ_REG(DMA2D->CR) & DMA2D_CR_START) != 0U);
    
    if (DMA2D->CR & DMA2D_CR_TCIE) {
        /* DMA2D interrupt enabled, wait until ISR has been executed, flags are cleared by the ISR */
        while ((DMA2D->ISR & DMA2D_CR_TCIE) != 0u); //or while ((DMA2D->ISR & DMA2D_ISR_TCIF) != 0u);
    } else {
        /* DMA2D interrupt disabled, manually clear transfer flags */
        WRITE_REG(DMA2D->IFCR, DMA2D_FLAG_TC|DMA2D_FLAG_CE|DMA2D_FLAG_TE);
    }
}​

 


Suggestion 2:

 

//in stm32h7xx_hal_dma2d.c

if ((isrflags & DMA2D_FLAG_TC) != 0U)

//changed to 

if ((isrflags & DMA2D_FLAG_TC) != 0U || isrflags == 0U)​

 

 

I am out of ideas here. Do anyone have any input? Any suggestions on how to debug this further? 

 

Here's the stack when the screen freezes.

Spoiler
Thread #11 [UITask] 604002396 (Suspended : Container)
xQueueSemaphoreTake() at queue.c:1 573 0x4cee
osSemaphoreWait() at cmsis_os.c:806 0x3fa0
touchgfx::OSWrappers::takeFrameBufferSemaphore() at OSWrappers.cpp:50 0x900d3c68
touchgfx::HAL::lockFrameBuffer() at 0x9013c9fa
touchgfx::LCD24bpp::drawGlyph() at 0x90146a0a
touchgfx::LCD::drawStringInternal() at 0x9013e734
touchgfx::LCD::drawStringLTR() at 0x9013eb5e
touchgfx::LCD::drawString() at Texts.cpp:54 0x9008843a
touchgfx::TextAreaWithWildcardBase::draw() at TextAreaWithWildcard.cpp:28 0x90027e20
touchgfx::Screen::JSMOC() at 0x90140d28
touchgfx::Screen::JSMOC() at 0x90140c5c
touchgfx::Screen::JSMOC() at 0x90140c5c
touchgfx::Screen::startSMOC() at 0x90140d7e
touchgfx::Screen::draw() at 0x90140dac
touchgfx::Application::draw() at 0x9013f18c
touchgfx::Application::drawCachedAreas() at 0x9013fe0e
touchgfx::HAL::tick() at 0x9013c066
touchgfx::HAL::backPorchExited() at HAL.hpp:641 0x900d37ca
TouchGFXHAL::taskEntry() at TouchGFXHAL.cpp:60 0x900d3a6c
touchgfx_taskEntry() at TouchGFXConfiguration.cpp:73 0x900d4e5a
MX_TouchGFX_Process() at app_touchgfx.c:80 0x9003e3a0

 

1 ACCEPTED SOLUTION

Accepted Solutions
PontusL
Associate III

In my case, it came down to the initialization order of LTDC, DMA2D and TouchGFX. If either of LTDC or DMA2D was initialized after TouchGFX, this issue would show up. Previously, I had the function calls MX_LTDC_Init() and MX_DMA2D_Init() in my UI thread, before running MX_TouchGFX_Process(). I moved the inits back to main and lets CubeMX generate the function calls, which solved my issues.

View solution in original post

1 REPLY 1
PontusL
Associate III

In my case, it came down to the initialization order of LTDC, DMA2D and TouchGFX. If either of LTDC or DMA2D was initialized after TouchGFX, this issue would show up. Previously, I had the function calls MX_LTDC_Init() and MX_DMA2D_Init() in my UI thread, before running MX_TouchGFX_Process(). I moved the inits back to main and lets CubeMX generate the function calls, which solved my issues.