Skip to content

Commit 44738f4

Browse files
committed
Malloc support for allocating to DRAM and/or IRAM.
1 parent 4c93c7b commit 44738f4

File tree

17 files changed

+111
-54
lines changed

17 files changed

+111
-54
lines changed

FreeRTOS/Source/portable/esp8266/port.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,8 @@ portBASE_TYPE xPortStartScheduler( void )
172172
return pdTRUE;
173173
}
174174

175-
/* Determine free heap size via libc sbrk function & mallinfo
175+
/* Determine free heap size via mallinfo
176176
177-
sbrk gives total size in totally unallocated memory,
178177
mallinfo.fordblks gives free space inside area dedicated to heap.
179178
180179
mallinfo is possibly non-portable, although glibc & newlib both support
@@ -183,14 +182,7 @@ portBASE_TYPE xPortStartScheduler( void )
183182
size_t xPortGetFreeHeapSize( void )
184183
{
185184
struct mallinfo mi = mallinfo();
186-
uint32_t brk_val = (uint32_t) sbrk(0);
187-
188-
intptr_t sp = (intptr_t)xPortSupervisorStackPointer;
189-
if (sp == 0) {
190-
/* scheduler not started */
191-
SP(sp);
192-
}
193-
return sp - brk_val + mi.fordblks;
185+
return mi.fordblks;
194186
}
195187

196188
void vPortEndScheduler( void )

FreeRTOS/Source/tasks.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,11 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
754754
/* Allocate space for the stack used by the task being created.
755755
The base of the stack memory stored in the TCB so the task can
756756
be deleted later if required. */
757+
758+
/* Allocate the stack in dram, not iram. */
759+
uint32_t malloc_mask = set_malloc_regions(MALLOC_MASK_DRAM);
757760
pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
761+
set_malloc_regions(malloc_mask);
758762

759763
if( pxNewTCB->pxStack == NULL )
760764
{
@@ -769,7 +773,10 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
769773
StackType_t *pxStack;
770774

771775
/* Allocate space for the stack used by the task being created. */
776+
/* Allocate the stack in dram, not iram. */
777+
uint32_t malloc_mask = set_malloc_regions(MALLOC_MASK_DRAM);
772778
pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
779+
set_malloc_regions(malloc_mask);
773780

774781
if( pxStack != NULL )
775782
{
@@ -988,7 +995,16 @@ UBaseType_t x;
988995
{
989996
/* Initialise this task's Newlib reent structure. */
990997
_REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) );
991-
}
998+
999+
if (strcmp(pcName, "ppTask") == 0 ||
1000+
strcmp(pcName, "rtc_timer_task") == 0 ||
1001+
strcmp(pcName, "Tmr Svc") == 0) {
1002+
pxNewTCB->xNewLib_reent.malloc_region_mask = MALLOC_MASK_DRAM;
1003+
} else {
1004+
pxNewTCB->xNewLib_reent.malloc_region_mask = MALLOC_MASK_PREFER_DRAM;
1005+
//pxNewTCB->xNewLib_reent.malloc_region_mask = MALLOC_MASK_PREFER_IRAM;
1006+
}
1007+
}
9921008
#endif
9931009

9941010
#if( INCLUDE_xTaskAbortDelay == 1 )

core/app_main.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ static void IRAM default_putc(char c) {
137137
void init_newlib_locks(void);
138138
extern uint8_t sdk_wDevCtrl[];
139139
void nano_malloc_insert_chunk(void *start, size_t size);
140+
extern uint8_t _heap_start[];
141+
extern uint8_t _text_end[];
142+
extern uint8_t enable_low_icache;
140143

141144
// .text+0x258
142145
void IRAM sdk_user_start(void) {
@@ -202,8 +205,13 @@ void IRAM sdk_user_start(void) {
202205
cksum_value = buf32[5 + boot_slot];
203206
ic_flash_addr = (flash_sectors - 3 + boot_slot) * sdk_flashchip.sector_size;
204207
sdk_SPIRead(ic_flash_addr, buf32, sizeof(struct sdk_g_ic_saved_st));
208+
209+
#ifdef ESP8266_ENABLE_LOW_ICACHE
210+
enable_low_icache = ESP8266_ENABLE_LOW_ICACHE;
211+
#endif
205212
Cache_Read_Enable(0, 0, 1);
206213
zero_bss();
214+
207215
sdk_os_install_putc1(default_putc);
208216

209217
/* HACK Reclaim a region of unused bss from wdev.o. This would not be
@@ -212,6 +220,26 @@ void IRAM sdk_user_start(void) {
212220
* it is in very useful dram. */
213221
nano_malloc_insert_chunk((void *)(sdk_wDevCtrl + 0x2190), 8000);
214222

223+
/* Use all the used DRAM is for the dynamic heap. */
224+
nano_malloc_insert_chunk(_heap_start, 0x3FFFC000 - (uintptr_t)_heap_start);
225+
226+
/* Add unused IRAM to the malloc free list. */
227+
if (enable_low_icache) {
228+
/* The memory region 0x40108000 to 0x4010C000 is used for icache so can
229+
* not be used, but there might still be some unused IRAM */
230+
nano_malloc_insert_chunk(_text_end, 0x40108000 - (uintptr_t)_text_end);
231+
} else {
232+
/* The memory region 0x40108000 to 0x4010C000 is not used as part of the
233+
* instruction cache and is usable as extra IRAM. */
234+
nano_malloc_insert_chunk(_text_end, 0x4010C000 - (uintptr_t)_text_end);
235+
}
236+
237+
/* The preferred memory region to start allocate the early data. If the app
238+
* has ample memory the use the DRAM, other if the app is running low on
239+
* DRAM then it might help the allocated to the IRAM when possible. */
240+
set_malloc_regions(MALLOC_MASK_PREFER_DRAM);
241+
//set_malloc_regions(MALLOC_MASK_PREFER_IRAM);
242+
215243
init_newlib_locks();
216244

217245
if (cksum_magic == 0xffffffff) {
@@ -361,6 +389,7 @@ void sdk_user_init_task(void *params) {
361389
/* The start up stack is not used after scheduling has started, so all of
362390
* the top area of RAM which was stack can be used for the dynamic heap. */
363391
xPortSupervisorStackPointer = (void *)0x40000000;
392+
nano_malloc_insert_chunk((void *)0x3FFFC000, 0x4000);
364393

365394
sdk_ets_timer_init();
366395
printf("\nESP-Open-SDK ver: %s compiled @ %s %s\n", OS_VERSION_STR, __DATE__, __TIME__);

core/include/common_macros.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,5 +117,10 @@
117117
#define IROM __attribute__((section(".irom0.literal"))) const
118118
#endif
119119

120+
uint32_t set_malloc_regions(uint32_t mask);
121+
#define MALLOC_MASK_PREFER_IRAM 0xfffdfffc
122+
#define MALLOC_MASK_PREFER_DRAM 0
123+
#define MALLOC_MASK_DRAM 0xfffffffe
124+
#define MALLOC_MASK_IRAM 0xfffffffd
120125

121126
#endif

core/newlib_syscalls.c

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,39 +34,30 @@
3434
#error Too many lwip sockets for the FD_SETSIZE.
3535
#endif
3636

37-
extern void *xPortSupervisorStackPointer;
37+
void *_sbrk_r (struct _reent *r, ptrdiff_t incr)
38+
{
39+
r->_errno = ENOMEM;
40+
return (caddr_t)-1;
41+
}
3842

39-
IRAM void *_sbrk_r (struct _reent *r, ptrdiff_t incr)
43+
/* If there is a restriction on the dram usage then skip this chunk if in dram,
44+
* and if there is a restriction on the iram usage then skip this chunk if in
45+
* iram */
46+
IRAM int _malloc_region_masked(void *r, unsigned int mask)
4047
{
41-
extern char _heap_start; /* linker script defined */
42-
static char * heap_end;
43-
char * prev_heap_end;
44-
45-
if (heap_end == NULL)
46-
heap_end = &_heap_start;
47-
prev_heap_end = heap_end;
48-
49-
intptr_t sp = (intptr_t)xPortSupervisorStackPointer;
50-
if(sp == 0) /* scheduler not started */
51-
SP(sp);
52-
53-
if ((intptr_t)heap_end + incr >= sp)
54-
{
55-
r->_errno = ENOMEM;
56-
return (caddr_t)-1;
48+
if ( ((mask & 1) && (uint32_t)r < 0x40000000) ||
49+
((mask & 2) && (uint32_t)r >= 0x40100000) ) {
50+
return 1;
5751
}
5852

59-
heap_end += incr;
60-
61-
return (caddr_t) prev_heap_end;
53+
return 0;
6254
}
6355

64-
65-
/* Insert a disjoint region into the nano malloc pool. Create a malloc chunk,
66-
* filling the size as newlib nano malloc expects, and then free it. */
67-
void nano_malloc_insert_chunk(void *start, size_t size) {
68-
*(uint32_t *)start = size;
69-
free(start + sizeof(size_t));
56+
uint32_t set_malloc_regions(uint32_t mask)
57+
{
58+
uint32_t malloc_mask = _REENT->malloc_region_mask;
59+
_REENT->malloc_region_mask = mask;
60+
return malloc_mask;
7061
}
7162

7263
/* syscall implementation for stdio write to UART */

extras/wificfg/wificfg.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,11 @@ static const char *http_wificfg_content[] = {
599599
#include "content/wificfg/index.html"
600600
};
601601

602+
extern unsigned nano_malloc_region_total_0;
603+
extern unsigned nano_malloc_region_free_0;
604+
extern unsigned nano_malloc_region_total_1;
605+
extern unsigned nano_malloc_region_free_1;
606+
602607
static int handle_wificfg_index(int s, wificfg_method method,
603608
uint32_t content_length,
604609
wificfg_content_type content_type,
@@ -632,7 +637,19 @@ static int handle_wificfg_index(int s, wificfg_method method,
632637
xTaskGetTickCount() * portTICK_PERIOD_MS / 1000);
633638
if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1;
634639

635-
snprintf(buf, len, "<dt>Free heap</dt><dd>%u bytes</dd>", (int)xPortGetFreeHeapSize());
640+
snprintf(buf, len, "<dt>Free dram heap</dt><dd>%u of %u bytes</dd>",
641+
nano_malloc_region_free_0, nano_malloc_region_total_0);
642+
if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1;
643+
644+
set_malloc_regions(MALLOC_MASK_IRAM);
645+
snprintf(buf, len, "<dt>Free iram heap</dt><dd>%u of %u bytes</dd>",
646+
nano_malloc_region_free_1, nano_malloc_region_total_1);
647+
if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1;
648+
649+
set_malloc_regions(MALLOC_MASK_PREFER_DRAM);
650+
snprintf(buf, len, "<dt>Free heap</dt><dd>%u of %u bytes</dd>",
651+
nano_malloc_region_free_0 + nano_malloc_region_free_1,
652+
nano_malloc_region_total_0 + nano_malloc_region_total_1);
636653
if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1;
637654

638655
snprintf(buf, len, "<dt>Flash ID</dt><dd>0x%08x</dd>", sdk_spi_flash_get_id());

libc/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Newlib from git://sourceware.org/git/newlib-cygwin.git with xtensa & locking patches see https://github.com/ourairquality/newlib and built from commit 984b749fb223daab954060c04720933290584f00
1+
Newlib from git://sourceware.org/git/newlib-cygwin.git with xtensa & locking patches see https://github.com/ourairquality/newlib and built from commit caca074d485916de2f85d6cb585d773f0413fba7
22

33
The build commands were:
44

libc/xtensa-lx106-elf/include/pthread.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ int pthread_attr_getschedparam (const pthread_attr_t *__attr,
156156
int pthread_getschedparam (pthread_t __pthread, int *__policy,
157157
struct sched_param *__param);
158158
int pthread_setschedparam (pthread_t __pthread, int __policy,
159-
struct sched_param *__param);
159+
const struct sched_param *__param);
160160

161161
/* Set Scheduling Priority of a Thread */
162162
int pthread_setschedprio (pthread_t thread, int prio);
@@ -190,7 +190,7 @@ int pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *__attr,
190190

191191
int pthread_mutex_setprioceiling (pthread_mutex_t *__mutex,
192192
int __prioceiling, int *__old_ceiling);
193-
int pthread_mutex_getprioceiling (pthread_mutex_t *__mutex,
193+
int pthread_mutex_getprioceiling (const pthread_mutex_t *__restrict __mutex,
194194
int *__prioceiling);
195195

196196
#endif /* _POSIX_THREAD_PRIO_PROTECT */

libc/xtensa-lx106-elf/include/stdlib.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,7 @@ void qsort (void *__base, size_t __nmemb, size_t __size, __compar_fn_t _compar);
144144
int rand (void);
145145
void * realloc (void *__r, size_t __size) _NOTHROW;
146146
#if __BSD_VISIBLE
147-
void *reallocarray(void *, size_t, size_t) __result_use_check __alloc_size(2)
148-
__alloc_size(3);
147+
void *reallocarray(void *, size_t, size_t) __result_use_check __alloc_size((2,3));
149148
void * reallocf (void *__r, size_t __size);
150149
#endif
151150
#if __BSD_VISIBLE || __XSI_VISIBLE >= 4
@@ -329,8 +328,8 @@ extern long double strtold (const char *__restrict, char **__restrict);
329328
* If we're in a mode greater than C99, expose C11 functions.
330329
*/
331330
#if __ISO_C_VISIBLE >= 2011
332-
void * aligned_alloc(size_t, size_t) __malloc_like __alloc_align(1)
333-
__alloc_size(2);
331+
void * aligned_alloc(size_t, size_t) __malloc_like __alloc_align((1))
332+
__alloc_size((2));
334333
int at_quick_exit(void (*)(void));
335334
_Noreturn void
336335
quick_exit(int);

libc/xtensa-lx106-elf/include/sys/_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,10 @@ typedef _CLOCK_T_ __clock_t;
193193
#endif
194194
typedef _TIME_T_ __time_t;
195195

196+
#ifndef __machine_clockid_t_defined
196197
#define _CLOCKID_T_ unsigned long
198+
#endif
199+
197200
typedef _CLOCKID_T_ __clockid_t;
198201

199202
#define _TIMER_T_ unsigned long

0 commit comments

Comments
 (0)