diff --git a/makefiles/libc/picolibc.mk b/makefiles/libc/picolibc.mk index 94263d082b..158d5080e0 100644 --- a/makefiles/libc/picolibc.mk +++ b/makefiles/libc/picolibc.mk @@ -11,14 +11,10 @@ endif ifeq (1,$(USE_PICOLIBC)) LINKFLAGS += -specs=picolibc.specs - # RIOT uses _sheap and _eheap for heap start and end, PicoLIBC uses - # __heap_start and __heap_end. This glues these different names together. - LINKFLAGS += -Wl,--defsym=__heap_end=_eheap - LINKFLAGS += -Wl,--defsym=__heap_start=_sheap CFLAGS += -specs=picolibc.specs ifeq (,$(filter printf_float scanf_float,$(USEMODULE))) - CFLAGS += -DPICOLIBC_INTEGER_PRINTF_SCANF - LINKFLAGS += -DPICOLIBC_INTEGER_PRINTF_SCANF + CFLAGS += -DPICOLIBC_INTEGER_PRINTF_SCANF + LINKFLAGS += -DPICOLIBC_INTEGER_PRINTF_SCANF endif endif diff --git a/sys/picolibc_syscalls_default/syscalls.c b/sys/picolibc_syscalls_default/syscalls.c index 1782610d08..31758ea8f6 100644 --- a/sys/picolibc_syscalls_default/syscalls.c +++ b/sys/picolibc_syscalls_default/syscalls.c @@ -28,6 +28,81 @@ #include "periph/pm.h" #include "stdio_base.h" +#ifndef NUM_HEAPS +#define NUM_HEAPS 1 +#endif + +/** + * @brief manage the heap + */ +extern char _sheap; /* start of the heap */ +extern char _eheap; /* end of the heap */ +#define __eheap &_eheap + +/** + * @brief Additional heap sections that may be defined in the linkerscript. + * + * The compiler should not generate references to those symbols if + * they are not used, so only provide them if additional memory sections + * that can be used as heap are available. + * @{ + */ +extern char _sheap1; +extern char _eheap1; + +extern char _sheap2; +extern char _eheap2; + +extern char _sheap3; +extern char _eheap3; +/* @} */ + +struct heap { + char* start; + char* end; +}; + +static char *heap_top[NUM_HEAPS] = { + &_sheap, +#if NUM_HEAPS > 1 + &_sheap1, +#endif +#if NUM_HEAPS > 2 + &_sheap2, +#endif +#if NUM_HEAPS > 3 + &_sheap3, +#endif +#if NUM_HEAPS > 4 +#error "Unsupported NUM_HEAPS value, edit newlib_syscalls_default/syscalls.c to add more heaps." +#endif +}; + +static const struct heap heaps[NUM_HEAPS] = { + { + .start = &_sheap, + .end = __eheap + }, +#if NUM_HEAPS > 1 + { + .start = &_sheap1, + .end = &_eheap1 + }, +#endif +#if NUM_HEAPS > 2 + { + .start = &_sheap2, + .end = &_eheap2 + }, +#endif +#if NUM_HEAPS > 3 + { + .start = &_sheap3, + .end = &_eheap3 + }, +#endif +}; + /** * @brief Exit a program without cleaning up files * @@ -44,6 +119,32 @@ _exit(int n) while(1); } +/** + * @brief Allocate memory from the heap. + * + * @return pointer to the newly allocated memory on success + * @return pointer set to address `-1` on failure + */ +void *sbrk(ptrdiff_t incr) +{ + void *res = (void*)UINTPTR_MAX; + unsigned int state = irq_disable(); + + for (unsigned i = 0; i < NUM_HEAPS; ++i) { + if ((heap_top[i] + incr > heaps[i].end) || + (heap_top[i] + incr < heaps[i].start)) { + continue; + } + + res = heap_top[i]; + heap_top[i] += incr; + break; + } + + irq_restore(state); + return res; +} + /** * @brief Send a signal to a thread *