cancel
Showing results for 
Search instead for 
Did you mean: 

Using CubeIDE 1.2.1 on Windows 10, TouchGFXDesigner's generated code doesn't implement virtual method HAL::taskEntry() in TouchGFXGeneratedHAL or ToughGFXHAL..

CDew.1
Associate III

I've generated a STM32F429I-DISCO project using CubeIDE's CubeMX.

I've added the X-CUBE-TOUCHGFX 4.13.0 software to the project, under Additional Software.

By changing LTDC and FMC settings, I was able to configure X-CUBE-TOUCHGFX successfully.

The project had a file with a .part extension. (I can't remember the filename, but an ApplicationTemplate.touchgfx.part still exists, it might well be that.) Clicking that launched TouchGFX Designer.

I used the designer to choose a template project, saved it and also clicked Generate Code.

Exiting TouchGFX designer, I found that it had generated code in the CubeIDE project. Specifically project/Middlewares/ST/touchgfx and project/TouchGFX trees had been added.

After a few include-path tweaks, the project built and ran, but showed only a white screen.

When I looked at the generated main.c code, I found only a dummy task. No GUI task had been created or added.

I added the following, based on other questions on this site:

#define GUI_TASK_PRIORITY                 ( tskIDLE_PRIORITY + 3 )
#define GUI_TASK_STK_SIZE                 ( 1024 )
 
void *guiTaskHandle;
 
void touchgfx_taskEntry();
void GUI_Task(void * argument)
{
  touchgfx_taskEntry();
}
...
int main(void) {
  ...
  xTaskCreate(GUI_Task,
              "GUI",
              GUI_TASK_STK_SIZE,
              NULL,
              GUI_TASK_PRIORITY,
              &guiTaskHandle);

(When I add my own infinite loop and a breakpoint into GUI_Task I can see it being successfully run by the scheduler, so I'm happy that it's not a FreeRTOS issue. touchgfx_init() is being called by MX_TouchGFX_Init(), so that's also not the issue.)

touchgfx_taskentry() is defined in the generated project/TouchGFX/target/generated/TouchGFXConfiguration.cpp: 

void touchgfx_taskEntry()
{
 /*
  * Main event loop. Will wait for VSYNC signal, and then process next frame. Call
  * this function from your GUI task.
  *
  * Note This function never returns
  */
  hal.taskEntry();
}

When I ran this code in the debugger, I could not step into hal.taskEntry(), it returned immediately.

Then I learned that it is possible for a unimplemented virtual function to called in C++ and for the program to still compile. (I haven't used C++ since last century, so I'm rusty.)

Using grep over the whole project directory, I was unable to find an implementation of HAL::taskEntry(). (I'm normally a Linux developer. I'm just using Windows for TouchGFXDesigner (which is a Windows executable) so I use WSL and Linux tools, rather than PowerShell.)

vm@DESKTOP-2IPU7SQ:/mnt/c/Users/vm/STM32CubeIDE/workspace_1.1.0/project$ grep -R taskEntry * 2> /dev/null | grep -v "Binary file"
Core/Src/main.c:void touchgfx_taskEntry();
Core/Src/main.c: touchgfx_taskEntry();
Debug/f429.list:void touchgfx_taskEntry();
Debug/f429.list: touchgfx_taskEntry();
Debug/f429.list: 8000600:       f013 fdec       bl      80141dc <touchgfx_taskEntry>
Debug/f429.list:080141dc <touchgfx_taskEntry>:
Debug/f429.list:void touchgfx_taskEntry()
Debug/f429.list:  hal.taskEntry();
Debug/f429.list: 80141e0:       4802            ldr     r0, [pc, #8]    ; (80141ec <touchgfx_taskEntry+0x10>)
Debug/f429.list: 80141e2:       f001 f8d0       bl      8015386 <_ZN8touchgfx3HAL9taskEntryEv>
Debug/f429.list:08015386 <_ZN8touchgfx3HAL9taskEntryEv>:
Debug/f429.list: 80153a0:       e7f8            b.n     8015394 <_ZN8touchgfx3HAL9taskEntryEv+0xe>
Debug/f429.map: .text.touchgfx_taskEntry
Debug/f429.map:                0x00000000080141dc                touchgfx_taskEntry
Debug/f429.map: .text._ZN8touchgfx3HAL9taskEntryEv
Debug/f429.map:                0x0000000008015386                touchgfx::HAL::taskEntry()
Debug/TouchGFX/target/generated/TouchGFXConfiguration.su:TouchGFXConfiguration.cpp:51:6:void touchgfx_taskEntry()      8static
Middlewares/ST/touchgfx/framework/include/platform/hal/simulator/sdl2/HALSDL2.hpp:     * @fn virtual void HALSDL2::taskEntry();
Middlewares/ST/touchgfx/framework/include/platform/hal/simulator/sdl2/HALSDL2.hpp:    virtual void taskEntry();
Middlewares/ST/touchgfx/framework/include/touchgfx/hal/HAL.hpp:     * @fn virtual void HAL::taskEntry();
Middlewares/ST/touchgfx/framework/include/touchgfx/hal/HAL.hpp:    virtual void taskEntry();
Middlewares/ST/touchgfx/framework/source/platform/hal/simulator/sdl2/HALSDL2.cpp:void HALSDL2::taskEntry()
TouchGFX/App/app_touchgfx.c:void touchgfx_taskEntry(void);
TouchGFX/App/app_touchgfx.c:  touchgfx_taskEntry();
TouchGFX/App/app_touchgfx.c:  touchgfx_taskEntry();
TouchGFX/simulator/main.cpp:    touchgfx::HAL::getInstance()->taskEntry(); //Never returns
TouchGFX/target/generated/TouchGFXConfiguration.cpp:extern "C" void touchgfx_taskEntry();
TouchGFX/target/generated/TouchGFXConfiguration.cpp:void touchgfx_taskEntry()
TouchGFX/target/generated/TouchGFXConfiguration.cpp:  hal.taskEntry();

TouchGFXHAL derives from TouchGFXGeneratedHAL which derives from HAL. taskEntry is virtual in HAL:

/**
     * @fn virtual void HAL::taskEntry();
     *
     * @brief Main event loop.
     *
     *        Main event loop. Will wait for VSYNC signal, and then process next frame. Call
     *        this function from your GUI task.
     *
     * @note This function never returns!
     */
    virtual void taskEntry();

and not mentioned in TouchGFGeneratedHAL.[ch]pp or TouchGFXHAL.[ch]pp.

How do I make TouchGFX Designer generate this essential code?

2 REPLIES 2
CDew.1
Associate III

I found a libtouchgfx-float-abi-hard.a library which TouchGFXDesigner must have added to the CubeIDE project.

Disassembling it, with /usr/arm-none-eabi/bin/objdump -d libtouchgfx-float-abi-hard.a, I found:

Disassembly of section .text._ZN8touchgfx3HAL9taskEntryEv:
 
00000000 <_ZN8touchgfx3HAL9taskEntryEv>:
   0:   b508            push    {r3, lr}
   2:   6803            ldr     r3, [r0, #0]
   4:   4604            mov     r4, r0
   6:   6e9b            ldr     r3, [r3, #104]  ; 0x68
   8:   4798            blx     r3
   a:   6823            ldr     r3, [r4, #0]
   c:   6e1b            ldr     r3, [r3, #96]   ; 0x60
   e:   4620            mov     r0, r4
  10:   4798            blx     r3
  12:   f7ff fffe       bl      0 <_ZN8touchgfx10OSWrappers12waitForVSyncEv>
  16:   6823            ldr     r3, [r4, #0]
  18:   6d9b            ldr     r3, [r3, #88]   ; 0x58
  1a:   e7f8            b.n     e <_ZN8touchgfx3HAL9taskEntryEv+0xe>

The name _ZN8touchgfx3HAL8endFrameEv demangles to touchgfx::HAL::taskEntry(). Thanks https://demangler.com/

So it seems to have a default implementation in the (closed-source?) touchgfx library.

Is this why the debugger refuses to step into .taskEntry()?

How can I debug through closed-source code?

nwm_35
Associate III

Did you ever figure this out? I'm having this exact issue right now. STM32u5 and the hal::taskEntry() function doesn't seem to exist