From 9e6d1683b89cc79bfe422b9f784dbf70f3e335bf Mon Sep 17 00:00:00 2001 From: Adam Green Date: Fri, 30 Aug 2013 18:15:25 -0700 Subject: [PATCH] gcc: Provide _sbrk implementation compatible with RTX I verified that the hang issue I was seeing when building and running the mbed official networking tests with GCC_ARM was related to this issue reported on the mbed forums: http://mbed.org/forum/mbed/topic/3803/?page=1#comment-18934 If you are using the 4.7 2013q1 update of GCC_ARM or newer then it will have a _sbrk() implementation which checks the new top of heap pointer against the current thread SP, stack pointer. See this GCC_ARM related thread for more information: https://answers.launchpad.net/gcc-arm-embedded/+question/218972 When using RTX RTOS threads, the thread's stack pointer can easily point to an address which is below the current top of heap so this check will incorrectly fail the allocation. I have added a _sbrk() implementation to the mbed SDK which checks the heap pointer against the MSP instead of the current thread SP. I have only enabled this for TOOLCHAIN_GCC_ARM as this is the only GCC based toolchain that I am sure requires this. --- libraries/mbed/common/retarget.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/libraries/mbed/common/retarget.cpp b/libraries/mbed/common/retarget.cpp index 62f069758b..987e5e4242 100644 --- a/libraries/mbed/common/retarget.cpp +++ b/libraries/mbed/common/retarget.cpp @@ -425,3 +425,30 @@ extern "C" void __iar_argc_argv() { mbed_main(); } #endif + +// Provide implementation of _sbrk (low-level dynamic memory allocation +// routine) for GCC_ARM which compares new heap pointer with MSP instead of +// SP. This make it compatible with RTX RTOS thread stacks. +#if defined(TOOLCHAIN_GCC_ARM) +// Linker defined symbol used by _sbrk to indicate where heap should start. +extern "C" int __end__; + +// Turn off the errno macro and use actual global variable instead. +#undef errno +extern "C" int errno; + +// Dynamic memory allocation related syscall. +extern "C" caddr_t _sbrk(int incr) { + static unsigned char* heap = (unsigned char*)&__end__; + unsigned char* prev_heap = heap; + unsigned char* new_heap = heap + incr; + + if (new_heap >= (unsigned char*)__get_MSP()) { + errno = ENOMEM; + return (caddr_t)-1; + } + + heap = new_heap; + return (caddr_t) prev_heap; +} +#endif