diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 4b292e45ceb..9fe97c472fe 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -70,6 +70,7 @@ if(CONFIG_IDF_DOC_BUILD OR CONFIG_BT_ENABLED) add_subdirectory(esp_ble_audio) list(APPEND srcs ${ble_audio_srcs}) list(APPEND include_dirs ${ble_audio_include_dirs}) + list(APPEND ldscripts ${ble_audio_ldscripts}) # BLE profiles (host-agnostic profile cores + shared profile infrastructure) add_subdirectory(ble_profiles) diff --git a/components/bt/esp_ble_audio/CMakeLists.txt b/components/bt/esp_ble_audio/CMakeLists.txt index fcc052ee98d..8cdaff9965a 100644 --- a/components/bt/esp_ble_audio/CMakeLists.txt +++ b/components/bt/esp_ble_audio/CMakeLists.txt @@ -11,6 +11,7 @@ endfunction() set(ble_audio_srcs "" PARENT_SCOPE) set(ble_audio_include_dirs "" PARENT_SCOPE) +set(ble_audio_ldscripts "" PARENT_SCOPE) # API headers that are used in the docs are also compiled # even if CONFIG_BT_ENABLED=n as long as CONFIG_IDF_DOC_BUILD=y @@ -176,3 +177,4 @@ endif() # Export the variables to the parent scope set(ble_audio_srcs "${ble_audio_srcs}" PARENT_SCOPE) set(ble_audio_include_dirs "${ble_audio_include_dirs}" PARENT_SCOPE) +set(ble_audio_ldscripts "${CMAKE_CURRENT_LIST_DIR}/linker.lf" PARENT_SCOPE) diff --git a/components/bt/esp_ble_audio/Kconfig.in b/components/bt/esp_ble_audio/Kconfig.in index ab5be28b4cd..28ce2fdd637 100644 --- a/components/bt/esp_ble_audio/Kconfig.in +++ b/components/bt/esp_ble_audio/Kconfig.in @@ -99,6 +99,40 @@ menu "OTS Options" rsource "host/services/ots/Kconfig.ots.in" endmenu +config BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY + bool "Place BLE Audio .bss segment in external SPIRAM" + depends on BT_ISO_BSS_SEG_EXTERNAL_MEMORY + default n + help + Place the zero-initialized (.bss) static data of the BLE Audio + profiles in external SPIRAM instead of internal DRAM. Covers both the + esp_ble_audio IDF source files and the .bss of the prebuilt BLE Audio + library (libble_audio.a), the latter relocated via a linker fragment. + + Depends on BT_ISO_BSS_SEG_EXTERNAL_MEMORY: the audio layer sits on top + of the ISO/host layer, so its static data is moved to SPIRAM only when + the ISO layer's is, keeping the placement coherent. + + Requires SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY. Only .bss is moved; + initialized (.data) statistics stay internal. + +config BT_AUDIO_HEAP_EXTERNAL_MEMORY + bool "Place BLE Audio heap allocations in external SPIRAM" + depends on BT_ISO_HEAP_EXTERNAL_MEMORY + default n + help + Route BLE Audio runtime heap allocations to external SPIRAM instead of + internal DRAM. Covers both the esp_ble_audio profiles and the prebuilt + BLE Audio library (libble_audio.a): both allocate via idf_ext_calloc / + idf_ext_malloc, which this switch points at the ISO layer's SPIRAM + helper (heap_caps_*(MALLOC_CAP_SPIRAM)). + + Depends on BT_ISO_HEAP_EXTERNAL_MEMORY: the audio allocator hook reuses + the ISO layer's helper, available only when the ISO layer routes to + SPIRAM too. + + On SPIRAM exhaustion allocations return NULL (no internal fallback). + config BT_AUDIO_NO_LOG bool "Disable BLE Audio Lib Debug Log" default n diff --git a/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/cas.c b/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/cas.c index 2a93afc5512..00ce6a82de2 100644 --- a/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/cas.c +++ b/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/cas.c @@ -16,13 +16,14 @@ #include "bluedroid/server.h" #include "common/host.h" +#include "common/audio_attr.h" #include "../../../lib/include/audio.h" LOG_MODULE_REGISTER(LEA_CAS, CONFIG_BT_ISO_LOG_LEVEL); #if CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER -static struct inc_svc_inst inc_csis_inst; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct inc_svc_inst inc_csis_inst; struct inc_svc_inst *cas_not_included_inst(void) { diff --git a/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/csis.c b/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/csis.c index 19e2be17869..02068fbfb07 100644 --- a/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/csis.c +++ b/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/csis.c @@ -16,6 +16,7 @@ #include "bluedroid/server.h" #include "common/host.h" +#include "common/audio_attr.h" #include "../../../lib/include/audio.h" @@ -23,11 +24,11 @@ LOG_MODULE_REGISTER(LEA_CSIS, CONFIG_BT_ISO_LOG_LEVEL); #define CSIS_SVC_COUNT CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT -static struct csis_inst { +static BT_AUDIO_EXT_RAM_BSS_ATTR struct csis_inst { struct bt_gatt_service *svc_p; } csis_insts[CSIS_SVC_COUNT]; -static uint8_t csis_svc_count; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t csis_svc_count; int bt_le_bluedroid_csis_init(void *svc, uint8_t count) { diff --git a/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/mcs.c b/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/mcs.c index 6869b474c04..5f0d815f581 100644 --- a/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/mcs.c +++ b/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/mcs.c @@ -16,6 +16,7 @@ #include "bluedroid/server.h" #include "common/host.h" +#include "common/audio_attr.h" #include "../../../lib/include/audio.h" @@ -29,7 +30,7 @@ LOG_MODULE_REGISTER(LEA_MCS, CONFIG_BT_ISO_LOG_LEVEL); /* GMCS includes a single secondary OTS instance. Mirrors the CAS->CSIS included- * secondary pattern: create the secondary before the primary so the include * declaration in the GMCS table resolves to OTS's live handle. */ -static struct inc_svc_inst inc_ots_inst; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct inc_svc_inst inc_ots_inst; struct inc_svc_inst *gmcs_not_included_inst(void) { diff --git a/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/mics.c b/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/mics.c index b8941321600..d1e79e02ed8 100644 --- a/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/mics.c +++ b/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/mics.c @@ -18,15 +18,17 @@ #include "common/host.h" +#include "common/audio_attr.h" + #include "../../../lib/include/audio.h" LOG_MODULE_REGISTER(LEA_MICS, CONFIG_BT_ISO_LOG_LEVEL); #define AICS_INST_COUNT CONFIG_BT_MICP_MIC_DEV_AICS_INSTANCE_COUNT -static uint8_t inc_aics_svc_count; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t inc_aics_svc_count; -static struct inc_svc_inst inc_aics_insts[AICS_INST_COUNT]; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct inc_svc_inst inc_aics_insts[AICS_INST_COUNT]; struct inc_svc_inst *mics_not_included_inst(void) { diff --git a/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/vcs.c b/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/vcs.c index af5674646d6..0dd65e7e920 100644 --- a/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/vcs.c +++ b/components/bt/esp_ble_audio/host/adapter/bluedroid/profiles/vcs.c @@ -17,6 +17,7 @@ #include "bluedroid/server.h" #include "common/host.h" +#include "common/audio_attr.h" #include "../../../lib/include/audio.h" @@ -25,11 +26,11 @@ LOG_MODULE_REGISTER(LEA_VCS, CONFIG_BT_ISO_LOG_LEVEL); #define VOCS_INST_COUNT CONFIG_BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT #define AICS_INST_COUNT CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT -static uint8_t inc_vocs_svc_count; -static uint8_t inc_aics_svc_count; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t inc_vocs_svc_count; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t inc_aics_svc_count; -static struct inc_svc_inst inc_vocs_insts[VOCS_INST_COUNT]; -static struct inc_svc_inst inc_aics_insts[AICS_INST_COUNT]; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct inc_svc_inst inc_vocs_insts[VOCS_INST_COUNT]; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct inc_svc_inst inc_aics_insts[AICS_INST_COUNT]; struct inc_svc_inst *vcs_not_included_inst(void) { diff --git a/components/bt/esp_ble_audio/host/adapter/bluedroid/server.c b/components/bt/esp_ble_audio/host/adapter/bluedroid/server.c index b7d306eb678..78f1e73718b 100644 --- a/components/bt/esp_ble_audio/host/adapter/bluedroid/server.c +++ b/components/bt/esp_ble_audio/host/adapter/bluedroid/server.c @@ -23,14 +23,15 @@ #include "bluedroid/server.h" #include "common/host.h" +#include "common/audio_attr.h" LOG_MODULE_REGISTER(LEA_GSRV, CONFIG_BT_ISO_LOG_LEVEL); -static uint8_t svc_in_progress; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t svc_in_progress; -static uint16_t inc_svc_handle; -static uint16_t svc_handle; -static uint16_t chrc_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t inc_svc_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t svc_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t chrc_handle; static bool is_primary_svc(void) { @@ -413,12 +414,12 @@ static uint8_t get_svc_inst_id(uint16_t svc_uuid) * For LE Audio, some service could have multiple instances. */ - static uint8_t aics_count; - static uint8_t csis_count; - static uint8_t vocs_count; - static uint8_t mcs_count; - static uint8_t ots_count; - static uint8_t tbs_count; + static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t aics_count; + static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t csis_count; + static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t vocs_count; + static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t mcs_count; + static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t ots_count; + static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t tbs_count; switch (svc_uuid) { case BT_UUID_AICS_VAL: diff --git a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/ascs.c b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/ascs.c index 2b82fdd6145..dfba6d7a868 100644 --- a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/ascs.c +++ b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/ascs.c @@ -26,6 +26,7 @@ #include "nimble/server.h" #include "common/host.h" +#include "common/audio_attr.h" #include "../../../lib/include/audio.h" @@ -35,9 +36,9 @@ static const ble_uuid16_t ascs_uuid_ase_cp = BLE_UUID16_INIT(BT_UUID_ASCS_ASE_CP static const ble_uuid16_t ascs_uuid_ase_snk = BLE_UUID16_INIT(BT_UUID_ASCS_ASE_SNK_VAL); static const ble_uuid16_t ascs_uuid_ase_src = BLE_UUID16_INIT(BT_UUID_ASCS_ASE_SRC_VAL); -static uint16_t ase_control_point_handle; -static uint16_t ase_snk_handle[CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT]; -static uint16_t ase_src_handle[CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT]; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t ase_control_point_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t ase_snk_handle[CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT]; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t ase_src_handle[CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT]; static struct ble_gatt_svc_def gatt_svc_ascs[] = { { @@ -209,7 +210,7 @@ int bt_le_nimble_ascs_init(void) LOG_DBG("[N]AscsInit[%u]", chr_count); - gatt_svc_ascs[0].characteristics = calloc(chr_count, sizeof(struct ble_gatt_chr_def)); + gatt_svc_ascs[0].characteristics = bt_le_ext_calloc(chr_count, sizeof(struct ble_gatt_chr_def)); assert(gatt_svc_ascs[0].characteristics); ascs_svc_add_ase_cp_chr((void *)(gatt_svc_ascs[0].characteristics + 0)); diff --git a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/bass.c b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/bass.c index e0499d5e2d0..375659993e8 100644 --- a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/bass.c +++ b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/bass.c @@ -26,6 +26,7 @@ #include "nimble/server.h" #include "common/host.h" +#include "common/audio_attr.h" #include "../../../lib/include/audio.h" @@ -34,8 +35,8 @@ LOG_MODULE_REGISTER(LEA_BASS, CONFIG_BT_ISO_LOG_LEVEL); static const ble_uuid16_t bass_uuid_control_point = BLE_UUID16_INIT(BT_UUID_BASS_CONTROL_POINT_VAL); static const ble_uuid16_t bass_uuid_recv_state = BLE_UUID16_INIT(BT_UUID_BASS_RECV_STATE_VAL); -static uint16_t bass_control_point_handle; -static uint16_t bass_recv_state_handle[CONFIG_BT_BAP_SCAN_DELEGATOR_RECV_STATE_COUNT]; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t bass_control_point_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t bass_recv_state_handle[CONFIG_BT_BAP_SCAN_DELEGATOR_RECV_STATE_COUNT]; static struct ble_gatt_svc_def gatt_svc_bass[] = { { @@ -179,7 +180,7 @@ int bt_le_nimble_bass_init(void) LOG_DBG("[N]BassInit[%u]", chr_count); - gatt_svc_bass->characteristics = calloc(chr_count, sizeof(struct ble_gatt_chr_def)); + gatt_svc_bass->characteristics = bt_le_ext_calloc(chr_count, sizeof(struct ble_gatt_chr_def)); assert(gatt_svc_bass->characteristics); bass_svc_add_control_point_chr((void *)(gatt_svc_bass->characteristics + 0)); diff --git a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/cas.c b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/cas.c index db2f25527c7..d89ae99da8e 100644 --- a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/cas.c +++ b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/cas.c @@ -18,6 +18,7 @@ #include "host/ble_gatt.h" #include "common/host.h" +#include "common/audio_attr.h" #include "../../../lib/include/audio.h" @@ -26,7 +27,7 @@ LOG_MODULE_REGISTER(LEA_CAS, CONFIG_BT_ISO_LOG_LEVEL); #if CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER extern struct ble_gatt_svc_def *cas_get_included_csis(void *csis_svc_p); -static struct bt_gatt_service *inc_csis_svc; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct bt_gatt_service *inc_csis_svc; static struct ble_gatt_svc_def *cas_inc_svcs[] = { NULL, diff --git a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/csis.c b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/csis.c index fa803b60c51..7b2533a77e1 100644 --- a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/csis.c +++ b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/csis.c @@ -28,6 +28,7 @@ #include "nimble/server.h" #include "common/host.h" +#include "common/audio_attr.h" #include "../../../lib/include/audio.h" @@ -75,7 +76,7 @@ static const ble_uuid16_t csis_uuid_set_lock = BLE_UUID16_INIT(BT_UUID_CSIS_SET_ static const ble_uuid16_t csis_uuid_rank = BLE_UUID16_INIT(BT_UUID_CSIS_RANK_VAL); static const ble_uuid16_t csis_uuid_set_name = BLE_UUID16_INIT(BT_UUID_CSIS_SET_NAME_VAL); -static struct csis_inst { +static BT_AUDIO_EXT_RAM_BSS_ATTR struct csis_inst { struct bt_gatt_service *svc_p; uint16_t sirk_handle; uint16_t set_size_handle; @@ -84,10 +85,10 @@ static struct csis_inst { uint16_t set_name_handle; } csis_insts[CSIS_SVC_COUNT]; -static uint8_t csis_svc_count; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t csis_svc_count; /* Extra one for terminating the CSIS service array */ -static struct ble_gatt_svc_def gatt_svc_csis[CSIS_SVC_COUNT + 1]; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct ble_gatt_svc_def gatt_svc_csis[CSIS_SVC_COUNT + 1]; struct ble_gatt_svc_def *cas_get_included_csis(void *csis_svc_p) { @@ -244,7 +245,7 @@ static void csis_svc_init(struct csis_inst *inst, svc->uuid = &csis_uuid_svc.u; svc->includes = NULL; - svc->characteristics = calloc(CSIS_CHR_COUNT, sizeof(struct ble_gatt_chr_def)); + svc->characteristics = bt_le_ext_calloc(CSIS_CHR_COUNT, sizeof(struct ble_gatt_chr_def)); assert(svc->characteristics); /* Build the NimBLE characteristics from the ones actually present in the Zephyr diff --git a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/gmas.c b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/gmas.c index 525923fa7db..9552de1c6eb 100644 --- a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/gmas.c +++ b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/gmas.c @@ -24,6 +24,7 @@ #include "nimble/server.h" #include "common/host.h" +#include "common/audio_attr.h" #include "../../../lib/include/audio.h" @@ -35,9 +36,9 @@ LOG_MODULE_REGISTER(LEA_GMAS, CONFIG_BT_ISO_LOG_LEVEL); #define GMAS_MAX_CHRS (1 + 4) /* GMAP Role + up to one feature char per role */ static const ble_uuid16_t gmas_svc_uuid = BLE_UUID16_INIT(BT_UUID_GMAS_VAL); -static ble_uuid16_t gmas_chr_uuids[GMAS_MAX_CHRS]; -static struct ble_gatt_chr_def gmas_chrs[GMAS_MAX_CHRS + 1]; -static struct ble_gatt_svc_def gatt_svc_gmas[2]; +static BT_AUDIO_EXT_RAM_BSS_ATTR ble_uuid16_t gmas_chr_uuids[GMAS_MAX_CHRS]; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct ble_gatt_chr_def gmas_chrs[GMAS_MAX_CHRS + 1]; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct ble_gatt_svc_def gatt_svc_gmas[2]; /* Mirror the lib's GMAS table (primary + role char + registered feature chars, each value attr following a 0x2803 declaration) into the NimBLE service def. */ diff --git a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/has.c b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/has.c index 4eeff2d4343..cabc09f500c 100644 --- a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/has.c +++ b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/has.c @@ -26,6 +26,7 @@ #include "nimble/server.h" #include "common/host.h" +#include "common/audio_attr.h" #include "../../../lib/include/audio.h" @@ -35,9 +36,9 @@ static const ble_uuid16_t has_uuid_features = BLE_UUID16_INIT(BT_UUID_HAS_HEARIN static const ble_uuid16_t has_uuid_control_point = BLE_UUID16_INIT(BT_UUID_HAS_PRESET_CONTROL_POINT_VAL); static const ble_uuid16_t has_uuid_preset_index = BLE_UUID16_INIT(BT_UUID_HAS_ACTIVE_PRESET_INDEX_VAL); -static uint16_t has_features_handle; -static uint16_t has_control_point_handle; -static uint16_t has_preset_index_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t has_features_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t has_control_point_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t has_preset_index_handle; static struct ble_gatt_svc_def gatt_svc_has[] = { { @@ -204,7 +205,7 @@ int bt_le_nimble_has_init(void) LOG_DBG("[N]HasInit[%u]", chr_count); - gatt_svc_has->characteristics = calloc(chr_count, sizeof(struct ble_gatt_chr_def)); + gatt_svc_has->characteristics = bt_le_ext_calloc(chr_count, sizeof(struct ble_gatt_chr_def)); assert(gatt_svc_has->characteristics); has_svc_add_features_chr((void *)(gatt_svc_has->characteristics + 0)); diff --git a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/mcs.c b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/mcs.c index c5e1e351517..80fde052b30 100644 --- a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/mcs.c +++ b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/mcs.c @@ -31,6 +31,7 @@ #include "nimble/server.h" #include "common/host.h" +#include "common/audio_attr.h" #include "../../../lib/include/audio.h" @@ -76,21 +77,21 @@ LOG_MODULE_REGISTER(LEA_MCS, CONFIG_BT_ISO_LOG_LEVEL); #define INC_OTS_CHR_FLAGS_LIST_CP \ (BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_INDICATE | BLE_GATT_CHR_F_WRITE_ENC) -static uint8_t inc_ots_svc_count; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t inc_ots_svc_count; -static struct bt_ots *ots; -static uint16_t inc_ots_chr_feature_handle; -static uint16_t inc_ots_chr_name_handle; -static uint16_t inc_ots_chr_type_handle; -static uint16_t inc_ots_chr_size_handle; -static uint16_t inc_ots_chr_id_handle; -static uint16_t inc_ots_chr_props_handle; -static uint16_t inc_ots_chr_action_cp_handle; -static uint16_t inc_ots_chr_list_cp_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct bt_ots *ots; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t inc_ots_chr_feature_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t inc_ots_chr_name_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t inc_ots_chr_type_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t inc_ots_chr_size_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t inc_ots_chr_id_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t inc_ots_chr_props_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t inc_ots_chr_action_cp_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t inc_ots_chr_list_cp_handle; -static struct ble_gatt_svc_def *gatt_svc_inc_ots; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct ble_gatt_svc_def *gatt_svc_inc_ots; -static struct ble_gatt_svc_def **gmcs_inc_svcs; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct ble_gatt_svc_def **gmcs_inc_svcs; static const ble_uuid16_t inc_ots_uuid_svc = BLE_UUID16_INIT(BT_UUID_OTS_VAL); static const ble_uuid16_t inc_ots_uuid_feature = BLE_UUID16_INIT(BT_UUID_OTS_FEATURE_VAL); @@ -103,34 +104,34 @@ static const ble_uuid16_t inc_ots_uuid_action_cp = BLE_UUID16_INIT(BT_UUID_OTS_A static const ble_uuid16_t inc_ots_uuid_list_cp = BLE_UUID16_INIT(BT_UUID_OTS_LIST_CP_VAL); #endif /* CONFIG_BT_OTS */ -static uint16_t mcs_player_name_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_player_name_handle; #if CONFIG_BT_OTS -static uint16_t mcs_icon_obj_id_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_icon_obj_id_handle; #endif /* CONFIG_BT_OTS */ -static uint16_t mcs_icon_url_handle; -static uint16_t mcs_track_changed_handle; -static uint16_t mcs_track_title_handle; -static uint16_t mcs_track_duration_handle; -static uint16_t mcs_track_position_handle; -static uint16_t mcs_playback_speed_handle; -static uint16_t mcs_seeking_speed_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_icon_url_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_track_changed_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_track_title_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_track_duration_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_track_position_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_playback_speed_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_seeking_speed_handle; #if CONFIG_BT_OTS -static uint16_t mcs_track_segments_obj_id_handle; -static uint16_t mcs_current_track_obj_id_handle; -static uint16_t mcs_next_track_obj_id_handle; -static uint16_t mcs_parent_group_obj_id_handle; -static uint16_t mcs_current_group_obj_id_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_track_segments_obj_id_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_current_track_obj_id_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_next_track_obj_id_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_parent_group_obj_id_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_current_group_obj_id_handle; #endif /* CONFIG_BT_OTS */ -static uint16_t mcs_playing_order_handle; -static uint16_t mcs_playing_orders_handle; -static uint16_t mcs_media_state_handle; -static uint16_t mcs_media_control_point_handle; -static uint16_t mcs_media_control_opcodes_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_playing_order_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_playing_orders_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_media_state_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_media_control_point_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_media_control_opcodes_handle; #if CONFIG_BT_OTS -static uint16_t mcs_search_control_point_handle; -static uint16_t mcs_search_results_obj_id_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_search_control_point_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mcs_search_results_obj_id_handle; #endif /* CONFIG_BT_OTS */ -static uint16_t ccid_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t ccid_handle; static struct ble_gatt_svc_def gatt_svc_gmcs[] = { { @@ -355,7 +356,7 @@ static struct ble_gatt_svc_def gatt_svc_gmcs[] = { /* Discrete MCS (0x1848): INSTANCE_COUNT instances sharing GMCS's characteristic table * and OTS include (val_handle vars are write-only here, so sharing is safe). Built in * bt_le_nimble_mcs_init as an N+1 NULL-terminated array for the GATT DB lifetime. */ -static struct ble_gatt_svc_def *gatt_svc_mcs; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct ble_gatt_svc_def *gatt_svc_mcs; static const ble_uuid16_t mcs_uuid_svc = BLE_UUID16_INIT(BT_UUID_MCS_VAL); #if CONFIG_BT_OTS @@ -574,7 +575,7 @@ static int inc_ots_svc_init(void) svc->includes = NULL; /* An additional characteristic consist of all 0s indicating end of characteristics */ - svc->characteristics = calloc(INC_OTS_CHR_COUNT + 1, sizeof(struct ble_gatt_chr_def)); + svc->characteristics = bt_le_ext_calloc(INC_OTS_CHR_COUNT + 1, sizeof(struct ble_gatt_chr_def)); assert(svc->characteristics); /* Characteristic - OTS Feature */ @@ -640,11 +641,11 @@ int bt_le_nimble_gmcs_init(bool ots_included) inc_ots_svc_count = 1; /* Extra one for terminating the included service array with NULL */ - gmcs_inc_svcs = calloc(2, sizeof(struct ble_gatt_svc_def *)); + gmcs_inc_svcs = bt_le_ext_calloc(2, sizeof(struct ble_gatt_svc_def *)); assert(gmcs_inc_svcs); /* Extra one for terminating the OTS service array */ - gatt_svc_inc_ots = calloc(2, sizeof(struct ble_gatt_svc_def)); + gatt_svc_inc_ots = bt_le_ext_calloc(2, sizeof(struct ble_gatt_svc_def)); assert(gatt_svc_inc_ots); ots = lib_mcs_get_ots(); @@ -809,7 +810,7 @@ int bt_le_nimble_mcs_init(void) /* One ble_gatt_svc_def per instance + a zeroed terminator. Persists for the * GATT DB lifetime (NimBLE references these defs until ble_gatts_start). */ - gatt_svc_mcs = calloc(count + 1, sizeof(struct ble_gatt_svc_def)); + gatt_svc_mcs = bt_le_ext_calloc(count + 1, sizeof(struct ble_gatt_svc_def)); assert(gatt_svc_mcs); for (int i = 0; i < count; i++) { diff --git a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/mics.c b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/mics.c index 472729d2a3e..714d60916f2 100644 --- a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/mics.c +++ b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/mics.c @@ -26,6 +26,7 @@ #include "nimble/server.h" #include "common/host.h" +#include "common/audio_attr.h" #include "../../../lib/include/audio.h" @@ -52,9 +53,9 @@ LOG_MODULE_REGISTER(LEA_MICS, CONFIG_BT_ISO_LOG_LEVEL); (BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_WRITE_NO_RSP | \ BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC) -static uint8_t inc_aics_svc_count; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t inc_aics_svc_count; -static struct inc_aics_inst { +static BT_AUDIO_EXT_RAM_BSS_ATTR struct inc_aics_inst { struct bt_gatt_service *svc_p; uint16_t state_handle; uint16_t gain_handle; @@ -64,7 +65,7 @@ static struct inc_aics_inst { uint16_t description_handle; } *inc_aics_insts; -static struct ble_gatt_svc_def *gatt_svc_inc_aics; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct ble_gatt_svc_def *gatt_svc_inc_aics; static const ble_uuid16_t inc_aics_uuid_svc = BLE_UUID16_INIT(BT_UUID_AICS_VAL); static const ble_uuid16_t inc_aics_uuid_state = BLE_UUID16_INIT(BT_UUID_AICS_STATE_VAL); @@ -74,9 +75,9 @@ static const ble_uuid16_t inc_aics_uuid_status = BLE_UUID16_INIT(BT_UUID_AICS_IN static const ble_uuid16_t inc_aics_uuid_control = BLE_UUID16_INIT(BT_UUID_AICS_CONTROL_VAL); static const ble_uuid16_t inc_aics_uuid_description = BLE_UUID16_INIT(BT_UUID_AICS_DESCRIPTION_VAL); -static struct ble_gatt_svc_def **mics_inc_svcs; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct ble_gatt_svc_def **mics_inc_svcs; -static uint16_t mics_mute_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t mics_mute_handle; static struct ble_gatt_svc_def gatt_svc_mics[] = { { @@ -305,7 +306,7 @@ static void inc_aics_svc_init(struct inc_aics_inst *inst, svc->uuid = &inc_aics_uuid_svc.u; svc->includes = NULL; - svc->characteristics = calloc(INC_AICS_CHR_COUNT, sizeof(struct ble_gatt_chr_def)); + svc->characteristics = bt_le_ext_calloc(INC_AICS_CHR_COUNT, sizeof(struct ble_gatt_chr_def)); assert(svc->characteristics); /* Characteristic - Audio Input State */ @@ -369,16 +370,16 @@ int bt_le_nimble_mics_init(void *micp_inc) /* Extra one for terminating the included service array with NULL */ inc_count = inc_aics_svc_count + 1; - mics_inc_svcs = calloc(inc_count, sizeof(struct ble_gatt_svc_def *)); + mics_inc_svcs = bt_le_ext_calloc(inc_count, sizeof(struct ble_gatt_svc_def *)); assert(mics_inc_svcs); /* MICS may include zero or more instances of AICS */ if (inc_aics_svc_count) { - inc_aics_insts = calloc(inc_aics_svc_count, sizeof(struct inc_aics_inst)); + inc_aics_insts = bt_le_ext_calloc(inc_aics_svc_count, sizeof(struct inc_aics_inst)); assert(inc_aics_insts); /* Extra one for terminating the AICS service array */ - gatt_svc_inc_aics = calloc(inc_aics_svc_count + 1, sizeof(struct ble_gatt_svc_def)); + gatt_svc_inc_aics = bt_le_ext_calloc(inc_aics_svc_count + 1, sizeof(struct ble_gatt_svc_def)); assert(gatt_svc_inc_aics); for (size_t i = 0; i < inc_aics_svc_count; i++) { diff --git a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/pacs.c b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/pacs.c index c93107a5150..93e90d87246 100644 --- a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/pacs.c +++ b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/pacs.c @@ -24,27 +24,28 @@ #include "nimble/server.h" #include "common/host.h" +#include "common/audio_attr.h" #include "../../../lib/include/audio.h" LOG_MODULE_REGISTER(LEA_PACS, CONFIG_BT_ISO_LOG_LEVEL); #if CONFIG_BT_PAC_SNK -static uint16_t pacs_snk_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t pacs_snk_handle; #if CONFIG_BT_PAC_SNK_LOC -static uint16_t pacs_snk_loc_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t pacs_snk_loc_handle; #endif /* CONFIG_BT_PAC_SNK_LOC */ #endif /* CONFIG_BT_PAC_SNK */ #if CONFIG_BT_PAC_SRC -static uint16_t pacs_src_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t pacs_src_handle; #if CONFIG_BT_PAC_SRC_LOC -static uint16_t pacs_src_loc_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t pacs_src_loc_handle; #endif /* CONFIG_BT_PAC_SRC_LOC */ #endif /* CONFIG_BT_PAC_SRC */ -static uint16_t pacs_ava_ctx_handle; -static uint16_t pacs_sup_ctx_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t pacs_ava_ctx_handle; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t pacs_sup_ctx_handle; static const struct ble_gatt_svc_def gatt_svc_pacs[] = { { diff --git a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/vcs.c b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/vcs.c index 2c775fe6f5e..b4565bda388 100644 --- a/components/bt/esp_ble_audio/host/adapter/nimble/profiles/vcs.c +++ b/components/bt/esp_ble_audio/host/adapter/nimble/profiles/vcs.c @@ -26,6 +26,7 @@ #include "nimble/server.h" #include "common/host.h" +#include "common/audio_attr.h" #include "../../../lib/include/audio.h" @@ -49,9 +50,9 @@ LOG_MODULE_REGISTER(LEA_VCS, CONFIG_BT_ISO_LOG_LEVEL); (BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_WRITE_NO_RSP | \ BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC) -static uint8_t inc_vocs_svc_count; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t inc_vocs_svc_count; -static struct inc_vocs_inst { +static BT_AUDIO_EXT_RAM_BSS_ATTR struct inc_vocs_inst { struct bt_gatt_service *svc_p; uint16_t state_handle; uint16_t location_handle; @@ -59,7 +60,7 @@ static struct inc_vocs_inst { uint16_t description_handle; } inc_vocs_insts[VOCS_INST_COUNT]; -static struct ble_gatt_svc_def *gatt_svc_inc_vocs; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct ble_gatt_svc_def *gatt_svc_inc_vocs; static const ble_uuid16_t inc_vocs_uuid_svc = BLE_UUID16_INIT(BT_UUID_VOCS_VAL); static const ble_uuid16_t inc_vocs_uuid_state = BLE_UUID16_INIT(BT_UUID_VOCS_STATE_VAL); @@ -90,9 +91,9 @@ static const ble_uuid16_t inc_vocs_uuid_description = BLE_UUID16_INIT(BT_UUID_VO (BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_WRITE_NO_RSP | \ BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC) -static uint8_t inc_aics_svc_count; +static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t inc_aics_svc_count; -static struct inc_aics_inst { +static BT_AUDIO_EXT_RAM_BSS_ATTR struct inc_aics_inst { struct bt_gatt_service *svc_p; uint16_t state_handle; uint16_t gain_handle; @@ -102,7 +103,7 @@ static struct inc_aics_inst { uint16_t description_handle; } inc_aics_insts[AICS_INST_COUNT]; -static struct ble_gatt_svc_def *gatt_svc_inc_aics; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct ble_gatt_svc_def *gatt_svc_inc_aics; static const ble_uuid16_t inc_aics_uuid_svc = BLE_UUID16_INIT(BT_UUID_AICS_VAL); static const ble_uuid16_t inc_aics_uuid_state = BLE_UUID16_INIT(BT_UUID_AICS_STATE_VAL); @@ -112,7 +113,7 @@ static const ble_uuid16_t inc_aics_uuid_status = BLE_UUID16_INIT(BT_UUID_AICS_IN static const ble_uuid16_t inc_aics_uuid_control = BLE_UUID16_INIT(BT_UUID_AICS_CONTROL_VAL); static const ble_uuid16_t inc_aics_uuid_description = BLE_UUID16_INIT(BT_UUID_AICS_DESCRIPTION_VAL); -static struct ble_gatt_svc_def **vcs_inc_svcs; +static BT_AUDIO_EXT_RAM_BSS_ATTR struct ble_gatt_svc_def **vcs_inc_svcs; static struct ble_gatt_svc_def gatt_svc_vcs[] = { { @@ -448,7 +449,7 @@ static void inc_vocs_svc_init(struct inc_vocs_inst *inst, svc->uuid = &inc_vocs_uuid_svc.u; svc->includes = NULL; - svc->characteristics = calloc(INC_VOCS_CHR_COUNT, sizeof(struct ble_gatt_chr_def)); + svc->characteristics = bt_le_ext_calloc(INC_VOCS_CHR_COUNT, sizeof(struct ble_gatt_chr_def)); assert(svc->characteristics); /* Characteristic - Volume Offset State */ @@ -501,7 +502,7 @@ static void inc_aics_svc_init(struct inc_aics_inst *inst, svc->uuid = &inc_aics_uuid_svc.u; svc->includes = NULL; - svc->characteristics = calloc(INC_AICS_CHR_COUNT, sizeof(struct ble_gatt_chr_def)); + svc->characteristics = bt_le_ext_calloc(INC_AICS_CHR_COUNT, sizeof(struct ble_gatt_chr_def)); assert(svc->characteristics); /* Characteristic - Audio Input State */ @@ -569,13 +570,13 @@ int bt_le_nimble_vcs_init(void *vcp_inc) /* Extra one for terminating the included service array with NULL */ inc_count = inc_vocs_svc_count + inc_aics_svc_count + 1; - vcs_inc_svcs = calloc(inc_count, sizeof(struct ble_gatt_svc_def *)); + vcs_inc_svcs = bt_le_ext_calloc(inc_count, sizeof(struct ble_gatt_svc_def *)); assert(vcs_inc_svcs); /* VCS may include zero or more instances of VOCS */ if (inc_vocs_svc_count) { /* Extra one for terminating the VOCS service array */ - gatt_svc_inc_vocs = calloc(inc_vocs_svc_count + 1, sizeof(struct ble_gatt_svc_def)); + gatt_svc_inc_vocs = bt_le_ext_calloc(inc_vocs_svc_count + 1, sizeof(struct ble_gatt_svc_def)); assert(gatt_svc_inc_vocs); for (size_t i = 0; i < inc_vocs_svc_count; i++) { @@ -612,7 +613,7 @@ int bt_le_nimble_vcs_init(void *vcp_inc) /* VCS may include zero or more instances of AICS */ if (inc_aics_svc_count) { /* Extra one for terminating the AICS service array */ - gatt_svc_inc_aics = calloc(inc_aics_svc_count + 1, sizeof(struct ble_gatt_svc_def)); + gatt_svc_inc_aics = bt_le_ext_calloc(inc_aics_svc_count + 1, sizeof(struct ble_gatt_svc_def)); assert(gatt_svc_inc_aics); for (size_t i = 0; i < inc_aics_svc_count; i++) { diff --git a/components/bt/esp_ble_audio/host/adapter/nimble/server.c b/components/bt/esp_ble_audio/host/adapter/nimble/server.c index 28b0a248749..938a05bc241 100644 --- a/components/bt/esp_ble_audio/host/adapter/nimble/server.c +++ b/components/bt/esp_ble_audio/host/adapter/nimble/server.c @@ -123,7 +123,7 @@ static int gatts_access_cb(uint16_t conn_handle, uint16_t attr_handle, return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); } - data = calloc(1, alloc_len); + data = bt_le_ext_calloc(1, alloc_len); assert(data); rc = os_mbuf_copydata(ctx->om, 0, OS_MBUF_PKTLEN(ctx->om), data); @@ -136,7 +136,7 @@ static int gatts_access_cb(uint16_t conn_handle, uint16_t attr_handle, } else { LOG_DBG("[N]Wr[%u]", OS_MBUF_PKTLEN(ctx->om)); - data = calloc(1, OS_MBUF_PKTLEN(ctx->om)); + data = bt_le_ext_calloc(1, OS_MBUF_PKTLEN(ctx->om)); assert(data); rc = os_mbuf_copydata(ctx->om, 0, OS_MBUF_PKTLEN(ctx->om), data); diff --git a/components/bt/esp_ble_audio/host/common/include/common/audio_attr.h b/components/bt/esp_ble_audio/host/common/include/common/audio_attr.h new file mode 100644 index 00000000000..84ef93aac8f --- /dev/null +++ b/components/bt/esp_ble_audio/host/common/include/common/audio_attr.h @@ -0,0 +1,34 @@ +/* + * 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 esp_ble_audio source files. Host-neutral: + * used by the bluedroid adapter profiles AND the host-agnostic OTS service, so + * it lives in the audio component's common include (not under bluedroid/). + * + * Distinct from esp_ble_iso's utils/iso_attr.h in both name and include prefix, so + * neither collides on the bt component's shared flat include path. + * + * - BT_AUDIO_EXT_RAM_BSS_ATTR: eligible for external SPIRAM (cold, task-context, + * non-DMA). Moves to PSRAM when BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY is set, else + * expands to nothing. + * - BT_AUDIO_CTRL_BSS_ATTR: must stay in internal DRAM (marker only). + * + * net_buf pools (NET_BUF_POOL_FIXED_DEFINE / NET_BUF_SIMPLE_DEFINE_STATIC) hide + * their .bss backing behind auto-generated names and cannot take a per-variable + * attribute; those objects (e.g. ots_l2cap) are moved via the linker fragment in + * linker_common.lf instead. + */ +#if CONFIG_BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY +#define BT_AUDIO_EXT_RAM_BSS_ATTR EXT_RAM_BSS_ATTR +#else +#define BT_AUDIO_EXT_RAM_BSS_ATTR +#endif + +#define BT_AUDIO_CTRL_BSS_ATTR diff --git a/components/bt/esp_ble_audio/host/common/init.c b/components/bt/esp_ble_audio/host/common/init.c index 08505740f3c..6c4f241f174 100644 --- a/components/bt/esp_ble_audio/host/common/init.c +++ b/components/bt/esp_ble_audio/host/common/init.c @@ -44,6 +44,8 @@ #include <../host/conn_internal.h> #include <../host/hci_core.h> +#include "utils/mem.h" + #if CONFIG_BT_BLUEDROID_ENABLED #include "bluedroid/init.h" #else @@ -1227,8 +1229,13 @@ static const struct lib_ext_funcs ext_funcs = { ._assert = (void *)assert_fatal, +#if CONFIG_BT_AUDIO_HEAP_EXTERNAL_MEMORY + ._malloc = (void *)bt_le_ext_malloc, + ._calloc = (void *)bt_le_ext_calloc, +#else ._malloc = (void *)malloc, ._calloc = (void *)calloc, +#endif ._free = (void *)free, ._rand = (void *)bt_rand, diff --git a/components/bt/esp_ble_audio/linker.lf b/components/bt/esp_ble_audio/linker.lf new file mode 100644 index 00000000000..d810e860e83 --- /dev/null +++ b/components/bt/esp_ble_audio/linker.lf @@ -0,0 +1,31 @@ +# BLE Audio external-RAM (.bss -> PSRAM) link-time placement. +# +# The bt_extram_bss scheme and bt_bss/bt_common sections referenced below are +# defined in the component's linker_common.lf. ldgen merges all registered +# fragments into one model, so the cross-file reference resolves. + +# Prebuilt archive: EXT_RAM_BSS_ATTR can't apply at its compile time, so move +# its .bss to SPIRAM at link time instead. +[mapping:ble_audio] +archive: libble_audio.a +entries: + if BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY = y: + * (bt_extram_bss) + +# Move the OTS objects' .bss to SPIRAM at link time (their net_buf pools can't +# take a per-var attr). Gates mirror CMakeLists so no entry names an object +# that isn't built. +[mapping:ble_audio_ots] +archive: libbt.a +entries: + if BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY = y && (BT_OTS = y || BT_OTS_CLIENT = y): + ots_l2cap (bt_extram_bss) + if BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY = y && BT_OTS = y: + ots (bt_extram_bss) + ots_oacp (bt_extram_bss) + ots_obj_manager (bt_extram_bss) + ots_olcp (bt_extram_bss) + if BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY = y && BT_OTS = y && BT_OTS_DIR_LIST_OBJ = y: + ots_dir_list (bt_extram_bss) + if BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY = y && BT_OTS_CLIENT = y: + ots_client (bt_extram_bss) diff --git a/components/bt/esp_ble_iso/CMakeLists.txt b/components/bt/esp_ble_iso/CMakeLists.txt index 6c3e32f58a0..4db9e815cba 100644 --- a/components/bt/esp_ble_iso/CMakeLists.txt +++ b/components/bt/esp_ble_iso/CMakeLists.txt @@ -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" diff --git a/components/bt/esp_ble_iso/Kconfig.in b/components/bt/esp_ble_iso/Kconfig.in index ebb4f041719..5238b01bd47 100644 --- a/components/bt/esp_ble_iso/Kconfig.in +++ b/components/bt/esp_ble_iso/Kconfig.in @@ -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 diff --git a/components/bt/esp_ble_iso/host/adapter/bluedroid/gap.c b/components/bt/esp_ble_iso/host/adapter/bluedroid/gap.c index ceb63f64dba..0d9e98a3972 100644 --- a/components/bt/esp_ble_iso/host/adapter/bluedroid/gap.c +++ b/components/bt/esp_ble_iso/host/adapter/bluedroid/gap.c @@ -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; diff --git a/components/bt/esp_ble_iso/host/adapter/bluedroid/gatt/gatt.c b/components/bt/esp_ble_iso/host/adapter/bluedroid/gatt/gatt.c index 28aa82bb80a..e61431e1e48 100644 --- a/components/bt/esp_ble_iso/host/adapter/bluedroid/gatt/gatt.c +++ b/components/bt/esp_ble_iso/host/adapter/bluedroid/gatt/gatt.c @@ -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); diff --git a/components/bt/esp_ble_iso/host/adapter/bluedroid/hci.c b/components/bt/esp_ble_iso/host/adapter/bluedroid/hci.c index 6dffd4aa135..0dbfb79a416 100644 --- a/components/bt/esp_ble_iso/host/adapter/bluedroid/hci.c +++ b/components/bt/esp_ble_iso/host/adapter/bluedroid/hci.c @@ -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) { diff --git a/components/bt/esp_ble_iso/host/adapter/bluedroid/iso.c b/components/bt/esp_ble_iso/host/adapter/bluedroid/iso.c index 2716859fe33..baf82de4f00 100644 --- a/components/bt/esp_ble_iso/host/adapter/bluedroid/iso.c +++ b/components/bt/esp_ble_iso/host/adapter/bluedroid/iso.c @@ -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; diff --git a/components/bt/esp_ble_iso/host/adapter/nimble/gap.c b/components/bt/esp_ble_iso/host/adapter/nimble/gap.c index 5ca85a1dc6b..295d0c31127 100644 --- a/components/bt/esp_ble_iso/host/adapter/nimble/gap.c +++ b/components/bt/esp_ble_iso/host/adapter/nimble/gap.c @@ -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); diff --git a/components/bt/esp_ble_iso/host/adapter/nimble/gatt/gatt.c b/components/bt/esp_ble_iso/host/adapter/nimble/gatt/gatt.c index 4c582efbf64..5056b7eebd9 100644 --- a/components/bt/esp_ble_iso/host/adapter/nimble/gatt/gatt.c +++ b/components/bt/esp_ble_iso/host/adapter/nimble/gatt/gatt.c @@ -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; diff --git a/components/bt/esp_ble_iso/host/adapter/nimble/gatt/gatt.db.c b/components/bt/esp_ble_iso/host/adapter/nimble/gatt/gatt.db.c index 7e28339e5aa..4ef5d898c55 100644 --- a/components/bt/esp_ble_iso/host/adapter/nimble/gatt/gatt.db.c +++ b/components/bt/esp_ble_iso/host/adapter/nimble/gatt/gatt.db.c @@ -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]); + } +} diff --git a/components/bt/esp_ble_iso/host/adapter/nimble/gatt/gatt.nrp.c b/components/bt/esp_ble_iso/host/adapter/nimble/gatt/gatt.nrp.c index c40b1142ecd..a690b7aae10 100644 --- a/components/bt/esp_ble_iso/host/adapter/nimble/gatt/gatt.nrp.c +++ b/components/bt/esp_ble_iso/host/adapter/nimble/gatt/gatt.nrp.c @@ -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]); + } +} diff --git a/components/bt/esp_ble_iso/host/adapter/nimble/include/nimble/gatt.h b/components/bt/esp_ble_iso/host/adapter/nimble/include/nimble/gatt.h index 01f246e04a0..9f189238422 100644 --- a/components/bt/esp_ble_iso/host/adapter/nimble/include/nimble/gatt.h +++ b/components/bt/esp_ble_iso/host/adapter/nimble/include/nimble/gatt.h @@ -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 diff --git a/components/bt/esp_ble_iso/host/adapter/nimble/iso.c b/components/bt/esp_ble_iso/host/adapter/nimble/iso.c index e83958c32f4..78bbe740ea2 100644 --- a/components/bt/esp_ble_iso/host/adapter/nimble/iso.c +++ b/components/bt/esp_ble_iso/host/adapter/nimble/iso.c @@ -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; diff --git a/components/bt/esp_ble_iso/host/adapter/nimble/l2cap.c b/components/bt/esp_ble_iso/host/adapter/nimble/l2cap.c index 53bedbc3506..64d7dd7dd82 100644 --- a/components/bt/esp_ble_iso/host/adapter/nimble/l2cap.c +++ b/components/bt/esp_ble_iso/host/adapter/nimble/l2cap.c @@ -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); diff --git a/components/bt/esp_ble_iso/host/common/adv.c b/components/bt/esp_ble_iso/host/common/adv.c index a359d95f575..2318ff3a322 100644 --- a/components/bt/esp_ble_iso/host/common/adv.c +++ b/components/bt/esp_ble_iso/host/common/adv.c @@ -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) { diff --git a/components/bt/esp_ble_iso/host/common/app/gap.c b/components/bt/esp_ble_iso/host/common/app/gap.c index ebf9aa79b8e..607bcb5da46 100644 --- a/components/bt/esp_ble_iso/host/common/app/gap.c +++ b/components/bt/esp_ble_iso/host/common/app/gap.c @@ -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) { diff --git a/components/bt/esp_ble_iso/host/common/app/gatt.c b/components/bt/esp_ble_iso/host/common/app/gatt.c index 36015841dfa..8d603e76eed 100644 --- a/components/bt/esp_ble_iso/host/common/app/gatt.c +++ b/components/bt/esp_ble_iso/host/common/app/gatt.c @@ -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) { diff --git a/components/bt/esp_ble_iso/host/common/conn.c b/components/bt/esp_ble_iso/host/common/conn.c index c59ccba4244..c616ab3cdc8 100644 --- a/components/bt/esp_ble_iso/host/common/conn.c +++ b/components/bt/esp_ble_iso/host/common/conn.c @@ -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) diff --git a/components/bt/esp_ble_iso/host/common/gatt.c b/components/bt/esp_ble_iso/host/common/gatt.c index ea5b1aabaa9..76b68669195 100644 --- a/components/bt/esp_ble_iso/host/common/gatt.c +++ b/components/bt/esp_ble_iso/host/common/gatt.c @@ -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; } diff --git a/components/bt/esp_ble_iso/host/common/hci.c b/components/bt/esp_ble_iso/host/common/hci.c index e897997ebab..399794ff19a 100644 --- a/components/bt/esp_ble_iso/host/common/hci.c +++ b/components/bt/esp_ble_iso/host/common/hci.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #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) diff --git a/components/bt/esp_ble_iso/host/common/host.c b/components/bt/esp_ble_iso/host/common/host.c index 127542a3ec7..8fef5976970 100644 --- a/components/bt/esp_ble_iso/host/common/host.c +++ b/components/bt/esp_ble_iso/host/common/host.c @@ -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(); diff --git a/components/bt/esp_ble_iso/host/common/include/common/host.h b/components/bt/esp_ble_iso/host/common/include/common/host.h index 80b4bc15431..1765db340f8 100644 --- a/components/bt/esp_ble_iso/host/common/include/common/host.h +++ b/components/bt/esp_ble_iso/host/common/include/common/host.h @@ -14,6 +14,9 @@ #include #include +#include "utils/iso_attr.h" +#include "utils/mem.h" + #include "common/adv.h" #include "common/conn.h" #include "common/iso.h" diff --git a/components/bt/esp_ble_iso/host/common/iso.c b/components/bt/esp_ble_iso/host/common/iso.c index 31e1dd0cd5d..e87cba7d501 100644 --- a/components/bt/esp_ble_iso/host/common/iso.c +++ b/components/bt/esp_ble_iso/host/common/iso.c @@ -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; diff --git a/components/bt/esp_ble_iso/host/common/l2cap.c b/components/bt/esp_ble_iso/host/common/l2cap.c index 79dc4256964..ca868ee83c6 100644 --- a/components/bt/esp_ble_iso/host/common/l2cap.c +++ b/components/bt/esp_ble_iso/host/common/l2cap.c @@ -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) { diff --git a/components/bt/esp_ble_iso/host/common/scan.c b/components/bt/esp_ble_iso/host/common/scan.c index a07686d9ba4..e34d7f6a528 100644 --- a/components/bt/esp_ble_iso/host/common/scan.c +++ b/components/bt/esp_ble_iso/host/common/scan.c @@ -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) diff --git a/components/bt/esp_ble_iso/host/common/task.c b/components/bt/esp_ble_iso/host/common/task.c index 60f0898efa2..e9d07fdeac8 100644 --- a/components/bt/esp_ble_iso/host/common/task.c +++ b/components/bt/esp_ble_iso/host/common/task.c @@ -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; diff --git a/components/bt/esp_ble_iso/host/iso/iso.c b/components/bt/esp_ble_iso/host/iso/iso.c index efb0352d6ea..99537c51d08 100644 --- a/components/bt/esp_ble_iso/host/iso/iso.c +++ b/components/bt/esp_ble_iso/host/iso/iso.c @@ -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) { diff --git a/components/bt/esp_ble_iso/host/utils/bt_str.c b/components/bt/esp_ble_iso/host/utils/bt_str.c index 43054e7e93b..b795f45675a 100644 --- a/components/bt/esp_ble_iso/host/utils/bt_str.c +++ b/components/bt/esp_ble_iso/host/utils/bt_str.c @@ -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 #include +#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)); diff --git a/components/bt/esp_ble_iso/host/utils/include/utils/iso_attr.h b/components/bt/esp_ble_iso/host/utils/include/utils/iso_attr.h new file mode 100644 index 00000000000..0061036ed80 --- /dev/null +++ b/components/bt/esp_ble_iso/host/utils/include/utils/iso_attr.h @@ -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 diff --git a/components/bt/esp_ble_iso/host/utils/include/utils/mem.h b/components/bt/esp_ble_iso/host/utils/include/utils/mem.h new file mode 100644 index 00000000000..419c3300678 --- /dev/null +++ b/components/bt/esp_ble_iso/host/utils/include/utils/mem.h @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +/* 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); diff --git a/components/bt/esp_ble_iso/host/utils/utils.c b/components/bt/esp_ble_iso/host/utils/keys.c similarity index 93% rename from components/bt/esp_ble_iso/host/utils/utils.c rename to components/bt/esp_ble_iso/host/utils/keys.c index 0a300567a12..4198a2446dd 100644 --- a/components/bt/esp_ble_iso/host/utils/utils.c +++ b/components/bt/esp_ble_iso/host/utils/keys.c @@ -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. */ diff --git a/components/bt/esp_ble_iso/host/utils/mem.c b/components/bt/esp_ble_iso/host/utils/mem.c new file mode 100644 index 00000000000..514fd9407ca --- /dev/null +++ b/components/bt/esp_ble_iso/host/utils/mem.c @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#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); +} diff --git a/examples/bluetooth/esp_ble_audio/bap/broadcast_sink/sdkconfig.defaults b/examples/bluetooth/esp_ble_audio/bap/broadcast_sink/sdkconfig.defaults index 85ae6dd730f..e694c177637 100644 --- a/examples/bluetooth/esp_ble_audio/bap/broadcast_sink/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_audio/bap/broadcast_sink/sdkconfig.defaults @@ -29,3 +29,12 @@ CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE=60 CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y CONFIG_FREERTOS_HZ=1000 + +# To place LE Audio .bss + control-plane heap in PSRAM, uncomment the +# lines below (needs a PSRAM-capable target, e.g. esp32s31/esp32h4). +# CONFIG_SPIRAM=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_HEAP_EXTERNAL_MEMORY=y diff --git a/examples/bluetooth/esp_ble_audio/bap/broadcast_source/sdkconfig.defaults b/examples/bluetooth/esp_ble_audio/bap/broadcast_source/sdkconfig.defaults index cbc059c54a9..2b99b23e1f6 100644 --- a/examples/bluetooth/esp_ble_audio/bap/broadcast_source/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_audio/bap/broadcast_source/sdkconfig.defaults @@ -19,3 +19,12 @@ CONFIG_BT_BAP_BROADCAST_SOURCE=y CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y CONFIG_FREERTOS_HZ=1000 + +# To place LE Audio .bss + control-plane heap in PSRAM, uncomment the +# lines below (needs a PSRAM-capable target, e.g. esp32s31/esp32h4). +# CONFIG_SPIRAM=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_HEAP_EXTERNAL_MEMORY=y diff --git a/examples/bluetooth/esp_ble_audio/bap/unicast_client/sdkconfig.defaults b/examples/bluetooth/esp_ble_audio/bap/unicast_client/sdkconfig.defaults index 56525a97b23..8b50eed32c4 100644 --- a/examples/bluetooth/esp_ble_audio/bap/unicast_client/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_audio/bap/unicast_client/sdkconfig.defaults @@ -21,3 +21,12 @@ CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT=2 CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y CONFIG_FREERTOS_HZ=1000 + +# To place LE Audio .bss + control-plane heap in PSRAM, uncomment the +# lines below (needs a PSRAM-capable target, e.g. esp32s31/esp32h4). +# CONFIG_SPIRAM=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_HEAP_EXTERNAL_MEMORY=y diff --git a/examples/bluetooth/esp_ble_audio/bap/unicast_server/sdkconfig.defaults b/examples/bluetooth/esp_ble_audio/bap/unicast_server/sdkconfig.defaults index 0b97edc72f0..fc2a7709d10 100644 --- a/examples/bluetooth/esp_ble_audio/bap/unicast_server/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_audio/bap/unicast_server/sdkconfig.defaults @@ -28,3 +28,12 @@ CONFIG_BT_PACS_SUPPORTED_CONTEXT_NOTIFIABLE=y CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y CONFIG_FREERTOS_HZ=1000 + +# To place LE Audio .bss + control-plane heap in PSRAM, uncomment the +# lines below (needs a PSRAM-capable target, e.g. esp32s31/esp32h4). +# CONFIG_SPIRAM=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_HEAP_EXTERNAL_MEMORY=y diff --git a/examples/bluetooth/esp_ble_audio/cap/acceptor/sdkconfig.defaults b/examples/bluetooth/esp_ble_audio/cap/acceptor/sdkconfig.defaults index 1da6c3dbbcf..34e1e3fa68e 100644 --- a/examples/bluetooth/esp_ble_audio/cap/acceptor/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_audio/cap/acceptor/sdkconfig.defaults @@ -35,3 +35,12 @@ CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y CONFIG_EXAMPLE_UNICAST=y CONFIG_FREERTOS_HZ=1000 + +# To place LE Audio .bss + control-plane heap in PSRAM, uncomment the +# lines below (needs a PSRAM-capable target, e.g. esp32s31/esp32h4). +# CONFIG_SPIRAM=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_HEAP_EXTERNAL_MEMORY=y diff --git a/examples/bluetooth/esp_ble_audio/cap/initiator/sdkconfig.defaults b/examples/bluetooth/esp_ble_audio/cap/initiator/sdkconfig.defaults index 63c1276ecd2..22330e5305d 100644 --- a/examples/bluetooth/esp_ble_audio/cap/initiator/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_audio/cap/initiator/sdkconfig.defaults @@ -26,3 +26,12 @@ CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y CONFIG_EXAMPLE_UNICAST=y CONFIG_FREERTOS_HZ=1000 + +# To place LE Audio .bss + control-plane heap in PSRAM, uncomment the +# lines below (needs a PSRAM-capable target, e.g. esp32s31/esp32h4). +# CONFIG_SPIRAM=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_HEAP_EXTERNAL_MEMORY=y diff --git a/examples/bluetooth/esp_ble_audio/tmap/bmr/sdkconfig.defaults b/examples/bluetooth/esp_ble_audio/tmap/bmr/sdkconfig.defaults index 5febc040e4e..7323c7888a9 100644 --- a/examples/bluetooth/esp_ble_audio/tmap/bmr/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_audio/tmap/bmr/sdkconfig.defaults @@ -26,3 +26,12 @@ CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE=60 CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y CONFIG_FREERTOS_HZ=1000 + +# To place LE Audio .bss + control-plane heap in PSRAM, uncomment the +# lines below (needs a PSRAM-capable target, e.g. esp32s31/esp32h4). +# CONFIG_SPIRAM=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_HEAP_EXTERNAL_MEMORY=y diff --git a/examples/bluetooth/esp_ble_audio/tmap/bms/sdkconfig.defaults b/examples/bluetooth/esp_ble_audio/tmap/bms/sdkconfig.defaults index 31c481d6a80..9d7da1839e5 100644 --- a/examples/bluetooth/esp_ble_audio/tmap/bms/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_audio/tmap/bms/sdkconfig.defaults @@ -21,3 +21,12 @@ CONFIG_BT_BAP_BROADCAST_SOURCE=y CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y CONFIG_FREERTOS_HZ=1000 + +# To place LE Audio .bss + control-plane heap in PSRAM, uncomment the +# lines below (needs a PSRAM-capable target, e.g. esp32s31/esp32h4). +# CONFIG_SPIRAM=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_HEAP_EXTERNAL_MEMORY=y diff --git a/examples/bluetooth/esp_ble_audio/tmap/central/sdkconfig.defaults b/examples/bluetooth/esp_ble_audio/tmap/central/sdkconfig.defaults index c0d383c7c12..8ca94a85a33 100644 --- a/examples/bluetooth/esp_ble_audio/tmap/central/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_audio/tmap/central/sdkconfig.defaults @@ -31,6 +31,15 @@ CONFIG_BT_MCTL_LOCAL_PLAYER_REMOTE_CONTROL=y CONFIG_BT_TBS=y CONFIG_BT_TBS_SUPPORTED_FEATURES=3 +# To place LE Audio .bss + control-plane heap in PSRAM, uncomment the +# lines below (needs a PSRAM-capable target, e.g. esp32s31/esp32h4). +# CONFIG_SPIRAM=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_HEAP_EXTERNAL_MEMORY=y + CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y CONFIG_FREERTOS_HZ=1000 diff --git a/examples/bluetooth/esp_ble_audio/tmap/peripheral/sdkconfig.defaults b/examples/bluetooth/esp_ble_audio/tmap/peripheral/sdkconfig.defaults index bfd6b33c04b..f573f8b6e7d 100644 --- a/examples/bluetooth/esp_ble_audio/tmap/peripheral/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_audio/tmap/peripheral/sdkconfig.defaults @@ -45,3 +45,12 @@ CONFIG_EXAMPLE_TMAP_PER_DUO=y CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y CONFIG_FREERTOS_HZ=1000 + +# To place LE Audio .bss + control-plane heap in PSRAM, uncomment the +# lines below (needs a PSRAM-capable target, e.g. esp32s31/esp32h4). +# CONFIG_SPIRAM=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_AUDIO_HEAP_EXTERNAL_MEMORY=y diff --git a/examples/bluetooth/esp_ble_iso/big_broadcaster/sdkconfig.defaults b/examples/bluetooth/esp_ble_iso/big_broadcaster/sdkconfig.defaults index 8cad6879b3c..fda2934b82e 100644 --- a/examples/bluetooth/esp_ble_iso/big_broadcaster/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_iso/big_broadcaster/sdkconfig.defaults @@ -17,3 +17,10 @@ CONFIG_BT_ISO_MAX_CHAN=2 CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y CONFIG_FREERTOS_HZ=1000 + +# To place BLE ISO .bss + control-plane heap in PSRAM, uncomment the +# lines below (needs a PSRAM-capable target, e.g. esp32s31/esp32h4). +# CONFIG_SPIRAM=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY=y diff --git a/examples/bluetooth/esp_ble_iso/big_receiver/sdkconfig.defaults b/examples/bluetooth/esp_ble_iso/big_receiver/sdkconfig.defaults index bb0d86ba91f..068acc465b5 100644 --- a/examples/bluetooth/esp_ble_iso/big_receiver/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_iso/big_receiver/sdkconfig.defaults @@ -17,3 +17,10 @@ CONFIG_BT_ISO_MAX_CHAN=2 CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y CONFIG_FREERTOS_HZ=1000 + +# To place BLE ISO .bss + control-plane heap in PSRAM, uncomment the +# lines below (needs a PSRAM-capable target, e.g. esp32s31/esp32h4). +# CONFIG_SPIRAM=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY=y diff --git a/examples/bluetooth/esp_ble_iso/cis_central/sdkconfig.defaults b/examples/bluetooth/esp_ble_iso/cis_central/sdkconfig.defaults index 6da20d7e9c1..43e53ecc242 100644 --- a/examples/bluetooth/esp_ble_iso/cis_central/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_iso/cis_central/sdkconfig.defaults @@ -16,3 +16,10 @@ CONFIG_BT_ISO_CENTRAL=y CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y CONFIG_FREERTOS_HZ=1000 + +# To place BLE ISO .bss + control-plane heap in PSRAM, uncomment the +# lines below (needs a PSRAM-capable target, e.g. esp32s31/esp32h4). +# CONFIG_SPIRAM=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY=y diff --git a/examples/bluetooth/esp_ble_iso/cis_peripheral/sdkconfig.defaults b/examples/bluetooth/esp_ble_iso/cis_peripheral/sdkconfig.defaults index b412ca65563..888a87fa0a4 100644 --- a/examples/bluetooth/esp_ble_iso/cis_peripheral/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_iso/cis_peripheral/sdkconfig.defaults @@ -16,3 +16,10 @@ CONFIG_BT_ISO_PERIPHERAL=y CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y CONFIG_FREERTOS_HZ=1000 + +# To place BLE ISO .bss + control-plane heap in PSRAM, uncomment the +# lines below (needs a PSRAM-capable target, e.g. esp32s31/esp32h4). +# CONFIG_SPIRAM=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_BT_ISO_HEAP_EXTERNAL_MEMORY=y