Merge branch 'nimble/misc_host_flow_ctrl_changes_v3.3' into 'release/v3.3'

NimBLE: Misc fixes in NimBLE host (backport v3.3)

See merge request espressif/esp-idf!7960
This commit is contained in:
Jiang Jiang Jian 2020-03-16 13:26:37 +08:00
commit 13d4ab5afb
10 changed files with 275 additions and 31 deletions

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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)

@ -1 +1 @@
Subproject commit 5250d712a5454b2623bf92343c027d77477ca804
Subproject commit ecb1e9e5e3efb830d0b04dc3382be7b1012fdeaa

View file

@ -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

View file

@ -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__ */

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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 :