Skip to main content
CDew.1
Associate III
March 11, 2020
Question

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

  • March 11, 2020
  • 2 replies
  • 1413 views

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?

This topic has been closed for replies.

2 replies

CDew.1
CDew.1Author
Associate III
March 11, 2020

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?

Associate
November 15, 2023

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