Skip to main content
Graduate II
July 3, 2024
Question

I want to move the ucHeap of the FreeRTOS from RAM_D1 to External RAM (HYPERRAM)

  • July 3, 2024
  • 6 replies
  • 3119 views
Board Using - STM32H735G-DK

1. I tried moving the whole .bss section into HYPERRAM

 /* 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;
 } >HYPERRAM /* RAM_D1 */

 

This causes HardFault Error and the Display is a white screen.
Observation/Guess : maybe because the code that starts the board/MCU is in the bss section and the HYPERRAM is not initialized at the start so the code to initialize the HYPERRAM is inside HYPERRAM. So it is not working.

2. Moving only ucHeap to HYPERRAM

Edited the linkerscript to create a new section

.freertos_data (NOLOAD) :
 {
 . = ALIGN(4);
 _freertos_data_begin = .;
 *(.freertos_data)
 *(.freertos_data*)
 . = ALIGN(4);
 _freertos_data_end = .;
 } >HYPERRAM

Inside FreeRTOS.h file changed the to 1 

#ifndef configAPPLICATION_ALLOCATED_HEAP
	#define configAPPLICATION_ALLOCATED_HEAP 1
#endif

in main.c
created an array for ucHeap

/* USER CODE BEGIN PV */
uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] __attribute__ ((section (".freertos_data")));
/* USER CODE END PV */

 Now downloaded the program using Debug
Error: Program gets HardFault Error even before going into main() function.

I think because i put a breakpoint in first line of main() function it is not reaching and i cannot 'reset` the debug using the reverse curved arrow.
What error is shown: 

vishnu_illikkal_0-1719985981744.pngvishnu_illikkal_1-1719986482100.png

vishnu_illikkal_2-1719987844486.pngheap_4.c having the problem

Observation/Guess : FreeRTOS functions are calling before the init of the External RAM or even before the program is fully start.
Some RWX permission warning also hapening i don't know what that is

vishnu_illikkal_3-1719988025394.png

If anyone knows this problem please replay. 
Thanks.

 

 

 

 

 

    This topic has been closed for replies.

    6 replies

    Graduate II
    July 3, 2024

    I'm using H735-DK's HyperRAM, and it must be initialized in memory-mapped mode before I touch any variables in the HypeRAM section.

    So do you init HyperRAM before starting any RTOS stuff?

    Technical Moderator
    July 3, 2024
    uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] __attribute__ ((section (".freertos_data")));

    This needs that the HypeRAM to be initialized before calling the main() i.e. in SystemInit()

    I suggest to inspire from the OSPI initialization from STM32H735G-DK\Examples\OSPI\OSPI_HyperRAM_MemoryMapped example and implement it in direct access to the registers in SystemInit().

    Graduate II
    July 4, 2024

    I will Try, Thanks

    Graduate II
    July 10, 2024

    I have no idea what touchgfx or Cube or HAL are doing, I set up HyperRam via the registers.

    BUT I remember that I started with a working init for HyperRam in MM mode with a HAL setup from Cube.

    Super User
    July 10, 2024

    @vishnu_illikkal The 2nd attempt was a good try... but it looks from the stack trace like C++ got you ))

    There are some static TouchGFX things that initialize before main() and create FreeRTOS objects - which allocate from your new pool in hyperram.  But MX_OCTOSPI2_Init likely is called in your main() - which has not been run yet.

    Now - if this guesswork is correct - you can easily fix it.

     

    Graduate II
    July 11, 2024

    @Pavel A. 

    Your guess is correct
    1. I have started a fully working code using TouchGFX Designer

            It has TouchGFX working, FreeRTOS working and all needed stuff working
    2. Currently the ucHeap of FreeRTOS is placed in RAM_D1 by default.
            I need to change this to External OSPI HyperRam

            This HyperRam is already setup and working properly in the project i created in step 1
    3. When i try to move this to HyperRAM since it is not initialized untill the function  MX_OCTOSPI2_Init(); is called the HyperRAM becomes only available after this.
            But some FreeRTOS functions (see original post images) are trying to access the ucHeap even before the main() function is called.

           So it gives me a HardFault ErrorSo as per the suggestion of @mƎALLEm  i am trying to initialize the OCTOSPI2 ram inside the SystemInit() function
          1. So I need to find the register values 
           2. i have read the various registers of the OCTOSPI2 from the working code from step 1

          3. Now what i need to know is what other registers do i need to set up for the OCTOSPI2 to work?
                     1. Like for example GPIO , Clock etc
                      2. Also how can i read the GPIO registers of the OCTOSPI2 pins?

    Graduate II
    July 11, 2024

     

     

    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 ------------*/
    
     /* Increasing the CPU frequency */
     if(FLASH_LATENCY_DEFAULT > (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
     {
     /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
    	MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
     }
    
     /* Set HSION bit */
     RCC->CR |= RCC_CR_HSION;
    
     /* Reset CFGR register */
     RCC->CFGR = 0x00000000;
    
     /* Reset HSEON, HSECSSON, CSION, HSI48ON, CSIKERON, PLL1ON, PLL2ON and PLL3ON bits */
     RCC->CR &= 0xEAF6ED7FU;
    
     /* Decreasing the number of wait states because of lower CPU frequency */
     if(FLASH_LATENCY_DEFAULT < (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
     {
     /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
    	MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
     }
    
    #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 = 0x02020200;
    
     /* Reset PLLCFGR register */
     RCC->PLLCFGR = 0x01FF0000;
     /* Reset PLL1DIVR register */
     RCC->PLL1DIVR = 0x01010280;
     /* Reset PLL1FRACR register */
     RCC->PLL1FRACR = 0x00000000;
    
     /* Reset PLL2DIVR register */
     RCC->PLL2DIVR = 0x01010280;
    
     /* Reset PLL2FRACR register */
    
     RCC->PLL2FRACR = 0x00000000;
     /* Reset PLL3DIVR register */
     RCC->PLL3DIVR = 0x01010280;
    
     /* Reset PLL3FRACR register */
     RCC->PLL3FRACR = 0x00000000;
    
     /* Reset HSEBYP bit */
     RCC->CR &= 0xFFFBFFFFU;
    
     /* Disable all interrupts */
     RCC->CIER = 0x00000000;
    
    #if (STM32H7_DEV_ID == 0x450UL)
     /* 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;
     }
    #endif
    
    #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_D2SRAM3EN)
     RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN | RCC_AHB2ENR_D2SRAM3EN);
    #elif defined(RCC_AHB2ENR_D2SRAM2EN)
     RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN);
    #else
     RCC->AHB2ENR |= (RCC_AHB2ENR_AHBSRAM1EN | RCC_AHB2ENR_AHBSRAM2EN);
    #endif /* RCC_AHB2ENR_D2SRAM3EN */
    
     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_AXISRAM_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
    
     /*
     * Disable the FMC bank1 (enabled after reset).
     * This, prevents CPU speculation access on this bank which blocks the use of FMC during
     * 24us. During this time the others FMC master (such as LTDC) cannot use it!
     */
     FMC_Bank1_R->BTCR[0] = 0x000030D2;
    
     /* 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 AXI-RAM */
    #else
     SCB->VTOR = FLASH_BANK1_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
    #endif
    
    #endif /*DUAL_CORE && CORE_CM4*/
    
    
     /* our code */
    
     /* Enable clocks for GPIO ports used by OCTOSPI2 */
     RCC->AHB4ENR |= RCC_AHB4ENR_GPIOGEN; // Enable GPIOG clock
     RCC->AHB4ENR |= RCC_AHB4ENR_GPIOFEN; // Enable GPIOF clock
    
     /* Configure GPIOG */
     GPIOG->MODER = 0x6eabaf7a;
     GPIOG->OTYPER = 0;
     GPIOG->OSPEEDR = 0x33fcf0cf;
     GPIOG->PUPDR = 0;
     GPIOG->AFR[0] = 0xea000099;
    
     /* Configure GPIOF */
     GPIOF->MODER = 0xaeeffeaa;
     GPIOF->OTYPER = 0xc000;
     GPIOF->OSPEEDR = 0xa33003ff;
     GPIOF->PUPDR = 0x50000000;
     GPIOF->AFR[0] = 0x99999;
    
     /* Enable clock for OCTOSPI2 */
    // RCC->AHB3ENR |= RCC_AHB3ENR_OCTOSPI2EN;
     RCC->AHB3ENR = 0x284010;
     /* Configure and enable PLL2 for OCTOSPI */
     RCC->PLLCKSELR = 0x1905022; // PLL2M = 5, Source = HSE
     RCC->PLL2DIVR = 0x101084f; // PLL2N = 80, PLL2P = 2, PLL2Q = 2, PLL2R = 2
     RCC->PLLCFGR = 0x1ff031d; // PLL2 Range = 2, VCO = Wide
    // RCC->CR |= RCC_CR_PLL2ON; // Enable PLL2
     RCC->CR = 0x3f03c025;
     while ((RCC->CR & RCC_CR_PLL2RDY) == 0) {} // Wait until PLL2 is ready
    
     /* Set PLL2 as the clock source for OCTOSPI */
    // RCC->D1CCIPR = (RCC->D1CCIPR & ~RCC_D1CCIPR_OSPISEL_Msk) | RCC_D1CCIPR_OSPISEL_PLL2;
     RCC->D1CCIPR = 0x20;
     /* Initialize OCTOSPI2 with the values from the working project */
     OCTOSPI2->CR = 0;
     OCTOSPI2->DCR1 = 0x04170300;
     OCTOSPI2->DCR2 = 0x1;
     OCTOSPI2->DCR3 = 0x170000;
     OCTOSPI2->DCR4 = 0x190;
     OCTOSPI2->CCR = 0x2c003c00;
     OCTOSPI2->TCR = 0x10000000;
     OCTOSPI2->WCCR = 0x2c003c00;
     OCTOSPI2->CR = 0x30000301;
    
     /* Verify PLL settings */
    // RCC->PLLCKSELR = 0x1905022;
    // RCC->PLL2DIVR = 0x101084f;
    // RCC->PLLCFGR = 0x1ff031d;
    // RCC->CR = 0x3f03c025;
    // RCC->D1CCIPR = 0x20;
    
     uint32_t gpio1 = GPIOG->MODER;		// 0x6eabaf7a
     uint32_t	 gpio2 = GPIOG->OTYPER;		//
     uint32_t	 gpio3 = GPIOG->OSPEEDR;		// 0x33fcf0cf
     uint32_t	 gpio4 = GPIOG->PUPDR;			//
     uint32_t	 gpio5 = GPIOG->AFR[0];		// 0xea000099
    
    	 uint32_t	 gpio11 = GPIOF->MODER;			// 0xaeeffeaa
    	 uint32_t gpio22 = GPIOF->OTYPER;		// 0xc000
    	 uint32_t gpio33 = GPIOF->OSPEEDR;		// 0xa33003ff
    	 uint32_t gpio44 = GPIOF->PUPDR;			// 0x50000000
    	 uint32_t gpio55 = GPIOF->AFR[0];		// 0x99999
    
     /* our code */
    }

     

     

    I tried to write the registers with the values i read , now no HardFault error occurs but the code gets stcuk at startup_stm32h735xx.s file

     

     

    /**
     ******************************************************************************
     * @file startup_stm32h735xx.s
     * @author MCD Application Team
     * @brief STM32H735xx Devices vector table for GCC based toolchain. 
     * This module performs:
     * - Set the initial SP
     * - Set the initial PC == Reset_Handler,
     * - Set the vector table entries with the exceptions ISR address
     * - Branches to main in the C library (which eventually
     * calls main()).
     * After Reset the Cortex-M processor is in Thread mode,
     * priority is Privileged, and the Stack is set to Main.
     ******************************************************************************
     * @attention
     *
     * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
     * All rights reserved.</center></h2>
     *
     * This software component is licensed by ST under BSD 3-Clause license,
     * the "License"; You may not use this file except in compliance with the
     * License. You may obtain a copy of the License at:
     * opensource.org/licenses/BSD-3-Clause
     *
     ******************************************************************************
     */
     
     .syntax unified
     .cpu cortex-m7
     .fpu softvfp
     .thumb
    
    .global g_pfnVectors
    .global Default_Handler
    
    /* start address for the initialization values of the .data section. 
    defined in linker script */
    .word _sidata
    /* start address for the .data section. defined in linker script */ 
    .word _sdata
    /* end address for the .data section. defined in linker script */
    .word _edata
    /* start address for the .bss section. defined in linker script */
    .word _sbss
    /* end address for the .bss section. defined in linker script */
    .word _ebss
    /* stack used for SystemInit_ExtMemCtl; always internal RAM used */
    
    /**
     * @brief This is the code that gets called when the processor first
     * starts execution following a reset event. Only the absolutely
     * necessary set is performed, after which the application
     * supplied main() routine is called. 
     * @PAram None
     * @retval : None
    */
    
     .section .text.Reset_Handler
     .weak Reset_Handler
     .type Reset_Handler, %function
    Reset_Handler: 
     ldr sp, =_estack /* set stack pointer */
    
    /* Call the clock system intitialization function.*/
     bl SystemInit
    
    /* Copy the data segment initializers from flash to SRAM */ 
     movs r1, #0
     b LoopCopyDataInit
    
    CopyDataInit:
     ldr r3, =_sidata
     ldr r3, [r3, r1]
     str r3, [r0, r1]
     adds r1, r1, #4
     
    LoopCopyDataInit:
     ldr r0, =_sdata
     ldr r3, =_edata
     adds r2, r0, r1
     cmp r2, r3
     bcc CopyDataInit
     ldr r2, =_sbss
     b LoopFillZerobss
    /* Zero fill the bss segment. */ 
    FillZerobss:
     movs r3, #0
     str r3, [r2], #4
     
    LoopFillZerobss:
     ldr r3, = _ebss
     cmp r2, r3
     bcc FillZerobss
     
    /* Call static constructors */
     bl __libc_init_array
    /* Call the application's entry point.*/
     bl main
     bx lr 
    .size Reset_Handler, .-Reset_Handler
    
    rest of the codes

     

     

    Reset_Handler:

    ldr sp, =_estack /* set stack pointer */ THIS IS THE LINE THAT STUCK

     

    Super User
    July 11, 2024

    Yes, logically the SystemInit function is where the clocks and memories should be prepared. SystemInit is called before main() and all the C/C++ initializers. But this is not how the ST examples and Cube-generated projects actually are written. Maybe, because all the library code is in C, and it assumes the C initializers already run, and it all goes upside down... You need just to make a decision how/where the stuff should be initialized in your project.