diff --git a/FreeRTOS/Source/portable/esp8266/port.c b/FreeRTOS/Source/portable/esp8266/port.c index b11a1c5..d27460a 100644 --- a/FreeRTOS/Source/portable/esp8266/port.c +++ b/FreeRTOS/Source/portable/esp8266/port.c @@ -172,9 +172,8 @@ portBASE_TYPE xPortStartScheduler( void ) return pdTRUE; } -/* Determine free heap size via libc sbrk function & mallinfo +/* Determine free heap size via mallinfo - sbrk gives total size in totally unallocated memory, mallinfo.fordblks gives free space inside area dedicated to heap. mallinfo is possibly non-portable, although glibc & newlib both support @@ -183,14 +182,7 @@ portBASE_TYPE xPortStartScheduler( void ) size_t xPortGetFreeHeapSize( void ) { struct mallinfo mi = mallinfo(); - uint32_t brk_val = (uint32_t) sbrk(0); - - intptr_t sp = (intptr_t)xPortSupervisorStackPointer; - if (sp == 0) { - /* scheduler not started */ - SP(sp); - } - return sp - brk_val + mi.fordblks; + return mi.fordblks; } void vPortEndScheduler( void ) diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c index b7af046..8b18fa9 100644 --- a/FreeRTOS/Source/tasks.c +++ b/FreeRTOS/Source/tasks.c @@ -754,7 +754,11 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION; /* Allocate space for the stack used by the task being created. The base of the stack memory stored in the TCB so the task can be deleted later if required. */ + + /* Allocate the stack in dram, not iram. */ + uint32_t malloc_mask = set_malloc_regions(MALLOC_MASK_DRAM); pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + set_malloc_regions(malloc_mask); if( pxNewTCB->pxStack == NULL ) { @@ -769,7 +773,10 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION; StackType_t *pxStack; /* Allocate space for the stack used by the task being created. */ + /* Allocate the stack in dram, not iram. */ + uint32_t malloc_mask = set_malloc_regions(MALLOC_MASK_DRAM); pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + set_malloc_regions(malloc_mask); if( pxStack != NULL ) { @@ -990,7 +997,16 @@ UBaseType_t x; { /* Initialise this task's Newlib reent structure. */ _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) ); - } + + if (strcmp(pcName, "ppTask") == 0 || + strcmp(pcName, "rtc_timer_task") == 0 || + strcmp(pcName, "Tmr Svc") == 0) { + pxNewTCB->xNewLib_reent.malloc_region_mask = MALLOC_MASK_DRAM; + } else { + pxNewTCB->xNewLib_reent.malloc_region_mask = MALLOC_MASK_PREFER_DRAM; + //pxNewTCB->xNewLib_reent.malloc_region_mask = MALLOC_MASK_PREFER_IRAM; + } + } #endif #if( INCLUDE_xTaskAbortDelay == 1 ) diff --git a/core/app_main.c b/core/app_main.c index f854dce..a37d779 100644 --- a/core/app_main.c +++ b/core/app_main.c @@ -137,6 +137,9 @@ static void IRAM default_putc(char c) { void init_newlib_locks(void); extern uint8_t sdk_wDevCtrl[]; void nano_malloc_insert_chunk(void *start, size_t size); +extern uint8_t _heap_start[]; +extern uint8_t _text_end[]; +extern uint8_t enable_low_icache; // .text+0x258 void IRAM sdk_user_start(void) { @@ -209,8 +212,13 @@ void IRAM sdk_user_start(void) { cksum_value = buf32[5 + boot_slot]; ic_flash_addr = (flash_sectors - 3 + boot_slot) * sdk_flashchip.sector_size; sdk_SPIRead(ic_flash_addr, buf32, sizeof(struct sdk_g_ic_saved_st)); + +#ifdef ESP8266_ENABLE_LOW_ICACHE + enable_low_icache = ESP8266_ENABLE_LOW_ICACHE; +#endif Cache_Read_Enable(0, 0, 1); zero_bss(); + sdk_os_install_putc1(default_putc); /* HACK Reclaim a region of unused bss from wdev.o. This would not be @@ -219,6 +227,26 @@ void IRAM sdk_user_start(void) { * it is in very useful dram. */ nano_malloc_insert_chunk((void *)(sdk_wDevCtrl + 0x2190), 8000); + /* Use all the used DRAM is for the dynamic heap. */ + nano_malloc_insert_chunk(_heap_start, 0x3FFFC000 - (uintptr_t)_heap_start); + + /* Add unused IRAM to the malloc free list. */ + if (enable_low_icache) { + /* The memory region 0x40108000 to 0x4010C000 is used for icache so can + * not be used, but there might still be some unused IRAM */ + nano_malloc_insert_chunk(_text_end, 0x40108000 - (uintptr_t)_text_end); + } else { + /* The memory region 0x40108000 to 0x4010C000 is not used as part of the + * instruction cache and is usable as extra IRAM. */ + nano_malloc_insert_chunk(_text_end, 0x4010C000 - (uintptr_t)_text_end); + } + + /* The preferred memory region to start allocate the early data. If the app + * has ample memory the use the DRAM, other if the app is running low on + * DRAM then it might help the allocated to the IRAM when possible. */ + set_malloc_regions(MALLOC_MASK_PREFER_DRAM); + //set_malloc_regions(MALLOC_MASK_PREFER_IRAM); + init_newlib_locks(); if (cksum_magic == 0xffffffff) { @@ -368,6 +396,7 @@ void sdk_user_init_task(void *params) { /* The start up stack is not used after scheduling has started, so all of * the top area of RAM which was stack can be used for the dynamic heap. */ xPortSupervisorStackPointer = (void *)0x40000000; + nano_malloc_insert_chunk((void *)0x3FFFC000, 0x4000); sdk_ets_timer_init(); printf("\nESP-Open-SDK ver: %s compiled @ %s %s\n", OS_VERSION_STR, __DATE__, __TIME__); diff --git a/core/include/common_macros.h b/core/include/common_macros.h index 7034787..3a07acf 100644 --- a/core/include/common_macros.h +++ b/core/include/common_macros.h @@ -117,5 +117,10 @@ #define IROM __attribute__((section(".irom0.literal"))) const #endif +uint32_t set_malloc_regions(uint32_t mask); +#define MALLOC_MASK_PREFER_IRAM 0xfffdfffc +#define MALLOC_MASK_PREFER_DRAM 0 +#define MALLOC_MASK_DRAM 0xfffffffe +#define MALLOC_MASK_IRAM 0xfffffffd #endif diff --git a/core/newlib_syscalls.c b/core/newlib_syscalls.c index 50d0d30..d243a40 100644 --- a/core/newlib_syscalls.c +++ b/core/newlib_syscalls.c @@ -34,39 +34,30 @@ #error Too many lwip sockets for the FD_SETSIZE. #endif -extern void *xPortSupervisorStackPointer; - -IRAM void *_sbrk_r (struct _reent *r, ptrdiff_t incr) +void *_sbrk_r (struct _reent *r, ptrdiff_t incr) { - extern char _heap_start; /* linker script defined */ - static char * heap_end; - char * prev_heap_end; - - if (heap_end == NULL) - heap_end = &_heap_start; - prev_heap_end = heap_end; - - intptr_t sp = (intptr_t)xPortSupervisorStackPointer; - if(sp == 0) /* scheduler not started */ - SP(sp); - - if ((intptr_t)heap_end + incr >= sp) - { - r->_errno = ENOMEM; - return (caddr_t)-1; - } - - heap_end += incr; - - return (caddr_t) prev_heap_end; + r->_errno = ENOMEM; + return (caddr_t)-1; } +/* If there is a restriction on the dram usage then skip this chunk if in dram, + * and if there is a restriction on the iram usage then skip this chunk if in + * iram */ +IRAM int _malloc_region_masked(void *r, unsigned int mask) +{ + if ( ((mask & 1) && (uint32_t)r < 0x40000000) || + ((mask & 2) && (uint32_t)r >= 0x40100000) ) { + return 1; + } -/* Insert a disjoint region into the nano malloc pool. Create a malloc chunk, - * filling the size as newlib nano malloc expects, and then free it. */ -void nano_malloc_insert_chunk(void *start, size_t size) { - *(uint32_t *)start = size; - free(start + sizeof(size_t)); + return 0; +} + +uint32_t set_malloc_regions(uint32_t mask) +{ + uint32_t malloc_mask = _REENT->malloc_region_mask; + _REENT->malloc_region_mask = mask; + return malloc_mask; } /* syscall implementation for stdio write to UART */ diff --git a/extras/wificfg/wificfg.c b/extras/wificfg/wificfg.c index 1e4c5d2..3e5f167 100644 --- a/extras/wificfg/wificfg.c +++ b/extras/wificfg/wificfg.c @@ -599,6 +599,11 @@ static const char *http_wificfg_content[] = { #include "content/wificfg/index.html" }; +extern unsigned nano_malloc_region_total_0; +extern unsigned nano_malloc_region_free_0; +extern unsigned nano_malloc_region_total_1; +extern unsigned nano_malloc_region_free_1; + static int handle_wificfg_index(int s, wificfg_method method, uint32_t content_length, wificfg_content_type content_type, @@ -632,7 +637,19 @@ static int handle_wificfg_index(int s, wificfg_method method, xTaskGetTickCount() * portTICK_PERIOD_MS / 1000); if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; - snprintf(buf, len, "