Skip to content

Commit 145fef1

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

File tree

13 files changed

+97
-42
lines changed

13 files changed

+97
-42
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 8eaccaa1e840de60501a1e5b79045cd7c1683789
22

33
The build commands were:
44

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,8 @@ struct _reent
416416
__FILE *__sf; /* file descriptors */
417417
struct _misc_reent *_misc; /* strtok, multibyte states */
418418
char *_signal_buf; /* strsignal */
419+
420+
unsigned int malloc_region_mask;
419421
};
420422

421423
#ifdef _REENT_GLOBAL_STDIO_STREAMS
@@ -482,7 +484,8 @@ extern const struct __sFILE_fake __sf_fake_stderr;
482484
{_NULL, 0, _NULL}, \
483485
_NULL, \
484486
_NULL, \
485-
_NULL \
487+
_NULL, \
488+
0 \
486489
}
487490

488491
#define _REENT_INIT_PTR_ZEROED(var) \

libc/xtensa-lx106-elf/lib/libc.a

18.3 KB
Binary file not shown.

libc/xtensa-lx106-elf/lib/libg.a

18.3 KB
Binary file not shown.

0 commit comments

Comments
 (0)