Linker error: undefined reference to `_sbrk'

I get the following error when trying to use sprintf():

~/.platformio/packages/toolchain-gccarmnoneeabi@1.70201.0/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v7-m\libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\genericSTM32F103VE\firmware.elf] Error 1

I have opened an issue on GitHub and you can find more details here: GitHub issue #606
I know that developers are super busy and currently it is a hard time. Thus I post here to see if anyone has encountered the same problem and solved it. Thanks!

It looks like you’ve downgraded the used framework to baremetal and then readded the STM32Cube files? Why not directly framework = stm32cube and then don’t include the HAL files in the project? See e.g. here.

The sprintf(adc2DecStr, "%ld", adc2Value); you do apparently wants to allocate heap memory (?) and therefore needs _sbrk as a dependency of malloc().

STM32CubeMX generated projects comewith a syscalls.c file that implement this primitive, referencing a special linkerscript place:

#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>

caddr_t _sbrk(int incr)
{
	extern char end asm("end");
	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();
		errno = ENOMEM;
		return (caddr_t) -1;
	}

	heap_end += incr;

	return (caddr_t) prev_heap_end;
}

this works due to the auto-generated linker script having a user heap stack section with the provided end symbol

  /* 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

Alternatively, try to add in newlib-nano via this extra script

that you reference via

extra_scripts = add_newlibnano.py

in the platformio.ini.

2 Likes

I tried this just now and it worked like a charm. Thank you so much!

The reason why I don’t use the provided framework is because I followed some tutorials on personal blogs. I was totally a newbie to embedded system few weeks ago, those tutorials worked fine so I stick with them.

Definitely I will take a look at all the links you provided. Also I will learn the “official” or “recommend” way to use Platformio together with CubeMX. If I can figure these out, I will close the issue on Github later.

Thank you again!

There are also automated conversion tools: GitHub - ussserrr/stm32pio: Automate managing of STM32CubeMX + PlatformIO projects.

But really all that does it copy the files to the places where PlatformIO expects them. The needed folder structure is PlatformIO-standardized, as e.g. linked in the all the example projects platform-ststm32/examples at master · platformio/platform-ststm32 · GitHub.