cancel
Showing results for 
Search instead for 
Did you mean: 

GPU2D not working on Custom board with STM32H7S7I8Tx

Leo_Berna99
Associate III

Good morning everyone, I need your help.
I am developing a custom board in which I mount the STM32H7S7I8x micro and a 7-inch 1024 x 600 LCD.
I have already developed the application, the graphics run correctly in the display and everything works fine.
For timing issues momentarily I have only used DMA2D for the graphics part and everything works perfectly apart from some slowness in some animations or scroll of big pages.
I then wanted to try adding GPU2D to see if the performance would improve, but I am having several problems.
Below I am including photos of how I configured it on CubeMX.
In fact I am in the situation where it is called once return HALGPU2D::beginFrame(); and then that is it, the code runs but does not give errors. It stays in “loop” in prvIdleTask. It does not flush (HALGPU2D::flushFrameBuffer(rect);) or even HALGPU2D::endFrame();
I don't understand how I can move, following the example codes in Demo ST it all looks “identical”.
The thing I find strange is that by enabling only DMA2D in the Middleware->TouchGFX section all my (already quite advanced) graphics work perfectly without bugs (except for a slight slowness in some situations)
Is there something I am missing to properly enable GPU2D on my micro? Besides the configuration on CubeMX?

8 REPLIES 8
GaetanGodart
ST Employee

Hello @Leo_Berna99 ,

 

XCubeTouchGFX.png :

GaetanGodart_0-1741876176552.png

Here you have not enabled DMA2D, only GPU2D.

When you enabled GPU2D, did you disabled DMA2D in the process?

You can enable both at the same time, perhaps this is what you should do.
Here is the configuration for the STM32H7S7 TBS:

GaetanGodart_1-1741876334864.png

 

Regards,

Gaetan Godart
Software engineer at ST (TouchGFX)

Hello @GaetanGodart , 

Thanks for your reply. Yes, I've already tried that solution, both DMA2D and GPU2D but it didn't work.

The result of the debug is the same unfortunately. 

The only working solution is enabling the DMA2D and no GPU2D, but I need that.

Any other suggestion?

@GaetanGodart Have you got any other suggestion?
The screenshot I sent you wss the only solution that worked for me.

Hello,

Have you enabled the GPU2D peripheral in CubeMX, so it is initialised?

Can you share your linker file?

Hello, Yes, it is enable on CubeMX and in the debug it is also initialised correctly. The problem seems to be in the situation where it is called "return HALGPU2D::beginFrame();" and then that is it, the code runs but does not give errors. It stays in “loop” in prvIdleTask. It does not flush (HALGPU2D::flushFrameBuffer(rect);) or even HALGPU2D::endFrame();

But the initialization returns a correct value.

/*
******************************************************************************
**
** @file        : LinkerScript.ld
**
** @author      : STM32CubeIDE
**
**  Abstract    : Linker script for STM32H7Sxx Device
**                      128KBytes FLASH
**                      456KBytes RAM
**
**                Set heap size, stack size and stack location according
**                to application requirements.
**
**                Set memory bank area and size if external memory is used
**
**  Target      : STMicroelectronics STM32
**
**  Distribution: The file is distributed as is, without any warranty
**                of any kind.
**
******************************************************************************
** @attention
**
** Copyright (c) 2024 STMicroelectronics.
** All rights reserved.
**
** This software is licensed under terms that can be found in the LICENSE file
** in the root directory of this software component.
** If no LICENSE file comes with this software, it is provided AS-IS.
**
******************************************************************************
*/

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = ORIGIN(DTCM) + LENGTH(DTCM); /* end of "DTCM" Ram type memory */

_Min_Heap_Size = 0x1000; /* required amount of heap */
_Min_Stack_Size = 0x1000; /* required amount of stack */

__FLASH_BEGIN  = 0x90000000;			/* prima di 0x400 mettimo crc */
__FLASH_SIZE   = 0x08000000;


__RAM_BEGIN    = 0x24000000;
__RAM_SIZE     = 0x71C00;
__RAM_NONCACHEABLEBUFFER_SIZE = 0x400;

/* Memories definition */
MEMORY
{
  RAM       (xrw) : ORIGIN = 0x24000000, LENGTH = 0x0006e000
  RAM_CMD   (rw)  : ORIGIN = 0x2406e000, LENGTH = 0x00004000
  RAM_NONCACHEABLEBUFFER (xrw) : ORIGIN = __RAM_BEGIN + __RAM_SIZE,  LENGTH = __RAM_NONCACHEABLEBUFFER_SIZE

  ITCM      (xrw) : ORIGIN = 0x00000000,    LENGTH = 0x00010000
  DTCM       (rw) : ORIGIN = 0x20000000,    LENGTH = 0x00003000			/*prima lenght era 0x00010000*/
  DTCM_RTOS (rw)  : ORIGIN = 0x20003000, LENGTH = 0x0000D000
  SRAMAHB   (rw)  : ORIGIN = 0x30000000,  LENGTH = 0x00008000
  BKPSRAM   (rw)  : ORIGIN = 0x38800000,  LENGTH = 0x00001000

  FLASH     (xrw) : ORIGIN = __FLASH_BEGIN, LENGTH = 0x00200000  /* prima era 0x00200000 tolti 0x400 per agg */
  FLASH_GFX (r)   : ORIGIN = 0x90200000, LENGTH = 0x09e00000
  EXTRAM    (rw)  : ORIGIN = 0xC0000000, LENGTH = 0x02000000
}

/* Sections */
SECTIONS
{
  /* The startup code into "FLASH" FLASH type memory */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH

  /* The program code and other data into "FLASH" FLASH type memory */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH

  /* Constant data into "FLASH" FLASH type memory */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH

  .ARM.extab (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    . = ALIGN(4);
  } >FLASH
  .ARM (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    . = ALIGN(4);
  } >FLASH

  .preinit_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    . = ALIGN(4);
  } >FLASH

  .init_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(4);
  } >FLASH

  .fini_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
    . = ALIGN(4);
  } >FLASH

  /* Used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  FreeRtosHeapSection :
  {
    *(.bss.ucHeap)
    . = ALIGN(0x8);
  } >DTCM_RTOS

  /* Initialized data sections into "RAM" Ram type memory */
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
    *(.RamFunc)        /* .RamFunc sections */
    *(.RamFunc*)       /* .RamFunc* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */

  } >RAM AT> FLASH
  
  /* Uninitialized data section into "RAM" Ram type memory */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss section */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM

  RW_NONCACHEABLE :
  {
    __NONCACHEABLEBUFFER_BEGIN = .;/* create symbol for start of section */
    KEEP(*(noncacheable_buffer))
    __NONCACHEABLEBUFFER_END = .;  /* create symbol for start of section */
  } > RAM_NONCACHEABLEBUFFER

  /* User_heap_stack section, used to check that there is enough "RAM" Ram  type memory left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >DTCM

  /* Remove information from the compiler libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
  
    BufferSection (NOLOAD) :
  {
    *(TouchGFX_Framebuffer TouchGFX_Framebuffer.*)
    *(.gnu.linkonce.r.*)
    . = ALIGN(0x8);

    *(Nemagfx_Stencil_Buffer Nemagfx_Stencil_Buffer.*)
    *(.gnu.linkonce.r.*)
    . = ALIGN(0x8);
  } >EXTRAM

  UncachedSection (NOLOAD) :
  {
    *(Nemagfx_Memory_Pool_Buffer Nemagfx_Memory_Pool_Buffer.*)
    *(.gnu.linkonce.r.*)
    . = ALIGN(0x8);
  } >RAM_CMD
  
    FontFlashSection :
  {
    *(FontFlashSection FontFlashSection.*)
    *(.gnu.linkonce.r.*)
    . = ALIGN(0x4);
  } >FLASH_GFX

  TextFlashSection :
  {
    *(TextFlashSection TextFlashSection.*)
    *(.gnu.linkonce.r.*)
    . = ALIGN(0x4);
  } >FLASH_GFX

  ExtFlashSection :
  {
    *(ExtFlashSection ExtFlashSection.*)
    *(.gnu.linkonce.r.*)
    . = ALIGN(0x4);
  } >FLASH_GFX
}

 

Have you enabled "ICACHE_GPU2D" under System core in CubeMX as well? It should be set to 2-way set associate.

The GPU2D command list is linked to the section 

RAM_CMD   (rw)  : ORIGIN = 0x2406e000, LENGTH = 0x00004000

The TouchGFX board setup uses these values:

RAM_CMD   (rw)  : ORIGIN = 0x2406c000, LENGTH = 0x00006000

If you have the memory to spare, I would suggest trying to match that. In any case, you should set up an MPU region to cover the memory area as shown in the screenshot.

cmdlistmpu.png

Hi @mathiasmarkussen , thank you very much.
Well, with this MPU configuration the "white page" problem is gone. My graphic now is "running".
BUT it is not running smootly, as a matter of fact, I have a lot of graphic artifact, like flickering.
Probably this are linked to the invalidation process of particular widget.

for example on a page I have a text area (representing my system time) that is updated through UART every second in a hadleTickEvent(). The flicker I see is synchronized with the seconds precisely.
In other pages, where I have no such updates I have no flicker but I have them for example when I make a page change or at the start of a slider.
What I don't understand is how this never gave any problem with ONLY dma2D active and now that I add GPU2D I have them.
I attach below the configuration used for GPU2D in the middleware area in STMCubeMX.

I can't understand if this is a "graphic" problem, like too many widget layered together or I have a wrong configuration of my peripherals.

Thank you very much for your help.
Leo



Is DMA2D disabled as shown in you screen shot? There should be no harm in keeping that enabled.

Have you tried flashing a different UI, for example importing one of the demos that are supplied with the designer and seeing how that performs?

You can flash them even though they have sad faces because the resolution does not match.