From 4eca9f9694c13b94d996594d719c99b07fd9fefe Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 16 Apr 2021 10:34:28 +0200 Subject: [PATCH 1/6] Add heap_useNewlib_ST.c from Dave Nadler to support newlib 3.1 https://nadler.com/embedded/newlibAndFreeRTOS.html https://github.com/DRNadler/FreeRTOS_helpers Signed-off-by: Frederic Pillon --- portable/MemMang/heap_useNewlib_ST.c | 284 +++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 portable/MemMang/heap_useNewlib_ST.c diff --git a/portable/MemMang/heap_useNewlib_ST.c b/portable/MemMang/heap_useNewlib_ST.c new file mode 100644 index 0000000..cf30cb5 --- /dev/null +++ b/portable/MemMang/heap_useNewlib_ST.c @@ -0,0 +1,284 @@ +/** + * \file heap_useNewlib_ST.c + * \brief Wrappers required to use newlib malloc-family within FreeRTOS. + * + * \par Overview + * Route FreeRTOS memory management functions to newlib's malloc family. + * Thus newlib and FreeRTOS share memory-management routines and memory pool, + * and all newlib's internal memory-management requirements are supported. + * + * \author Dave Nadler + * \date 20-August-2019 + * \version 27-Jun-2020 Correct "FreeRTOS.h" capitalization, commentary + * \version 24-Jun-2020 commentary only + * \version 11-Sep-2019 malloc accounting, comments, newlib version check + * + * \see http://www.nadler.com/embedded/newlibAndFreeRTOS.html + * \see https://sourceware.org/newlib/libc.html#Reentrancy + * \see https://sourceware.org/newlib/libc.html#malloc + * \see https://sourceware.org/newlib/libc.html#index-_005f_005fenv_005flock + * \see https://sourceware.org/newlib/libc.html#index-_005f_005fmalloc_005flock + * \see https://sourceforge.net/p/freertos/feature-requests/72/ + * \see http://www.billgatliff.com/newlib.html + * \see http://wiki.osdev.org/Porting_Newlib + * \see http://www.embecosm.com/appnotes/ean9/ean9-howto-newlib-1.0.html + * + * + * \copyright + * (c) Dave Nadler 2017-2020, All Rights Reserved. + * Web: http://www.nadler.com + * email: drn@nadler.com + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Use or redistributions of source code must retain the above copyright notice, + * this list of conditions, and the following disclaimer. + * + * - Use or redistributions of source code must retain ALL ORIGINAL COMMENTS, AND + * ANY CHANGES MUST BE DOCUMENTED, INCLUDING: + * - Reason for change (purpose) + * - Functional change + * - Date and author contact + * + * - Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// ================================================================================================ +// ======================================= Configuration ======================================== +// These configuration symbols could be provided by from build... +#define STM_VERSION // Replace sane LD symbols with STM CubeMX's poor standard exported LD symbols +#define ISR_STACK_LENGTH_BYTES (configISR_STACK_SIZE_WORDS*4) // bytes to reserve for ISR (MSP) stack +// ======================================= Configuration ======================================== +// ================================================================================================ + + +#include // maps to newlib... +#include // mallinfo... +#include // ENOMEM +#include +#include + +#include "newlib.h" +#if ((__NEWLIB__ == 2) && (__NEWLIB_MINOR__ < 5)) ||((__NEWLIB__ == 3) && (__NEWLIB_MINOR__ > 1)) + #warning "This wrapper was verified for newlib versions 2.5 - 3.1; please ensure newlib's external requirements for malloc-family are unchanged!" +#endif + +#include "FreeRTOS.h" // defines public interface we're implementing here +#if !defined(configUSE_NEWLIB_REENTRANT) || (configUSE_NEWLIB_REENTRANT!=1) + #warning "#define configUSE_NEWLIB_REENTRANT 1 // Required for thread-safety of newlib sprintf, dtoa, strtok, etc..." + // If you're *REALLY* sure you don't need FreeRTOS's newlib reentrancy support, comment out the above warning... +#endif +#include "task.h" + +// ================================================================================================ +// External routines required by newlib's malloc (sbrk/_sbrk, __malloc_lock/unlock) +// ================================================================================================ + +// Simplistic sbrk implementations assume stack grows downwards from top of memory, +// and heap grows upwards starting just after BSS. +// FreeRTOS normally allocates task stacks from a pool placed within BSS or DATA. +// Thus within a FreeRTOS task, stack pointer is always below end of BSS. +// When using this module, stacks are allocated from malloc pool, still always prior +// current unused heap area... + +// Doesn't work with FreeRTOS: STM CubeMX 2018-2019 Incorrect Implementation +#if 0 + caddr_t _sbrk(int incr) + { + extern char end asm("end"); // From linker: lowest unused RAM address, just beyond end of BSS. + 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) // Fails here: always true for FreeRTOS task stacks + { + errno = ENOMEM; // ...so first call inside a FreeRTOS task lands here + return (caddr_t) -1; + } + heap_end += incr; + return (caddr_t) prev_heap_end; + } +#endif + +register char * stack_ptr asm("sp"); + +#ifdef STM_VERSION // Use STM CubeMX LD symbols for heap+stack area + // To avoid modifying STM LD file (and then having CubeMX trash it), use available STM symbols + // Unfortunately STM does not provide standardized markers for RAM suitable for heap! + // STM CubeMX-generated LD files provide the following symbols: + // end /* aligned first word beyond BSS */ + // _estack /* one word beyond end of "RAM" Ram type memory, for STM32F429 0x20030000 */ + // Kludge below uses CubeMX-generated symbols instead of sane LD definitions + #define __HeapBase end + #define __HeapLimit _estack // In K64F LD this is already adjusted for ISR stack space... + static int heapBytesRemaining; + // no DRN HEAP_SIZE symbol from LD... // that's (&__HeapLimit)-(&__HeapBase) + uint32_t TotalHeapSize; // publish for diagnostic routines; filled in first _sbrk call. +#else + // Note: DRN's K64F LD provided: __StackTop (byte beyond end of memory), __StackLimit, HEAP_SIZE, STACK_SIZE + // __HeapLimit was already adjusted to be below reserved stack area. + extern char HEAP_SIZE; // make sure to define this symbol in linker LD command file + static int heapBytesRemaining = (int)&HEAP_SIZE; // that's (&__HeapLimit)-(&__HeapBase) +#endif + + +#ifdef MALLOCS_INSIDE_ISRs // STM code to avoid malloc within ISR (USB CDC stack) + // We can't use vTaskSuspendAll() within an ISR. + // STM's stunningly bad coding malpractice calls malloc within ISRs (for example, on USB connect function USBD_CDC_Init) + // So, we must just suspend/resume interrupts, lengthening max interrupt response time, aarrggg... + #define DRN_ENTER_CRITICAL_SECTION(_usis) { _usis = taskENTER_CRITICAL_FROM_ISR(); } // Disables interrupts (after saving prior state) + #define DRN_EXIT_CRITICAL_SECTION(_usis) { taskEXIT_CRITICAL_FROM_ISR(_usis); } // Re-enables interrupts (unless already disabled prior taskENTER_CRITICAL) +#else + #define DRN_ENTER_CRITICAL_SECTION(_usis) vTaskSuspendAll(); // Note: safe to use before FreeRTOS scheduler started, but not in ISR + #define DRN_EXIT_CRITICAL_SECTION(_usis) xTaskResumeAll(); // Note: safe to use before FreeRTOS scheduler started, but not in ISR +#endif + +#ifndef NDEBUG + static int totalBytesProvidedBySBRK = 0; +#endif +extern char __HeapBase, __HeapLimit; // symbols from linker LD command file + +// Use of vTaskSuspendAll() in _sbrk_r() is normally redundant, as newlib malloc family routines call +// __malloc_lock before calling _sbrk_r(). Note vTaskSuspendAll/xTaskResumeAll support nesting. + +//! _sbrk_r version supporting reentrant newlib (depends upon above symbols defined by linker control file). +void * _sbrk_r(struct _reent *pReent, int incr) { + #ifdef MALLOCS_INSIDE_ISRs // block interrupts during free-storage use + UBaseType_t usis; // saved interrupt status + #endif + static char *currentHeapEnd = &__HeapBase; + #ifdef STM_VERSION // Use STM CubeMX LD symbols for heap + if(TotalHeapSize==0) { + TotalHeapSize = heapBytesRemaining = (int)((&__HeapLimit)-(&__HeapBase))-ISR_STACK_LENGTH_BYTES; + }; + #endif + char* limit = (xTaskGetSchedulerState()==taskSCHEDULER_NOT_STARTED) ? + stack_ptr : // Before scheduler is started, limit is stack pointer (risky!) + &__HeapLimit-ISR_STACK_LENGTH_BYTES; // Once running, OK to reuse all remaining RAM except ISR stack (MSP) stack + DRN_ENTER_CRITICAL_SECTION(usis); + if (currentHeapEnd + incr > limit) { + // Ooops, no more memory available... + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + extern void vApplicationMallocFailedHook( void ); + DRN_EXIT_CRITICAL_SECTION(usis); + vApplicationMallocFailedHook(); + } + #elif defined(configHARD_STOP_ON_MALLOC_FAILURE) + // If you want to alert debugger or halt... + // WARNING: brkpt instruction may prevent watchdog operation... + while(1) { __asm("bkpt #0"); }; // Stop in GUI as if at a breakpoint (if debugging, otherwise loop forever) + #else + // Default, if you prefer to believe your application will gracefully trap out-of-memory... + pReent->_errno = ENOMEM; // newlib's thread-specific errno + DRN_EXIT_CRITICAL_SECTION(usis); + #endif + return (char *)-1; // the malloc-family routine that called sbrk will return 0 + } + // 'incr' of memory is available: update accounting and return it. + char *previousHeapEnd = currentHeapEnd; + currentHeapEnd += incr; + heapBytesRemaining -= incr; + #ifndef NDEBUG + totalBytesProvidedBySBRK += incr; + #endif + DRN_EXIT_CRITICAL_SECTION(usis); + return (char *) previousHeapEnd; +} +//! non-reentrant sbrk uses is actually reentrant by using current context +// ... because the current _reent structure is pointed to by global _impure_ptr +char * sbrk(int incr) { return _sbrk_r(_impure_ptr, incr); } +//! _sbrk is a synonym for sbrk. +char * _sbrk(int incr) { return sbrk(incr); }; + +#ifdef MALLOCS_INSIDE_ISRs // block interrupts during free-storage use + static UBaseType_t malLock_uxSavedInterruptStatus; +#endif +void __malloc_lock(struct _reent *r) { + #if defined(MALLOCS_INSIDE_ISRs) + DRN_ENTER_CRITICAL_SECTION(malLock_uxSavedInterruptStatus); + #else + bool insideAnISR = xPortIsInsideInterrupt(); + configASSERT( !insideAnISR ); // Make damn sure no more mallocs inside ISRs!! + vTaskSuspendAll(); + #endif +}; +void __malloc_unlock(struct _reent *r) { + #if defined(MALLOCS_INSIDE_ISRs) + DRN_EXIT_CRITICAL_SECTION(malLock_uxSavedInterruptStatus); + #else + (void)xTaskResumeAll(); + #endif +}; + +// newlib also requires implementing locks for the application's environment memory space, +// accessed by newlib's setenv() and getenv() functions. +// As these are trivial functions, momentarily suspend task switching (rather than semaphore). +// Not required (and trimmed by linker) in applications not using environment variables. +// ToDo: Move __env_lock/unlock to a separate newlib helper file. +void __env_lock() { vTaskSuspendAll(); }; +void __env_unlock() { (void)xTaskResumeAll(); }; + +#if 1 // Provide malloc debug and accounting wrappers + /// /brief Wrap malloc/malloc_r to help debug who requests memory and why. + /// To use these, add linker options: -Xlinker --wrap=malloc -Xlinker --wrap=_malloc_r + // Note: These functions are normally unused and stripped by linker. + size_t TotalMallocdBytes; + int MallocCallCnt; + static bool inside_malloc; + void *__wrap_malloc(size_t nbytes) { + extern void * __real_malloc(size_t nbytes); + MallocCallCnt++; + TotalMallocdBytes += nbytes; + inside_malloc = true; + void *p = __real_malloc(nbytes); // will call malloc_r... + inside_malloc = false; + return p; + }; + void *__wrap__malloc_r(void *reent, size_t nbytes) { + extern void * __real__malloc_r(size_t nbytes); + if(!inside_malloc) { + MallocCallCnt++; + TotalMallocdBytes += nbytes; + }; + void *p = __real__malloc_r(nbytes); + return p; + }; +#endif + +// ================================================================================================ +// Implement FreeRTOS's memory API using newlib-provided malloc family. +// ================================================================================================ + +void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION { + void *p = malloc(xSize); + return p; +} +void vPortFree( void *pv ) PRIVILEGED_FUNCTION { + free(pv); +}; + +size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION { + struct mallinfo mi = mallinfo(); // available space now managed by newlib + return mi.fordblks + heapBytesRemaining; // plus space not yet handed to newlib by sbrk +} + +// GetMinimumEverFree is not available in newlib's malloc implementation. +// So, no implementation is provided: size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION; + +//! No implementation needed, but stub provided in case application already calls vPortInitialiseBlocks +void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION {}; From 4b76cae7f0cea717ebc1dec44fde62571e689ca5 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 16 Apr 2021 16:25:09 +0200 Subject: [PATCH 2/6] Update to use the heap_useNewlib_ST.c from Dave Nadler Signed-off-by: Frederic Pillon --- README.md | 2 +- portable/MemMang/heap_useNewlib.c | 166 ------------------------------ src/FreeRTOSConfig_Default.h | 6 +- src/heap.c | 4 +- 4 files changed, 6 insertions(+), 172 deletions(-) delete mode 100644 portable/MemMang/heap_useNewlib.c diff --git a/README.md b/README.md index 3203f7f..ae6aee2 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ By default, the `heap_useNewlib.c` is used. It can be changed thanks a define in ``` /* Define memory allocation implementations to use: * 1 to 5 for heap_[1-5].c - * -1 for heap_useNewlib.c + * -1 for heap_useNewlib_ST.c * Default -1 see heap.c */ ``` diff --git a/portable/MemMang/heap_useNewlib.c b/portable/MemMang/heap_useNewlib.c deleted file mode 100644 index 7c62f5c..0000000 --- a/portable/MemMang/heap_useNewlib.c +++ /dev/null @@ -1,166 +0,0 @@ -/** - * \file heap_useNewlib.c - * \brief Wrappers required to use newlib malloc-family within FreeRTOS. - * - * \par Overview - * Route FreeRTOS memory management functions to newlib's malloc family. - * Thus newlib and FreeRTOS share memory-management routines and memory pool, - * and all newlib's internal memory-management requirements are supported. - * - * \author Dave Nadler - * \date 2-July-2017 - * - * \see http://www.nadler.com/embedded/newlibAndFreeRTOS.html - * \see https://sourceware.org/newlib/libc.html#Reentrancy - * \see https://sourceware.org/newlib/libc.html#malloc - * \see https://sourceware.org/newlib/libc.html#index-_005f_005fenv_005flock - * \see https://sourceware.org/newlib/libc.html#index-_005f_005fmalloc_005flock - * \see https://sourceforge.net/p/freertos/feature-requests/72/ - * \see http://www.billgatliff.com/newlib.html - * \see http://wiki.osdev.org/Porting_Newlib - * \see http://www.embecosm.com/appnotes/ean9/ean9-howto-newlib-1.0.html - * - * - * \copyright - * (c) Dave Nadler 2017, All Rights Reserved. - * Web: http://www.nadler.com - * email: drn@nadler.com - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * - Use or redistributions of source code must retain the above copyright notice, - * this list of conditions, ALL ORIGINAL COMMENTS, and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include // maps to newlib... -#include // mallinfo... -#include // ENOMEM - -#include "newlib.h" -#if (__NEWLIB__ != 2) || (__NEWLIB_MINOR__ != 5) - #warning "This wrapper was verified for newlib version 2.5.0; please ensure newlib's external requirements for malloc-family are unchanged!" -#endif - -#include "FreeRTOS.h" // defines public interface we're implementing here -#if !defined(configUSE_NEWLIB_REENTRANT) || (configUSE_NEWLIB_REENTRANT!=1) - #warning "#define configUSE_NEWLIB_REENTRANT 1 // Required for thread-safety of newlib sprintf, strtok, etc..." - // If you're *really* sure you don't need FreeRTOS's newlib reentrancy support, remove this warning... -#endif -#include "task.h" - -// ================================================================================================ -// External routines required by newlib's malloc (sbrk/_sbrk, __malloc_lock/unlock) -// ================================================================================================ - -#ifndef NDEBUG - static int totalBytesProvidedBySBRK = 0; -#endif -extern char _end; // Defined in the linker script -static int heapBytesRemaining = -1; // configTOTAL_HEAP_SIZE is not constant will be init later - -//! sbrk/_sbrk version supporting reentrant newlib (depends upon above symbols defined by linker control file). -char * sbrk(int incr) { - static char *currentHeapEnd = &_end; - vTaskSuspendAll(); // Note: safe to use before FreeRTOS scheduler started - if (heapBytesRemaining == -1) { - heapBytesRemaining = configTOTAL_HEAP_SIZE; - } - char *previousHeapEnd = currentHeapEnd; - if (currentHeapEnd + incr > &_end + configTOTAL_HEAP_SIZE) { - #if( configUSE_MALLOC_FAILED_HOOK == 1 ) - { - extern void vApplicationMallocFailedHook( void ); - vApplicationMallocFailedHook(); - } - #elif 0 - // If you want to alert debugger or halt... - while(1) { __asm("bkpt #0"); }; // Stop in GUI as if at a breakpoint (if debugging, otherwise loop forever) - #else - // If you prefer to believe your application will gracefully trap out-of-memory... - _impure_ptr->_errno = ENOMEM; // newlib's thread-specific errno - xTaskResumeAll(); - #endif - return (char *)-1; // the malloc-family routine that called sbrk will return 0 - } - currentHeapEnd += incr; - heapBytesRemaining -= incr; - #ifndef NDEBUG - totalBytesProvidedBySBRK += incr; - #endif - xTaskResumeAll(); - return (char *) previousHeapEnd; -} -//! Synonym for sbrk. -char * _sbrk(int incr) { return sbrk(incr); }; - -#if (__NEWLIB__ >= 3) -void __malloc_lock(struct _reent *ptr __attribute__((__unused__))) { vTaskSuspendAll(); }; -void __malloc_unlock(struct _reent *ptr __attribute__((__unused__))) { (void)xTaskResumeAll(); }; -#else -void __malloc_lock() { vTaskSuspendAll(); }; -void __malloc_unlock() { (void)xTaskResumeAll(); }; -#endif - -// newlib also requires implementing locks for the application's environment memory space, -// accessed by newlib's setenv() and getenv() functions. -// As these are trivial functions, momentarily suspend task switching (rather than semaphore). -// ToDo: Move __env_lock/unlock to a separate newlib helper file. -void __env_lock() { vTaskSuspendAll(); }; -void __env_unlock() { (void)xTaskResumeAll(); }; - -/// /brief Wrap malloc/malloc_r to help debug who requests memory and why. -/// Add to the linker command line: -Xlinker --wrap=malloc -Xlinker --wrap=_malloc_r -// Note: These functions are normally unused and stripped by linker. -void *__wrap_malloc(size_t nbytes) { - extern void * __real_malloc(size_t nbytes); - void *p = __real_malloc(nbytes); // Solely for debug breakpoint... - return p; -}; -void *__wrap__malloc_r(void *reent __attribute__((__unused__)), size_t nbytes) { - extern void * __real__malloc_r(size_t nbytes); - void *p = __real__malloc_r(nbytes); // Solely for debug breakpoint... - return p; -}; - - -// ================================================================================================ -// Implement FreeRTOS's memory API using newlib-provided malloc family. -// ================================================================================================ - -void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION { - void *p = malloc(xSize); - return p; -} -void vPortFree( void *pv ) PRIVILEGED_FUNCTION { - free(pv); -}; - -size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION { - struct mallinfo mi = mallinfo(); - if (heapBytesRemaining == -1) { - heapBytesRemaining = configTOTAL_HEAP_SIZE; - } - return mi.fordblks + heapBytesRemaining; -} - -// GetMinimumEverFree is not available in newlib's malloc implementation. -// So, no implementation provided: size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION; - -//! No implementation needed, but stub provided in case application already calls vPortInitialiseBlocks -void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION {}; diff --git a/src/FreeRTOSConfig_Default.h b/src/FreeRTOSConfig_Default.h index b76cc09..61560a9 100644 --- a/src/FreeRTOSConfig_Default.h +++ b/src/FreeRTOSConfig_Default.h @@ -44,7 +44,7 @@ /* Begin custom definitions for STM32 */ /* Define memory allocation implementations to use: * 1 to 5 for heap_[1-5].c - * -1 for heap_useNewlib.c + * -1 for heap_useNewlib_ST.c * Default -1 see heap.c */ /*#define configMEMMANG_HEAP_NB 3*/ @@ -82,7 +82,7 @@ #define configMINIMAL_STACK_SIZE ((uint16_t)128) #define configTOTAL_HEAP_SIZE ((size_t)(15 * 1024)) - +#define configISR_STACK_SIZE_WORDS (0x100) #else extern char _end; /* Defined in the linker script */ extern char _estack; /* Defined in the linker script */ @@ -97,7 +97,7 @@ extern char _Min_Stack_Size; /* Defined in the linker script */ */ #define configMINIMAL_STACK_SIZE ((uint16_t)((uint32_t)&_Min_Stack_Size/8)) #define configTOTAL_HEAP_SIZE ((size_t)(&_estack - _Min_Stack_Size - &_end)) - +#define configISR_STACK_SIZE_WORDS ((uint32_t)&_Min_Stack_Size/4) #endif /* configUSE_CMSIS_RTOS_V2 */ #define configUSE_PREEMPTION 1 diff --git a/src/heap.c b/src/heap.c index 6a25e7a..238afbf 100644 --- a/src/heap.c +++ b/src/heap.c @@ -2,7 +2,7 @@ * @file heap.c * @author Frederic Pillon for STMicroelectronics. * @brief Provide Memory allocation implementations included in the FreeRTOS source - * heap_useNewlib - thread-safe memory manager using C runtime (Newlib) + * heap_useNewlib_ST - thread-safe memory manager using C runtime (Newlib) * heap_1 - the very simplest, does not permit memory to be freed * heap_2 - permits memory to be freed, but not does coalescence adjacent free blocks. * heap_3 - simply wraps the standard malloc() and free() for thread safety @@ -16,7 +16,7 @@ #endif #if (configMEMMANG_HEAP_NB == -1) -#include "../portable/MemMang/heap_useNewlib.c" +#include "../portable/MemMang/heap_useNewlib_ST.c" #elif (configMEMMANG_HEAP_NB == 1) #include "../portable/MemMang/heap_1.c" #elif (configMEMMANG_HEAP_NB == 2) From 778bf9db98886e38fe469b1a67120e422a46162c Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 16 Apr 2021 17:47:10 +0200 Subject: [PATCH 3/6] Fix unused parameters warning in heap_useNewlib_ST.c Signed-off-by: Frederic Pillon --- portable/MemMang/heap_useNewlib_ST.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/portable/MemMang/heap_useNewlib_ST.c b/portable/MemMang/heap_useNewlib_ST.c index cf30cb5..1fb3987 100644 --- a/portable/MemMang/heap_useNewlib_ST.c +++ b/portable/MemMang/heap_useNewlib_ST.c @@ -209,6 +209,7 @@ char * _sbrk(int incr) { return sbrk(incr); }; static UBaseType_t malLock_uxSavedInterruptStatus; #endif void __malloc_lock(struct _reent *r) { + (void)(r); #if defined(MALLOCS_INSIDE_ISRs) DRN_ENTER_CRITICAL_SECTION(malLock_uxSavedInterruptStatus); #else @@ -218,6 +219,7 @@ void __malloc_lock(struct _reent *r) { #endif }; void __malloc_unlock(struct _reent *r) { + (void)(r); #if defined(MALLOCS_INSIDE_ISRs) DRN_EXIT_CRITICAL_SECTION(malLock_uxSavedInterruptStatus); #else @@ -250,6 +252,7 @@ void __env_unlock() { (void)xTaskResumeAll(); }; return p; }; void *__wrap__malloc_r(void *reent, size_t nbytes) { + (void)(reent); extern void * __real__malloc_r(size_t nbytes); if(!inside_malloc) { MallocCallCnt++; From 6e74eb4606c0c39d01f9faf7e5931b5f0528f0bb Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 16 Apr 2021 19:34:56 +0200 Subject: [PATCH 4/6] Fix for CM0 with heap_useNewlib_ST Signed-off-by: Frederic Pillon --- src/portmacro.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/portmacro.h b/src/portmacro.h index f3ff239..e0b2cbd 100644 --- a/src/portmacro.h +++ b/src/portmacro.h @@ -14,6 +14,8 @@ #if (__CORTEX_M == 0x00U) #include "../portable/GCC/ARM_CM0/portmacro.h" +/* Stub for heap_useNewlib_ST */ +inline __attribute__(( always_inline )) static BaseType_t xPortIsInsideInterrupt( void ) { return pdFALSE; } #endif #if (__CORTEX_M == 0x03U) From 23ba1f9efad201b26d69bfcaa6f2fd0ceb69d7a3 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 16 Apr 2021 19:39:35 +0200 Subject: [PATCH 5/6] Update newlib version check Tested with newlib 3.3 of the xPack GNU Arm Embedded GCC v9.3.1-1.3 Signed-off-by: Frederic Pillon --- portable/MemMang/heap_useNewlib_ST.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/portable/MemMang/heap_useNewlib_ST.c b/portable/MemMang/heap_useNewlib_ST.c index 1fb3987..e957f56 100644 --- a/portable/MemMang/heap_useNewlib_ST.c +++ b/portable/MemMang/heap_useNewlib_ST.c @@ -73,8 +73,8 @@ #include #include "newlib.h" -#if ((__NEWLIB__ == 2) && (__NEWLIB_MINOR__ < 5)) ||((__NEWLIB__ == 3) && (__NEWLIB_MINOR__ > 1)) - #warning "This wrapper was verified for newlib versions 2.5 - 3.1; please ensure newlib's external requirements for malloc-family are unchanged!" +#if ((__NEWLIB__ == 2) && (__NEWLIB_MINOR__ < 5)) ||((__NEWLIB__ == 3) && (__NEWLIB_MINOR__ > 3)) + #warning "This wrapper was verified for newlib versions 2.5 - 3.3; please ensure newlib's external requirements for malloc-family are unchanged!" #endif #include "FreeRTOS.h" // defines public interface we're implementing here From 4adcfbd52bbe43261e75ba1ab5d3e48d23b0f4d3 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Sat, 17 Apr 2021 14:27:05 +0200 Subject: [PATCH 6/6] Review size definition Fix issue raised in issue comment: https://github.com/stm32duino/STM32FreeRTOS/issues/39#issuecomment-815126173 when configMEMMANG_HEAP_NB is equal to 1, 2 or 4 Signed-off-by: Frederic Pillon --- src/FreeRTOSConfig_Default.h | 19 ++++++++++++------- src/heap.c | 6 ++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/FreeRTOSConfig_Default.h b/src/FreeRTOSConfig_Default.h index 61560a9..7bc0793 100644 --- a/src/FreeRTOSConfig_Default.h +++ b/src/FreeRTOSConfig_Default.h @@ -79,26 +79,31 @@ * which is not suitable for the new CMSIS-RTOS v2 priority range */ #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 - +/* Require to be a value as used in cmsis_os2.c as array size */ +#ifndef configMINIMAL_STACK_SIZE #define configMINIMAL_STACK_SIZE ((uint16_t)128) -#define configTOTAL_HEAP_SIZE ((size_t)(15 * 1024)) -#define configISR_STACK_SIZE_WORDS (0x100) +#endif #else +#define configMAX_PRIORITIES (7) +#endif /* configUSE_CMSIS_RTOS_V2 */ + extern char _end; /* Defined in the linker script */ extern char _estack; /* Defined in the linker script */ extern char _Min_Stack_Size; /* Defined in the linker script */ - -#define configMAX_PRIORITIES (7) - /* * _Min_Stack_Size is often set to 0x400 in the linker script * Use it divided by 8 to set minmimal stack size of a task to 128 by default. * End user will have to properly configure those value depending to their needs. */ +#ifndef configMINIMAL_STACK_SIZE #define configMINIMAL_STACK_SIZE ((uint16_t)((uint32_t)&_Min_Stack_Size/8)) +#endif +#ifndef configTOTAL_HEAP_SIZE #define configTOTAL_HEAP_SIZE ((size_t)(&_estack - _Min_Stack_Size - &_end)) +#endif +#ifndef configISR_STACK_SIZE_WORDS #define configISR_STACK_SIZE_WORDS ((uint32_t)&_Min_Stack_Size/4) -#endif /* configUSE_CMSIS_RTOS_V2 */ +#endif #define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 1 diff --git a/src/heap.c b/src/heap.c index 238afbf..5f1e676 100644 --- a/src/heap.c +++ b/src/heap.c @@ -15,6 +15,12 @@ #define configMEMMANG_HEAP_NB -1 #endif +#if configMEMMANG_HEAP_NB != -1 +/* Need to be redefined as a value as it used in some heap_*.c as array size */ +#undef configTOTAL_HEAP_SIZE +#define configTOTAL_HEAP_SIZE ((size_t)(15 * 1024)) +#endif + #if (configMEMMANG_HEAP_NB == -1) #include "../portable/MemMang/heap_useNewlib_ST.c" #elif (configMEMMANG_HEAP_NB == 1)