Malloc support for allocating to DRAM and/or IRAM.

This commit is contained in:
Our Air Quality 2018-03-01 15:18:39 +11:00
parent 9d57176d8e
commit cc4bd3c58f
18 changed files with 113 additions and 56 deletions

View file

@ -172,9 +172,8 @@ portBASE_TYPE xPortStartScheduler( void )
return pdTRUE; 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.fordblks gives free space inside area dedicated to heap.
mallinfo is possibly non-portable, although glibc & newlib both support mallinfo is possibly non-portable, although glibc & newlib both support
@ -183,14 +182,7 @@ portBASE_TYPE xPortStartScheduler( void )
size_t xPortGetFreeHeapSize( void ) size_t xPortGetFreeHeapSize( void )
{ {
struct mallinfo mi = mallinfo(); struct mallinfo mi = mallinfo();
uint32_t brk_val = (uint32_t) sbrk(0); return mi.fordblks;
intptr_t sp = (intptr_t)xPortSupervisorStackPointer;
if (sp == 0) {
/* scheduler not started */
SP(sp);
}
return sp - brk_val + mi.fordblks;
} }
void vPortEndScheduler( void ) void vPortEndScheduler( void )

View file

@ -754,7 +754,11 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
/* Allocate space for the stack used by the task being created. /* 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 The base of the stack memory stored in the TCB so the task can
be deleted later if required. */ 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. */ 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 ) if( pxNewTCB->pxStack == NULL )
{ {
@ -769,7 +773,10 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
StackType_t *pxStack; StackType_t *pxStack;
/* Allocate space for the stack used by the task being created. */ /* 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. */ 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 ) if( pxStack != NULL )
{ {
@ -990,6 +997,15 @@ UBaseType_t x;
{ {
/* Initialise this task's Newlib reent structure. */ /* Initialise this task's Newlib reent structure. */
_REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) ); _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 #endif

View file

@ -137,6 +137,9 @@ static void IRAM default_putc(char c) {
void init_newlib_locks(void); void init_newlib_locks(void);
extern uint8_t sdk_wDevCtrl[]; extern uint8_t sdk_wDevCtrl[];
void nano_malloc_insert_chunk(void *start, size_t size); 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 // .text+0x258
void IRAM sdk_user_start(void) { void IRAM sdk_user_start(void) {
@ -209,8 +212,13 @@ void IRAM sdk_user_start(void) {
cksum_value = buf32[5 + boot_slot]; cksum_value = buf32[5 + boot_slot];
ic_flash_addr = (flash_sectors - 3 + boot_slot) * sdk_flashchip.sector_size; 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)); 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); Cache_Read_Enable(0, 0, 1);
zero_bss(); zero_bss();
sdk_os_install_putc1(default_putc); sdk_os_install_putc1(default_putc);
/* HACK Reclaim a region of unused bss from wdev.o. This would not be /* 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. */ * it is in very useful dram. */
nano_malloc_insert_chunk((void *)(sdk_wDevCtrl + 0x2190), 8000); 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(); init_newlib_locks();
if (cksum_magic == 0xffffffff) { 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 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. */ * the top area of RAM which was stack can be used for the dynamic heap. */
xPortSupervisorStackPointer = (void *)0x40000000; xPortSupervisorStackPointer = (void *)0x40000000;
nano_malloc_insert_chunk((void *)0x3FFFC000, 0x4000);
sdk_ets_timer_init(); sdk_ets_timer_init();
printf("\nESP-Open-SDK ver: %s compiled @ %s %s\n", OS_VERSION_STR, __DATE__, __TIME__); printf("\nESP-Open-SDK ver: %s compiled @ %s %s\n", OS_VERSION_STR, __DATE__, __TIME__);

View file

@ -117,5 +117,10 @@
#define IROM __attribute__((section(".irom0.literal"))) const #define IROM __attribute__((section(".irom0.literal"))) const
#endif #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 #endif

View file

@ -34,39 +34,30 @@
#error Too many lwip sockets for the FD_SETSIZE. #error Too many lwip sockets for the FD_SETSIZE.
#endif #endif
extern void *xPortSupervisorStackPointer; void *_sbrk_r (struct _reent *r, ptrdiff_t incr)
IRAM 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; r->_errno = ENOMEM;
return (caddr_t)-1; return (caddr_t)-1;
} }
heap_end += incr; /* 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
return (caddr_t) prev_heap_end; * 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;
} }
return 0;
}
/* Insert a disjoint region into the nano malloc pool. Create a malloc chunk, uint32_t set_malloc_regions(uint32_t mask)
* filling the size as newlib nano malloc expects, and then free it. */ {
void nano_malloc_insert_chunk(void *start, size_t size) { uint32_t malloc_mask = _REENT->malloc_region_mask;
*(uint32_t *)start = size; _REENT->malloc_region_mask = mask;
free(start + sizeof(size_t)); return malloc_mask;
} }
/* syscall implementation for stdio write to UART */ /* syscall implementation for stdio write to UART */

View file

@ -599,6 +599,11 @@ static const char *http_wificfg_content[] = {
#include "content/wificfg/index.html" #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, static int handle_wificfg_index(int s, wificfg_method method,
uint32_t content_length, uint32_t content_length,
wificfg_content_type content_type, wificfg_content_type content_type,
@ -632,7 +637,19 @@ static int handle_wificfg_index(int s, wificfg_method method,
xTaskGetTickCount() * portTICK_PERIOD_MS / 1000); xTaskGetTickCount() * portTICK_PERIOD_MS / 1000);
if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1;
snprintf(buf, len, "<dt>Free heap</dt><dd>%u bytes</dd>", (int)xPortGetFreeHeapSize()); snprintf(buf, len, "<dt>Free dram heap</dt><dd>%u of %u bytes</dd>",
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, "<dt>Free iram heap</dt><dd>%u of %u bytes</dd>",
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, "<dt>Free heap</dt><dd>%u of %u bytes</dd>",
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; if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1;
snprintf(buf, len, "<dt>Flash ID</dt><dd>0x%08x</dd>", sdk_spi_flash_get_id()); snprintf(buf, len, "<dt>Flash ID</dt><dd>0x%08x</dd>", sdk_spi_flash_get_id());

View file

@ -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: The build commands were:

View file

@ -156,7 +156,7 @@ int pthread_attr_getschedparam (const pthread_attr_t *__attr,
int pthread_getschedparam (pthread_t __pthread, int *__policy, int pthread_getschedparam (pthread_t __pthread, int *__policy,
struct sched_param *__param); struct sched_param *__param);
int pthread_setschedparam (pthread_t __pthread, int __policy, int pthread_setschedparam (pthread_t __pthread, int __policy,
struct sched_param *__param); const struct sched_param *__param);
/* Set Scheduling Priority of a Thread */ /* Set Scheduling Priority of a Thread */
int pthread_setschedprio (pthread_t thread, int prio); 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 pthread_mutex_setprioceiling (pthread_mutex_t *__mutex,
int __prioceiling, int *__old_ceiling); 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); int *__prioceiling);
#endif /* _POSIX_THREAD_PRIO_PROTECT */ #endif /* _POSIX_THREAD_PRIO_PROTECT */

View file

@ -144,8 +144,7 @@ void qsort (void *__base, size_t __nmemb, size_t __size, __compar_fn_t _compar);
int rand (void); int rand (void);
void * realloc (void *__r, size_t __size) _NOTHROW; void * realloc (void *__r, size_t __size) _NOTHROW;
#if __BSD_VISIBLE #if __BSD_VISIBLE
void *reallocarray(void *, size_t, size_t) __result_use_check __alloc_size(2) void *reallocarray(void *, size_t, size_t) __result_use_check __alloc_size((2,3));
__alloc_size(3);
void * reallocf (void *__r, size_t __size); void * reallocf (void *__r, size_t __size);
#endif #endif
#if __BSD_VISIBLE || __XSI_VISIBLE >= 4 #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 we're in a mode greater than C99, expose C11 functions.
*/ */
#if __ISO_C_VISIBLE >= 2011 #if __ISO_C_VISIBLE >= 2011
void * aligned_alloc(size_t, size_t) __malloc_like __alloc_align(1) void * aligned_alloc(size_t, size_t) __malloc_like __alloc_align((1))
__alloc_size(2); __alloc_size((2));
int at_quick_exit(void (*)(void)); int at_quick_exit(void (*)(void));
_Noreturn void _Noreturn void
quick_exit(int); quick_exit(int);

View file

@ -193,7 +193,10 @@ typedef _CLOCK_T_ __clock_t;
#endif #endif
typedef _TIME_T_ __time_t; typedef _TIME_T_ __time_t;
#ifndef __machine_clockid_t_defined
#define _CLOCKID_T_ unsigned long #define _CLOCKID_T_ unsigned long
#endif
typedef _CLOCKID_T_ __clockid_t; typedef _CLOCKID_T_ __clockid_t;
#define _TIMER_T_ unsigned long #define _TIMER_T_ unsigned long

View file

@ -258,12 +258,12 @@
#define __section(x) __attribute__((__section__(x))) #define __section(x) __attribute__((__section__(x)))
#endif #endif
#if __GNUC_PREREQ__(4, 3) || __has_attribute(__alloc_size__) #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 #else
#define __alloc_size(x) #define __alloc_size(x)
#endif #endif
#if __GNUC_PREREQ__(4, 9) || __has_attribute(__alloc_align__) #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 #else
#define __alloc_align(x) #define __alloc_align(x)
#endif #endif

View file

@ -174,9 +174,9 @@ extern void __sinit (struct _reent *);
__sinit (ptr); \ __sinit (ptr); \
} \ } \
while (0) while (0)
#else #else /* _REENT_SMALL && !_REENT_GLOBAL_STDIO_STREAMS */
# define _REENT_SMALL_CHECK_INIT(ptr) /* nothing */ # define _REENT_SMALL_CHECK_INIT(ptr) /* nothing */
#endif #endif /* _REENT_SMALL && !_REENT_GLOBAL_STDIO_STREAMS */
struct __sFILE { struct __sFILE {
unsigned char *_p; /* current position in (some) buffer */ unsigned char *_p; /* current position in (some) buffer */
@ -416,6 +416,8 @@ struct _reent
__FILE *__sf; /* file descriptors */ __FILE *__sf; /* file descriptors */
struct _misc_reent *_misc; /* strtok, multibyte states */ struct _misc_reent *_misc; /* strtok, multibyte states */
char *_signal_buf; /* strsignal */ char *_signal_buf; /* strsignal */
unsigned int malloc_region_mask;
}; };
#ifdef _REENT_GLOBAL_STDIO_STREAMS #ifdef _REENT_GLOBAL_STDIO_STREAMS
@ -453,7 +455,7 @@ extern __FILE __sf[3];
(var)->_stderr = &__sf[2]; \ (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_stdin;
extern const struct __sFILE_fake __sf_fake_stdout; extern const struct __sFILE_fake __sf_fake_stdout;
@ -482,7 +484,8 @@ extern const struct __sFILE_fake __sf_fake_stderr;
{_NULL, 0, _NULL}, \ {_NULL, 0, _NULL}, \
_NULL, \ _NULL, \
_NULL, \ _NULL, \
_NULL \ _NULL, \
0 \
} }
#define _REENT_INIT_PTR_ZEROED(var) \ #define _REENT_INIT_PTR_ZEROED(var) \
@ -491,7 +494,7 @@ extern const struct __sFILE_fake __sf_fake_stderr;
(var)->_stderr = (__FILE *)&__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. */ /* Only add assert() calls if we are specified to debug. */
#ifdef _REENT_CHECK_DEBUG #ifdef _REENT_CHECK_DEBUG

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -178,7 +178,9 @@ size_t ooseq_bytes_limit(struct tcp_pcb *pcb)
ooseq_blen += p->tot_len; ooseq_blen += p->tot_len;
} }
uint32_t malloc_mask = set_malloc_regions(MALLOC_MASK_DRAM);
size_t free = xPortGetFreeHeapSize(); size_t free = xPortGetFreeHeapSize();
set_malloc_regions(malloc_mask);
ssize_t target = ((ssize_t)free - 8000) + ooseq_blen; ssize_t target = ((ssize_t)free - 8000) + ooseq_blen;
if (target < 0) { if (target < 0) {

@ -1 +1 @@
Subproject commit d74e9ad2f7c9db996fb398cd41bf59ef463ae6fe Subproject commit c1d247296af423741f901bcfd4a8c2739e881565