diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index b07098759..266fb86a4 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -127,6 +127,13 @@ config SPIRAM_MALLOC_ALWAYSINTERNAL than this size in internal memory, while allocations larger than this will be done from external RAM. If allocation from the preferred region fails, an attempt is made to allocate from the non-preferred region instead, so malloc() will not suddenly fail when either internal or external memory is full. + +config WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST + bool "Try to allocate memories of WiFi and LWIP in SPIRAM firstly. If failed, allocate internal memory" + depends on SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC + default "n" + help + Try to allocate memories of WiFi and LWIP in SPIRAM firstly. If failed, try to allocate internal memory then. config SPIRAM_MALLOC_RESERVE_INTERNAL int "Reserve this amount of bytes for data that specifically needs to be in DMA or internal memory" diff --git a/components/esp32/include/esp_wifi_internal.h b/components/esp32/include/esp_wifi_internal.h index 6627636df..9dd6e7e8e 100644 --- a/components/esp32/include/esp_wifi_internal.h +++ b/components/esp32/include/esp_wifi_internal.h @@ -121,6 +121,41 @@ esp_err_t esp_wifi_internal_reg_rxcb(wifi_interface_t ifx, wifi_rxcb_t fn); */ esp_err_t esp_wifi_internal_set_sta_ip(void); +/** + * @brief Allocate a chunk of memory for WiFi driver + * + * @attention This API is not used for DMA memory allocation. + * + * @param size_t size : Size, in bytes, of the amount of memory to allocate + * + * @return A pointer to the memory allocated on success, NULL on failure + */ +void *wifi_malloc( size_t size ); + +/** + * @brief Reallocate a chunk of memory for WiFi driver + * + * @attention This API is not used for DMA memory allocation. + * + * @param void * ptr : Pointer to previously allocated memory, or NULL for a new allocation. + * @param size_t size : Size, in bytes, of the amount of memory to allocate + * + * @return A pointer to the memory allocated on success, NULL on failure + */ +void *wifi_realloc( void *ptr, size_t size ); + +/** + * @brief Callocate memory for WiFi driver + * + * @attention This API is not used for DMA memory allocation. + * + * @param size_t n : Number of continuing chunks of memory to allocate + * @param size_t size : Size, in bytes, of the amount of memory to allocate + * + * @return A pointer to the memory allocated on success, NULL on failure + */ +void *wifi_calloc( size_t n, size_t size ); + #ifdef __cplusplus } #endif diff --git a/components/esp32/lib b/components/esp32/lib index 1c132fda6..1f5831849 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 1c132fda65587f87e677d6ae2ed5d0ae68431956 +Subproject commit 1f583184974518ad959c5510fff310170c6aaebd diff --git a/components/esp32/wifi_internal.c b/components/esp32/wifi_internal.c new file mode 100644 index 000000000..350f2cb86 --- /dev/null +++ b/components/esp32/wifi_internal.c @@ -0,0 +1,56 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_attr.h" +#include "esp_heap_caps.h" +#include "sdkconfig.h" + +/* + If CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly. + If failed, try to allocate it in internal memory then. + */ +IRAM_ATTR void *wifi_malloc( size_t size ) +{ +#if CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST + return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); +#else + return malloc(size); +#endif +} + +/* + If CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly. + If failed, try to allocate it in internal memory then. + */ +IRAM_ATTR void *wifi_realloc( void *ptr, size_t size ) +{ +#if CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST + return heap_caps_realloc_prefer(ptr, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); +#else + return realloc(ptr, size); +#endif +} + +/* + If CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly. + If failed, try to allocate it in internal memory then. + */ +IRAM_ATTR void *wifi_calloc( size_t n, size_t size ) +{ +#if CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST + return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); +#else + return calloc(n, size); +#endif +} diff --git a/components/heap/heap_caps.c b/components/heap/heap_caps.c index af632add7..7bc2ea706 100644 --- a/components/heap/heap_caps.c +++ b/components/heap/heap_caps.c @@ -188,6 +188,60 @@ IRAM_ATTR void *heap_caps_realloc_default( void *ptr, size_t size ) } } +/* + Memory allocation as preference in decreasing order. + */ +IRAM_ATTR void *heap_caps_malloc_prefer( size_t size, size_t num, ... ) +{ + va_list argp; + va_start( argp, num ); + void *r = NULL; + while (num--) { + uint32_t caps = va_arg( argp, uint32_t ); + r = heap_caps_malloc( size, caps ); + if (r != NULL) { + break; + } + } + va_end( argp ); + return r; +} + +/* + Memory reallocation as preference in decreasing order. + */ +IRAM_ATTR void *heap_caps_realloc_prefer( void *ptr, size_t size, size_t num, ... ) +{ + va_list argp; + va_start( argp, num ); + void *r = NULL; + while (num--) { + uint32_t caps = va_arg( argp, uint32_t ); + r = heap_caps_realloc( ptr, size, caps ); + if (r != NULL || size == 0) { + break; + } + } + va_end( argp ); + return r; +} + +/* + Memory callocation as preference in decreasing order. + */ +IRAM_ATTR void *heap_caps_calloc_prefer( size_t n, size_t size, size_t num, ... ) +{ + va_list argp; + va_start( argp, num ); + void *r = NULL; + while (num--) { + uint32_t caps = va_arg( argp, uint32_t ); + r = heap_caps_calloc( n, size, caps ); + if (r != NULL) break; + } + va_end( argp ); + return r; +} /* Find the heap which belongs to ptr, or return NULL if it's not in any heap. @@ -269,6 +323,16 @@ IRAM_ATTR void *heap_caps_realloc( void *ptr, size_t size, int caps) return NULL; } +IRAM_ATTR void *heap_caps_calloc( size_t n, size_t size, uint32_t caps) +{ + void *r; + r = heap_caps_malloc(n*size, caps); + if (r != NULL) { + bzero(r, n*size); + } + return r; +} + size_t heap_caps_get_free_size( uint32_t caps ) { size_t ret = 0; diff --git a/components/heap/include/esp_heap_caps.h b/components/heap/include/esp_heap_caps.h index f2aa0a4c4..a5a9a39cf 100644 --- a/components/heap/include/esp_heap_caps.h +++ b/components/heap/include/esp_heap_caps.h @@ -81,6 +81,21 @@ void heap_caps_free( void *ptr); */ void *heap_caps_realloc( void *ptr, size_t size, int caps); +/** + * @brief Allocate a chunk of memory which has the given capabilities. The initialized value in the memory is set to zero. + * + * Equivalent semantics to libc calloc(), for capability-aware memory. + * + * In IDF, ``calloc(p)`` is equivalent to ``heaps_caps_calloc(p, MALLOC_CAP_8BIT)``. + * + * @param n Number of continuing chunks of memory to allocate + * @param size Size, in bytes, of a chunk of memory to allocate + * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type + * of memory to be returned + * + * @return A pointer to the memory allocated on success, NULL on failure + */ +void *heap_caps_calloc(size_t n, size_t size, uint32_t caps); /** * @brief Get the total free size of all the regions that have the given capabilities @@ -224,3 +239,40 @@ bool heap_caps_check_integrity_addr(intptr_t addr, bool print_errors); * @param limit Limit, in bytes. */ void heap_caps_malloc_extmem_enable(size_t limit); + +/** + * @brief Allocate a chunk of memory as preference in decreasing order. + * + * @attention The variable parameters are bitwise OR of MALLOC_CAP_* flags indicating the type of memory. + * This API prefers to allocate memory with the first parameter. If failed, allocate memory with + * the next parameter. It will try in this order until allocating a chunk of memory successfully + * or fail to allocate memories with any of the parameters. + * + * @param size Size, in bytes, of the amount of memory to allocate + * @param num Number of variable paramters + * + * @return A pointer to the memory allocated on success, NULL on failure + */ +void *heap_caps_malloc_prefer( size_t size, size_t num, ... ); + +/** + * @brief Allocate a chunk of memory as preference in decreasing order. + * + * @param ptr Pointer to previously allocated memory, or NULL for a new allocation. + * @param size Size of the new buffer requested, or 0 to free the buffer. + * @param num Number of variable paramters + * + * @return Pointer to a new buffer of size 'size', or NULL if allocation failed. + */ +void *heap_caps_realloc_prefer( void *ptr, size_t size, size_t num, ... ); + +/** + * @brief Allocate a chunk of memory as preference in decreasing order. + * + * @param n Number of continuing chunks of memory to allocate + * @param size Size, in bytes, of a chunk of memory to allocate + * @param num Number of variable paramters + * + * @return A pointer to the memory allocated on success, NULL on failure + */ +void *heap_caps_calloc_prefer( size_t n, size_t size, size_t num, ... ); diff --git a/components/lwip/apps/dhcpserver.c b/components/lwip/apps/dhcpserver.c index bc3cfda73..910219dde 100644 --- a/components/lwip/apps/dhcpserver.c +++ b/components/lwip/apps/dhcpserver.c @@ -800,13 +800,13 @@ static s16_t parse_msg(struct dhcps_msg *m, u16_t len) pdhcps_pool = NULL; pnode = NULL; } else { - pdhcps_pool = (struct dhcps_pool *)malloc(sizeof(struct dhcps_pool)); + pdhcps_pool = (struct dhcps_pool *)mem_malloc(sizeof(struct dhcps_pool)); memset(pdhcps_pool , 0x00 , sizeof(struct dhcps_pool)); pdhcps_pool->ip.addr = client_address.addr; memcpy(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac)); pdhcps_pool->lease_timer = lease_timer; - pnode = (list_node *)malloc(sizeof(list_node)); + pnode = (list_node *)mem_malloc(sizeof(list_node)); memset(pnode , 0x00 , sizeof(list_node)); pnode->pnode = pdhcps_pool; @@ -905,7 +905,7 @@ static void handle_dhcp(void *arg, malloc_len = p->tot_len; } - pmsg_dhcps = (struct dhcps_msg *)malloc(malloc_len); + pmsg_dhcps = (struct dhcps_msg *)mem_malloc(malloc_len); if (NULL == pmsg_dhcps) { pbuf_free(p); return; diff --git a/components/lwip/include/lwip/lwip/mem.h b/components/lwip/include/lwip/lwip/mem.h index a90d07256..966d6bbb0 100755 --- a/components/lwip/include/lwip/lwip/mem.h +++ b/components/lwip/include/lwip/lwip/mem.h @@ -54,12 +54,26 @@ typedef size_t mem_size_t; #ifndef mem_free #define mem_free free #endif +/** + * lwip_malloc: if CONFIG_ALLOC_MEMORY_IN_SPIRAM_FIRST is enabled, Try to + * allocate memory for lwip in SPIRAM firstly. If failed, try to allocate + * internal memory then. + */ +#if CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST +#ifndef mem_malloc +#define mem_malloc(size) heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL) +#endif +#ifndef mem_calloc +#define mem_calloc(n, size) heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL) +#endif +#else #ifndef mem_malloc #define mem_malloc malloc #endif #ifndef mem_calloc #define mem_calloc calloc #endif +#endif /* Since there is no C library allocation function to shrink memory without moving it, define this to nothing. */ diff --git a/components/lwip/netif/ppp/auth.c b/components/lwip/netif/ppp/auth.c index 2f611d571..382201e5e 100755 --- a/components/lwip/netif/ppp/auth.c +++ b/components/lwip/netif/ppp/auth.c @@ -509,7 +509,7 @@ set_noauth_addr(argv) int l = strlen(addr) + 1; struct wordlist *wp; - wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l); + wp = (struct wordlist *) mem_malloc(sizeof(struct wordlist) + l); if (wp == NULL) novm("allow-ip argument"); wp->word = (char *) (wp + 1); @@ -531,7 +531,7 @@ set_permitted_number(argv) int l = strlen(number) + 1; struct wordlist *wp; - wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l); + wp = (struct wordlist *) mem_malloc(sizeof(struct wordlist) + l); if (wp == NULL) novm("allow-number argument"); wp->word = (char *) (wp + 1); @@ -2048,7 +2048,7 @@ set_allowed_addrs(unit, addrs, opts) n = wordlist_count(addrs) + wordlist_count(noauth_addrs); if (n == 0) return; - ip = (struct permitted_ip *) malloc((n + 1) * sizeof(struct permitted_ip)); + ip = (struct permitted_ip *) mem_malloc((n + 1) * sizeof(struct permitted_ip)); if (ip == 0) return; @@ -2417,7 +2417,7 @@ scan_authfile(f, client, server, secret, addrs, opts, filename, flags) if (!getword(f, word, &newline, filename) || newline) break; ap = (struct wordlist *) - malloc(sizeof(struct wordlist) + strlen(word) + 1); + mem_malloc(sizeof(struct wordlist) + strlen(word) + 1); if (ap == NULL) novm("authorized addresses"); ap->word = (char *) (ap + 1); diff --git a/components/lwip/netif/ppp/demand.c b/components/lwip/netif/ppp/demand.c index 1cd9b6145..7a018aefe 100755 --- a/components/lwip/netif/ppp/demand.c +++ b/components/lwip/netif/ppp/demand.c @@ -89,7 +89,7 @@ demand_conf() if (framemax < PPP_MRU) */ framemax = PPP_MRU; framemax += PPP_HDRLEN + PPP_FCSLEN; - frame = malloc(framemax); + frame = mem_malloc(framemax); if (frame == NULL) novm("demand frame"); framelen = 0; @@ -296,7 +296,7 @@ loop_frame(frame, len) if (!active_packet(frame, len)) return 0; - pkt = (struct packet *) malloc(sizeof(struct packet) + len); + pkt = (struct packet *) mem_malloc(sizeof(struct packet) + len); if (pkt != NULL) { pkt->length = len; pkt->next = NULL; diff --git a/components/lwip/netif/ppp/eap.c b/components/lwip/netif/ppp/eap.c index 588206524..39cd21e05 100755 --- a/components/lwip/netif/ppp/eap.c +++ b/components/lwip/netif/ppp/eap.c @@ -1215,7 +1215,7 @@ name_of_pn_file() } file = _PATH_PSEUDONYM; pl = strlen(user) + strlen(file) + 2; - path = malloc(pl); + path = mem_malloc(pl); if (path == NULL) return (NULL); (void) slprintf(path, pl, "%s/%s", user, file); diff --git a/components/lwip/netif/ppp/multilink.c b/components/lwip/netif/ppp/multilink.c index 3bea516a5..6be69e4d6 100755 --- a/components/lwip/netif/ppp/multilink.c +++ b/components/lwip/netif/ppp/multilink.c @@ -170,7 +170,7 @@ mp_join_bundle() l += 3 * ho->endpoint.length + 8; if (bundle_name) l += 3 * strlen(bundle_name) + 2; - bundle_id = malloc(l); + bundle_id = mem_malloc(l); if (bundle_id == 0) novm("bundle identifier"); @@ -186,7 +186,7 @@ mp_join_bundle() /* Make the key for the list of links belonging to the bundle */ l = p - bundle_id; - blinks_id = malloc(l + 7); + blinks_id = mem_malloc(l + 7); if (blinks_id == NULL) novm("bundle links key"); slprintf(blinks_id, l + 7, "BUNDLE_LINKS=%s", bundle_id + 7); @@ -322,7 +322,7 @@ static void make_bundle_links(int append) return; } l = rec.dsize + strlen(entry); - p = malloc(l); + p = mem_malloc(l); if (p == NULL) novm("bundle link list"); slprintf(p, l, "%s%s", rec.dptr, entry); diff --git a/components/lwip/port/debug/lwip_debug.c b/components/lwip/port/debug/lwip_debug.c index c1fa7db12..c2bd89f3e 100644 --- a/components/lwip/port/debug/lwip_debug.c +++ b/components/lwip/port/debug/lwip_debug.c @@ -40,7 +40,7 @@ static void dbg_lwip_tcp_pcb_cnt_show(struct tcp_pcb *pcb) char *p; int i; - buf = malloc(512); + buf = mem_malloc(512); if (!buf) { return; } diff --git a/components/lwip/port/freertos/sys_arch.c b/components/lwip/port/freertos/sys_arch.c index fe8c2a463..5f1ca0898 100755 --- a/components/lwip/port/freertos/sys_arch.c +++ b/components/lwip/port/freertos/sys_arch.c @@ -195,7 +195,7 @@ sys_sem_free(sys_sem_t *sem) err_t sys_mbox_new(sys_mbox_t *mbox, int size) { - *mbox = malloc(sizeof(struct sys_mbox_s)); + *mbox = mem_malloc(sizeof(struct sys_mbox_s)); if (*mbox == NULL){ LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("fail to new *mbox\n")); return ERR_MEM; @@ -513,7 +513,7 @@ static void sys_thread_tls_free(int index, void* data) sys_sem_t* sys_thread_sem_init(void) { - sys_sem_t *sem = (sys_sem_t*)malloc(sizeof(sys_sem_t*)); + sys_sem_t *sem = (sys_sem_t*)mem_malloc(sizeof(sys_sem_t*)); if (!sem){ ESP_LOGE(TAG, "thread_sem_init: out of memory");