Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9c03660

Browse filesBrowse files
authored
Merge pull request #10 from fpistm/newlib
Use thread-safe memory manager using C runtime (Newlib)
2 parents 10766d7 + f7c63ad commit 9c03660
Copy full SHA for 9c03660

File tree

Expand file treeCollapse file tree

3 files changed

+181
-5
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+181
-5
lines changed

‎portable/MemMang/heap_useNewlib.c

Copy file name to clipboard
+161Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/**
2+
* \file heap_useNewlib.c
3+
* \brief Wrappers required to use newlib malloc-family within FreeRTOS.
4+
*
5+
* \par Overview
6+
* Route FreeRTOS memory management functions to newlib's malloc family.
7+
* Thus newlib and FreeRTOS share memory-management routines and memory pool,
8+
* and all newlib's internal memory-management requirements are supported.
9+
*
10+
* \author Dave Nadler
11+
* \date 2-July-2017
12+
*
13+
* \see http://www.nadler.com/embedded/newlibAndFreeRTOS.html
14+
* \see https://sourceware.org/newlib/libc.html#Reentrancy
15+
* \see https://sourceware.org/newlib/libc.html#malloc
16+
* \see https://sourceware.org/newlib/libc.html#index-_005f_005fenv_005flock
17+
* \see https://sourceware.org/newlib/libc.html#index-_005f_005fmalloc_005flock
18+
* \see https://sourceforge.net/p/freertos/feature-requests/72/
19+
* \see http://www.billgatliff.com/newlib.html
20+
* \see http://wiki.osdev.org/Porting_Newlib
21+
* \see http://www.embecosm.com/appnotes/ean9/ean9-howto-newlib-1.0.html
22+
*
23+
*
24+
* \copyright
25+
* (c) Dave Nadler 2017, All Rights Reserved.
26+
* Web: http://www.nadler.com
27+
* email: drn@nadler.com
28+
*
29+
* Redistribution and use in source and binary forms, with or without modification,
30+
* are permitted provided that the following conditions are met:
31+
*
32+
* - Use or redistributions of source code must retain the above copyright notice,
33+
* this list of conditions, ALL ORIGINAL COMMENTS, and the following disclaimer.
34+
*
35+
* - Redistributions in binary form must reproduce the above copyright notice, this
36+
* list of conditions and the following disclaimer in the documentation and/or
37+
* other materials provided with the distribution.
38+
*
39+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
40+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
41+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
43+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
44+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
46+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
48+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49+
*/
50+
51+
#include <stdlib.h> // maps to newlib...
52+
#include <malloc.h> // mallinfo...
53+
#include <errno.h> // ENOMEM
54+
55+
#include "newlib.h"
56+
#if (__NEWLIB__ != 2) || (__NEWLIB_MINOR__ != 5)
57+
#warning "This wrapper was verified for newlib version 2.5.0; please ensure newlib's external requirements for malloc-family are unchanged!"
58+
#endif
59+
60+
#include "FreeRTOS.h" // defines public interface we're implementing here
61+
#if !defined(configUSE_NEWLIB_REENTRANT) || (configUSE_NEWLIB_REENTRANT!=1)
62+
#warning "#define configUSE_NEWLIB_REENTRANT 1 // Required for thread-safety of newlib sprintf, strtok, etc..."
63+
// If you're *really* sure you don't need FreeRTOS's newlib reentrancy support, remove this warning...
64+
#endif
65+
#include "task.h"
66+
67+
// ================================================================================================
68+
// External routines required by newlib's malloc (sbrk/_sbrk, __malloc_lock/unlock)
69+
// ================================================================================================
70+
71+
#ifndef NDEBUG
72+
static int totalBytesProvidedBySBRK = 0;
73+
#endif
74+
extern char _end; // Defined in the linker script
75+
static int heapBytesRemaining = -1; // configTOTAL_HEAP_SIZE is not constant will be init later
76+
77+
//! sbrk/_sbrk version supporting reentrant newlib (depends upon above symbols defined by linker control file).
78+
char * sbrk(int incr) {
79+
static char *currentHeapEnd = &_end;
80+
vTaskSuspendAll(); // Note: safe to use before FreeRTOS scheduler started
81+
if (heapBytesRemaining == -1) {
82+
heapBytesRemaining = configTOTAL_HEAP_SIZE;
83+
}
84+
char *previousHeapEnd = currentHeapEnd;
85+
if (currentHeapEnd + incr > &_end + configTOTAL_HEAP_SIZE) {
86+
#if( configUSE_MALLOC_FAILED_HOOK == 1 )
87+
{
88+
extern void vApplicationMallocFailedHook( void );
89+
vApplicationMallocFailedHook();
90+
}
91+
#elif 0
92+
// If you want to alert debugger or halt...
93+
while(1) { __asm("bkpt #0"); }; // Stop in GUI as if at a breakpoint (if debugging, otherwise loop forever)
94+
#else
95+
// If you prefer to believe your application will gracefully trap out-of-memory...
96+
_impure_ptr->_errno = ENOMEM; // newlib's thread-specific errno
97+
xTaskResumeAll();
98+
#endif
99+
return (char *)-1; // the malloc-family routine that called sbrk will return 0
100+
}
101+
currentHeapEnd += incr;
102+
heapBytesRemaining -= incr;
103+
#ifndef NDEBUG
104+
totalBytesProvidedBySBRK += incr;
105+
#endif
106+
xTaskResumeAll();
107+
return (char *) previousHeapEnd;
108+
}
109+
//! Synonym for sbrk.
110+
char * _sbrk(int incr) { return sbrk(incr); };
111+
112+
void __malloc_lock() { vTaskSuspendAll(); };
113+
void __malloc_unlock() { (void)xTaskResumeAll(); };
114+
115+
// newlib also requires implementing locks for the application's environment memory space,
116+
// accessed by newlib's setenv() and getenv() functions.
117+
// As these are trivial functions, momentarily suspend task switching (rather than semaphore).
118+
// ToDo: Move __env_lock/unlock to a separate newlib helper file.
119+
void __env_lock() { vTaskSuspendAll(); };
120+
void __env_unlock() { (void)xTaskResumeAll(); };
121+
122+
/// /brief Wrap malloc/malloc_r to help debug who requests memory and why.
123+
/// Add to the linker command line: -Xlinker --wrap=malloc -Xlinker --wrap=_malloc_r
124+
// Note: These functions are normally unused and stripped by linker.
125+
void *__wrap_malloc(size_t nbytes) {
126+
extern void * __real_malloc(size_t nbytes);
127+
void *p = __real_malloc(nbytes); // Solely for debug breakpoint...
128+
return p;
129+
};
130+
void *__wrap__malloc_r(void *reent, size_t nbytes) {
131+
extern void * __real__malloc_r(size_t nbytes);
132+
void *p = __real__malloc_r(nbytes); // Solely for debug breakpoint...
133+
return p;
134+
};
135+
136+
137+
// ================================================================================================
138+
// Implement FreeRTOS's memory API using newlib-provided malloc family.
139+
// ================================================================================================
140+
141+
void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION {
142+
void *p = malloc(xSize);
143+
return p;
144+
}
145+
void vPortFree( void *pv ) PRIVILEGED_FUNCTION {
146+
free(pv);
147+
};
148+
149+
size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION {
150+
struct mallinfo mi = mallinfo();
151+
if (heapBytesRemaining == -1) {
152+
heapBytesRemaining = configTOTAL_HEAP_SIZE;
153+
}
154+
return mi.fordblks + heapBytesRemaining;
155+
}
156+
157+
// GetMinimumEverFree is not available in newlib's malloc implementation.
158+
// So, no implementation provided: size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
159+
160+
//! No implementation needed, but stub provided in case application already calls vPortInitialiseBlocks
161+
void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION {};

‎src/FreeRTOSConfig_Default.h

Copy file name to clipboardExpand all lines: src/FreeRTOSConfig_Default.h
+15-3Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,11 @@
8484
*----------------------------------------------------------*/
8585

8686
/* Begin custom definitions for STM32 */
87-
/* Default (3) Memory allocation implementations (heap_[1-5].c) */
87+
/* Define memory allocation implementations to use:
88+
* 1 to 5 for heap_[1-5].c
89+
* -1 for heap_useNewlib.c
90+
* Default -1 see heap.c
91+
*/
8892
/*#define configMEMMANG_HEAP_NB 3*/
8993
/* End custom definitions for STM32 */
9094

@@ -93,15 +97,23 @@
9397
#include <stdint.h>
9498
extern uint32_t SystemCoreClock;
9599
#endif
100+
extern char _end; /* Defined in the linker script */
101+
extern char _estack; /* Defined in the linker script */
102+
extern char _Min_Stack_Size; /* Defined in the linker script */
96103

97104
#define configUSE_PREEMPTION 1
98105
#define configUSE_IDLE_HOOK 1
99106
#define configUSE_TICK_HOOK 1
100107
#define configCPU_CLOCK_HZ (SystemCoreClock)
101108
#define configTICK_RATE_HZ ((TickType_t)1000)
102109
#define configMAX_PRIORITIES (7)
103-
#define configMINIMAL_STACK_SIZE ((uint16_t)128)
104-
#define configTOTAL_HEAP_SIZE ((size_t)(15 * 1024))
110+
/*
111+
* _Min_Stack_Size is often set to 0x400 in the linker script
112+
* Use it divided by 8 to set minmimal stack size of a task to 128 by default.
113+
* End user will have to properly configure those value depending to their needs.
114+
*/
115+
#define configMINIMAL_STACK_SIZE ((uint16_t)((uint32_t)&_Min_Stack_Size/8))
116+
#define configTOTAL_HEAP_SIZE ((size_t)(&_estack - _Min_Stack_Size - &_end))
105117
#define configMAX_TASK_NAME_LEN (16)
106118
#define configUSE_TRACE_FACILITY 1
107119
#define configUSE_16_BIT_TICKS 0

‎src/heap.c

Copy file name to clipboardExpand all lines: src/heap.c
+5-2Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* @file heap.c
33
* @author Frederic Pillon <frederic.pillon@st.com> for STMicroelectronics.
44
* @brief Provide Memory allocation implementations included in the FreeRTOS source
5+
* heap_useNewlib - thread-safe memory manager using C runtime (Newlib)
56
* heap_1 - the very simplest, does not permit memory to be freed
67
* heap_2 - permits memory to be freed, but not does coalescence adjacent free blocks.
78
* heap_3 - simply wraps the standard malloc() and free() for thread safety
@@ -11,10 +12,12 @@
1112
#include "FreeRTOS.h"
1213

1314
#ifndef configMEMMANG_HEAP_NB
14-
#define configMEMMANG_HEAP_NB 3
15+
#define configMEMMANG_HEAP_NB -1
1516
#endif
1617

17-
#if (configMEMMANG_HEAP_NB == 1)
18+
#if (configMEMMANG_HEAP_NB == -1)
19+
#include "../portable/MemMang/heap_useNewlib.c"
20+
#elif (configMEMMANG_HEAP_NB == 1)
1821
#include "../portable/MemMang/heap_1.c"
1922
#elif (configMEMMANG_HEAP_NB == 2)
2023
#include "../portable/MemMang/heap_2.c"

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.