cancel
Showing results for 
Search instead for 
Did you mean: 

UI flickering resolved, but unclear how (ITM/DWT?)

etamarin
Associate III

I am in a pretty strange situation here.

I have an application using FreeRTOS and TouchGFX. This application occasionally sees screen flickering. I have tried different ways to mitigate it but have been unsuccessful until recently.

I tried enabling ITM and DWT to use the CYCCNT counter and ITM port 0 for some debug messages. I perform a print through the ITM port every 500 ms or so.

As far as I can tell, the addition of printing through the ITM port has reduced the flickering significantly. I have switched between my commits and this is pretty much the only change that's led to this improvement.

Personally I find this counterintuitive, as the printf call could only make things worse in terms of timings and memory accesses. However, this is not what I observe and so my questions are as follows:

  • Is there any process by which enable the ITM/DWT debug frameworks could make the screen flickering issue disappear?
  • Is there a good way to calculate timings for TouchGFX related processes and memoery accesses to compare the performace before and after?

Further information: I am using double framebuffer strategy (with animation buffer as well), LTDC, FMC is configured to use SDRAM bank 2 and has a 512Mbit memory connected to it. MCU is STM32H750.

Any help is appreciated.

12 REPLIES 12

Interesting, could you please share your linker script? 

Mohammad MORADI
ST Software Developer | TouchGFX

Here it is:

/* Entry Point */
ENTRY(Reset_Handler)

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

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

/* Memories definition */
MEMORY
{
  DTCMRAM      (xrw)    : ORIGIN = 0x20000000,   LENGTH = 128K
  ITCMRAM      (xrw)    : ORIGIN = 0x00000000,   LENGTH = 64K
  RAM_D1       (xrw)    : ORIGIN = 0x24000000,   LENGTH = 512K
  RAM_D2       (xrw)    : ORIGIN = 0x30000000,   LENGTH = 288K
  RAM_D3       (xrw)    : ORIGIN = 0x38000000,   LENGTH = 64K
  SDRAM        (xrw)    : ORIGIN = 0xD0000000,   LENGTH = 8M
  FLASH	       (xrw)    : ORIGIN = 0x90000000,   LENGTH = 2048K
  ASSETS_FLASH (r)      : ORIGIN = 0x90200000,   LENGTH = 126M
  BOOTLOADER   (xrw)    : ORIGIN = 0x08000000,   LENGTH = 128k
}

TARGET(binary) /* specify the file format of binary file */
OUTPUT_FORMAT(default) /* restore the out file format */

/* Sections */
SECTIONS
{

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

  /* The program code and other data into "FLASH" Rom 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" Rom type memory */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH

  .ARM.extab   : {
    . = ALIGN(4);
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    . = ALIGN(4);
  } >FLASH

  .ARM : {
    . = ALIGN(4);
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    . = ALIGN(4);
  } >FLASH

  .preinit_array     :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    . = ALIGN(4);
  } >FLASH

  .init_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(4);
  } >FLASH

  .fini_array :
  {
    . = 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);

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

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

  } >RAM_D1 AT> FLASH

  /* Uninitialized data section into "RAM_D1" 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_D1

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

  /* Remove information from the compiler libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }
  
  /* Add memory to RAM_D2 */
  /* Put __attribute__ ((section(".second_ram_buf"), used)) before a variable to store it here */
  .second_ram_buf(NOLOAD):
  {
  	. = ALIGN(4);
  	*(.second_ram_buf)
  	*(.second_ram_buf*)
  } >RAM_D2
  
  .third_ram_buf(NOLOAD):
  {
  	. = ALIGN(4);
  	*(.third_ram_buf)
  	*(.third_ram_buf*)
  } >RAM_D3

  .ARM.attributes 0 : { *(.ARM.attributes) }



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

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

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

  BmpCacheSection (NOLOAD) : { *(BmpCacheSection) } >SDRAM
  TouchGFX_Framebuffer (NOLOAD) : { *(TouchGFX_Framebuffer) } >SDRAM

}

The linker script looks good.

I suggest using an oscilloscope or logic analyzer to check how much the writings you mentioned affect TouchGFX performance. There is documentation available here to help you do the monitoring. 

Please give it a try if possible for you and share your findings with us

Mohammad MORADI
ST Software Developer | TouchGFX