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, "
Free heap
%u bytes
", (int)xPortGetFreeHeapSize()); + snprintf(buf, len, "
Free dram heap
%u of %u bytes
", + nano_malloc_region_free_0, nano_malloc_region_total_0); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + set_malloc_regions(MALLOC_MASK_IRAM); + snprintf(buf, len, "
Free iram heap
%u of %u bytes
", + nano_malloc_region_free_1, nano_malloc_region_total_1); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + set_malloc_regions(MALLOC_MASK_PREFER_DRAM); + snprintf(buf, len, "
Free heap
%u of %u bytes
", + nano_malloc_region_free_0 + nano_malloc_region_free_1, + nano_malloc_region_total_0 + nano_malloc_region_total_1); if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; snprintf(buf, len, "
Flash ID
0x%08x
", sdk_spi_flash_get_id()); diff --git a/libc/README.md b/libc/README.md index e3c84cb..04c6d2d 100644 --- a/libc/README.md +++ b/libc/README.md @@ -1,4 +1,4 @@ -Newlib from git://sourceware.org/git/newlib-cygwin.git with xtensa & locking patches see https://github.com/ourairquality/newlib and built from commit 984b749fb223daab954060c04720933290584f00 +Newlib from git://sourceware.org/git/newlib-cygwin.git with xtensa & locking patches see https://github.com/ourairquality/newlib and built from commit e06f70041061344a62c2e5b8f0a602a902e72306 The build commands were: diff --git a/libc/xtensa-lx106-elf/include/pthread.h b/libc/xtensa-lx106-elf/include/pthread.h index 3dee1c9..c9d24d6 100644 --- a/libc/xtensa-lx106-elf/include/pthread.h +++ b/libc/xtensa-lx106-elf/include/pthread.h @@ -156,7 +156,7 @@ int pthread_attr_getschedparam (const pthread_attr_t *__attr, int pthread_getschedparam (pthread_t __pthread, int *__policy, struct sched_param *__param); int pthread_setschedparam (pthread_t __pthread, int __policy, - struct sched_param *__param); + const struct sched_param *__param); /* Set Scheduling Priority of a Thread */ int pthread_setschedprio (pthread_t thread, int prio); @@ -190,7 +190,7 @@ int pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *__attr, int pthread_mutex_setprioceiling (pthread_mutex_t *__mutex, int __prioceiling, int *__old_ceiling); -int pthread_mutex_getprioceiling (pthread_mutex_t *__mutex, +int pthread_mutex_getprioceiling (const pthread_mutex_t *__restrict __mutex, int *__prioceiling); #endif /* _POSIX_THREAD_PRIO_PROTECT */ diff --git a/libc/xtensa-lx106-elf/include/stdlib.h b/libc/xtensa-lx106-elf/include/stdlib.h index 5417ac0..87297ed 100644 --- a/libc/xtensa-lx106-elf/include/stdlib.h +++ b/libc/xtensa-lx106-elf/include/stdlib.h @@ -144,8 +144,7 @@ void qsort (void *__base, size_t __nmemb, size_t __size, __compar_fn_t _compar); int rand (void); void * realloc (void *__r, size_t __size) _NOTHROW; #if __BSD_VISIBLE -void *reallocarray(void *, size_t, size_t) __result_use_check __alloc_size(2) - __alloc_size(3); +void *reallocarray(void *, size_t, size_t) __result_use_check __alloc_size((2,3)); void * reallocf (void *__r, size_t __size); #endif #if __BSD_VISIBLE || __XSI_VISIBLE >= 4 @@ -329,8 +328,8 @@ extern long double strtold (const char *__restrict, char **__restrict); * If we're in a mode greater than C99, expose C11 functions. */ #if __ISO_C_VISIBLE >= 2011 -void * aligned_alloc(size_t, size_t) __malloc_like __alloc_align(1) - __alloc_size(2); +void * aligned_alloc(size_t, size_t) __malloc_like __alloc_align((1)) + __alloc_size((2)); int at_quick_exit(void (*)(void)); _Noreturn void quick_exit(int); diff --git a/libc/xtensa-lx106-elf/include/sys/_types.h b/libc/xtensa-lx106-elf/include/sys/_types.h index 72e1dc1..d8e8c0b 100644 --- a/libc/xtensa-lx106-elf/include/sys/_types.h +++ b/libc/xtensa-lx106-elf/include/sys/_types.h @@ -193,7 +193,10 @@ typedef _CLOCK_T_ __clock_t; #endif typedef _TIME_T_ __time_t; +#ifndef __machine_clockid_t_defined #define _CLOCKID_T_ unsigned long +#endif + typedef _CLOCKID_T_ __clockid_t; #define _TIMER_T_ unsigned long diff --git a/libc/xtensa-lx106-elf/include/sys/cdefs.h b/libc/xtensa-lx106-elf/include/sys/cdefs.h index fc564a5..b3f8d19 100644 --- a/libc/xtensa-lx106-elf/include/sys/cdefs.h +++ b/libc/xtensa-lx106-elf/include/sys/cdefs.h @@ -258,12 +258,12 @@ #define __section(x) __attribute__((__section__(x))) #endif #if __GNUC_PREREQ__(4, 3) || __has_attribute(__alloc_size__) -#define __alloc_size(x) __attribute__((__alloc_size__(x))) +#define __alloc_size(x) __attribute__((__alloc_size__ x)) #else #define __alloc_size(x) #endif #if __GNUC_PREREQ__(4, 9) || __has_attribute(__alloc_align__) -#define __alloc_align(x) __attribute__((__alloc_align__(x))) +#define __alloc_align(x) __attribute__((__alloc_align__ x)) #else #define __alloc_align(x) #endif diff --git a/libc/xtensa-lx106-elf/include/sys/reent.h b/libc/xtensa-lx106-elf/include/sys/reent.h index 0f21c68..27f68a3 100644 --- a/libc/xtensa-lx106-elf/include/sys/reent.h +++ b/libc/xtensa-lx106-elf/include/sys/reent.h @@ -174,9 +174,9 @@ extern void __sinit (struct _reent *); __sinit (ptr); \ } \ while (0) -#else +#else /* _REENT_SMALL && !_REENT_GLOBAL_STDIO_STREAMS */ # define _REENT_SMALL_CHECK_INIT(ptr) /* nothing */ -#endif +#endif /* _REENT_SMALL && !_REENT_GLOBAL_STDIO_STREAMS */ struct __sFILE { unsigned char *_p; /* current position in (some) buffer */ @@ -416,6 +416,8 @@ struct _reent __FILE *__sf; /* file descriptors */ struct _misc_reent *_misc; /* strtok, multibyte states */ char *_signal_buf; /* strsignal */ + + unsigned int malloc_region_mask; }; #ifdef _REENT_GLOBAL_STDIO_STREAMS @@ -453,7 +455,7 @@ extern __FILE __sf[3]; (var)->_stderr = &__sf[2]; \ } -#else +#else /* _REENT_GLOBAL_STDIO_STREAMS */ extern const struct __sFILE_fake __sf_fake_stdin; extern const struct __sFILE_fake __sf_fake_stdout; @@ -482,7 +484,8 @@ extern const struct __sFILE_fake __sf_fake_stderr; {_NULL, 0, _NULL}, \ _NULL, \ _NULL, \ - _NULL \ + _NULL, \ + 0 \ } #define _REENT_INIT_PTR_ZEROED(var) \ @@ -491,7 +494,7 @@ extern const struct __sFILE_fake __sf_fake_stderr; (var)->_stderr = (__FILE *)&__sf_fake_stderr; \ } -#endif +#endif /* _REENT_GLOBAL_STDIO_STREAMS */ /* Only add assert() calls if we are specified to debug. */ #ifdef _REENT_CHECK_DEBUG diff --git a/libc/xtensa-lx106-elf/lib/crt0.o b/libc/xtensa-lx106-elf/lib/crt0.o index efc11bc..57bed6b 100644 Binary files a/libc/xtensa-lx106-elf/lib/crt0.o and b/libc/xtensa-lx106-elf/lib/crt0.o differ diff --git a/libc/xtensa-lx106-elf/lib/libc.a b/libc/xtensa-lx106-elf/lib/libc.a index 457de25..70d9b12 100644 Binary files a/libc/xtensa-lx106-elf/lib/libc.a and b/libc/xtensa-lx106-elf/lib/libc.a differ diff --git a/libc/xtensa-lx106-elf/lib/libg.a b/libc/xtensa-lx106-elf/lib/libg.a index 457de25..70d9b12 100644 Binary files a/libc/xtensa-lx106-elf/lib/libg.a and b/libc/xtensa-lx106-elf/lib/libg.a differ diff --git a/libc/xtensa-lx106-elf/lib/libm.a b/libc/xtensa-lx106-elf/lib/libm.a index e7c0969..f9422f3 100644 Binary files a/libc/xtensa-lx106-elf/lib/libm.a and b/libc/xtensa-lx106-elf/lib/libm.a differ diff --git a/lwip/esp_interface.c b/lwip/esp_interface.c index 77ad177..c21a525 100644 --- a/lwip/esp_interface.c +++ b/lwip/esp_interface.c @@ -178,7 +178,9 @@ size_t ooseq_bytes_limit(struct tcp_pcb *pcb) ooseq_blen += p->tot_len; } + uint32_t malloc_mask = set_malloc_regions(MALLOC_MASK_DRAM); size_t free = xPortGetFreeHeapSize(); + set_malloc_regions(malloc_mask); ssize_t target = ((ssize_t)free - 8000) + ooseq_blen; if (target < 0) { diff --git a/lwip/lwip b/lwip/lwip index d74e9ad..c1d2472 160000 --- a/lwip/lwip +++ b/lwip/lwip @@ -1 +1 @@ -Subproject commit d74e9ad2f7c9db996fb398cd41bf59ef463ae6fe +Subproject commit c1d247296af423741f901bcfd4a8c2739e881565