cancel
Showing results for 
Search instead for 
Did you mean: 

STM32CubeMx generated _sbrk() in syscalls.c not working with FreeRTOS

Katzenberger.Michael
Associate III

Hi !

I'm working on a project using STM32CubeMx and FreeRTOS (version 9.0.0, MEMORY_ALLOCATION = STATIC) and running into trouble as soon as the new operator is used (in my case implicitly be the library function gmtime()).

The problem seems to be the function _sbrk() in the generated file syscalls.c:

The check in line 15 fails if using FreeRTOS due to each FreeRTOS task is using its own different stack pointer.

register char * stack_ptr asm("sp");
 
...
 
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;
}

How can this be fixed ???

  • is there a "special" version of _sbrk() available which can handle a non-continuous stack pointer memory space ?
  • simply disable the check by modifying the generated file ? But neither the function is weak nor there are user code hooks implemented)

Thanks,

Michael.

4 REPLIES 4
AFrie.0
Associate

Hello,

I'm runing into this issue too, as I updated an STM32F405 Projekt initialy created with CubeMX 4.something and FW V 1.18.0 to CubeMX 5.1.0 and FW V 1.24.0. Now there will be created an syscalls.c file like the one above. But when looking into the example files (coming with the FW V 1.24.0) there is an syscalls.c with an _sbrk function like :

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;
#ifdef FreeRTOS
	/* Use the NVIC offset register to locate the main stack pointer. */
	min_stack_ptr = (char*)(*(unsigned int *)*(unsigned int *)0xE000ED08);
	/* Locate the STACK bottom address */
	min_stack_ptr -= MAX_STACK_SIZE;
 
	if (heap_end + incr > min_stack_ptr)
#else
	if (heap_end + incr > stack_ptr)
#endif
	{
//		write(1, "Heap and stack collision\n", 25);
//		abort();
		errno = ENOMEM;
		return (caddr_t) -1;
	}
 
	heap_end += incr;
 
	return (caddr_t) prev_heap_end;
}

which enables the malloc function to succeed even if the FreeRTOS is running.

I did not find from what source "my" syscalls.c file is generated, and why the syscalls.c files from the examples are different.

In fact with the CubeMX 5.1 I running into some more problems as now the linker.ld file will be overwritten each time - but sometimes failed as a zero byte file will be created - and sometimes the files under drivers won't be created.

Regrads, Andy

Here's the info you're looking for including sbrk code: http://www.nadler.com/embedded/newlibAndFreeRTOS.html

Thank you, Dave!

Your article and zip file helped me a lot. Great work!

This _sbrk is very wrong. Each FreeRTOS task has its own stack and it may be anywhere in RAM.

The scheme described in Dave Nadler's page of wrapping the FreeRTOS allocator functions inside newlib's is good. An added benefit, FreeRTOS's allocator/deallocator work before FreeRTOS is started.