2024-05-10 07:38 AM - edited 2024-05-10 08:08 AM
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:
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.
2024-06-26 02:40 AM
Interesting, could you please share your linker script?
2024-06-26 02:57 AM
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
}
2024-06-27 02:59 AM
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.