Explorar el Código

Merge branch 'nimble/misc_host_flow_ctrl_changes_v4.1' into 'release/v4.1'

NimBLE: Misc changes in host flow control, ble_gap_unpair, ble_hs_hci_rx_evt, memory management & example (backport v4.1)

See merge request espressif/esp-idf!7857
Island hace 6 años
padre
commit
0e21d1e372

+ 2 - 1
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")

+ 2 - 1
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

+ 60 - 0
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
@@ -187,6 +216,37 @@ config BT_NIMBLE_HCI_EVT_LO_BUF_COUNT
         low-priority event buffers, then an incoming advertising report will
         get dropped
 
+config BT_NIMBLE_HS_FLOW_CTRL
+    bool "Enable Host Flow control"
+    depends on BT_NIMBLE_ENABLED
+    default y
+    help
+        Enable Host Flow control
+
+config BT_NIMBLE_HS_FLOW_CTRL_ITVL
+    int "Host Flow control interval"
+    depends on BT_NIMBLE_HS_FLOW_CTRL
+    default 1000
+    help
+        Host flow control interval in msecs
+
+config BT_NIMBLE_HS_FLOW_CTRL_THRESH
+    int "Host Flow control threshold"
+    depends on BT_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 BT_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT
+    bool "Host Flow control on disconnect"
+    depends on BT_NIMBLE_HS_FLOW_CTRL
+    default y
+    help
+        Enable this option to send number-of-completed-packets event to
+        controller after disconnection
+
 menuconfig BT_NIMBLE_MESH
     bool "Enable BLE mesh functionality"
     select BT_NIMBLE_SM_SC

+ 70 - 18
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)

+ 1 - 1
components/bt/host/nimble/nimble

@@ -1 +1 @@
-Subproject commit 4a4be394951942cb86b8ed3f779d0c6e733f6e6b
+Subproject commit 664d3d73bd4d6f8f57d46d6a1dc5d35429fb6563

+ 7 - 3
components/bt/host/nimble/port/include/esp_nimble_cfg.h

@@ -452,19 +452,23 @@
 #endif
 
 #ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL
+#ifdef CONFIG_BT_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_BT_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_BT_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_BT_NIMBLE_FLOW_CTRL_TX_ON_DISCONNECT
 #endif
 
 #ifndef MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS

+ 39 - 0
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 <stdlib.h>
+
+#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__ */

+ 52 - 0
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);
+}

+ 11 - 3
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;
     }
 }