Skip to main content
heyo
Associate III
June 28, 2023
Question

FrontendHeap store in to external SDRAM hardfault

  • June 28, 2023
  • 11 replies
  • 7443 views

Hi, still can't to upload frontend heap to my 8MB external SDRAM.

My linker script:

 

/*
******************************************************************************
**
** File : LinkerScript.ld
**
** Author : STM32CubeIDE
**
** Abstract : Linker script for STM32H7 series
** 2048Kbytes FLASH and 1056Kbytes 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) 2022 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(RAM_D1) + LENGTH(RAM_D1); /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x1000; /* required amount of heap */
_Min_Stack_Size = 0x1000; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
 FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
 DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
 RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512K
 RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K
 RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K
 ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K
 QUADSPI (r) : ORIGIN = 0x90000000, LENGTH = 16M
 SDRAM (xrw) : ORIGIN = 0xC0000000, LENGTH = 8M
}

/* Define output sections */
SECTIONS
{
 /* The startup code goes first into FLASH */
 .isr_vector :
 {
 . = ALIGN(4);
 KEEP(*(.isr_vector)) /* Startup code */
 . = ALIGN(4);
 } >FLASH
 /* The program code and other data goes into FLASH */
 .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 goes into FLASH */
 .rodata :
 {
 . = ALIGN(4);
 *(.rodata) /* .rodata sections (constants, strings, etc.) */
 *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
 . = ALIGN(4);
 } >FLASH

 .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
 .ARM : {
 __exidx_start = .;
 *(.ARM.exidx*)
 __exidx_end = .;
 } >FLASH

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

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

 .fini_array :
 {
 PROVIDE_HIDDEN (__fini_array_start = .);
 KEEP (*(SORT(.fini_array.*)))
 KEEP (*(.fini_array*))
 PROVIDE_HIDDEN (__fini_array_end = .);
 } >FLASH

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

 /* Initialized data sections goes into RAM, load LMA copy after code */
 .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_D1 AT> FLASH

 /* Uninitialized data section */
 . = 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 left */
 ._user_heap_stack :
 {
 . = ALIGN(8);
 PROVIDE ( end = . );
 PROVIDE ( _end = . );
 . = . + _Min_Heap_Size;
 . = . + _Min_Stack_Size;
 . = ALIGN(8);
 } >RAM_D1


	.sdram_section (NOLOAD) : { *(.sdram_section) }> SDRAM
 TouchGFX_Framebuffer (NOLOAD) : { *(TouchGFX_Framebuffer) } >SDRAM
 /* Remove information from the standard libraries */
 /DISCARD/ :
 {
 libc.a ( * )
 libm.a ( * )
 libgcc.a ( * )
 }
 .ARM.attributes 0 : { *(.ARM.attributes) }

 FontFlashSection(NOLOAD) : /*DELETE (NOLOAD) IF U WANT TO UPDATE QSPI FLASH*/
 {
 *(FontFlashSection FontFlashSection.*)
 *(.gnu.linkonce.r.*)
 . = ALIGN(0x4);
 } >QUADSPI

 TextFlashSection(NOLOAD) :/*DELETE (NOLOAD) IF U WANT TO UPDATE QSPI FLASH*/
 {
 *(TextFlashSection TextFlashSection.*)
 *(.gnu.linkonce.r.*)
 . = ALIGN(0x4);
 } >QUADSPI

 ExtFlashSection(NOLOAD) :/*DELETE (NOLOAD) IF U WANT TO UPDATE QSPI FLASH*/
 {
 *(ExtFlashSection ExtFlashSection.*)
 *(.gnu.linkonce.r.*)
 . = ALIGN(0x4);
 } >QUADSPI
}

 

I placed my double framebuffer to other address:

heyo_0-1687933999431.png

Set framebuffer in LTDC start:

heyo_1-1687934027748.png

And add line to FrontendHeap.hpp:

heyo_2-1687934079010.png

And I always get hardfault at : (__attribute__ ((section (".sdram_section")))) .Maybe someone see the mistake and can help? Thank you.

 

This topic has been closed for replies.

11 replies

uilter
Senior
June 29, 2023

Did you setup your MPU peripheral?

This is an example that works for me, but in my case the SDRAM have 16MB.
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.BaseAddress = 0xC0000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;

 

heyo
heyoAuthor
Associate III
June 29, 2023

Do I really need to do that to store frontend heap to my external sdram?

uilter
Senior
June 29, 2023

Only if you have enough internal RAM memory, and it will not affect your application, no is not an obligation.

To know it, you need to calculate the size of your frame buffer. "framebuffer is width * height * color depth in bits / 8 bytes." This link is nice to check it https://support.touchgfx.com/docs/basic-concepts/framebuffer#memory-consumption

Another tip, if you are using an external SDRAM, make sure you are able to write and read it.
It may be that your FMC peripheral is wrongly configured, and that is why it is generating these faults.

 

 

Tesla DeLorean
Guru
June 29, 2023

Likely Hard Faults because you fail to initialize the memory interface before the C/C++ constructors are called.

Should enable the memory in SystemInit(), and in startup.s this should be called before __libc_init_array

Look at the code that's actually faulting to understand why.. the code the MCU is executing at and immediately prior.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
heyo
heyoAuthor
Associate III
June 29, 2023

What and where i should enable in this?

 

void SystemInit (void)
{
#if defined (DATA_IN_D2_SRAM)
 __IO uint32_t tmpreg;
#endif /* DATA_IN_D2_SRAM */

 /* FPU settings ------------------------------------------------------------*/
 #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
 SCB->CPACR |= ((3UL << (10*2))|(3UL << (11*2))); /* set CP10 and CP11 Full Access */
 #endif
 /* Reset the RCC clock configuration to the default reset state ------------*/
 /* Set HSION bit */
 RCC->CR |= RCC_CR_HSION;

 /* Reset CFGR register */
 RCC->CFGR = 0x00000000;

 /* Reset HSEON, CSSON , CSION,RC48ON, CSIKERON PLL1ON, PLL2ON and PLL3ON bits */
 RCC->CR &= 0xEAF6ED7FU;

#if defined(D3_SRAM_BASE)
 /* Reset D1CFGR register */
 RCC->D1CFGR = 0x00000000;

 /* Reset D2CFGR register */
 RCC->D2CFGR = 0x00000000;

 /* Reset D3CFGR register */
 RCC->D3CFGR = 0x00000000;
#else
 /* Reset CDCFGR1 register */
 RCC->CDCFGR1 = 0x00000000;

 /* Reset CDCFGR2 register */
 RCC->CDCFGR2 = 0x00000000;

 /* Reset SRDCFGR register */
 RCC->SRDCFGR = 0x00000000;
#endif
 /* Reset PLLCKSELR register */
 RCC->PLLCKSELR = 0x00000000;

 /* Reset PLLCFGR register */
 RCC->PLLCFGR = 0x00000000;
 /* Reset PLL1DIVR register */
 RCC->PLL1DIVR = 0x00000000;
 /* Reset PLL1FRACR register */
 RCC->PLL1FRACR = 0x00000000;

 /* Reset PLL2DIVR register */
 RCC->PLL2DIVR = 0x00000000;

 /* Reset PLL2FRACR register */

 RCC->PLL2FRACR = 0x00000000;
 /* Reset PLL3DIVR register */
 RCC->PLL3DIVR = 0x00000000;

 /* Reset PLL3FRACR register */
 RCC->PLL3FRACR = 0x00000000;

 /* Reset HSEBYP bit */
 RCC->CR &= 0xFFFBFFFFU;

 /* Disable all interrupts */
 RCC->CIER = 0x00000000;

#if defined (DATA_IN_D2_SRAM)
 /* in case of initialized data in D2 SRAM (AHB SRAM) , enable the D2 SRAM clock ((AHB SRAM clock) */
#if defined(RCC_AHB2ENR_D2SRAM1EN)
 RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN | RCC_AHB2ENR_D2SRAM3EN);
#else
 RCC->AHB2ENR |= (RCC_AHB2ENR_AHBSRAM1EN | RCC_AHB2ENR_AHBSRAM2EN);
#endif /* RCC_AHB2ENR_D2SRAM1EN */

 tmpreg = RCC->AHB2ENR;
 (void) tmpreg;
#endif /* DATA_IN_D2_SRAM */

#if defined(DUAL_CORE) && defined(CORE_CM4)
 /* Configure the Vector Table location add offset address for cortex-M4 ------------------*/
#ifdef VECT_TAB_SRAM
 SCB->VTOR = D2_AHBSRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
 SCB->VTOR = FLASH_BANK2_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif /* VECT_TAB_SRAM */

#else
 /* dual core CM7 or single core line */
 if((DBGMCU->IDCODE & 0xFFFF0000U) < 0x20000000U)
 {
 /* if stm32h7 revY*/
 /* Change the switch matrix read issuing capability to 1 for the AXI SRAM target (Target 7) */
 *((__IO uint32_t*)0x51008108) = 0x000000001U;
 }

 /* Configure the Vector Table location add offset address for cortex-M7 ------------------*/
#ifdef VECT_TAB_SRAM
 SCB->VTOR = D1_AXISRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D1 AXI-RAM */
#else
 SCB->VTOR = FLASH_BANK1_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif

#endif /*DUAL_CORE && CORE_CM4*/

}

 

Can I edit startup.s file? It looks like first call __libc_init_array then systeminit.

/* Call the clock system initialization function.*/
 bl SystemInit

/* Copy the data segment initializers from flash to SRAM */
 ldr r0, =_sdata
 ldr r1, =_edata
 ldr r2, =_sidata
 movs r3, #0
 b LoopCopyDataInit

CopyDataInit:
 ldr r4, [r2, r3]
 str r4, [r0, r3]
 adds r3, r3, #4

LoopCopyDataInit:
 adds r4, r0, r3
 cmp r4, r1
 bcc CopyDataInit
/* Zero fill the bss segment. */
 ldr r2, =_sbss
 ldr r4, =_ebss
 movs r3, #0
 b LoopFillZerobss

FillZerobss:
 str r3, [r2]
 adds r2, r2, #4

LoopFillZerobss:
 cmp r2, r4
 bcc FillZerobss

/* Call static constructors */
 bl __libc_init_array
/* Call the application's entry point.*/
 bl main
 bx lr
.size Reset_Handler, .-Reset_Handler

 

 

Tesla DeLorean
Guru
June 29, 2023

>>What and where i should enable in this?

Clocks, Pins and Peripheral related to the SDRAM

Before it exits, and Before you touch the SDRAM Memory.

startup.s looks to be doing things in an appropriate order. You likely get the Hard Fault currently because you don't initialize the SDRAM properly until you get to main()

https://github.com/STMicroelectronics/STM32CubeH7/blob/master/Projects/STM32H747I-EVAL/Applications/USB_Device/CustomHID_Standalone/Common/Src/system_stm32h7xx.c#L384

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Flemming Gram CHRISTENSEN
ST Employee
June 30, 2023

The framebuffer is not initialized by C++. 

Could you provide a stack trace when you get the fault? and also disassembly of the code.

In some cases it is a wrong configuration of SDRAM. The DMA2D and LTDC performs block access to the frame buffer, but the code may use byte access to the heap.

Can you test that byte access is working. Try reading and writing all 4 bytes in a word in SDRAM.

 

Flemming Gram CHRISTENSEN
ST Employee
June 30, 2023

BTW, what is the reason to move the heap to SDRAM? How big is your heap?
Maybe you can move just one big element to SDRAM. E.g. if you have a big array in Model.

heyo
heyoAuthor
Associate III
June 30, 2023

It looks like my SDRAM is working correctly: 

heyo_1-1688114048981.png

 

I have a lot of arrays in model.hpp. It would be great to store frontend heap to my external SDRAM cause in RAM_D1 left only 100KB

heyo_0-1688113794228.png

Now I get MemManage_Handler:

heyo_2-1688114458121.png

 

 

Associate III
October 29, 2023

were you able to solve the problem? I am having a similar problem. I have a section defined in my linker for SDRAM that is used to store large amounts of data. I also have touchGFX configured—my system hard-fault when I try to access the data in SDRAM. 

heyo
heyoAuthor
Associate III
July 5, 2023

How to config MPU if I want to store FrontendHeap to my external SDRAM?

Flemming Gram CHRISTENSEN
ST Employee
October 30, 2023

Hello Cleonb322

You should start by testing your SDRAM. Write a program that write bytes, shorts, and words to different addresses in the SDRAM. Then read the values to check that it is correct.

It is important that you can write bytes in all addresses, without modifying the nearby bytes.

Associate III
October 30, 2023

I'm using the SDRAM for TouchGFX. It crashes only when I try to define a struct in SDRAM. 

 

Flemming Gram CHRISTENSEN
ST Employee
October 30, 2023

Do you mean that you have your framebuffers in SDRAM and that works?

Then this is only using 16bit access (assuming you have 16 bit colors) and maybe only is large chunks.

Try to see if you can read and write chars in the first addresses of the framebuffer.

 

Associate III
October 30, 2023

yes, my framebuffer works just fine. I was able to get my struct variable working (it no longer crashes) by forcing my struct alignment with "__attribute__((aligned(4)))". I guess I do not have access to individual bytes that are not aligned by 4. I will have to do some more research and testing.  or maybe the issue is with the way I cast my variable.

See the attached file for an example of my variable usage:

 

 

Flemming Gram CHRISTENSEN
ST Employee
October 31, 2023

What is the 

**bleep**S_CFG

type? 

Associate III
October 31, 2023

 yes, **bleep**S_CFG is defined in another file. I think it is obvious that it is a struct type.

heyo
heyoAuthor
Associate III
November 1, 2023

If you get hardfault when you store frontendheap to SDRAM, try to add this "/0" in every text last character. SDRAM hardfault because he does not see the end of text and this "/0" simbolize the end of text.