diff --git a/components/bt/Kconfig b/components/bt/Kconfig index e6ee2e0787..6f990efdb6 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -1338,6 +1338,36 @@ menu Bluetooth help This enables NimBLE host stack + choice NIMBLE_MEM_ALLOC_MODE + prompt "Memory allocation strategy" + default NIMBLE_MEM_ALLOC_MODE_INTERNAL + depends on NIMBLE_ENABLED + 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 NIMBLE_MEM_ALLOC_MODE_INTERNAL + bool "Internal memory" + + config NIMBLE_MEM_ALLOC_MODE_EXTERNAL + bool "External SPIRAM" + depends on ESP32_SPIRAM_SUPPORT + + config NIMBLE_MEM_ALLOC_MODE_DEFAULT + bool "Default alloc mode" + + endchoice + config NIMBLE_MAX_CONNECTIONS int "Maximum number of concurrent connections" range 1 9 @@ -1526,6 +1556,56 @@ menu Bluetooth low-priority event buffers, then an incoming advertising report will get dropped + config NIMBLE_MSYS1_BLOCK_COUNT + int "MSYS_1 Block Count" + depends on NIMBLE_ENABLED + default 12 + help + MSYS is a system level mbuf registry. For prepare write & prepare + responses MBUFs are allocated out of msys_1 pool. For NIMBLE_MESH + enabled cases, this block count is increased by 8 than user defined + count. + + config NIMBLE_HS_FLOW_CTRL + bool "Enable Host Flow control" + depends on NIMBLE_ENABLED + default y + help + Enable Host Flow control + + config NIMBLE_HS_FLOW_CTRL_ITVL + int "Host Flow control interval" + depends on NIMBLE_HS_FLOW_CTRL + default 1000 + help + Host flow control interval in msecs + + config NIMBLE_HS_FLOW_CTRL_THRESH + int "Host Flow control threshold" + depends on NIMBLE_HS_FLOW_CTRL + default 2 + help + Host flow control threshold, if the number of free buffers are at or + below this threshold, send an immediate number-of-completed-packets + event + + config NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT + bool "Host Flow control on disconnect" + depends on NIMBLE_HS_FLOW_CTRL + default y + help + Enable this option to send number-of-completed-packets event to + controller after disconnection + + config NIMBLE_RPA_TIMEOUT + int "RPA timeout in seconds" + range 1 41400 + depends on NIMBLE_ENABLED + default 900 + help + Time interval between RPA address change. This is applicable in case of + Host based RPA + menuconfig NIMBLE_MESH bool "Enable BLE mesh functionality" select NIMBLE_SM_SC diff --git a/components/nimble/CMakeLists.txt b/components/nimble/CMakeLists.txt index cf573b36e6..ce92e7f817 100644 --- a/components/nimble/CMakeLists.txt +++ b/components/nimble/CMakeLists.txt @@ -70,6 +70,7 @@ if(CONFIG_NIMBLE_ENABLED) "./nimble/nimble/host/src/ble_hs_adv.c" "./nimble/nimble/host/src/ble_hs_hci.c" "./nimble/nimble/host/src/ble_hs_hci_util.c" + "./nimble/nimble/host/src/ble_hs_resolv.c" "./nimble/nimble/host/store/ram/src/ble_store_ram.c" "./nimble/nimble/host/store/config/src/ble_store_config.c" "./nimble/nimble/host/store/config/src/ble_store_nvs.c" @@ -85,7 +86,8 @@ if(CONFIG_NIMBLE_ENABLED) "./nimble/porting/nimble/src/mem.c" "./nimble/porting/nimble/src/os_mbuf.c" "./nimble/porting/nimble/src/os_cputime.c" - "./esp-hci/src/esp_nimble_hci.c") + "./esp-hci/src/esp_nimble_hci.c" + "./port/src/esp_nimble_mem.c") if(NOT CONFIG_NIMBLE_CRYPTO_STACK_MBEDTLS) diff --git a/components/nimble/component.mk b/components/nimble/component.mk index fccef82467..c3f7ed46d1 100644 --- a/components/nimble/component.mk +++ b/components/nimble/component.mk @@ -37,7 +37,8 @@ COMPONENT_SRCDIRS += nimble/nimble/host/src \ nimble/nimble/host/util/src \ nimble/nimble/host/store/ram/src \ nimble/nimble/host/store/config/src \ - esp-hci/src + esp-hci/src \ + port/src ifndef CONFIG_NIMBLE_CRYPTO_STACK_MBEDTLS COMPONENT_SRCDIRS += nimble/ext/tinycrypt/src diff --git a/components/nimble/esp-hci/src/esp_nimble_hci.c b/components/nimble/esp-hci/src/esp_nimble_hci.c index 0d1e4112f3..92acaf6a08 100644 --- a/components/nimble/esp-hci/src/esp_nimble_hci.c +++ b/components/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" @@ -48,30 +49,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, @@ -378,24 +372,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) @@ -444,7 +489,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/nimble/nimble b/components/nimble/nimble index 5250d712a5..ecb1e9e5e3 160000 --- a/components/nimble/nimble +++ b/components/nimble/nimble @@ -1 +1 @@ -Subproject commit 5250d712a5454b2623bf92343c027d77477ca804 +Subproject commit ecb1e9e5e3efb830d0b04dc3382be7b1012fdeaa diff --git a/components/nimble/port/include/esp_nimble_cfg.h b/components/nimble/port/include/esp_nimble_cfg.h index 1298ec71b1..3c99575188 100644 --- a/components/nimble/port/include/esp_nimble_cfg.h +++ b/components/nimble/port/include/esp_nimble_cfg.h @@ -15,9 +15,9 @@ /*** kernel/os */ #ifndef MYNEWT_VAL_MSYS_1_BLOCK_COUNT #ifdef CONFIG_NIMBLE_MESH -#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (20) +#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (CONFIG_NIMBLE_MSYS1_BLOCK_COUNT + 8) #else -#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (12) +#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT CONFIG_NIMBLE_MSYS1_BLOCK_COUNT #endif #endif @@ -444,19 +444,23 @@ #endif #ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL +#ifdef CONFIG_NIMBLE_HS_FLOW_CTRL +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL (1) +#else #define MYNEWT_VAL_BLE_HS_FLOW_CTRL (0) #endif +#endif #ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL -#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL (1000) +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL CONFIG_NIMBLE_HS_FLOW_CTRL_ITVL #endif #ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH -#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH (2) +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH CONFIG_NIMBLE_HS_FLOW_CTRL_THRESH #endif #ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT -#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT (0) +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT CONFIG_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT #endif #ifndef MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS @@ -531,8 +535,12 @@ #define MYNEWT_VAL_BLE_MONITOR_UART_DEV ("uart0") #endif +#ifndef MYNEWT_VAL_BLE_HOST_BASED_PRIVACY +#define MYNEWT_VAL_BLE_HOST_BASED_PRIVACY (1) +#endif + #ifndef MYNEWT_VAL_BLE_RPA_TIMEOUT -#define MYNEWT_VAL_BLE_RPA_TIMEOUT (300) +#define MYNEWT_VAL_BLE_RPA_TIMEOUT (CONFIG_NIMBLE_RPA_TIMEOUT) #endif #ifndef MYNEWT_VAL_BLE_SM_BONDING diff --git a/components/nimble/port/include/esp_nimble_mem.h b/components/nimble/port/include/esp_nimble_mem.h new file mode 100644 index 0000000000..90e52a20d5 --- /dev/null +++ b/components/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/nimble/port/src/esp_nimble_mem.c b/components/nimble/port/src/esp_nimble_mem.c new file mode 100644 index 0000000000..ee20130345 --- /dev/null +++ b/components/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_NIMBLE_MEM_ALLOC_MODE_INTERNAL + return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#elif CONFIG_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_NIMBLE_MEM_ALLOC_MODE_INTERNAL + return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#elif CONFIG_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); +} diff --git a/examples/bluetooth/nimble/blecent/main/main.c b/examples/bluetooth/nimble/blecent/main/main.c index be179a0699..604ca3cacf 100644 --- a/examples/bluetooth/nimble/blecent/main/main.c +++ b/examples/bluetooth/nimble/blecent/main/main.c @@ -319,6 +319,7 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc) static void blecent_connect_if_interesting(const struct ble_gap_disc_desc *disc) { + uint8_t own_addr_type; int rc; /* Don't do anything if we don't care about this advertiser. */ @@ -333,16 +334,23 @@ blecent_connect_if_interesting(const struct ble_gap_disc_desc *disc) return; } + /* Figure out address to use for connect (no privacy for now) */ + rc = ble_hs_id_infer_auto(0, &own_addr_type); + if (rc != 0) { + MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc); + return; + } + /* Try to connect the the advertiser. Allow 30 seconds (30000 ms) for * timeout. */ - rc = ble_gap_connect(BLE_OWN_ADDR_PUBLIC, &disc->addr, 30000, NULL, + rc = ble_gap_connect(own_addr_type, &disc->addr, 30000, NULL, blecent_gap_event, NULL); if (rc != 0) { MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d " - "addr=%s\n", - disc->addr.type, addr_str(disc->addr.val)); + "addr=%s; rc=%d\n", + disc->addr.type, addr_str(disc->addr.val), rc); return; } } diff --git a/examples/bluetooth/nimble/bleprph/README.md b/examples/bluetooth/nimble/bleprph/README.md index b518c81f82..0fb0ee494a 100644 --- a/examples/bluetooth/nimble/bleprph/README.md +++ b/examples/bluetooth/nimble/bleprph/README.md @@ -10,9 +10,11 @@ This example aims at understanding GATT database configuration, advertisement an It also demonstrates security features of NimBLE stack. SMP parameters like I/O capabilities of device, Bonding flag, MITM protection flag and Secure Connection only mode etc., can be configured through menuconfig options. +For RPA feature (currently Host based privacy feature is supported), use API `ble_hs_pvcy_rpa_config` to enable/disable host based privacy, `own_addr_type` needs to be set to `BLE_ADDR_RANDOM` to use this feature. Please include `ble_hs_pvcy.h` while using this API. As `ble_hs_pvcy_rpa_config` configures host privacy and sets address in controller, it is necessary to call this API after host-controller are synced (e.g. in `bleprph_on_sync` callback). + To test this demo, any BLE scanner app can be used. -A Python based utility `bleprph_test.py` is also provided (which will run as a BLE GATT Client) and can be used to test this example. +A Python based utility `bleprph_test.py` is also provided (which will run as a BLE GATT Client) and can be used to test this example. Note :