diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 7032057e5..a3d6fa944 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -495,7 +495,8 @@ if(CONFIG_BT_ENABLED) "host/nimble/nimble/porting/nimble/src/mem.c" "host/nimble/nimble/porting/nimble/src/os_mbuf.c" "host/nimble/nimble/porting/nimble/src/os_cputime.c" - "host/nimble/esp-hci/src/esp_nimble_hci.c") + "host/nimble/esp-hci/src/esp_nimble_hci.c" + "host/nimble/port/src/esp_nimble_mem.c") if (CONFIG_BLE_MESH) list(APPEND srcs "esp_ble_mesh/mesh_core/nimble_host/mesh_bearer_adapt.c") diff --git a/components/bt/component.mk b/components/bt/component.mk index 7e8e4464b..5c1a29e6c 100644 --- a/components/bt/component.mk +++ b/components/bt/component.mk @@ -197,7 +197,8 @@ COMPONENT_SRCDIRS += host/nimble/nimble/nimble/host/src host/nimble/nimble/nimble/host/util/src \ host/nimble/nimble/nimble/host/store/ram/src \ host/nimble/nimble/nimble/host/store/config/src \ - host/nimble/esp-hci/src + host/nimble/esp-hci/src \ + host/nimble/port/src ifndef CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS COMPONENT_SRCDIRS += host/nimble/nimble/ext/tinycrypt/src diff --git a/components/bt/host/nimble/Kconfig.in b/components/bt/host/nimble/Kconfig.in index b56b900f3..918ba48e7 100644 --- a/components/bt/host/nimble/Kconfig.in +++ b/components/bt/host/nimble/Kconfig.in @@ -1,4 +1,33 @@ +choice BT_NIMBLE_MEM_ALLOC_MODE + prompt "Memory allocation strategy" + default BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL + help + Allocation strategy for NimBLE host stack, essentially provides ability to + allocate all required dynamic allocations from, + + - Internal DRAM memory only + - External SPIRAM memory only + - Either internal or external memory based on default malloc() + behavior in ESP-IDF + + Recommended mode here is always internal, since that is most preferred + from security perspective. But if application requirement does not + allow sufficient free internal memory then alternate mode can be + selected. + + config BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL + bool "Internal memory" + + config BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL + bool "External SPIRAM" + depends on ESP32_SPIRAM_SUPPORT + + config BT_NIMBLE_MEM_ALLOC_MODE_DEFAULT + bool "Default alloc mode" + +endchoice + config BT_NIMBLE_MAX_CONNECTIONS int "Maximum number of concurrent connections" range 1 9 diff --git a/components/bt/host/nimble/esp-hci/src/esp_nimble_hci.c b/components/bt/host/nimble/esp-hci/src/esp_nimble_hci.c index 0c0e9ce98..e4ab99932 100644 --- a/components/bt/host/nimble/esp-hci/src/esp_nimble_hci.c +++ b/components/bt/host/nimble/esp-hci/src/esp_nimble_hci.c @@ -26,6 +26,7 @@ #include "nimble/nimble_port.h" #include "nimble/nimble_port_freertos.h" #include "esp_nimble_hci.h" +#include "esp_nimble_mem.h" #include "esp_bt.h" #include "freertos/semphr.h" #include "esp_compiler.h" @@ -49,30 +50,23 @@ static struct os_mempool_ext ble_hci_acl_pool; + BLE_MBUF_MEMBLOCK_OVERHEAD \ + BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT) -static os_membuf_t ble_hci_acl_buf[ - OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_ACL_BUF_COUNT), - ACL_BLOCK_SIZE)]; +static os_membuf_t *ble_hci_acl_buf; static struct os_mempool ble_hci_cmd_pool; -static os_membuf_t ble_hci_cmd_buf[ - OS_MEMPOOL_SIZE(1, BLE_HCI_TRANS_CMD_SZ) -]; +static os_membuf_t *ble_hci_cmd_buf; static struct os_mempool ble_hci_evt_hi_pool; -static os_membuf_t ble_hci_evt_hi_buf[ - OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT), - MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) -]; +static os_membuf_t *ble_hci_evt_hi_buf; static struct os_mempool ble_hci_evt_lo_pool; -static os_membuf_t ble_hci_evt_lo_buf[ - OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT), - MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) -]; +static os_membuf_t *ble_hci_evt_lo_buf; static SemaphoreHandle_t vhci_send_sem; const static char *TAG = "NimBLE"; +int os_msys_buf_alloc(void); +void os_msys_buf_free(void); + void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb, void *cmd_arg, ble_hci_trans_rx_acl_fn *acl_cb, @@ -379,24 +373,75 @@ static const esp_vhci_host_callback_t vhci_host_cb = { .notify_host_recv = host_rcv_pkt, }; +static void ble_buf_free(void) +{ + os_msys_buf_free(); + + nimble_platform_mem_free(ble_hci_evt_hi_buf); + ble_hci_evt_hi_buf = NULL; + nimble_platform_mem_free(ble_hci_evt_lo_buf); + ble_hci_evt_lo_buf = NULL; + nimble_platform_mem_free(ble_hci_cmd_buf); + ble_hci_cmd_buf = NULL; + nimble_platform_mem_free(ble_hci_acl_buf); + ble_hci_acl_buf = NULL; +} + +static esp_err_t ble_buf_alloc(void) +{ + if (os_msys_buf_alloc()) { + return ESP_ERR_NO_MEM; + } + + ble_hci_evt_hi_buf = (os_membuf_t *) nimble_platform_mem_calloc(1, + (sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT), + MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)))); + + ble_hci_evt_lo_buf = (os_membuf_t *) nimble_platform_mem_calloc(1, + (sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT), + MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)))); + + ble_hci_cmd_buf = (os_membuf_t *) nimble_platform_mem_calloc(1, + (sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(1, BLE_HCI_TRANS_CMD_SZ))); + + ble_hci_acl_buf = (os_membuf_t *) nimble_platform_mem_calloc(1, + (sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_ACL_BUF_COUNT), + ACL_BLOCK_SIZE))); + + if (!ble_hci_evt_hi_buf || !ble_hci_evt_lo_buf || !ble_hci_cmd_buf || !ble_hci_acl_buf) { + ble_buf_free(); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} esp_err_t esp_nimble_hci_init(void) { esp_err_t ret; + + ret = ble_buf_alloc(); + if (ret != ESP_OK) { + goto err; + } if ((ret = esp_vhci_host_register_callback(&vhci_host_cb)) != ESP_OK) { - return ret; + goto err; } ble_hci_transport_init(); vhci_send_sem = xSemaphoreCreateBinary(); if (vhci_send_sem == NULL) { - return ESP_ERR_NO_MEM; + ret = ESP_ERR_NO_MEM; + goto err; } xSemaphoreGive(vhci_send_sem); - return ESP_OK; + return ret; +err: + ble_buf_free(); + return ret; + } esp_err_t esp_nimble_hci_and_controller_init(void) @@ -445,7 +490,14 @@ esp_err_t esp_nimble_hci_deinit(void) vSemaphoreDelete(vhci_send_sem); vhci_send_sem = NULL; } - return ble_hci_transport_deinit(); + esp_err_t ret = ble_hci_transport_deinit(); + if (ret != ESP_OK) { + return ret; + } + + ble_buf_free(); + + return ESP_OK; } esp_err_t esp_nimble_hci_and_controller_deinit(void) diff --git a/components/bt/host/nimble/port/include/esp_nimble_mem.h b/components/bt/host/nimble/port/include/esp_nimble_mem.h new file mode 100644 index 000000000..90e52a20d --- /dev/null +++ b/components/bt/host/nimble/port/include/esp_nimble_mem.h @@ -0,0 +1,39 @@ +/* + * Copyright 2020 Espressif Systems (Shanghai) PTE LTD + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef __ESP_NIMBLE_MEM_H__ +#define __ESP_NIMBLE_MEM_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void *nimble_platform_mem_malloc(size_t size); +void *nimble_platform_mem_calloc(size_t n, size_t size); +void nimble_platform_mem_free(void *ptr); + +#ifdef __cplusplus +} +#endif + +#endif /* __ESP_NIMBLE_MEM_H__ */ diff --git a/components/bt/host/nimble/port/src/esp_nimble_mem.c b/components/bt/host/nimble/port/src/esp_nimble_mem.c new file mode 100644 index 000000000..95d0d930e --- /dev/null +++ b/components/bt/host/nimble/port/src/esp_nimble_mem.c @@ -0,0 +1,52 @@ +/* + * Copyright 2020 Espressif Systems (Shanghai) PTE LTD + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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" +#include "esp_nimble_mem.h" + +IRAM_ATTR void *nimble_platform_mem_malloc(size_t size) +{ +#ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL + return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL + return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); +#else + return malloc(size); +#endif +} + +IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size) +{ +#ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL + return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL + return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); +#else + return calloc(n, size); +#endif +} + +IRAM_ATTR void nimble_platform_mem_free(void *ptr) +{ + heap_caps_free(ptr); +}