Search code examples
c++cembeddedstm32dynamic-memory-allocation

STM32 - Dynamic Memory Allocation Implementation, how to correctly implement the _sbrk function?


I'm working on a bare-metal programming project written in C++ on a STM32F401RE board, and I need to implement malloc() and free() functions.

I know that dynamic memory allocation on embedded systems is not a good idea, but I need it.

Up to know I understood that in order to use malloc and free functions of the C standard library I need to manually implement a function named _sbkr(), and in order to do so I created a library with this single function and added it to the includes of the main.cpp source code.

The problem is that it doesn't work, when I try to dynamically allocate a variable it returns a NULL pointer.

Generating with gcc the assembly code of the main, it seems that the _sbrk function is not implemented in the final object which will be uploaded on the board.

How can I Correctly implement this function?


Solution

  • Assuming that you are using Newlib (the usual C library used with GCC on stand-alone systems), then the target specific porting layer ("syscalls") for the C library is defined at https://sourceware.org/newlib/libc.html#Syscalls.

    A minimal implementation suitable for standalone (no OS) environments is given there as an example:

    caddr_t sbrk(int incr) {
      extern char _end;     /* Defined by the linker */
      static char *heap_end;
      char *prev_heap_end;
     
      if (heap_end == 0) {
        heap_end = &_end;
      }
      prev_heap_end = heap_end;
      if (heap_end + incr > stack_ptr) {
        write (1, "Heap and stack collision\n", 25);
        abort ();
      }
    
      heap_end += incr;
      return (caddr_t) prev_heap_end;
    }
    

    Note also that if you are using an RTOS or threading library you will also need to implement __malloc_lock() and __malloc_unlock() using your RTOS/thread libraries mutex call.

    Note also that if you use ST's STM32CubeIDE that uses GCC and Newlib and has the syscalls layer implemented already.