Hi all,

I am porting a c++ project from the STM32H7 EVAL board to the STM32H7 Nucleo 144.

The project uses CubeMX to generate the project, then I port in all the source code and set the c/c++/linker directories, symbols and settings.

The project uses FreeRTOS and one thread of the RTOS is going to an infinite loop in a default error handler (_exit()) when calling new() on an instance of a library. The other threads continue to run ok.

The linker puts user data in RAMD1 because it is the largest section and I need the space.

Some things I have checked /tried:

  • Library is compiled with same C++ version as project (C++ 14)
  • Hardware FPU is enabled (Library uses floats)
  • Minimum stack and heap are sufficient in linker script
  • RTOS Thread allocated stack / heap sizes are sufficient
  • RAMD1 section is enabled with clock
  • Tried aligning data to both 4 and 8 bytes in linker
  • 128 / 4096 byte malloc() page size

Stepping through instructions, I can see this is the line that causes the issue.

bl   0x80aa7fe <_Znwj>

Here is my linker script in case that is of any help

/*
*****************************************************************************
**  File        : stm32_flash.ld
**  Abstract    : Linker script for STM32H743ZI Device with
**                2048KByte FLASH, 1056KByte 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
**  Environment : Atollic TrueSTUDIO(R)
**  Distribution: The file is distributed as is, without any warranty
**                of any kind.
**  You may use this file as-is or modify it according to the needs of your
**  project. This file may only be built (assembled or compiled and linked)
**  using the Atollic TrueSTUDIO(R) product. The use of this file together
**  with other tools than Atollic TrueSTUDIO(R) is not permitted.
*****************************************************************************
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x24080000;
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x20000;      /* required amount of heap  */
_Min_Stack_Size = 0x20000; /* required amount of stack */
/* Specify the memory areas */
MEMORY
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
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 2048K
/* 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 */
    . = 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 secion */
    _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(4);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(4);
  } >RAM_D1
  /* Remove information from the standard libraries */
  /DISCARD/ :
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  .ARM.attributes 0 : { *(.ARM.attributes) }
 

The library is known to be good, and is already running on the same IC on different hardware.

Any help greatly appreciated!

Well, Someone else figured this out for me.

It had to do with new, new[], and malloc() not using the FreeRTOS stack. A new version of syscalls.cpp which routes everything through the RTOS was required to prevent dynamic allocation crashing.

I'm surprised this isn't mentioned when generating a FreeRTOS project in CubeMX.

Well, Someone else figured this out for me.

It had to do with new, new[], and malloc() not using the FreeRTOS stack. A new version of syscalls.cpp which routes everything through the RTOS was required to prevent dynamic allocation crashing.

I'm surprised this isn't mentioned when generating a FreeRTOS project in CubeMX.

Hi, running into the same issue (I think) . Could you share where you found your syscalls.cpp? Thank you!

I know dynamic allocation isn't encouraged (nor should it be) in embedded programming, but getting onboard with crazy, weird and unusual API calls like "new" and "delete" is something I strongly recommend to STM. I mean, it's past the year 2000 after all

@Malachi​ you need to overload the new and delete operators.

Here is an example in the FreeRTOS Forum:

https://www.freertos.org/FreeRTOS_Support_Forum_Archive/February_2017/freertos_FreeRTOSs_compatibility_with_C_2aa2a047j.html

And here is a ready interface on git:

https://github.com/Benichou34/cmsis_cpp

Calling a virtual function seems to stop the execution of the MCU (Nucleo F446RE) in STM32 MCUs Embedded software STM32 I2C Not Working with Other Interrupts in STM32 MCUs Embedded software How to enable SDMMC + FATFS + FREERTOS on STM32H723ZGT6 in STM32 MCUs products