sbrk and newlib - is any malloc or free used?

gnuffel wrote on Monday, November 02, 2009:

I have pvPortMalloc and pvPortFree as provided in heap_2.c. As I understand it, these functions are used by FreeRTOS when crearing processes, and _can_ be used by my tasks for allocating memory aswell.

I am trying to get newlib up and running, and I now need to fill in sbrk_r() to get printf and similar to work. In examples I have seen, sbrk_r is mapped to use its own piece of RAM, which is not used by the alloc/free functions provided by heap_2.c which uses a static heap.

Does this also mean that the functions in newlib use their own malloc/free functions that in turn call the sbrk_r() which I am trying to provide as a stub function? Any help is appreciated as I am trying to cut back the confusion some…

rtel wrote on Monday, November 02, 2009:

Don’t know the answer, all I can suggest is that either you use heap_3.c instead, so everything uses the same allocator, or you do a grep on the NewLib sources to find places where malloc or free is called.

Maybe somebody with better knowledge of NewLib could provide a better answer.


gnuffel wrote on Monday, November 02, 2009:

Thanks for the reply,

I will try the built-in malloc/free approach you suggest. Will just have to avoid doing things that cause malloc/free when in time-sensitive parts of the code.

anders8 wrote on Tuesday, November 24, 2009:

printf is generally not reentrant unless specifically coded to be so. I’m unfamiliar with the libraries you’re discussing, but you’ll want to know the answer to this question.


anonymous wrote on Tuesday, November 24, 2009:

Hi all,

I use newlib on my projects based on STM32 and FreeRTOS.
This is my linker file…

        FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K
        SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
    .text :
    *(.text .text.* .gnu.linkonce.t.*)
    *(.rodata .rodata.* .gnu.linkonce.r.*)
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    . = ALIGN(4);
    . = ALIGN(4);
    __preinit_array_start = .;
    KEEP (*(.preinit_array))
    __preinit_array_end = .;
    . = ALIGN(4);
    __init_array_start = .;
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array))
    __init_array_end = .;
    . = ALIGN(0x4);
    KEEP (*crtbegin.o(.ctors))
    KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*crtend.o(.ctors))
    . = ALIGN(4);
    . = ALIGN(4);
    __fini_array_start = .;
    KEEP (*(.fini_array))
    KEEP (*(SORT(.fini_array.*)))
    __fini_array_end = .;
    KEEP (*crtbegin.o(.dtors))
    KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*crtend.o(.dtors))
    . = ALIGN(8);
    _etext = .;
    } >FLASH
    /* .ARM.exidx is sorted, so has to go in its own output section. */
    __exidx_start = .;
    .ARM.exidx :
    *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    } >FLASH
    __exidx_end = .;
    _flash_data = .;
    .data : AT (_flash_data)
    _data = .;
    _edata = .;
    } > SRAM
    .bss :
    _bss = .;
    _ebss = .;
    _end = .;
    __end = .;
    } > SRAM
    /* end of allocated ram _end */
    PROVIDE( _heap = _end );
    /* end of the heap -> align 8 byte */
    PROVIDE ( _eheap = ALIGN(ORIGIN(SRAM) + LENGTH(SRAM) - 8 ,8) );

…and this is my implementation of the _sbrk funtion…

    caddr_t _sbrk(int incr)
    caddr_t prevHeap;
    caddr_t nextHeap;
    if (heap == NULL)
    { // first allocation
    heap = (caddr_t) & _heap;
    prevHeap = heap;
    // Always return data aligned on a 8 byte boundary
    nextHeap = (caddr_t) (((unsigned int) (heap + incr) + 7) & ~7);
    // Check enough space and there is no collision with stack coming the other way
    // if stack is above start of heap
    if (nextHeap >= (caddr_t) & _eheap)
    errno = ENOMEM;
    return NULL; // error - no more memory
    heap = nextHeap;
    return (caddr_t) prevHeap;

Using these code (I arranged an implementation that was provided to me because I’m not a guru about this matter! :slight_smile:
all newlib functions use their own heap that is located at the end of the SRAM (look at the end of linker file). At the moment I’m using function like *printf and the one declared in math.h file.

This implementation should not be re-entrant even if I observed during a debug session that the _sbrk is called by _sbrk_r library function. I’d like to make more investigation and I’d like to implement the fully re-entrant newlib support. I think that I need to exted the TCB and the context switch function without break the compatibility with standard FreeRTOS API. This is due to the idea to support re-entrant version of standard C library is that each task has to provide its own set of variable used by C Library function and the scheduler must switch this set of variable during the context switch.

Is someone interested in working at this topics?

Regards and sorry for my  long reply,