ESP32-C6 BLE packet loss
Posted: Wed Jun 18, 2025 9:30 am
Hello,
I am developing a device using ESP32-C6 chip which shall use both BLE and Wi-Fi functionalities, with Matter protocol involved as well.
Our product is developed using ESP-IDF v5.2.3, ESP-Matter (release 1.4 branch) and NimBLE stack.
During our development we observed some strange packet losses, which doesn't seem to be random.
In the problematic scenario we have:
- Wi-Fi enabled and established
- ESP32-C6 in BLE peripheral mode with 2 16-byte services with 1 characteristic each. Characteristics support flags READ, WRITE and NOTIFY.
- Silabs BGM13S2 chip is used as BLE Central, connects to the ESP-32, without bonding
- both devices perform full service discovery and after it's complete BLE Central perform a write_access to the ESP32-C6 characteristics, with 3 packets of 20 bytes
The BLE connection parameters are (in ESP32-C6 units):
- connection interval: 36 (45 ms)
- MTU: 247
- latency: 0
- RSSI ~ -30-40 dbm
- supervision_timeout: 100
In this scenario we can observe about 15-20% of packet loss. The lost packets seem to be
I used nRF Devkit as a BLE sniffer and I can observe that there are retransmission packets from BLE central, and it seems the ESP32-C6 is not responding within connection interval (responses are in ~50-60 ms).
I would appreciate your support in this matter, as I already tried so many settings which don't seem to solve the issue.
Here is the source code of characteristics callback function:
Here are the sdkconfig settings related to BLE, that we set:
I am developing a device using ESP32-C6 chip which shall use both BLE and Wi-Fi functionalities, with Matter protocol involved as well.
Our product is developed using ESP-IDF v5.2.3, ESP-Matter (release 1.4 branch) and NimBLE stack.
During our development we observed some strange packet losses, which doesn't seem to be random.
In the problematic scenario we have:
- Wi-Fi enabled and established
- ESP32-C6 in BLE peripheral mode with 2 16-byte services with 1 characteristic each. Characteristics support flags READ, WRITE and NOTIFY.
- Silabs BGM13S2 chip is used as BLE Central, connects to the ESP-32, without bonding
- both devices perform full service discovery and after it's complete BLE Central perform a write_access to the ESP32-C6 characteristics, with 3 packets of 20 bytes
The BLE connection parameters are (in ESP32-C6 units):
- connection interval: 36 (45 ms)
- MTU: 247
- latency: 0
- RSSI ~ -30-40 dbm
- supervision_timeout: 100
In this scenario we can observe about 15-20% of packet loss. The lost packets seem to be
I used nRF Devkit as a BLE sniffer and I can observe that there are retransmission packets from BLE central, and it seems the ESP32-C6 is not responding within connection interval (responses are in ~50-60 ms).
I would appreciate your support in this matter, as I already tried so many settings which don't seem to solve the issue.
Here is the source code of characteristics callback function:
Code: Select all
#include "service.h"
#include "host/ble_gatt.h"
#include "host/ble_uuid.h"
#include "queue.h"
#include <esp_check.h>
#include <esp_log.h>
namespace bluetooth {
namespace services {
namespace first_service {
typedef int ble_err_t;
static constexpr const char *LOG_TAG = "ble/chr1";
static constexpr uint16_t SERVICE_UUID = 0xFFE0;
static constexpr uint16_t CHARACTERISTICS_UUID = 0xFFE1;
static constexpr ble_uuid16_t svc_uuid = BLE_UUID16_INIT(SERVICE_UUID);
static constexpr ble_uuid16_t chr_uuid = BLE_UUID16_INIT(CHARACTERISTICS_UUID);
static uint16_t chr_val_handle;
// Forward declarations
static ble_err_t on_chr_access_cb(uint16_t, uint16_t, ble_gatt_access_ctxt_t *, void *);
/**
* @brief Structure representing BLE Service
*
*/
static const ble_gatt_svc_def_t service[] = {
{
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t const *)&svc_uuid,
.characteristics =
(struct ble_gatt_chr_def[]){/* Characteristic define */
{.uuid = (ble_uuid_t const *)&chr_uuid,
.access_cb = on_chr_access_cb,
.arg = NULL,
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE_NO_RSP | BLE_GATT_CHR_F_NOTIFY,
.val_handle = &chr_val_handle},
{0}},
},
{
0, /* No more services. */
},
};
/**
* @brief Callback function for accessing characteristics
*
* @param conn_handle Connection handle ID
* @param attr_handle Attributte handle ID
* @param context Access context, providing operation type & buffer to send/receive data
* @param arg NULL
* @return ble_err_t
*/
static ble_err_t on_chr_access_cb(uint16_t conn_handle, uint16_t attr_handle, ble_gatt_access_ctxt_t *context, void *arg) {
ble_err_t reason{BLE_NO_ERROR};
ESP_RETURN_ON_FALSE(context, BLE_ATT_ERR_INVALID_HANDLE, LOG_TAG, "NULL context!");
ESP_RETURN_ON_FALSE(attr_handle == chr_val_handle,
BLE_ATT_ERR_INVALID_HANDLE,
LOG_TAG,
"Invalid attribute handle!");
/* Verify connection handle */
if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
ESP_LOGI(LOG_TAG, "access_cb by conn_handle=%d attr_handle=%d", conn_handle, attr_handle);
} else {
ESP_LOGI(LOG_TAG, "access_cb by nimble stack; attr_handle=%d", attr_handle);
}
/* Handle access events */
switch (context->op) {
/* Write characteristic event */
case BLE_GATT_ACCESS_OP_WRITE_CHR:
{
ESP_LOGW(LOG_TAG, "write_access, length=%d", context->om->om_len);
ESP_LOG_BUFFER_HEX(LOG_TAG, context->om->om_data, context->om->om_len);
event::event_t event_data;
event_data.type = event::BLE_SMARTPHONE_NOTIFY_REQUESTED;
event_data.network_data.conn_handle = conn_handle;
event_data.network_data.attr_handle = attr_handle;
os_mbuf_copydata(context->om, 0, OS_MBUF_PKTLEN(context->om), event_data.network_data.message.data);
event_data.network_data.message.length = context->om->om_len;
if (queue::send_event(&event_data) != ESP_OK) {
ESP_LOGE(LOG_TAG, "Failed to send event!");
}
break;
}
/* Read characteristic event */
case BLE_GATT_ACCESS_OP_READ_CHR:
{
ESP_LOGW(LOG_TAG, "read_access, length=%d", context->om->om_len);
ESP_LOG_BUFFER_HEX(LOG_TAG, context->om->om_data, context->om->om_len);
break;
}
/* Unknown event */
default:
reason = BLE_ATT_ERR_REQ_NOT_SUPPORTED;
break;
}
return reason;
}
} // namespace bridge_advertising_service
} // namespace services
} // namespace bluetooth
Code: Select all
# BT config
CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_DYNAMIC_SERVICE=y
CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=8192
CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE=8192
CONFIG_BT_NIMBLE_TASK_STACK_SIZE=8192
CONFIG_NIMBLE_TASK_STACK_SIZE=8192
CONFIG_FREERTOS_HZ=500
CONFIG_IPC_TASK_STACK_SIZE=2048
CONFIG_ESP_IPC_TASK_STACK_SIZE=2048
CONFIG_FREERTOS_ISR_STACKSIZE=2048
CONFIG_ESP_COEX_POWER_MANAGEMENT=n