mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
feat(ble_audio): BLE Audio PSRAM support
This commit is contained in:
@@ -48,9 +48,10 @@ list(APPEND ble_iso_srcs
|
||||
"${CMAKE_CURRENT_LIST_DIR}/host/utils/bt_str.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/host/utils/buf.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/host/utils/crypto.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/host/utils/keys.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/host/utils/mem.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/host/utils/timer.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/host/utils/utf8.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/host/utils/utils.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/host/utils/uuid.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/host/iso/iso.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/api/esp_ble_iso_common_api.c"
|
||||
@@ -74,6 +75,7 @@ endif()
|
||||
list(APPEND ble_iso_include_dirs
|
||||
"${CMAKE_CURRENT_LIST_DIR}/api/include"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/host/common/include"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/host/utils/include"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/subsys/bluetooth"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/subsys/bluetooth/host"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include"
|
||||
|
||||
@@ -104,6 +104,38 @@ if BT_ISO
|
||||
|
||||
endif # BT_ISO_BROADCAST
|
||||
|
||||
config BT_ISO_BSS_SEG_EXTERNAL_MEMORY
|
||||
bool "Place BLE ISO .bss segment in external SPIRAM"
|
||||
depends on SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||
default n
|
||||
help
|
||||
Place the zero-initialized (.bss) static data of the esp_ble_iso
|
||||
component in external SPIRAM instead of internal DRAM, to free
|
||||
internal RAM.
|
||||
|
||||
Safe because the esp_ble_iso sources register no IRAM ISRs: their
|
||||
data is only touched in task context, never while the flash cache
|
||||
is disabled. Hot ISO data-path state that must stay internal for
|
||||
latency is excluded at each placement site, not by this switch.
|
||||
|
||||
Requires SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY (which makes SPIRAM
|
||||
mandatory at boot). Only .bss is moved; initialized (.data) statistics
|
||||
stay internal.
|
||||
|
||||
config BT_ISO_HEAP_EXTERNAL_MEMORY
|
||||
bool "Place BLE ISO heap allocations in external SPIRAM"
|
||||
depends on SPIRAM
|
||||
default n
|
||||
help
|
||||
Route esp_ble_iso runtime heap allocations (control-plane only:
|
||||
GATT/GAP event marshalling, CIS/CIG setup params, CCC pools) to
|
||||
external SPIRAM via heap_caps_*(MALLOC_CAP_SPIRAM) instead of the
|
||||
internal heap.
|
||||
|
||||
The real-time ISO data path (TX/RX SDU packet buffers) is excluded
|
||||
at each allocation site and stays in internal DRAM. On SPIRAM
|
||||
exhaustion the allocation returns NULL (no internal fallback).
|
||||
|
||||
config BT_ISO_DISPATCH_MONITOR
|
||||
bool "Monitor ISO task callback dispatch latency"
|
||||
depends on !BT_ISO_NO_LOG
|
||||
|
||||
@@ -63,7 +63,9 @@ extern void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event,
|
||||
* matching the NimBLE host contract; then both this tracker and the
|
||||
* synthesis below become dead code. */
|
||||
#define ISO_PA_SYNC_HANDLE_NONE 0xFFFF
|
||||
static uint16_t active_pa_sync_handle = ISO_PA_SYNC_HANDLE_NONE;
|
||||
/* Reset in bt_le_bluedroid_gap_init() (not static init) so a deinit/init cycle
|
||||
* restarts from "no active sync"; static init runs only once at boot. */
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR uint16_t active_pa_sync_handle;
|
||||
#endif /* BLE_50_EXTEND_SYNC_EN == TRUE */
|
||||
|
||||
/* Fast-path BTA → iso-queue post.
|
||||
@@ -151,7 +153,7 @@ void bt_le_bluedroid_gap_post_event(uint16_t event, void *param)
|
||||
struct bt_le_gap_app_param *qev = NULL;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
/* Only AUTH_CMPL reaches here from the application's
|
||||
@@ -231,7 +233,7 @@ static void bt_le_bluedroid_gap_post_event_bta(tBTA_DM_BLE_5_GAP_EVENT event,
|
||||
enum iso_queue_item_type q_type;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
switch (event) {
|
||||
@@ -255,7 +257,7 @@ static void bt_le_bluedroid_gap_post_event_bta(tBTA_DM_BLE_5_GAP_EVENT event,
|
||||
qev->ext_scan_recv.data_len = r->adv_data_len;
|
||||
|
||||
if (qev->ext_scan_recv.data_len) {
|
||||
qev->ext_scan_recv.data = calloc(1, qev->ext_scan_recv.data_len);
|
||||
qev->ext_scan_recv.data = bt_le_ext_calloc(1, qev->ext_scan_recv.data_len);
|
||||
assert(qev->ext_scan_recv.data);
|
||||
memcpy(qev->ext_scan_recv.data, r->adv_data, qev->ext_scan_recv.data_len);
|
||||
}
|
||||
@@ -344,7 +346,7 @@ static void bt_le_bluedroid_gap_post_event_bta(tBTA_DM_BLE_5_GAP_EVENT event,
|
||||
qev->pa_sync_recv.data_len = r->data_length;
|
||||
|
||||
if (qev->pa_sync_recv.data_len) {
|
||||
qev->pa_sync_recv.data = calloc(1, qev->pa_sync_recv.data_len);
|
||||
qev->pa_sync_recv.data = bt_le_ext_calloc(1, qev->pa_sync_recv.data_len);
|
||||
assert(qev->pa_sync_recv.data);
|
||||
memcpy(qev->pa_sync_recv.data, r->data, qev->pa_sync_recv.data_len);
|
||||
}
|
||||
@@ -557,6 +559,10 @@ int bt_le_bluedroid_scan_stop(void)
|
||||
|
||||
int bt_le_bluedroid_gap_init(void)
|
||||
{
|
||||
#if (BLE_50_EXTEND_SYNC_EN == TRUE)
|
||||
active_pa_sync_handle = ISO_PA_SYNC_HANDLE_NONE;
|
||||
#endif
|
||||
|
||||
BTM_BleGapRegisterCallback(gap_app_cb);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -34,39 +34,29 @@ LOG_MODULE_REGISTER(ISO_BGAT, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
* module that follows this pattern. */
|
||||
#define GATTS_APP_UUID_BYTE 0x98
|
||||
|
||||
static const tBT_UUID gatts_app_uuid = {
|
||||
.len = LEN_UUID_128,
|
||||
.uu.uuid128 = {
|
||||
[0 ... 15] = GATTS_APP_UUID_BYTE,
|
||||
},
|
||||
};
|
||||
static tBTA_GATTS_IF gatts_if;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR tBT_UUID gatts_app_uuid;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR tBTA_GATTS_IF gatts_if;
|
||||
|
||||
/* Use UUID with a fixed pattern 0x99 for ISO & LE Audio GATT Client */
|
||||
#define GATTC_APP_UUID_BYTE 0x99
|
||||
|
||||
static tBT_UUID gattc_app_uuid = {
|
||||
.len = LEN_UUID_128,
|
||||
.uu.uuid128 = {
|
||||
[0 ... 15] = GATTC_APP_UUID_BYTE,
|
||||
},
|
||||
};
|
||||
static tBTA_GATTC_IF gattc_if;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR tBT_UUID gattc_app_uuid;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR tBTA_GATTC_IF gattc_if;
|
||||
|
||||
static struct gatts_svc_cb *gatts_svc_cb;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct gatts_svc_cb *gatts_svc_cb;
|
||||
|
||||
static struct gatt_conn gatt_conns[CONFIG_BT_MAX_CONN];
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct gatt_conn gatt_conns[CONFIG_BT_MAX_CONN];
|
||||
|
||||
/* Sems block bt_le_bluedroid_gatt_init() until the BTA app registrations
|
||||
* report back. gatts_sem is also reused by the audio adapter — only one
|
||||
* gatts_svc_cb is registered at a time, so sequential reuse is safe. */
|
||||
static struct k_sem gatts_sem;
|
||||
static struct k_sem gattc_sem;
|
||||
static BT_ISO_CTRL_BSS_ATTR struct k_sem gatts_sem;
|
||||
static BT_ISO_CTRL_BSS_ATTR struct k_sem gattc_sem;
|
||||
|
||||
/* Set by deinit before deleting the sems so a late BTA_*_REG_EVT skips the
|
||||
* give on a deleted handle. Same accepted residual race as hci.c's
|
||||
* direct_hci_shutting_down; the init-timeout window is near-unreachable. */
|
||||
static volatile bool gatt_shutting_down;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR volatile bool gatt_shutting_down;
|
||||
|
||||
enum {
|
||||
GATTC_OP_READ,
|
||||
@@ -90,7 +80,7 @@ static struct gattc_list_node *gattc_list_node_alloc(uint8_t type, void *params)
|
||||
{
|
||||
struct gattc_list_node *op;
|
||||
|
||||
op = calloc(1, sizeof(*op));
|
||||
op = bt_le_ext_calloc(1, sizeof(*op));
|
||||
if (op == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -180,7 +170,7 @@ static struct gatts_list_node *gatts_list_node_alloc(struct bt_gatt_indicate_par
|
||||
{
|
||||
struct gatts_list_node *n;
|
||||
|
||||
n = calloc(1, sizeof(*n));
|
||||
n = bt_le_ext_calloc(1, sizeof(*n));
|
||||
if (n == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -193,7 +183,7 @@ static struct gatts_list_node *gatts_list_node_alloc(struct bt_gatt_indicate_par
|
||||
if (ip->len > 0) {
|
||||
assert(ip->data);
|
||||
|
||||
n->data_copy = malloc(ip->len);
|
||||
n->data_copy = bt_le_ext_malloc(ip->len);
|
||||
if (n->data_copy == NULL) {
|
||||
free(n);
|
||||
return NULL;
|
||||
@@ -444,7 +434,7 @@ static void gattc_connect_event_handler(tBTA_GATTC_CONNECT *connect)
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTC_CONNECT_EVENT;
|
||||
@@ -467,7 +457,7 @@ static void gattc_disconnect_event_handler(tBTA_GATTC_DISCONNECT *disconnect)
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTC_DISCONNECT_EVENT;
|
||||
@@ -487,7 +477,7 @@ static void gattc_open_event_handler(tBTA_GATTC_OPEN *open)
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTC_OPEN_EVENT;
|
||||
@@ -507,7 +497,7 @@ static void gattc_mtu_event_handler(tBTA_GATTC_CFG_MTU *cfg_mtu)
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTC_MTU_EVENT;
|
||||
@@ -528,7 +518,7 @@ static void gattc_disc_cmpl_event_handler(tBTA_GATTC_DIS_CMPL *disc_cmpl)
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTC_DISC_CMPL_EVENT;
|
||||
@@ -548,7 +538,7 @@ static void gattc_read_chrc_event_handler(tBTA_GATTC_READ *read)
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTC_READ_CHRC_EVENT;
|
||||
@@ -562,7 +552,7 @@ static void gattc_read_chrc_event_handler(tBTA_GATTC_READ *read)
|
||||
read->p_value->p_value) {
|
||||
qev->gattc_read_chrc.len = read->p_value->len;
|
||||
|
||||
qev->gattc_read_chrc.value = calloc(1, read->p_value->len);
|
||||
qev->gattc_read_chrc.value = bt_le_ext_calloc(1, read->p_value->len);
|
||||
assert(qev->gattc_read_chrc.value);
|
||||
|
||||
memcpy(qev->gattc_read_chrc.value, read->p_value->p_value, read->p_value->len);
|
||||
@@ -583,7 +573,7 @@ static void gattc_write_chrc_event_handler(tBTA_GATTC_WRITE *write)
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTC_WRITE_CHRC_EVENT;
|
||||
@@ -605,7 +595,7 @@ static void gatts_notify_tx_event_handler(tBTA_GATTS_REQ *req)
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTS_NOTIFY_TX_EVENT;
|
||||
@@ -632,7 +622,7 @@ static void gattc_notify_rx_event_handler(tBTA_GATTC_NOTIFY *notify)
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTC_NOTIFY_RX_EVENT;
|
||||
@@ -644,7 +634,7 @@ static void gattc_notify_rx_event_handler(tBTA_GATTC_NOTIFY *notify)
|
||||
if (notify->len) {
|
||||
qev->gattc_notify_rx.len = notify->len;
|
||||
|
||||
qev->gattc_notify_rx.value = calloc(1, notify->len);
|
||||
qev->gattc_notify_rx.value = bt_le_ext_calloc(1, notify->len);
|
||||
assert(qev->gattc_notify_rx.value);
|
||||
|
||||
memcpy(qev->gattc_notify_rx.value, notify->value, notify->len);
|
||||
@@ -665,7 +655,7 @@ static void gatts_connect_event_handler(tBTA_GATTS_CONN *connect)
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTS_CONNECT_EVENT;
|
||||
@@ -688,7 +678,7 @@ static void gatts_disconnect_event_handler(tBTA_GATTS_CONN *disconnect)
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTS_DISCONNECT_EVENT;
|
||||
@@ -709,7 +699,7 @@ static void gatts_mtu_event_handler(tBTA_GATTS_REQ *req)
|
||||
int err;
|
||||
|
||||
/* req->p_data is non-NULL here: BTA always passes a stack object. */
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTS_MTU_EVENT;
|
||||
@@ -729,7 +719,7 @@ static void gatts_read_req_handler(tBTA_GATTS_REQ *req)
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTS_READ_EVENT;
|
||||
@@ -755,7 +745,7 @@ static void gatts_write_req_handler(tBTA_GATTS_REQ *req)
|
||||
int err;
|
||||
|
||||
/* req->p_data is non-NULL here: BTA always passes a stack object. */
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTS_WRITE_EVENT;
|
||||
@@ -771,7 +761,7 @@ static void gatts_write_req_handler(tBTA_GATTS_REQ *req)
|
||||
if (req->p_data->write_req.len) {
|
||||
qev->gatts_write.len = req->p_data->write_req.len;
|
||||
|
||||
qev->gatts_write.value = calloc(1, req->p_data->write_req.len);
|
||||
qev->gatts_write.value = bt_le_ext_calloc(1, req->p_data->write_req.len);
|
||||
assert(qev->gatts_write.value);
|
||||
|
||||
memcpy(qev->gatts_write.value, req->p_data->write_req.value, req->p_data->write_req.len);
|
||||
@@ -792,7 +782,7 @@ static void gatts_exec_write_req_handler(tBTA_GATTS_REQ *req)
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTS_EXEC_WRITE_EVENT;
|
||||
@@ -1378,7 +1368,7 @@ static void post_acl_connect_app_event(struct gatt_conn *gatt_conn)
|
||||
struct bt_le_gap_app_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GAP_APP_PARAM_ACL_CONNECT;
|
||||
@@ -1406,7 +1396,7 @@ static void post_acl_disconnect_app_event(uint16_t conn_handle, uint8_t reason)
|
||||
struct bt_le_gap_app_param *qev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GAP_APP_PARAM_ACL_DISCONNECT;
|
||||
@@ -1982,7 +1972,7 @@ static void handle_gatts_read_event(struct bt_le_gatts_read_event *event)
|
||||
/* The tBTA_GATT_STATUS structure is too large, hence use
|
||||
* dynamic memory here to avoid stack overflow.
|
||||
*/
|
||||
rsp = calloc(1, sizeof(*(rsp)));
|
||||
rsp = bt_le_ext_calloc(1, sizeof(*(rsp)));
|
||||
assert(rsp);
|
||||
|
||||
rsp->attr_value.handle = event->attr_handle;
|
||||
@@ -2078,7 +2068,7 @@ static void handle_gatts_prepare_write(struct bt_le_gatts_write_event *event)
|
||||
|
||||
if (status == BTA_GATT_OK) {
|
||||
/* The prepare-write response must echo handle/offset/value. */
|
||||
rsp = calloc(1, sizeof(*rsp));
|
||||
rsp = bt_le_ext_calloc(1, sizeof(*rsp));
|
||||
assert(rsp);
|
||||
|
||||
rsp->attr_value.handle = event->attr_handle;
|
||||
@@ -2553,7 +2543,7 @@ static int gatts_notify_enqueue(struct bt_conn *conn, uint16_t value_handle)
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
n = calloc(1, sizeof(*n));
|
||||
n = bt_le_ext_calloc(1, sizeof(*n));
|
||||
if (n == NULL) {
|
||||
LOG_ERR("[B]GattsNotifyNodeAllocFail[%u]", conn->handle);
|
||||
return -ENOMEM;
|
||||
@@ -3357,6 +3347,13 @@ int bt_le_bluedroid_gatt_init(void)
|
||||
* └─ btc_transfer_context classic app cb hops to BTC task here
|
||||
*/
|
||||
|
||||
/* Runtime init (not static) so the UUID is restored across a deinit/init
|
||||
* cycle; static init runs only once at boot. */
|
||||
gatts_app_uuid = (tBT_UUID){
|
||||
.len = LEN_UUID_128,
|
||||
.uu.uuid128 = { [0 ... 15] = GATTS_APP_UUID_BYTE },
|
||||
};
|
||||
|
||||
k_sem_reset(&gatts_sem);
|
||||
BTA_GATTS_AppRegister(&gatts_app_uuid, gatts_app_cb);
|
||||
|
||||
@@ -3365,6 +3362,11 @@ int bt_le_bluedroid_gatt_init(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
gattc_app_uuid = (tBT_UUID){
|
||||
.len = LEN_UUID_128,
|
||||
.uu.uuid128 = { [0 ... 15] = GATTC_APP_UUID_BYTE },
|
||||
};
|
||||
|
||||
k_sem_reset(&gattc_sem);
|
||||
BTA_GATTC_AppRegister(&gattc_app_uuid, gattc_app_cb);
|
||||
|
||||
|
||||
@@ -43,15 +43,15 @@ LOG_MODULE_REGISTER(ISO_BHCI, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
*
|
||||
* Concurrent safety: send_sync is serialized by callers via bt_le_host_lock,
|
||||
* so the static rsp_buf pointer / opcode latch are single-slot. */
|
||||
static struct k_sem direct_hci_sem;
|
||||
static BT_ISO_CTRL_BSS_ATTR struct k_sem direct_hci_sem;
|
||||
|
||||
/* Set by deinit before deleting the sem. Late-arriving cb's must check
|
||||
* this before touching the sem. Residual race exists (cb past the check
|
||||
* but pre-give vs. deinit completing the delete) — accepted in practice
|
||||
* because the BTU/HCI layer offers no way to cancel an in-flight cmd. */
|
||||
static volatile bool direct_hci_shutting_down;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR volatile bool direct_hci_shutting_down;
|
||||
|
||||
static struct {
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct {
|
||||
uint16_t opcode; /* expected — set by caller, verified by cb */
|
||||
uint8_t status; /* HCI status from Command_Complete */
|
||||
} direct_hci_rsp;
|
||||
@@ -64,8 +64,8 @@ static struct {
|
||||
* teardown race. Sized for the largest payload any direct-HCI caller reads
|
||||
* back (SET_CIG: 2 + 2*cis_count, ISO_READ_TX_SYNC: 11). */
|
||||
#define DIRECT_HCI_RSP_MAX MAX(2 + 2 * CONFIG_BT_ISO_MAX_CHAN, 11)
|
||||
static uint8_t direct_hci_rsp_data[DIRECT_HCI_RSP_MAX];
|
||||
static uint8_t direct_hci_rsp_data_len;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR uint8_t direct_hci_rsp_data[DIRECT_HCI_RSP_MAX];
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR uint8_t direct_hci_rsp_data_len;
|
||||
|
||||
static void direct_hci_complete_cb(BT_HDR *response, void *context)
|
||||
{
|
||||
|
||||
@@ -47,9 +47,9 @@ LOG_MODULE_REGISTER(ISO_BISO, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
* zero would yield bogus packet_seq_num / cis_handle to the lib).
|
||||
* K_SEM_SHORT must exceed the worst-case BTU dispatch chain. */
|
||||
|
||||
static struct k_sem iso_sem;
|
||||
static BT_ISO_CTRL_BSS_ATTR struct k_sem iso_sem;
|
||||
|
||||
static struct {
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct {
|
||||
uint8_t status;
|
||||
uint16_t conn_handle;
|
||||
uint16_t packet_seq_num;
|
||||
@@ -57,7 +57,7 @@ static struct {
|
||||
uint32_t time_offset;
|
||||
} tx_sync;
|
||||
|
||||
static struct {
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct {
|
||||
uint8_t status;
|
||||
uint8_t cig_id;
|
||||
uint8_t cis_count;
|
||||
@@ -183,7 +183,7 @@ static int hci_cmd_set_cig_params(struct net_buf *buf, struct net_buf **rsp)
|
||||
mtl_c_to_p = sys_get_le16(buf->data + 13);
|
||||
mtl_p_to_c = sys_get_le16(buf->data + 15);
|
||||
|
||||
cis_params = calloc(1, cis_count * sizeof(struct ble_hci_le_cis_params));
|
||||
cis_params = bt_le_ext_calloc(1, cis_count * sizeof(struct ble_hci_le_cis_params));
|
||||
assert(cis_params);
|
||||
|
||||
for (size_t i = 0; i < cis_count; i++) {
|
||||
@@ -301,7 +301,7 @@ static int hci_cmd_set_cig_params_test(struct net_buf *buf, struct net_buf **rsp
|
||||
packing = buf->data[15];
|
||||
framing = buf->data[16];
|
||||
|
||||
cis_params = calloc(1, cis_count * sizeof(struct ble_hci_le_cis_params_test));
|
||||
cis_params = bt_le_ext_calloc(1, cis_count * sizeof(struct ble_hci_le_cis_params_test));
|
||||
assert(cis_params);
|
||||
|
||||
for (size_t i = 0; i < cis_count; i++) {
|
||||
@@ -376,7 +376,7 @@ static int hci_cmd_create_cis(struct net_buf *buf, struct net_buf **rsp)
|
||||
|
||||
cis_count = buf->data[3];
|
||||
|
||||
cis_params = calloc(1, cis_count * sizeof(struct ble_hci_cis_hdls));
|
||||
cis_params = bt_le_ext_calloc(1, cis_count * sizeof(struct ble_hci_cis_hdls));
|
||||
assert(cis_params);
|
||||
|
||||
for (size_t i = 0; i < cis_count; i++) {
|
||||
@@ -858,7 +858,7 @@ static void iso_evt_handler(tBTM_BLE_ISO_EVENT event, tBTM_BLE_ISO_CB_PARAMS *pa
|
||||
struct bt_hci_evt_disconn_complete ev = {0};
|
||||
|
||||
qdata_len = 2 + sizeof(ev);
|
||||
qdata = calloc(1, qdata_len);
|
||||
qdata = bt_le_ext_calloc(1, qdata_len);
|
||||
assert(qdata);
|
||||
|
||||
ev.status = 0x00;
|
||||
@@ -875,7 +875,7 @@ static void iso_evt_handler(tBTM_BLE_ISO_EVENT event, tBTM_BLE_ISO_CB_PARAMS *pa
|
||||
struct bt_hci_evt_le_cis_established ev = {0};
|
||||
|
||||
qdata_len = 2 + 1 + sizeof(ev);
|
||||
qdata = calloc(1, qdata_len);
|
||||
qdata = bt_le_ext_calloc(1, qdata_len);
|
||||
assert(qdata);
|
||||
|
||||
ev.status = iso_hci_status(params->btm_cis_established_evt.status);
|
||||
@@ -906,7 +906,7 @@ static void iso_evt_handler(tBTM_BLE_ISO_EVENT event, tBTM_BLE_ISO_CB_PARAMS *pa
|
||||
struct bt_hci_evt_le_cis_req ev = {0};
|
||||
|
||||
qdata_len = 2 + 1 + sizeof(ev);
|
||||
qdata = calloc(1, qdata_len);
|
||||
qdata = bt_le_ext_calloc(1, qdata_len);
|
||||
assert(qdata);
|
||||
|
||||
ev.acl_handle = params->btm_cis_request_evt.acl_handle;
|
||||
@@ -925,7 +925,7 @@ static void iso_evt_handler(tBTM_BLE_ISO_EVENT event, tBTM_BLE_ISO_CB_PARAMS *pa
|
||||
struct bt_hci_evt_le_big_complete ev = {0};
|
||||
|
||||
qdata_len = 2 + 1 + sizeof(ev) + params->btm_big_cmpl.num_bis * 2;
|
||||
qdata = calloc(1, qdata_len);
|
||||
qdata = bt_le_ext_calloc(1, qdata_len);
|
||||
assert(qdata);
|
||||
|
||||
ev.status = iso_hci_status(params->btm_big_cmpl.status);
|
||||
@@ -956,7 +956,7 @@ static void iso_evt_handler(tBTM_BLE_ISO_EVENT event, tBTM_BLE_ISO_CB_PARAMS *pa
|
||||
struct bt_hci_evt_le_big_terminate ev = {0};
|
||||
|
||||
qdata_len = 2 + 1 + sizeof(ev);
|
||||
qdata = calloc(1, qdata_len);
|
||||
qdata = bt_le_ext_calloc(1, qdata_len);
|
||||
assert(qdata);
|
||||
|
||||
ev.big_handle = params->btm_big_term.big_handle;
|
||||
@@ -973,7 +973,7 @@ static void iso_evt_handler(tBTM_BLE_ISO_EVENT event, tBTM_BLE_ISO_CB_PARAMS *pa
|
||||
struct bt_hci_evt_le_big_sync_established ev = {0};
|
||||
|
||||
qdata_len = 2 + 1 + sizeof(ev) + params->btm_big_sync_estab.num_bis * 2;
|
||||
qdata = calloc(1, qdata_len);
|
||||
qdata = bt_le_ext_calloc(1, qdata_len);
|
||||
assert(qdata);
|
||||
|
||||
ev.status = iso_hci_status(params->btm_big_sync_estab.status);
|
||||
@@ -1002,7 +1002,7 @@ static void iso_evt_handler(tBTM_BLE_ISO_EVENT event, tBTM_BLE_ISO_CB_PARAMS *pa
|
||||
struct bt_hci_evt_le_big_sync_lost ev = {0};
|
||||
|
||||
qdata_len = 2 + 1 + sizeof(ev);
|
||||
qdata = calloc(1, qdata_len);
|
||||
qdata = bt_le_ext_calloc(1, qdata_len);
|
||||
assert(qdata);
|
||||
|
||||
ev.big_handle = params->btm_big_sync_lost.big_handle;
|
||||
@@ -1019,7 +1019,7 @@ static void iso_evt_handler(tBTM_BLE_ISO_EVENT event, tBTM_BLE_ISO_CB_PARAMS *pa
|
||||
struct bt_hci_evt_le_biginfo_adv_report ev = {0};
|
||||
|
||||
qdata_len = 2 + 1 + sizeof(ev);
|
||||
qdata = calloc(1, qdata_len);
|
||||
qdata = bt_le_ext_calloc(1, qdata_len);
|
||||
assert(qdata);
|
||||
|
||||
ev.sync_handle = params->btm_biginfo_report.sync_handle;
|
||||
|
||||
@@ -82,7 +82,7 @@ void bt_le_nimble_gap_post_event(void *param)
|
||||
enum iso_queue_item_type q_type;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
@@ -116,7 +116,7 @@ void bt_le_nimble_gap_post_event(void *param)
|
||||
qev->ext_scan_recv.data_len = ev->ext_disc.length_data;
|
||||
|
||||
if (qev->ext_scan_recv.data_len) {
|
||||
qev->ext_scan_recv.data = calloc(1, qev->ext_scan_recv.data_len);
|
||||
qev->ext_scan_recv.data = bt_le_ext_calloc(1, qev->ext_scan_recv.data_len);
|
||||
assert(qev->ext_scan_recv.data);
|
||||
|
||||
memcpy(qev->ext_scan_recv.data, ev->ext_disc.data, qev->ext_scan_recv.data_len);
|
||||
@@ -171,7 +171,7 @@ void bt_le_nimble_gap_post_event(void *param)
|
||||
qev->pa_sync_recv.data_len = ev->periodic_report.data_length;
|
||||
|
||||
if (qev->pa_sync_recv.data_len) {
|
||||
qev->pa_sync_recv.data = calloc(1, qev->pa_sync_recv.data_len);
|
||||
qev->pa_sync_recv.data = bt_le_ext_calloc(1, qev->pa_sync_recv.data_len);
|
||||
assert(qev->pa_sync_recv.data);
|
||||
|
||||
memcpy(qev->pa_sync_recv.data, ev->periodic_report.data, qev->pa_sync_recv.data_len);
|
||||
|
||||
@@ -44,7 +44,7 @@ void bt_le_nimble_gatt_post_event(void *param)
|
||||
return;
|
||||
}
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
switch (ev->type) {
|
||||
@@ -78,7 +78,7 @@ void bt_le_nimble_gatt_post_event(void *param)
|
||||
uint16_t total_len = OS_MBUF_PKTLEN(ev->notify_rx.om);
|
||||
qev->gattc_notify_rx.len = total_len;
|
||||
|
||||
qev->gattc_notify_rx.value = calloc(1, total_len);
|
||||
qev->gattc_notify_rx.value = bt_le_ext_calloc(1, total_len);
|
||||
assert(qev->gattc_notify_rx.value);
|
||||
|
||||
os_mbuf_copydata(ev->notify_rx.om, 0, total_len, qev->gattc_notify_rx.value);
|
||||
@@ -128,7 +128,7 @@ int bt_le_nimble_gatt_post_disc_event(uint16_t conn_handle, ble_uuid16_t *uuid,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTC_DISCOVER_EVENT;
|
||||
@@ -155,7 +155,7 @@ int bt_le_nimble_gatt_post_disc_cmpl_event(uint16_t conn_handle, uint8_t status)
|
||||
|
||||
LOG_DBG("[N]GattcDiscCmplEvtHdlr[%u][%02x]", conn_handle, status);
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
qev = bt_le_ext_calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTC_DISC_CMPL_EVENT;
|
||||
|
||||
@@ -104,7 +104,7 @@ struct gattc_db_dsc {
|
||||
sys_snode_t node;
|
||||
};
|
||||
|
||||
static struct gattc_db {
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct gattc_db {
|
||||
uint16_t conn_handle;
|
||||
enum {
|
||||
DISC_IDLE = 0,
|
||||
@@ -113,12 +113,7 @@ static struct gattc_db {
|
||||
DISC_FAIL,
|
||||
} status;
|
||||
sys_slist_t svc_list; /* List of the GATT server database of the connection */
|
||||
} gattc_db[CONFIG_BT_MAX_CONN] = {
|
||||
[0 ...(CONFIG_BT_MAX_CONN - 1)] = {
|
||||
.conn_handle = UINT16_MAX,
|
||||
.status = DISC_IDLE,
|
||||
},
|
||||
};
|
||||
} gattc_db[CONFIG_BT_MAX_CONN];
|
||||
|
||||
static struct gattc_db *gattc_db_add(uint16_t conn_handle)
|
||||
{
|
||||
@@ -186,7 +181,7 @@ static void gattc_db_svc_insert(struct gattc_db *adb, const struct ble_gatt_svc
|
||||
{
|
||||
struct gattc_db_svc *asvc;
|
||||
|
||||
asvc = calloc(1, sizeof(*asvc));
|
||||
asvc = bt_le_ext_calloc(1, sizeof(*asvc));
|
||||
assert(asvc);
|
||||
|
||||
memcpy(&asvc->svc, svc, sizeof(asvc->svc));
|
||||
@@ -202,7 +197,7 @@ static void gattc_db_inc_svc_insert(struct gattc_db_svc *asvc, const struct ble_
|
||||
{
|
||||
struct gattc_db_inc_svc *ainc_svc;
|
||||
|
||||
ainc_svc = calloc(1, sizeof(*ainc_svc));
|
||||
ainc_svc = bt_le_ext_calloc(1, sizeof(*ainc_svc));
|
||||
assert(ainc_svc);
|
||||
|
||||
memcpy(&ainc_svc->svc, inc_svc, sizeof(ainc_svc->svc));
|
||||
@@ -224,7 +219,7 @@ static void gattc_db_chrc_insert(sys_slist_t *chrc_list, const struct ble_gatt_c
|
||||
{
|
||||
struct gattc_db_chrc *achrc;
|
||||
|
||||
achrc = calloc(1, sizeof(*achrc));
|
||||
achrc = bt_le_ext_calloc(1, sizeof(*achrc));
|
||||
assert(achrc);
|
||||
|
||||
memcpy(&achrc->chrc, chrc, sizeof(achrc->chrc));
|
||||
@@ -1475,3 +1470,25 @@ void bt_le_nimble_gattc_db_remove(uint16_t conn_handle)
|
||||
|
||||
gattc_db_del(adb);
|
||||
}
|
||||
|
||||
/* Runtime init (not static): the array is .bss (PSRAM-eligible), so a
|
||||
* deinit/init cycle must restart with every slot free. conn_handle 0 is a
|
||||
* valid handle, so the free marker is UINT16_MAX. */
|
||||
void bt_le_nimble_gattc_db_init(void)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(gattc_db); i++) {
|
||||
gattc_db[i].conn_handle = UINT16_MAX;
|
||||
gattc_db[i].status = DISC_IDLE;
|
||||
sys_slist_init(&gattc_db[i].svc_list);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free each slot's discovery nodes on deinit so an init/deinit/re-init cycle stays
|
||||
* leak-free (mirrors the Bluedroid bt_le_bluedroid_gatt_deinit). gattc_db_del is a
|
||||
* safe no-op on an already-free slot. */
|
||||
void bt_le_nimble_gattc_db_deinit(void)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(gattc_db); i++) {
|
||||
gattc_db_del(&gattc_db[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,15 +79,11 @@ struct gatt_nrp_node {
|
||||
sys_snode_t node;
|
||||
};
|
||||
|
||||
static struct gatt_nrp {
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct gatt_nrp {
|
||||
uint16_t conn_handle;
|
||||
|
||||
sys_slist_t list; /* List of GATT need response pdu (e.g., read req, write req, indication, etc.) */
|
||||
} gatt_nrp[CONFIG_BT_MAX_CONN] = {
|
||||
[0 ...(CONFIG_BT_MAX_CONN - 1)] = {
|
||||
.conn_handle = UINT16_MAX,
|
||||
},
|
||||
};
|
||||
} gatt_nrp[CONFIG_BT_MAX_CONN];
|
||||
|
||||
static struct gatt_nrp *gatt_nrp_find(uint16_t conn_handle);
|
||||
|
||||
@@ -738,7 +734,7 @@ static int gatt_nrp_insert(struct bt_conn *conn, uint8_t type, void *params)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
nrp_node = calloc(1, sizeof(*nrp_node));
|
||||
nrp_node = bt_le_ext_calloc(1, sizeof(*nrp_node));
|
||||
assert(nrp_node);
|
||||
|
||||
nrp_node->type = type;
|
||||
@@ -760,7 +756,7 @@ static int gatt_nrp_insert(struct bt_conn *conn, uint8_t type, void *params)
|
||||
nrp_node->write_req.data_copy = NULL;
|
||||
if (wp->length > 0) {
|
||||
assert(wp->data);
|
||||
nrp_node->write_req.data_copy = malloc(wp->length);
|
||||
nrp_node->write_req.data_copy = bt_le_ext_malloc(wp->length);
|
||||
if (nrp_node->write_req.data_copy == NULL) {
|
||||
LOG_ERR("[N]GattNrpWrDataAllocFail[%u]", wp->length);
|
||||
free(nrp_node);
|
||||
@@ -780,7 +776,7 @@ static int gatt_nrp_insert(struct bt_conn *conn, uint8_t type, void *params)
|
||||
nrp_node->indicate.data_copy = NULL;
|
||||
if (ip->len > 0) {
|
||||
assert(ip->data);
|
||||
nrp_node->indicate.data_copy = malloc(ip->len);
|
||||
nrp_node->indicate.data_copy = bt_le_ext_malloc(ip->len);
|
||||
if (nrp_node->indicate.data_copy == NULL) {
|
||||
LOG_ERR("[N]GattNrpIndDataAllocFail[%u]", ip->len);
|
||||
free(nrp_node);
|
||||
@@ -1043,3 +1039,22 @@ void bt_le_nimble_gatt_nrp_clear(uint16_t conn_handle)
|
||||
|
||||
gatt_nrp_del(nrp);
|
||||
}
|
||||
|
||||
/* Runtime init (not static): .bss array (PSRAM-eligible) that a deinit/init
|
||||
* cycle must restart all-free (UINT16_MAX, since conn_handle 0 is valid). */
|
||||
void bt_le_nimble_gatt_nrp_init(void)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(gatt_nrp); i++) {
|
||||
gatt_nrp[i].conn_handle = UINT16_MAX;
|
||||
sys_slist_init(&gatt_nrp[i].list);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free each slot's queued NRP nodes on deinit (mirrors bt_le_nimble_gattc_db_deinit);
|
||||
* gatt_nrp_del is a safe no-op on an already-free slot. */
|
||||
void bt_le_nimble_gatt_nrp_deinit(void)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(gatt_nrp); i++) {
|
||||
gatt_nrp_del(&gatt_nrp[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,10 @@ int bt_le_nimble_gattc_db_auto_disc(uint16_t conn_handle);
|
||||
|
||||
void bt_le_nimble_gattc_db_remove(uint16_t conn_handle);
|
||||
|
||||
void bt_le_nimble_gattc_db_init(void);
|
||||
|
||||
void bt_le_nimble_gattc_db_deinit(void);
|
||||
|
||||
enum {
|
||||
GATTC_NRP_READ_BY_UUID,
|
||||
GATTC_NRP_READ_LONG,
|
||||
@@ -113,12 +117,14 @@ void bt_le_nimble_gatts_nrp_indicate_cb(uint16_t conn_handle,
|
||||
|
||||
int bt_le_nimble_gatt_nrp_insert(struct bt_conn *conn, uint8_t type, void *params);
|
||||
|
||||
/* err is forwarded only to the INDICATE func cb; other NRP types invoke their
|
||||
* own func with err in cb_safe and pass 0 here. */
|
||||
int bt_le_nimble_gatt_nrp_remove(struct bt_conn *conn, uint8_t type, void *params, uint8_t err);
|
||||
|
||||
void bt_le_nimble_gatt_nrp_clear(uint16_t conn_handle);
|
||||
|
||||
void bt_le_nimble_gatt_nrp_init(void);
|
||||
|
||||
void bt_le_nimble_gatt_nrp_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -105,12 +105,12 @@ static int hci_cmd_set_cig_params(struct net_buf *buf, struct net_buf **rsp)
|
||||
|
||||
/* The cis_count can be 0 */
|
||||
if (cis_count) {
|
||||
cis_params = calloc(1, cis_count * sizeof(struct ble_hci_le_cis_params));
|
||||
cis_params = bt_le_ext_calloc(1, cis_count * sizeof(struct ble_hci_le_cis_params));
|
||||
assert(cis_params);
|
||||
}
|
||||
|
||||
rp_len = sizeof(struct ble_hci_le_set_cig_params_rp) + cis_count * 2;
|
||||
rp = calloc(1, rp_len);
|
||||
rp = bt_le_ext_calloc(1, rp_len);
|
||||
assert(rp);
|
||||
|
||||
for (size_t i = 0; i < cis_count; i++) {
|
||||
@@ -199,12 +199,12 @@ static int hci_cmd_set_cig_params_test(struct net_buf *buf, struct net_buf **rsp
|
||||
|
||||
/* The cis_count can be 0 */
|
||||
if (cis_count) {
|
||||
cis_params = calloc(1, cis_count * sizeof(struct ble_hci_le_cis_params_test));
|
||||
cis_params = bt_le_ext_calloc(1, cis_count * sizeof(struct ble_hci_le_cis_params_test));
|
||||
assert(cis_params);
|
||||
}
|
||||
|
||||
rp_len = sizeof(struct ble_hci_le_set_cig_params_test_rp) + cis_count * 2;
|
||||
rp = calloc(1, rp_len);
|
||||
rp = bt_le_ext_calloc(1, rp_len);
|
||||
assert(rp);
|
||||
|
||||
for (size_t i = 0; i < cis_count; i++) {
|
||||
@@ -276,7 +276,7 @@ static int hci_cmd_create_cis(struct net_buf *buf, struct net_buf **rsp)
|
||||
|
||||
assert(buf->len >= 4 + cis_count * sizeof(struct ble_hci_le_create_cis_params));
|
||||
|
||||
cis_params = calloc(1, cis_count * sizeof(struct ble_hci_le_create_cis_params));
|
||||
cis_params = bt_le_ext_calloc(1, cis_count * sizeof(struct ble_hci_le_create_cis_params));
|
||||
assert(cis_params);
|
||||
|
||||
for (size_t i = 0; i < cis_count; i++) {
|
||||
@@ -792,7 +792,7 @@ static void iso_evt_rx(uint8_t event, const void *data,
|
||||
|
||||
qdata_len = len + 2;
|
||||
|
||||
qdata = calloc(1, qdata_len);
|
||||
qdata = bt_le_ext_calloc(1, qdata_len);
|
||||
assert(qdata);
|
||||
|
||||
qdata[0] = le_meta;
|
||||
|
||||
@@ -32,11 +32,11 @@ _Static_assert(CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM && "At least one L2CAP coc sha
|
||||
#define OTS_L2CAP_BUF_COUNT (3 * CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM)
|
||||
#define OTS_L2CAP_MEM_SIZE OS_MEMPOOL_SIZE(OTS_L2CAP_BUF_COUNT, L2CAP_LE_OTS_MTU * 2)
|
||||
|
||||
static os_membuf_t ots_mem[OTS_L2CAP_MEM_SIZE];
|
||||
static struct os_mempool ots_mbuf_mempool;
|
||||
static struct os_mbuf_pool ots_mbuf_pool;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR os_membuf_t ots_mem[OTS_L2CAP_MEM_SIZE];
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct os_mempool ots_mbuf_mempool;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct os_mbuf_pool ots_mbuf_pool;
|
||||
|
||||
static struct ble_l2cap_chan *ots_chan;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct ble_l2cap_chan *ots_chan;
|
||||
|
||||
static int ots_l2cap_recv_ready(struct ble_l2cap_chan *chan)
|
||||
{
|
||||
@@ -158,7 +158,7 @@ static int ots_l2cap_event_cb(struct ble_l2cap_event *event, void *arg)
|
||||
|
||||
sdu_len = OS_MBUF_PKTLEN(event->receive.sdu_rx);
|
||||
|
||||
sdu = calloc(1, sdu_len);
|
||||
sdu = bt_le_ext_calloc(1, sdu_len);
|
||||
assert(sdu);
|
||||
|
||||
err = os_mbuf_copydata(event->receive.sdu_rx, 0, sdu_len, sdu);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
LOG_MODULE_REGISTER(ISO_ADV, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
|
||||
static struct bt_le_ext_adv ext_adv_pool[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct bt_le_ext_adv ext_adv_pool[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
|
||||
|
||||
static struct bt_le_ext_adv *ext_adv_find(uint8_t adv_handle)
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
LOG_MODULE_REGISTER(ISO_AGAP, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
|
||||
static bt_le_gap_app_cb gap_app_cb;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR bt_le_gap_app_cb gap_app_cb;
|
||||
|
||||
int bt_le_gap_app_cb_register(bt_le_gap_app_cb cb)
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
LOG_MODULE_REGISTER(ISO_AGAT, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
|
||||
static bt_le_gatt_app_cb gatt_app_cb;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR bt_le_gatt_app_cb gatt_app_cb;
|
||||
|
||||
int bt_le_gatt_app_cb_register(bt_le_gatt_app_cb cb)
|
||||
{
|
||||
|
||||
@@ -23,18 +23,18 @@
|
||||
|
||||
LOG_MODULE_REGISTER(ISO_CONN, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
|
||||
static struct bt_conn acl_conns[CONFIG_BT_MAX_CONN];
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct bt_conn acl_conns[CONFIG_BT_MAX_CONN];
|
||||
|
||||
/* Per-ACL LTK backing store (indexed in lockstep with acl_conns[]). conn->le.keys is
|
||||
* a bare pointer the adapters fill after bonding; point it at the matching slot so the
|
||||
* lib's CSIS sirk_encrypt can read conn->le.keys->ltk.val. */
|
||||
static struct bt_keys conn_ltk[CONFIG_BT_MAX_CONN];
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct bt_keys conn_ltk[CONFIG_BT_MAX_CONN];
|
||||
|
||||
extern struct bt_conn iso_conns[CONFIG_BT_ISO_MAX_CHAN];
|
||||
|
||||
static sys_slist_t conn_cbs = SYS_SLIST_STATIC_INIT(&conn_cbs);
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR sys_slist_t conn_cbs;
|
||||
|
||||
static sys_slist_t auth_info_cbs = SYS_SLIST_STATIC_INIT(&auth_info_cbs);
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR sys_slist_t auth_info_cbs;
|
||||
|
||||
_IDF_ONLY
|
||||
void bt_conn_get_acl_conns(struct bt_conn **conns, uint8_t *count)
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
|
||||
LOG_MODULE_REGISTER(ISO_GATT, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
|
||||
static sys_slist_t gatt_db = SYS_SLIST_STATIC_INIT(&gatt_db);
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR sys_slist_t gatt_db;
|
||||
|
||||
static struct gattc_sub subscriptions[CONFIG_BT_MAX_CONN];
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct gattc_sub subscriptions[CONFIG_BT_MAX_CONN];
|
||||
|
||||
/* Each CCC descriptor's cfg is a heap pool (depth BT_GATT_CCC_MAX = bonded peers +
|
||||
* active conn), allocated here at registration; freed in gatts_free_svc_ccc_cfg. */
|
||||
@@ -44,7 +44,7 @@ static int gatts_alloc_svc_ccc_cfg(struct bt_gatt_service *svc)
|
||||
}
|
||||
|
||||
ccc = attr->user_data;
|
||||
ccc->cfg = calloc(BT_GATT_CCC_MAX, sizeof(struct bt_gatt_ccc_cfg));
|
||||
ccc->cfg = bt_le_ext_calloc(BT_GATT_CCC_MAX, sizeof(struct bt_gatt_ccc_cfg));
|
||||
if (ccc->cfg == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/buf.h>
|
||||
#include <zephyr/bluetooth/hci.h>
|
||||
#include <zephyr/bluetooth/hci_types.h>
|
||||
#include <zephyr/bluetooth/gap.h>
|
||||
|
||||
#include <../host/hci_core.h>
|
||||
#include <../host/iso_internal.h>
|
||||
@@ -23,6 +25,24 @@
|
||||
|
||||
LOG_MODULE_REGISTER(ISO_HCI, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
|
||||
/* Device/HCI state, not an ISO packet, task-context -> eligible for PSRAM. */
|
||||
BT_ISO_EXT_RAM_BSS_ATTR struct bt_dev bt_dev;
|
||||
|
||||
uint8_t bt_get_phy(uint8_t hci_phy)
|
||||
{
|
||||
switch (hci_phy) {
|
||||
case BT_HCI_LE_PHY_1M:
|
||||
return BT_GAP_LE_PHY_1M;
|
||||
case BT_HCI_LE_PHY_2M:
|
||||
return BT_GAP_LE_PHY_2M;
|
||||
case BT_HCI_LE_PHY_CODED:
|
||||
return BT_GAP_LE_PHY_CODED;
|
||||
default:
|
||||
LOG_WRN("UnknownHciPhy[%u]", hci_phy);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct cmd_data {
|
||||
/** HCI status of the command completion */
|
||||
uint8_t status;
|
||||
@@ -34,7 +54,7 @@ struct cmd_data {
|
||||
struct bt_hci_cmd_state_set *state;
|
||||
};
|
||||
|
||||
static struct cmd_data cmd_data;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct cmd_data cmd_data;
|
||||
|
||||
#define cmd(buf) (&cmd_data)
|
||||
|
||||
|
||||
@@ -20,11 +20,13 @@
|
||||
#if CONFIG_BT_BLUEDROID_ENABLED
|
||||
#include "bluedroid/gap.h"
|
||||
#include "bluedroid/gatt.h"
|
||||
#else
|
||||
#include "nimble/gatt.h"
|
||||
#endif
|
||||
|
||||
LOG_MODULE_REGISTER(ISO_HOST, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
|
||||
static struct k_mutex host_mutex;
|
||||
static BT_ISO_CTRL_BSS_ATTR struct k_mutex host_mutex;
|
||||
|
||||
#if HOST_LOCK_DEBUG
|
||||
void bt_le_host_lock_debug(const char *func, int line)
|
||||
@@ -97,6 +99,11 @@ int bt_le_host_init(void)
|
||||
if (err) {
|
||||
goto deinit_bluedroid_gatt;
|
||||
}
|
||||
#else
|
||||
/* nimble: reset the per-conn GATT cache/NRP arrays (now .bss/PSRAM, no
|
||||
* static init) so this init - and any later deinit/re-init - starts clean. */
|
||||
bt_le_nimble_gattc_db_init();
|
||||
bt_le_nimble_gatt_nrp_init();
|
||||
#endif /* CONFIG_BT_BLUEDROID_ENABLED */
|
||||
|
||||
err = bt_le_iso_init();
|
||||
@@ -137,6 +144,9 @@ void bt_le_host_deinit(void)
|
||||
bt_le_iso_deinit();
|
||||
#if CONFIG_BT_BLUEDROID_ENABLED
|
||||
bt_le_bluedroid_gatt_deinit();
|
||||
#else
|
||||
bt_le_nimble_gattc_db_deinit();
|
||||
bt_le_nimble_gatt_nrp_deinit();
|
||||
#endif /* CONFIG_BT_BLUEDROID_ENABLED */
|
||||
#if CONFIG_BT_OTS || CONFIG_BT_OTS_CLIENT
|
||||
bt_le_l2cap_deinit();
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
#include <zephyr/bluetooth/iso.h>
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
|
||||
#include "utils/iso_attr.h"
|
||||
#include "utils/mem.h"
|
||||
|
||||
#include "common/adv.h"
|
||||
#include "common/conn.h"
|
||||
#include "common/iso.h"
|
||||
|
||||
@@ -44,7 +44,7 @@ LOG_MODULE_REGISTER(ISO_SHIM, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
#define ISO_PKT_COMP_SDU (0b10)
|
||||
#define ISO_PKT_LAST_FRAG (0b11)
|
||||
|
||||
static sys_slist_t iso_cbs = SYS_SLIST_STATIC_INIT(&iso_cbs);
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR sys_slist_t iso_cbs;
|
||||
|
||||
#if CONFIG_BT_ISO_UNICAST
|
||||
static void hci_le_cis_disconnected(struct net_buf *buf);
|
||||
@@ -407,13 +407,13 @@ struct iso_tx_sdu_node {
|
||||
sys_snode_t node;
|
||||
};
|
||||
|
||||
static sys_slist_t iso_tx_sdu_list = SYS_SLIST_STATIC_INIT(&iso_tx_sdu_list);
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR sys_slist_t iso_tx_sdu_list;
|
||||
|
||||
static int iso_tx_sdu_insert(struct bt_iso_chan *chan, const uint8_t *sdu, uint16_t sdu_len)
|
||||
{
|
||||
struct iso_tx_sdu_node *sdu_node;
|
||||
|
||||
sdu_node = calloc(1, sizeof(*sdu_node));
|
||||
sdu_node = bt_le_int_calloc(1, sizeof(*sdu_node));
|
||||
if (sdu_node == NULL) {
|
||||
LOG_ERR("IsoTxSduInsertNoMem[%u]", sizeof(*sdu_node));
|
||||
return -ENOMEM;
|
||||
@@ -513,7 +513,7 @@ static int iso_tx_now(struct bt_iso_chan *chan, const uint8_t *sdu,
|
||||
* Check if ISO SDU needs to be fragmented here.
|
||||
*/
|
||||
|
||||
pkt = malloc(4 + data_total_len);
|
||||
pkt = bt_le_int_malloc(4 + data_total_len);
|
||||
if (pkt == NULL) {
|
||||
LOG_ERR("IsoTxNowNoMem[%u]", 4 + data_total_len);
|
||||
return -ENOMEM;
|
||||
@@ -689,7 +689,7 @@ static void iso_tx_comp_cb(uint16_t conn_handle, void *info, size_t size)
|
||||
|
||||
assert(size == sizeof(struct bt_iso_tx_cb_info));
|
||||
|
||||
evt = calloc(1, sizeof(*evt));
|
||||
evt = bt_le_int_calloc(1, sizeof(*evt));
|
||||
if (evt == NULL) {
|
||||
LOG_ERR("IsoTxCompNoMem[%u]", sizeof(*evt));
|
||||
return;
|
||||
@@ -743,7 +743,7 @@ int bt_le_iso_rx(const uint8_t *data, uint16_t len, void *arg)
|
||||
|
||||
ARG_UNUSED(arg);
|
||||
|
||||
rx_data = calloc(1, len);
|
||||
rx_data = bt_le_int_calloc(1, len);
|
||||
if (rx_data == NULL) {
|
||||
LOG_ERR("IsoRxNoMem[%u]", len);
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -35,7 +35,7 @@ LOG_MODULE_REGISTER(ISO_L2CAP, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
#define L2CAP_LE_PSM_DYN_END 0x00FF
|
||||
#define L2CAP_LE_PSM_IS_DYN(_psm) (_psm >= L2CAP_LE_PSM_DYN_START && _psm <= L2CAP_LE_PSM_DYN_END)
|
||||
|
||||
static sys_slist_t l2cap_servers = SYS_SLIST_STATIC_INIT(&l2cap_servers);
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR sys_slist_t l2cap_servers;
|
||||
|
||||
static struct bt_l2cap_chan *l2cap_lookup_tx_cid(struct bt_conn *conn, uint16_t cid)
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
LOG_MODULE_REGISTER(ISO_SCAN, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
|
||||
static sys_slist_t scan_cbs = SYS_SLIST_STATIC_INIT(&scan_cbs);
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR sys_slist_t scan_cbs;
|
||||
|
||||
_LIB_ONLY
|
||||
int bt_le_scan_cb_register(struct bt_le_scan_cb *cb)
|
||||
@@ -146,9 +146,9 @@ void bt_le_scan_recv_listener(uint16_t event_type,
|
||||
}
|
||||
}
|
||||
|
||||
static struct bt_le_per_adv_sync per_adv_sync_pool[CONFIG_BT_PER_ADV_SYNC_MAX];
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct bt_le_per_adv_sync per_adv_sync_pool[CONFIG_BT_PER_ADV_SYNC_MAX];
|
||||
|
||||
static sys_slist_t pa_sync_cbs = SYS_SLIST_STATIC_INIT(&pa_sync_cbs);
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR sys_slist_t pa_sync_cbs;
|
||||
|
||||
_LIB_ONLY
|
||||
int bt_le_per_adv_sync_cb_register(struct bt_le_per_adv_sync_cb *cb)
|
||||
|
||||
@@ -29,19 +29,19 @@ LOG_MODULE_REGISTER(ISO_TASK, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
* critical before normal before floodable, so a flood of GAP reports cannot
|
||||
* delay the latency-critical ISO data path. See common/task.h for the mapping.
|
||||
*/
|
||||
static QueueHandle_t iso_critical_queue;
|
||||
static QueueHandle_t iso_normal_queue;
|
||||
static QueueHandle_t iso_floodable_queue;
|
||||
static QueueSetHandle_t iso_queue_set;
|
||||
static BT_ISO_CTRL_BSS_ATTR QueueHandle_t iso_critical_queue;
|
||||
static BT_ISO_CTRL_BSS_ATTR QueueHandle_t iso_normal_queue;
|
||||
static BT_ISO_CTRL_BSS_ATTR QueueHandle_t iso_floodable_queue;
|
||||
static BT_ISO_CTRL_BSS_ATTR QueueSetHandle_t iso_queue_set;
|
||||
|
||||
static TaskHandle_t iso_task_handle;
|
||||
static BT_ISO_CTRL_BSS_ATTR TaskHandle_t iso_task_handle;
|
||||
|
||||
extern void bt_le_timer_handle_event(void *arg);
|
||||
|
||||
#if CONFIG_BT_ISO_DISPATCH_MONITOR
|
||||
/* Per-type dispatch timing, indexed by iso_queue_item_type. Written only by
|
||||
* iso_task (single writer); read by bt_le_iso_dispatch_stats_dump. */
|
||||
static struct iso_dispatch_stats {
|
||||
static BT_ISO_CTRL_BSS_ATTR struct iso_dispatch_stats {
|
||||
int64_t max_us;
|
||||
uint32_t count;
|
||||
uint32_t slow_count;
|
||||
|
||||
@@ -55,11 +55,13 @@ LOG_MODULE_REGISTER(ISO_CORE, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
|
||||
#define iso_chan(_iso) ((_iso)->iso.chan);
|
||||
|
||||
struct bt_conn iso_conns[CONFIG_BT_ISO_MAX_CHAN];
|
||||
/* ISO connection state, not the SDU buffers: task-context only, no ISR/DMA,
|
||||
* so PSRAM-eligible despite the per-SDU lookups. */
|
||||
BT_ISO_EXT_RAM_BSS_ATTR struct bt_conn iso_conns[CONFIG_BT_ISO_MAX_CHAN];
|
||||
|
||||
/* TODO: Allow more than one server? */
|
||||
#if defined(CONFIG_BT_ISO_CENTRAL)
|
||||
struct bt_iso_cig cigs[CONFIG_BT_ISO_MAX_CIG];
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct bt_iso_cig cigs[CONFIG_BT_ISO_MAX_CIG];
|
||||
|
||||
static struct bt_iso_cig *get_cig(const struct bt_iso_chan *iso_chan);
|
||||
static int hci_le_create_cis(const struct bt_iso_connect_param *param, size_t count);
|
||||
@@ -67,13 +69,13 @@ static int hci_le_create_cis(const struct bt_iso_connect_param *param, size_t co
|
||||
#endif /* CONFIG_BT_ISO_CENTRAL */
|
||||
|
||||
#if defined(CONFIG_BT_ISO_PERIPHERAL)
|
||||
static struct bt_iso_server *iso_server;
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct bt_iso_server *iso_server;
|
||||
|
||||
static struct bt_conn *bt_conn_add_iso(struct bt_conn *acl);
|
||||
#endif /* CONFIG_BT_ISO_PERIPHERAL */
|
||||
|
||||
#if defined(CONFIG_BT_ISO_BROADCAST)
|
||||
struct bt_iso_big bigs[CONFIG_BT_ISO_MAX_BIG];
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR struct bt_iso_big bigs[CONFIG_BT_ISO_MAX_BIG];
|
||||
|
||||
static struct bt_iso_big *lookup_big_by_handle(uint8_t big_handle);
|
||||
#endif /* CONFIG_BT_ISO_BROADCAST */
|
||||
@@ -2256,7 +2258,7 @@ int bt_iso_chan_connect(const struct bt_iso_connect_param *param, size_t count)
|
||||
#endif /* CONFIG_BT_ISO_UNICAST */
|
||||
|
||||
#if defined(CONFIG_BT_ISO_BROADCAST)
|
||||
static sys_slist_t iso_big_cbs = SYS_SLIST_STATIC_INIT(&iso_big_cbs);
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR sys_slist_t iso_big_cbs;
|
||||
|
||||
static struct bt_iso_big *lookup_big_by_handle(uint8_t big_handle)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -18,10 +19,12 @@
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/types.h>
|
||||
|
||||
#include "utils/iso_attr.h"
|
||||
|
||||
const char *bt_hex(const void *buf, size_t len)
|
||||
{
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
static char str[129];
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR char str[129];
|
||||
const uint8_t *b = buf;
|
||||
size_t i;
|
||||
|
||||
@@ -39,7 +42,7 @@ const char *bt_hex(const void *buf, size_t len)
|
||||
|
||||
const char *bt_addr_str(const bt_addr_t *addr)
|
||||
{
|
||||
static char str[BT_ADDR_STR_LEN];
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR char str[BT_ADDR_STR_LEN];
|
||||
|
||||
bt_addr_to_str(addr, str, sizeof(str));
|
||||
|
||||
@@ -48,7 +51,7 @@ const char *bt_addr_str(const bt_addr_t *addr)
|
||||
|
||||
const char *bt_addr_le_str(const bt_addr_le_t *addr)
|
||||
{
|
||||
static char str[BT_ADDR_LE_STR_LEN];
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR char str[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(addr, str, sizeof(str));
|
||||
|
||||
@@ -57,7 +60,7 @@ const char *bt_addr_le_str(const bt_addr_le_t *addr)
|
||||
|
||||
const char *bt_uuid_str(const struct bt_uuid *uuid)
|
||||
{
|
||||
static char str[BT_UUID_STR_LEN];
|
||||
static BT_ISO_EXT_RAM_BSS_ATTR char str[BT_UUID_STR_LEN];
|
||||
|
||||
bt_uuid_to_str(uuid, str, sizeof(str));
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_attr.h"
|
||||
|
||||
/* Static (.bss) placement markers for the esp_ble_iso component.
|
||||
*
|
||||
* These sources compile into libbt.a, where object names collide
|
||||
* (common/iso.c vs adapter/bluedroid/iso.c vs host/iso/iso.c, etc.), so a
|
||||
* linker fragment cannot target them cleanly - placement is done per-variable
|
||||
* via these attributes.
|
||||
*
|
||||
* - BT_ISO_EXT_RAM_BSS_ATTR: eligible for external SPIRAM (cold or
|
||||
* control-plane, task-context, non-DMA). Moves to PSRAM when
|
||||
* BT_ISO_BSS_SEG_EXTERNAL_MEMORY is set, else expands to nothing. Safe
|
||||
* because esp_ble_iso registers no IRAM ISR (nothing here is touched with
|
||||
* the flash cache disabled).
|
||||
*
|
||||
* - BT_ISO_CTRL_BSS_ATTR: must stay in internal DRAM - currently cannot go
|
||||
* to PSRAM. Marker only (expands to nothing = default internal placement).
|
||||
* Used for the real-time ISO data path and anything DMA-reachable or
|
||||
* otherwise unsafe/uncertain in PSRAM. Kernel-object wrappers (k_sem/k_mutex)
|
||||
* are marked CTRL too - synchronization primitives taken on hot/host paths
|
||||
* (incl. the ISO dispatch), kept internal for determinism (and tiny anyway).
|
||||
* net_buf pools and initialized (.data) statistics also stay internal but need
|
||||
* no marker (auto-named .bss cannot take a per-var attribute; .data cannot
|
||||
* use EXT_RAM_BSS).
|
||||
*
|
||||
* esp_ble_audio has its own equivalent (common/audio_attr.h, BT_AUDIO_* macros),
|
||||
* kept separate for the audio layer. The distinct name and include prefix
|
||||
* (utils/ here vs common/ there) avoid any collision on the bt component's shared
|
||||
* flat include path.
|
||||
*/
|
||||
#if CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY
|
||||
#define BT_ISO_EXT_RAM_BSS_ATTR EXT_RAM_BSS_ATTR
|
||||
#else
|
||||
#define BT_ISO_EXT_RAM_BSS_ATTR
|
||||
#endif
|
||||
|
||||
#define BT_ISO_CTRL_BSS_ATTR
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Heap allocation policy for LE Audio. Every runtime allocation should use one
|
||||
* of these two so intent is explicit (a bare malloc/calloc reads as "not yet
|
||||
* classified" and risks being rerouted by a later PSRAM sweep). Both pin the
|
||||
* allocation to a memory type with heap_caps, independent of the platform's
|
||||
* default malloc policy (which, under CONFIG_SPIRAM_USE_MALLOC, may itself hand
|
||||
* out PSRAM).
|
||||
*
|
||||
* - bt_le_ext_*: control-plane data (GATT/GAP event marshalling, profile setup,
|
||||
* per-conn state, ...). Placed in external SPIRAM (MALLOC_CAP_SPIRAM) when
|
||||
* BT_ISO_HEAP_EXTERNAL_MEMORY is set, else the internal heap. Returns NULL on
|
||||
* SPIRAM exhaustion (no internal fallback).
|
||||
*
|
||||
* - bt_le_int_*: the real-time ISO TX/RX data path (SDU packet buffers handed to
|
||||
* the controller, per-SDU nodes/events). Forced to internal DRAM
|
||||
* (MALLOC_CAP_INTERNAL): controller/DMA-reachable and latency-critical, so it
|
||||
* must never land in PSRAM. Plain malloc/calloc would NOT guarantee this -
|
||||
* under CONFIG_SPIRAM_USE_MALLOC they can return PSRAM.
|
||||
*
|
||||
* Both are freed with plain free() (valid for heap_caps allocations in ESP-IDF).
|
||||
*/
|
||||
void *bt_le_ext_malloc(size_t size);
|
||||
void *bt_le_ext_calloc(size_t n, size_t size);
|
||||
void *bt_le_int_malloc(size_t size);
|
||||
void *bt_le_int_calloc(size_t n, size_t size);
|
||||
-17
@@ -28,23 +28,6 @@
|
||||
|
||||
LOG_MODULE_REGISTER(ISO_UTILS, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
|
||||
struct bt_dev bt_dev;
|
||||
|
||||
uint8_t bt_get_phy(uint8_t hci_phy)
|
||||
{
|
||||
switch (hci_phy) {
|
||||
case BT_HCI_LE_PHY_1M:
|
||||
return BT_GAP_LE_PHY_1M;
|
||||
case BT_HCI_LE_PHY_2M:
|
||||
return BT_GAP_LE_PHY_2M;
|
||||
case BT_HCI_LE_PHY_CODED:
|
||||
return BT_GAP_LE_PHY_CODED;
|
||||
default:
|
||||
LOG_WRN("UnknownHciPhy[%u]", hci_phy);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Query the active host's persistent bond store (the old local key_pool was never
|
||||
* populated, so bt_le_bond_exists() was always false). `id` ignored (single identity);
|
||||
* addresses stay in native host byte order. */
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
#include "utils/mem.h"
|
||||
|
||||
void *bt_le_ext_malloc(size_t size)
|
||||
{
|
||||
#if CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY
|
||||
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
#else
|
||||
return malloc(size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *bt_le_ext_calloc(size_t n, size_t size)
|
||||
{
|
||||
#if CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY
|
||||
return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
#else
|
||||
return calloc(n, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ISO TX/RX data path: force internal DRAM. Plain malloc/calloc follow IDF's
|
||||
* default heap policy and could return PSRAM under CONFIG_SPIRAM_USE_MALLOC;
|
||||
* MALLOC_CAP_INTERNAL guarantees internal regardless. */
|
||||
void *bt_le_int_malloc(size_t size)
|
||||
{
|
||||
return heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
}
|
||||
|
||||
void *bt_le_int_calloc(size_t n, size_t size)
|
||||
{
|
||||
return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
}
|
||||
Reference in New Issue
Block a user