feat(bt): refactor bt sdk with broker for esp32h4 and esp32s31

This commit is contained in:
ShenWeilong
2026-08-13 11:07:06 +08:00
parent b418d72bb0
commit c48a8567a1
42 changed files with 7360 additions and 3938 deletions
+2 -2
View File
@@ -12,15 +12,15 @@ list(APPEND porting_srcs ${BTDM_COMMON_SRCS})
list(APPEND porting_include_dirs "${CMAKE_CURRENT_SOURCE_DIR}/controller/btdm_common/include")
# ble
list(APPEND porting_include_dirs "${CMAKE_CURRENT_SOURCE_DIR}/controller/ble/include")
if(CONFIG_BT_CTRL_BLE_ENABLE)
list(APPEND porting_include_dirs "${CMAKE_CURRENT_SOURCE_DIR}/controller/ble/include")
file(GLOB_RECURSE BLE_SRCS "controller/ble/src/*.c")
list(APPEND porting_srcs ${BLE_SRCS})
endif()
# bredr
list(APPEND porting_include_dirs "${CMAKE_CURRENT_SOURCE_DIR}/controller/bredr/include")
if(CONFIG_BT_CTRL_BREDR_ENABLE)
list(APPEND porting_include_dirs "${CMAKE_CURRENT_SOURCE_DIR}/controller/bredr/include")
file(GLOB_RECURSE BREDR_SRCS "controller/bredr/src/*.c")
list(APPEND porting_srcs ${BREDR_SRCS})
endif()
@@ -1,3 +1,112 @@
menu "Connection vendor/Optimization Options"
config BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS
bool "Enable enhanced Access Address check in CONNECT_IND"
default n
help
Enabling this option will add stricter verification of the Access Address in the CONNECT_IND PDU.
This improves security by ensuring that only connection requests with valid Access Addresses are accepted.
If disabled, only basic checks are applied, improving compatibility.
config BT_LE_CTRL_CHAN_ASS_EN
bool "Enable channel assessment(Experimental)"
default n
help
If this option is enabled, The Controller will records the communication quality
for each channel and then start a timer to check and update the channel map every 4 seconds.
menu "BLE disconnects when Instant Passed (0x28) occurs"
config BT_LE_CTRL_LLCP_CONN_UPDATE
bool "BLE ACL connection update procedure"
default n
help
If this option is enabled, Controller will terminate the connection
when Instant Passed (0x28) error occurs during connection update procedure.
config BT_LE_CTRL_LLCP_CHAN_MAP_UPDATE
bool "BLE ACL channel map update procedure"
default n
help
If this option is enabled, Controller will terminate the connection
when Instant Passed (0x28) error occurs in channel map update procedure.
config BT_LE_CTRL_LLCP_PHY_UPDATE
bool "BLE ACL PHY update procedure"
default n
help
If this option is enabled, Controller will terminate the connection
when Instant Passed (0x28) error occurs in PHY update procedure.
endmenu # "BLE disconnects when Instant Passed (0x28) occurs"
endmenu # "Connection vendor/Optimization Options"
menu "Scanning vendor/Optimization Options"
config BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX
int "The value of upperlimitmax during scan backoff procedure"
range 1 256
default 32
help
The value of upperlimitmax needs to be a power of 2.
endmenu # "Scanning vendor/Optimization Options"
menu "Advertising vendor/Optimization Options"
config BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX
bool "Enable aux packet when ext adv data length is zero(Experimental)"
default y
help
When this option is enabled, auxiliary packets will be present in the events of
'Non-Connectable and Non-Scannable' regardless of whether the advertising length is 0.
If this option is not enabled, auxiliary packets will only be present when the advertising length is not 0.
config BT_LE_CTRL_ADV_EVENT_INC_ON_FULL_TX_EN
bool "Increment advertising event count only on full PDU TX success"
default n
help
When enabled, the advertising event count is incremented only
if all PDUs in an advertising event are transmitted successfully.
If disabled, the event count is incremented regardless of transmission success.
config BT_LE_CTRL_ADV_CH38_39_TX_AVOID_CONFLICT_EN
bool "Delay advertising TX on channels 38/39 to avoid scheduling conflicts"
default n
help
When enabled, advertising transmissions on channels 38 and 39
are delayed if a scheduling conflict occurs.
config BT_LE_ADV_CH39_TXPWR_CONFIG_SEPARATELY_EN
bool "(Unsupported !!) Enable separate TX power for advertising on channel 39"
default n
help
When enabled, the TX power for advertising transmissions
on channel 39 can be configured independently of other channels.
config BT_LE_DFT_CH39_TX_POWER_LEVEL_DBM_EFF
int "Tx power for advertising on channel 39 (dBm)"
depends on BT_LE_ADV_CH39_TXPWR_CONFIG_SEPARATELY_EN
range -15 20
default 0
config BT_LE_CTRL_ADV_TX_CONTINUE_WHEN_EXCEED_ITVL_EN
bool "Allow advertising TX to continue if data TX exceeds interval"
default n
help
When enabled, advertising transmission continues even if the
TX duration for advertising data exceeds the configured advertising interval.
config BT_LE_CTRL_ADV_RAND_CH_IDX_EN
bool "Enable Randomized Advertising Channel Indexing"
default n
help
When enabled, the advertising channel sequence is randomized
according to the Randomized Advertising Channel Indexing feature.
If disabled, the standard channel sequence is used.
config BT_LE_CTRL_FAST_CONN_DATA_TX_EN
bool "Enable fast sending of connection data"
default y
help
If this option is enabled, The Controller will continue to
Send an empty PDU after sending valid connection data within an interval.
endmenu # "Advertising vendor/Optimization Options"
menuconfig BT_LE_50_FEATURE_SUPPORT
bool "Enable BLE 5 feature"
@@ -64,6 +173,19 @@ if BT_LE_EXT_ADV
help
This enables controller transfer periodic sync events to host
config BT_LE_PERIODIC_ADV_WITH_RESPONSE_ENABLED
bool "Enable BLE periodic advertising with response"
depends on BT_LE_ENABLE_PERIODIC_ADV && SOC_BLE_PERIODIC_ADV_WITH_RESPONSE
default n
help
This enables BLE periodic advertising with response feature
config BT_LE_PERIODIC_SYNC_WITH_RESPONSE_ENABLED
bool "Enable BLE periodic sync with response"
depends on BT_LE_ENABLE_PERIODIC_ADV && SOC_BLE_PERIODIC_ADV_WITH_RESPONSE
default n
help
This enables BLE periodic sync with response feature
endif
config BT_LE_MAX_PERIODIC_SYNCS
@@ -110,13 +232,6 @@ config BT_LE_CTE_FEATURE_ENABLED
This feature allows devices to determine the direction of a Bluetooth CTE signal,
enabling Angle of Arrival (AoA) and Angle of Departure (AoD) functionality.
config BT_LE_PERIODIC_ADV_WITH_RESPONSE_ENABLED
bool "Enable BLE periodic advertising with response"
depends on BT_LE_50_FEATURE_SUPPORT && SOC_BLE_PERIODIC_ADV_WITH_RESPONSE
default n
help
This enables BLE periodic advertising with response feature
menuconfig BT_LE_ISO_SUPPORT
bool "Enable BLE ISO feature"
default n
@@ -616,3 +731,23 @@ config BT_LE_DFT_TX_POWER_LEVEL_DBM_EFF
config BT_LE_DTM_ENABLED
bool "Enable Direct Test Mode (DTM) feature"
default n
menuconfig BT_CTRL_LE_VS_CMD_EVT_ENABLED
bool "Enable vendor-specific HCI commands"
default n if BT_CONTROLLER_ONLY
default y
help
Enable controller's vendor-specific HCI commands
config BT_CTRL_LE_VS_ADI_FILTER_ENABLED
depends on BT_CTRL_LE_VS_CMD_EVT_ENABLED && !BT_NIMBLE_ENABLED
bool "Use ADI to failter adv reports"
default n
help
ADI can be utilized to filter advertisement reports,
which will help to reduce time consumption on the secondary channel.
config BT_CTRL_LE_VS_CONST_EXT_ADV_DID
default n
depends on BT_CTRL_LE_VS_CMD_EVT_ENABLED && !BT_NIMBLE_ENABLED
bool "Allow setting constant extended advertisement DID"
@@ -16,6 +16,8 @@ int ble_stack_enable(void);
void ble_stack_disable(void);
void ble_stack_reset(void);
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
esp_err_t sleep_modem_ble_mac_modem_state_init(void);
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE
@@ -7,8 +7,9 @@
#ifndef __BLE_USER_CFG_H__
#define __BLE_USER_CFG_H__
#include <stdint.h>
#include <sdkconfig.h>
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
@@ -20,156 +21,339 @@ extern "C" {
#if CONFIG_BT_NIMBLE_ENABLED
#if CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY
#define BLE_LL_SCAN_PHY_NUMBER_N (2)
#else
#define BLE_LL_SCAN_PHY_NUMBER_N (1)
#endif
#define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST MYNEWT_VAL(BLE_MAX_PERIODIC_ADVERTISER_LIST)
#define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS MYNEWT_VAL(BLE_MAX_PERIODIC_SYNCS)
#define DEFAULT_BT_LE_MAX_CONNECTIONS MYNEWT_VAL(BLE_MAX_CONNECTIONS)
#define DEFAULT_BT_LE_ACL_BUF_SIZE MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE)
#define DEFAULT_BT_LE_ACL_BUF_COUNT MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_LL_COUNT)
#define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE MYNEWT_VAL(BLE_TRANSPORT_EVT_SIZE)
#define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)
#define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES)
#define DEFAULT_BT_NIMBLE_WHITELIST_SIZE MYNEWT_VAL(BLE_LL_WHITELIST_SIZE)
#define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT MYNEWT_VAL(BLE_TRANSPORT_EVT_COUNT)
#define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT MYNEWT_VAL(BLE_TRANSPORT_EVT_DISCARDABLE_COUNT)
#define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
#define DEFAULT_BT_LE_POWER_CONTROL_ENABLED MYNEWT_VAL(BLE_POWER_CONTROL)
#if CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY
#define BLE_LL_SCAN_PHY_NUMBER_N (2)
#else
#define BLE_LL_SCAN_PHY_NUMBER_N (1)
#endif
#define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST MYNEWT_VAL(BLE_MAX_PERIODIC_ADVERTISER_LIST)
#define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS MYNEWT_VAL(BLE_MAX_PERIODIC_SYNCS)
#define DEFAULT_BT_LE_MAX_CONNECTIONS MYNEWT_VAL(BLE_MAX_CONNECTIONS)
#define DEFAULT_BT_LE_ACL_BUF_SIZE MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE)
#define DEFAULT_BT_LE_ACL_BUF_COUNT MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_LL_COUNT)
#define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE MYNEWT_VAL(BLE_TRANSPORT_EVT_SIZE)
#define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)
#define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES)
#define DEFAULT_BT_NIMBLE_WHITELIST_SIZE MYNEWT_VAL(BLE_LL_WHITELIST_SIZE)
#define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT MYNEWT_VAL(BLE_TRANSPORT_EVT_COUNT)
#define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT MYNEWT_VAL(BLE_TRANSPORT_EVT_DISCARDABLE_COUNT)
#define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
#else
#if CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY
#define BLE_LL_SCAN_PHY_NUMBER_N (2)
#else
#define BLE_LL_SCAN_PHY_NUMBER_N (1)
#endif
#if defined(CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST)
#define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST)
#else
#define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (5)
#endif
#if defined(CONFIG_BT_LE_MAX_PERIODIC_SYNCS)
#define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (CONFIG_BT_LE_MAX_PERIODIC_SYNCS)
#else
#define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (1)
#endif
#if defined(CONFIG_BT_LE_MAX_CONNECTIONS)
#define DEFAULT_BT_LE_MAX_CONNECTIONS (CONFIG_BT_LE_MAX_CONNECTIONS)
#else
#define DEFAULT_BT_LE_MAX_CONNECTIONS (2)
#endif
#if defined(CONFIG_BT_LE_ACL_BUF_SIZE)
#define DEFAULT_BT_LE_ACL_BUF_SIZE (CONFIG_BT_LE_ACL_BUF_SIZE)
#else
#define DEFAULT_BT_LE_ACL_BUF_SIZE (255)
#endif
#if defined(CONFIG_BT_LE_ACL_BUF_COUNT)
#define DEFAULT_BT_LE_ACL_BUF_COUNT (CONFIG_BT_LE_ACL_BUF_COUNT)
#else
#define DEFAULT_BT_LE_ACL_BUF_COUNT (24)
#endif
#if defined(CONFIG_BT_LE_HCI_EVT_BUF_SIZE)
#define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE (CONFIG_BT_LE_HCI_EVT_BUF_SIZE)
#else
#define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE (70)
#endif
#if defined(CONFIG_BT_LE_EXT_ADV_MAX_SIZE)
#define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE (CONFIG_BT_LE_EXT_ADV_MAX_SIZE)
#else
#define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE (31)
#endif
#if defined(CONFIG_BT_LE_MAX_EXT_ADV_INSTANCES)
#define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES (CONFIG_BT_LE_MAX_EXT_ADV_INSTANCES)
#else
#define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES (1)
#endif
#if defined(CONFIG_BT_LE_WHITELIST_SIZE)
#define DEFAULT_BT_NIMBLE_WHITELIST_SIZE (CONFIG_BT_LE_WHITELIST_SIZE)
#else
#define DEFAULT_BT_NIMBLE_WHITELIST_SIZE (12)
#endif
#if defined(CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT)
#define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT (CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT)
#else
#define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT (30)
#endif
#if defined(CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT)
#define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT)
#else
#define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (8)
#endif
#define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
#if defined(CONFIG_BT_LE_POWER_CONTROL_ENABLED)
#define DEFAULT_BT_LE_POWER_CONTROL_ENABLED (CONFIG_BT_LE_POWER_CONTROL_ENABLED)
#else
#define DEFAULT_BT_LE_POWER_CONTROL_ENABLED (0)
#endif
#if CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY
#define BLE_LL_SCAN_PHY_NUMBER_N (2)
#else
#define BLE_LL_SCAN_PHY_NUMBER_N (1)
#endif
#if defined(CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST)
#define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST)
#else
#define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (5)
#endif
#if defined(CONFIG_BT_LE_MAX_PERIODIC_SYNCS)
#define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (CONFIG_BT_LE_MAX_PERIODIC_SYNCS)
#else
#define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (1)
#endif
#if defined(CONFIG_BT_LE_MAX_CONNECTIONS)
#define DEFAULT_BT_LE_MAX_CONNECTIONS (CONFIG_BT_LE_MAX_CONNECTIONS)
#else
#define DEFAULT_BT_LE_MAX_CONNECTIONS (2)
#endif
#if defined(CONFIG_BT_LE_ACL_BUF_SIZE)
#define DEFAULT_BT_LE_ACL_BUF_SIZE (CONFIG_BT_LE_ACL_BUF_SIZE)
#else
#define DEFAULT_BT_LE_ACL_BUF_SIZE (255)
#endif
#if defined(CONFIG_BT_LE_ACL_BUF_COUNT)
#define DEFAULT_BT_LE_ACL_BUF_COUNT (CONFIG_BT_LE_ACL_BUF_COUNT)
#else
#define DEFAULT_BT_LE_ACL_BUF_COUNT (24)
#endif
#if defined(CONFIG_BT_LE_HCI_EVT_BUF_SIZE)
#define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE (CONFIG_BT_LE_HCI_EVT_BUF_SIZE)
#else
#define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE (70)
#endif
#if defined(CONFIG_BT_LE_EXT_ADV_MAX_SIZE)
#define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE (CONFIG_BT_LE_EXT_ADV_MAX_SIZE)
#else
#define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE (31)
#endif
#if defined(CONFIG_BT_LE_MAX_EXT_ADV_INSTANCES)
#define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES (CONFIG_BT_LE_MAX_EXT_ADV_INSTANCES)
#else
#define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES (1)
#endif
#if defined(CONFIG_BT_LE_WHITELIST_SIZE)
#define DEFAULT_BT_NIMBLE_WHITELIST_SIZE (CONFIG_BT_LE_WHITELIST_SIZE)
#else
#define DEFAULT_BT_NIMBLE_WHITELIST_SIZE (12)
#endif
#if defined(CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT)
#define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT (CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT)
#else
#define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT (30)
#endif
#if defined(CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT)
#define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT)
#else
#define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (8)
#endif
#define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
#endif // CONFIG_BT_NIMBLE_ENABLED
#ifdef CONFIG_BT_LE_TX_CCA_ENABLED
#define DEFAULT_BT_LE_TX_CCA_ENABLED (CONFIG_BT_LE_TX_CCA_ENABLED)
#define DEFAULT_BT_LE_TX_CCA_ENABLED (CONFIG_BT_LE_TX_CCA_ENABLED)
#else
#define DEFAULT_BT_LE_TX_CCA_ENABLED (0)
#define DEFAULT_BT_LE_TX_CCA_ENABLED (0)
#endif
#ifdef CONFIG_BT_LE_CCA_RSSI_THRESH
#define DEFAULT_BT_LE_CCA_RSSI_THRESH (CONFIG_BT_LE_CCA_RSSI_THRESH)
#define DEFAULT_BT_LE_CCA_RSSI_THRESH (CONFIG_BT_LE_CCA_RSSI_THRESH)
#else
#define DEFAULT_BT_LE_CCA_RSSI_THRESH (50)
#define DEFAULT_BT_LE_CCA_RSSI_THRESH (50)
#endif
#define DEFAULT_BT_LE_SCAN_RSP_DATA_MAX_LEN_N DEFAULT_BT_LE_EXT_ADV_MAX_SIZE
#define UC_BLE_CTRL_CONN_ENABLED (1)
#if defined(CONFIG_BT_NIMBLE_AOA_AOD)
#define UC_BT_CTRL_LE_CTE_ENABLED (CONFIG_BT_NIMBLE_AOA_AOD)
#elif defined(CONFIG_BT_LE_CTE_ENABLED)
#define UC_BT_CTRL_LE_CTE_ENABLED (CONFIG_BT_LE_CTE_ENABLED)
#elif defined(CONFIG_BT_LE_CTE_FEATURE_ENABLED)
#define UC_BT_CTRL_LE_CTE_ENABLED (CONFIG_BT_LE_CTE_FEATURE_ENABLED)
#else
#define UC_BT_CTRL_LE_CTE_ENABLED (0)
#endif // CONFIG_BT_NIMBLE_AOA_AOD
#define UC_BT_CTRL_LE_CTE_CAL_ENABLED (0)
#if CONFIG_BT_LE_DTM_ENABLED
#define UC_BT_CTRL_LE_DTM_ENABLED (CONFIG_BT_LE_DTM_ENABLED)
#else
#define UC_BT_CTRL_LE_DTM_ENABLED (0)
#endif
#if defined(CONFIG_BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES)
#define UC_BLE_CTRL_PAWR_BCAST_SUPPORTED (CONFIG_BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES)
#elif defined(CONFIG_BT_BLE_FEAT_PAWR_EN)
#define UC_BLE_CTRL_PAWR_BCAST_SUPPORTED (CONFIG_BT_BLE_FEAT_PAWR_EN)
#elif defined(CONFIG_BT_LE_PERIODIC_ADV_WITH_RESPONSE_ENABLED)
#define UC_BLE_CTRL_PAWR_BCAST_SUPPORTED (CONFIG_BT_LE_PERIODIC_ADV_WITH_RESPONSE_ENABLED)
#else
#define UC_BLE_CTRL_PAWR_BCAST_SUPPORTED (0)
#endif // CONFIG_BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES
#if defined(CONFIG_BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES)
#define UC_BLE_CTRL_PAWR_SYNC_SUPPORTED (CONFIG_BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES)
#elif defined(CONFIG_BT_BLE_FEAT_PAWR_EN)
#define UC_BLE_CTRL_PAWR_SYNC_SUPPORTED (CONFIG_BT_BLE_FEAT_PAWR_EN)
#elif defined(CONFIG_BT_LE_PERIODIC_SYNC_WITH_RESPONSE_ENABLED)
#define UC_BLE_CTRL_PAWR_SYNC_SUPPORTED (CONFIG_BT_LE_PERIODIC_SYNC_WITH_RESPONSE_ENABLED)
#else
#define UC_BLE_CTRL_PAWR_SYNC_SUPPORTED (0)
#endif // CONFIG_BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES
#define UC_BT_CTRL_LE_BIS_BCAST_ENABLED (CONFIG_BT_LE_ISO_SUPPORT)
#define UC_BT_CTRL_LE_BIS_SYNC_ENABLED (CONFIG_BT_LE_ISO_SUPPORT)
#define UC_BT_CTRL_LE_CIS_CENT_ENABLED (CONFIG_BT_LE_ISO_SUPPORT)
#define UC_BT_CTRL_LE_CIS_PRPH_ENABLED (CONFIG_BT_LE_ISO_SUPPORT)
#define UC_BT_CTRL_LE_CIS_ENABLED (CONFIG_BT_LE_ISO_SUPPORT)
#define UC_BT_CTRL_LE_ISO_ENABLED (CONFIG_BT_LE_ISO_SUPPORT)
#define UC_BT_CTRL_LE_ISO_TEST_ENABLED (CONFIG_BT_LE_ISO_SUPPORT)
#if defined(CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT)
#define UC_BT_CTRL_LE_50_FEATURE_SUPPORT (CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT)
#elif defined(CONFIG_BT_LE_50_FEATURE_SUPPORT)
#define UC_BT_CTRL_LE_50_FEATURE_SUPPORT (CONFIG_BT_LE_50_FEATURE_SUPPORT)
#else
#define UC_BT_CTRL_LE_50_FEATURE_SUPPORT (0)
#endif // CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT
#if defined(CONFIG_BT_NIMBLE_SUBRATE)
#define UC_BT_CTRL_LE_SUBRATE_ENABLED (CONFIG_BT_NIMBLE_SUBRATE)
#elif defined(CONFIG_BT_BLE_FEAT_CONN_SUBRATING)
#define UC_BT_CTRL_LE_SUBRATE_ENABLED (CONFIG_BT_BLE_FEAT_CONN_SUBRATING)
#elif defined(CONFIG_BT_LE_SUBRATE_ENABLED)
#define UC_BT_CTRL_LE_SUBRATE_ENABLED (CONFIG_BT_LE_SUBRATE_ENABLED)
#else
#define UC_BT_CTRL_LE_SUBRATE_ENABLED (0)
#endif // CONFIG_BT_NIMBLE_SUBRATE
#if defined(CONFIG_BT_NIMBLE_BLE_POWER_CONTROL)
#define UC_BT_CTRL_LE_POWER_CONTROL_ENABLED (CONFIG_BT_NIMBLE_BLE_POWER_CONTROL)
#elif defined(CONFIG_BT_LE_POWER_CONTROL_ENABLED)
#define UC_BT_CTRL_LE_POWER_CONTROL_ENABLED (CONFIG_BT_LE_POWER_CONTROL_ENABLED)
#else
#define UC_BT_CTRL_LE_POWER_CONTROL_ENABLED (0)
#endif // CONFIG_BT_NIMBLE_BLE_POWER_CONTROL
#if defined(CONFIG_BT_CTRL_LE_VS_CMD_EVT_ENABLED)
#define UC_BT_CTRL_LE_VS_CMD_EVT_ENABLED (CONFIG_BT_CTRL_LE_VS_CMD_EVT_ENABLED)
#else
#define UC_BT_CTRL_LE_VS_CMD_EVT_ENABLED (0)
#endif // CONFIG_BT_CTRL_LE_VS_CMD_EVT_ENABLED
#if defined(CONFIG_BT_NIMBLE_ADV_SEND_CONSTANT_DID)
#define UC_BT_CTRL_LE_VS_CONST_EXT_ADV_DID (CONFIG_BT_NIMBLE_ADV_SEND_CONSTANT_DID)
#elif defined(CONFIG_BT_CTRL_LE_VS_CONST_EXT_ADV_DID)
#define UC_BT_CTRL_LE_VS_CONST_EXT_ADV_DID (CONFIG_BT_CTRL_LE_VS_CONST_EXT_ADV_DID)
#else
#define UC_BT_CTRL_LE_VS_CONST_EXT_ADV_DID (0)
#endif // CONFIG_BT_NIMBLE_ADV_SEND_CONSTANT_DID
#if defined(CONFIG_BT_NIMBLE_SCAN_ALLOW_ENH_ADI_FILTER)
#define UC_BT_CTRL_LE_VS_ADI_FILTER_ENABLED (CONFIG_BT_NIMBLE_SCAN_ALLOW_ENH_ADI_FILTER)
#elif defined(CONFIG_BT_CTRL_LE_VS_ADI_FILTER_ENABLED)
#define UC_BT_CTRL_LE_VS_ADI_FILTER_ENABLED (CONFIG_BT_CTRL_LE_VS_ADI_FILTER_ENABLED)
#else
#define UC_BT_CTRL_LE_VS_ADI_FILTER_ENABLED (0)
#endif // CONFIG_BT_NIMBLE_SCAN_ALLOW_ENH_ADI_FILTER
#if defined(CONFIG_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS)
#define UC_BT_CTRL_LE_CHECK_CONNECT_IND_ACCESS_ADDRESS (CONFIG_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS)
#else
#define UC_BT_CTRL_LE_CHECK_CONNECT_IND_ACCESS_ADDRESS (0)
#endif // CONFIG_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS
#if defined(CONFIG_BT_LE_CTRL_LLCP_CONN_UPDATE)
#define UC_BT_CTRL_LE_CONN_UPDATE_PASSED_DISC_FLAG (1 << 0)
#else
#define UC_BT_CTRL_LE_CONN_UPDATE_PASSED_DISC_FLAG (0 << 0)
#endif // CONFIG_BT_LE_CTRL_LLCP_CONN_UPDATE
#if defined(CONFIG_BT_LE_CTRL_LLCP_CHAN_MAP_UPDATE)
#define UC_BT_CTRL_LE_CHAN_UPDATE_PASSED_DISC_FLAG (1 << 1)
#else
#define UC_BT_CTRL_LE_CHAN_UPDATE_PASSED_DISC_FLAG (0 << 1)
#endif // CONFIG_BT_LE_CTRL_LLCP_CHAN_MAP_UPDATE
#if defined(CONFIG_BT_LE_CTRL_LLCP_PHY_UPDATE)
#define UC_BT_CTRL_LE_PHY_UPDATE_PASSED_DISC_FLAG (1 << 2)
#else
#define UC_BT_CTRL_LE_PHY_UPDATE_PASSED_DISC_FLAG (0 << 2)
#endif // CONFIG_BT_LE_CTRL_LLCP_PHY_UPDATE
#define UC_BT_CTRL_LLCP_INSTANT_PASSED_DISC_FLAGS \
(UC_BT_CTRL_LE_CONN_UPDATE_PASSED_DISC_FLAG | UC_BT_CTRL_LE_CHAN_UPDATE_PASSED_DISC_FLAG | \
UC_BT_CTRL_LE_PHY_UPDATE_PASSED_DISC_FLAG)
#if defined(CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX)
#define UC_BT_CTRL_LE_SCAN_BACKOFF_UPPERLIMITMAX (CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX)
#else
#define UC_BT_CTRL_LE_SCAN_BACKOFF_UPPERLIMITMAX (256)
#endif // CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX
#if defined(CONFIG_BT_LE_CTRL_CHAN_ASS_EN)
#define UC_BT_CTRL_LE_CHAN_ASS_ENABLED (CONFIG_BT_LE_CTRL_CHAN_ASS_EN)
#else
#define UC_BT_CTRL_LE_CHAN_ASS_ENABLED (0)
#endif // CONFIG_BT_LE_CTRL_CHAN_ASS_EN
#if defined(CONFIG_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX)
#define UC_BT_CTRL_LE_ADV_DATA_LENGTH_ZERO_AUX (CONFIG_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX)
#else
#define UC_BT_CTRL_LE_ADV_DATA_LENGTH_ZERO_AUX (1)
#endif // CONFIG_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX
#if defined(CONFIG_BT_LE_PTR_CHECK_ENABLED)
#define UC_BT_CTRL_LE_PTR_CHECK_ENABLED (CONFIG_BT_LE_PTR_CHECK_ENABLED)
#else
#define UC_BT_CTRL_LE_PTR_CHECK_ENABLED (0)
#endif // CONFIG_BT_LE_PTR_CHECK_ENABLED
#if defined(CONFIG_BT_LE_CTRL_ADV_EVENT_INC_ON_FULL_TX_EN)
#define UC_BT_CTRL_LE_ADV_EVENT_INC_ON_FULL_TX_EN (1 << 0)
#else
#define UC_BT_CTRL_LE_ADV_EVENT_INC_ON_FULL_TX_EN (0)
#endif // BT_LE_CTRL_ADV_EVENT_INC_ON_FULL_TX_EN
#if defined(CONFIG_BT_LE_CTRL_ADV_CH38_39_TX_AVOID_CONFLICT_EN)
#define UC_BT_CTRL_LE_ADV_CH38_39_TX_AVOID_CONFLICT_EN (1 << 1)
#else
#define UC_BT_CTRL_LE_ADV_CH38_39_TX_AVOID_CONFLICT_EN (0)
#endif // BT_LE_CTRL_ADV_CH38_39_TX_AVOID_CONFLICT_EN
#if defined(CONFIG_BT_LE_ADV_CH39_TXPWR_CONFIG_SEPARATELY_EN)
#define UC_BT_ADV__LECH39_TXPWR_CONFIG_SEPARATELY_EN (1 << 2)
#define UC_BT_CTRL_LE_CH39_TX_PWR_DBM (CONFIG_BT_LE_DFT_CH39_TX_POWER_LEVEL_DBM_EFF)
#else
#define UC_BT_ADV__LECH39_TXPWR_CONFIG_SEPARATELY_EN (0)
#define UC_BT_CTRL_LE_CH39_TX_PWR_DBM (CONFIG_BT_LE_DFT_TX_POWER_LEVEL_DBM_EFF)
#endif // BT_LE_ADV_CH39_TXPWR_CONFIG_SEPARATELY_EN
#if defined(CONFIG_BT_LE_CTRL_ADV_TX_CONTINUE_WHEN_EXCEED_ITVL_EN)
#define UC_BT_CTRL_LE_ADV_TX_CONTINUE_WHEN_EXCEED_ITVL_EN (1 << 3)
#else
#define UC_BT_CTRL_LE_ADV_TX_CONTINUE_WHEN_EXCEED_ITVL_EN (0)
#endif // BT_LE_CTRL_ADV_TX_CONTINUE_WHEN_EXCEED_ITVL_EN
#if defined(CONFIG_BT_LE_CTRL_ADV_RAND_CH_IDX_EN)
#define UC_BT_CTRL_LE_ADV_RAND_CH_IDX_EN (1 << 4)
#else
#define UC_BT_CTRL_LE_ADV_RAND_CH_IDX_EN (0)
#endif // BT_LE_CTRL_ADV_RAND_CH_IDX_EN
#define UC_BT_CTRL_LE_ADV_TX_OPTIONS \
(UC_BT_CTRL_LE_ADV_EVENT_INC_ON_FULL_TX_EN | UC_BT_CTRL_LE_ADV_CH38_39_TX_AVOID_CONFLICT_EN | \
UC_BT_ADV__LECH39_TXPWR_CONFIG_SEPARATELY_EN | \
UC_BT_CTRL_LE_ADV_TX_CONTINUE_WHEN_EXCEED_ITVL_EN | UC_BT_CTRL_LE_ADV_RAND_CH_IDX_EN)
#if defined(CONFIG_BT_LE_CTRL_FAST_CONN_DATA_TX_EN)
#define UC_BT_CTRL_LE_FAST_CONN_DATA_TX_EN (CONFIG_BT_LE_CTRL_FAST_CONN_DATA_TX_EN)
#else
#define UC_BT_CTRL_LE_FAST_CONN_DATA_TX_EN (0)
#endif // CONFIG_BT_LE_CTRL_FAST_CONN_DATA_TX_EN
/* Unchanged configuration */
#define BLE_LL_CTRL_PROC_TIMEOUT_MS_N (40000) /* ms */
#define BLE_LL_CTRL_PROC_TIMEOUT_MS_N (40000) /* ms */
#define BLE_LL_CFG_NUM_HCI_CMD_PKTS_N (1)
#define BLE_LL_CFG_NUM_HCI_CMD_PKTS_N (1)
#define BLE_LL_SCHED_ADV_MAX_USECS_N (852)
#define BLE_LL_SCHED_ADV_MAX_USECS_N (852)
#define BLE_LL_SCHED_DIRECT_ADV_MAX_USECS_N (502)
#define BLE_LL_SCHED_MAX_ADV_PDU_USECS_N (376)
#define BLE_LL_SCHED_MAX_ADV_PDU_USECS_N (376)
#define BLE_LL_SUB_VERS_NR_N (0x0000)
#define BLE_LL_SUB_VERS_NR_N (0x0000)
#define BLE_LL_JITTER_USECS_N (16)
#define BLE_LL_JITTER_USECS_N (16)
#define BLE_PHY_MAX_PWR_DBM_N (10)
#define BLE_PHY_MAX_PWR_DBM_N (10)
#define BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N (3000)
#define BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N (3000)
#define RTC_FREQ_N (32768) /* in Hz */
#define RTC_FREQ_N (32768) /* in Hz */
#define BLE_LL_TX_PWR_DBM_N (9)
#define BLE_LL_TX_PWR_DBM_N (9)
#ifdef CONFIG_BT_LE_BQB_TEST_EN
#define RUN_BQB_TEST (CONFIG_BT_LE_BQB_TEST_EN)
#define RUN_BQB_TEST (CONFIG_BT_LE_BQB_TEST_EN)
#else
#define RUN_BQB_TEST (0)
#define RUN_BQB_TEST (0)
#endif // CONFIG_BT_LE_BQB_TEST_EN
#define RUN_QA_TEST (0)
#define NIMBLE_DISABLE_SCAN_BACKOFF (0)
#define RUN_QA_TEST (0)
#define NIMBLE_DISABLE_SCAN_BACKOFF (0)
#ifdef __cplusplus
}
@@ -1,7 +1,9 @@
/*
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2019-2026 Espressif Systems (Shanghai) CO LTD
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -34,10 +36,9 @@
#define _OS_MEMPOOL_H_
#include <stdbool.h>
#include "os/os.h"
#include "os/os_error.h"
#include "os/queue.h"
#include "btdm_mempool.h"
#include "syscfg/syscfg.h"
#ifdef __cplusplus
extern "C" {
@@ -78,20 +79,28 @@ struct os_mempool {
SLIST_HEAD(,os_memblock);
/** Name for memory block */
const char *name;
#if MYNEWT_VAL(MP_BLOCK_REUSED)
/** The number of allocated blocks. */
uint16_t mp_alloc_blocks;
#endif // MYNEWT_VAL(MP_BLOCK_REUSED)
};
static_assert(sizeof(struct os_mempool) == sizeof(struct btdm_mempool),
"Error: size of os_mempool");
/**
* Indicates an extended mempool. Address can be safely cast to
* (struct os_mempool_ext *).
*/
#define OS_MEMPOOL_F_EXT 0x01
#define OS_MEMPOOL_F_EXT BIT(0)
/* Flag to indicate runtime allocation mode */
#define OS_MEMPOOL_F_RUNTIME 0x02
#define OS_MEMPOOL_F_RUNTIME BIT(1)
/* Flag to indicate reuse block for runtime allocation mode */
#define OS_MEMPOOL_F_REUSED 0x04
#define OS_MEMPOOL_F_REUSED BIT(2)
/* Flag to indicate no address range comparison */
#define OS_MEMPOOL_F_FRAG BIT(3)
/* Flag to indicate mempool source */
#define OS_MEMPOOL_F_CONTROLLER BIT(4)
#define OS_MEMPOOL_F_LOW_PRIO BIT(5)
#define OS_MEMPOOL_F_FORBID BIT(6)
#define OS_MEMPOOL_F_COMBINATION BIT(7)
struct os_mempool_ext;
@@ -116,12 +125,27 @@ struct os_mempool_ext;
typedef os_error_t os_mempool_put_fn(struct os_mempool_ext *ome, void *data,
void *arg);
/**
* Block get callback function. If configured, this callback gets executed
* whenever a block is fetched from the corresponding extended mempool.
*
* @param ome The extended mempool that a block is being
* fetched.
* @param arg Optional argument configured along with the
* callback.
*
* @return void * pointer of block, return NULL if get failed
*/
typedef void *os_mempool_get_fn(struct os_mempool_ext *ome, void *arg);
struct os_mempool_ext {
struct os_mempool mpe_mp;
/* Callback that is executed immediately when a block is freed. */
os_mempool_put_fn *mpe_put_cb;
void *mpe_put_arg;
os_mempool_get_fn *mpe_get_cb;
void *mpe_get_arg;
};
#define OS_MEMPOOL_INFO_NAME_LEN (32)
@@ -156,19 +180,6 @@ struct os_mempool_info {
struct os_mempool *os_mempool_info_get_next(struct os_mempool *,
struct os_mempool_info *);
/*
* To calculate size of the memory buffer needed for the pool. NOTE: This size
* is NOT in bytes! The size is the number of os_membuf_t elements required for
* the memory pool.
*/
#if MYNEWT_VAL(OS_MEMPOOL_GUARD)
/*
* Leave extra 4 bytes of guard area at the end.
*/
#define OS_MEMPOOL_BLOCK_SZ(sz) ((sz) + sizeof(os_membuf_t))
#else
#define OS_MEMPOOL_BLOCK_SZ(sz) (sz)
#endif
#if (OS_ALIGNMENT == 4)
typedef uint32_t os_membuf_t;
#elif (OS_ALIGNMENT == 8)
@@ -180,142 +191,11 @@ typedef __uint128_t os_membuf_t;
#endif /* OS_ALIGNMENT == * */
#define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + ((OS_ALIGNMENT)-1)) / (OS_ALIGNMENT)) * (n))
/**
* Calculates the number of bytes required to initialize a memory pool.
* When OS_MEMPOOL_GUARD is enabled, one extra os_membuf_t word per block is
* included for the guard pattern written by os_mempool_init; the buffer passed
* to os_mempool_init must be at least this size.
*/
#if CONFIG_BT_NIMBLE_ENABLED
#if MYNEWT_VAL(OS_MEMPOOL_GUARD)
#define OS_MEMPOOL_BYTES(n,blksize) \
(sizeof (os_membuf_t) * (OS_MEMPOOL_SIZE((n), (blksize)) + (n)))
#else
/** Calculates the number of bytes required to initialize a memory pool. */
#define OS_MEMPOOL_BYTES(n,blksize) \
(sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize)))
#endif
#else
#define OS_MEMPOOL_BYTES(n,blksize) \
(sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize)))
#endif
#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
/**
* Initialize a memory pool.
*
* @param mp Pointer to a pointer to a mempool
* @param blocks The number of blocks in the pool
* @param blocks_size The size of the block, in bytes.
* @param membuf Pointer to memory to contain blocks.
* @param name Name of the pool.
*
* @return os_error_t
*/
os_error_t r_os_mempool_init(struct os_mempool *mp, uint16_t blocks,
uint32_t block_size, void *membuf, const char *name);
#define os_mempool_init r_os_mempool_init
/**
* Initializes an extended memory pool. Extended attributes (e.g., callbacks)
* are not specified when this function is called; they are assigned manually
* after initialization.
*
* @param mpe The extended memory pool to initialize.
* @param blocks The number of blocks in the pool.
* @param block_size The size of each block, in bytes.
* @param membuf Pointer to memory to contain blocks.
* @param name Name of the pool.
*
* @return os_error_t
*/
os_error_t r_os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
uint32_t block_size, void *membuf, const char *name);
#define os_mempool_ext_init r_os_mempool_ext_init
/**
* Removes the specified mempool from the list of initialized mempools.
*
* @param mp The mempool to unregister.
*
* @return 0 on success;
* OS_INVALID_PARM if the mempool is not
* registered.
*/
// os_error_t r_os_mempool_unregister(struct os_mempool *mp);
#define os_mempool_unregister(mp)
/**
* Clears a memory pool.
*
* @param mp The mempool to clear.
*
* @return os_error_t
*/
os_error_t r_os_mempool_clear(struct os_mempool *mp);
#define os_mempool_clear r_os_mempool_clear
/**
* Performs an integrity check of the specified mempool. This function
* attempts to detect memory corruption in the specified memory pool.
*
* @param mp The mempool to check.
*
* @return true if the memory pool passes the integrity
* check;
* false if the memory pool is corrupt.
*/
bool r_os_mempool_is_sane(const struct os_mempool *mp);
#define os_mempool_is_sane r_os_mempool_is_sane
/**
* Checks if a memory block was allocated from the specified mempool.
*
* @param mp The mempool to check as parent.
* @param block_addr The memory block to check as child.
*
* @return 0 if the block does not belong to the mempool;
* 1 if the block does belong to the mempool.
*/
int r_os_memblock_from(const struct os_mempool *mp, const void *block_addr);
#define os_memblock_from r_os_memblock_from
/**
* Get a memory block from a memory pool
*
* @param mp Pointer to the memory pool
*
* @return void* Pointer to block if available; NULL otherwise
*/
void *r_os_memblock_get(struct os_mempool *mp);
#define os_memblock_get r_os_memblock_get
/**
* Puts the memory block back into the pool, ignoring the put callback, if any.
* This function should only be called from a put callback to free a block
* without causing infinite recursion.
*
* @param mp Pointer to memory pool
* @param block_addr Pointer to memory block
*
* @return os_error_t
*/
os_error_t r_os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr);
#define os_memblock_put_from_cb r_os_memblock_put_from_cb
/**
* Puts the memory block back into the pool
*
* @param mp Pointer to memory pool
* @param block_addr Pointer to memory block
*
* @return os_error_t
*/
os_error_t r_os_memblock_put(struct os_mempool *mp, void *block_addr);
#define os_memblock_put r_os_memblock_put
#else
#if !CONFIG_BT_DUAL_MODE_ARCH
/**
* Initialize a memory pool.
*
@@ -330,6 +210,24 @@ os_error_t r_os_memblock_put(struct os_mempool *mp, void *block_addr);
os_error_t os_mempool_init(struct os_mempool *mp, uint16_t blocks,
uint32_t block_size, void *membuf, const char *name);
/**
* @brief Initialize a memory pool.
* INTERNAL USE ONLY
*
* @param mp Pointer to a pointer to a mempool
* @param blocks The number of blocks in the pool
* @param blocks_size The size of the block, in bytes.
* @param membuf Pointer to memory to contain blocks.
* @param name Name of the pool.
* @param flags Mempool flags
*
* @return os_error_t
*/
os_error_t
os_mempool_init_internal(struct os_mempool *mp, uint16_t blocks,
uint32_t block_size, void *membuf, const char *name,
uint8_t flags);
/**
* Initializes an extended memory pool. Extended attributes (e.g., callbacks)
* are not specified when this function is called; they are assigned manually
@@ -346,6 +244,18 @@ os_error_t os_mempool_init(struct os_mempool *mp, uint16_t blocks,
os_error_t os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
uint32_t block_size, void *membuf, const char *name);
/**
* Assign the put and get callback for an extended memory pool.
*
* @param mpe The extended memory pool
* @param put_cb Block put callback function
* @param put_arg Argument for put callback
* @param get_cb Block put callback function
* @param get_arg Argument for get callback
*/
void os_ext_mempool_register_cb(struct os_mempool_ext *mpe, void *put_cb, void *put_arg,
void *get_cb, void *get_arg);
/**
* Removes the specified mempool from the list of initialized mempools.
*
@@ -428,7 +338,116 @@ os_error_t os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr);
* @return os_error_t
*/
os_error_t os_memblock_put(struct os_mempool *mp, void *block_addr);
#endif
/**
* @brief Set the mp_flags of memory pool
*
* @param mp Pointer to memory pool
* @param flags Flags value
*/
void os_mempool_flags_set(struct os_mempool *mp, uint8_t flags);
/**
* @brief Clear the mp_flags of memory pool
*
* @param mp Pointer to memory pool
* @param flags Flags value
*/
void os_mempool_flags_clear(struct os_mempool *mp, uint8_t flags);
#else /* !CONFIG_BT_DUAL_MODE_ARCH */
#include "btdm_mempool.h"
static_assert(sizeof(struct os_mempool) == sizeof(struct btdm_mempool), "Error: size of os_mempool");
static_assert(sizeof(struct os_mempool_ext) == sizeof(struct btdm_mempool_ext), "Error: size of os_mempool_ext");
static_assert(sizeof(struct os_memblock) == sizeof(struct btdm_memblock), "Error: size of os_memblock");
static inline os_error_t
os_mempool_init(struct os_mempool *mp, uint16_t blocks, uint32_t block_size,
void *membuf, const char *name)
{
return btdm_mempool_init((struct btdm_mempool *)mp, blocks, block_size,
membuf, name);
}
static inline os_error_t
os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
uint32_t block_size, void *membuf, const char *name)
{
return btdm_mempool_ext_init((struct btdm_mempool_ext *)mpe, blocks,
block_size, membuf, name);
}
static inline void
os_ext_mempool_register_cb(struct os_mempool_ext *mpe, void *put_cb,
void *put_arg, void *get_cb, void *get_arg)
{
btdm_mempool_ext_register_cb((struct btdm_mempool_ext *)mpe, put_cb,
put_arg, get_cb, get_arg);
}
static inline os_error_t
os_mempool_unregister(struct os_mempool *mp)
{
return btdm_mempool_unregister((struct btdm_mempool *)mp);
}
static inline os_error_t
os_mempool_clear(struct os_mempool *mp)
{
return btdm_mempool_clear((struct btdm_mempool *)mp);
}
static inline os_error_t
os_mempool_ext_clear(struct os_mempool_ext *mpe)
{
return btdm_mempool_ext_clear((struct btdm_mempool_ext *)mpe);
}
static inline bool
os_mempool_is_sane(const struct os_mempool *mp)
{
return btdm_mempool_is_sane((const struct btdm_mempool *)mp);
}
static inline int
os_memblock_from(const struct os_mempool *mp, const void *block_addr)
{
return btdm_memblock_from((const struct btdm_mempool *)mp, block_addr);
}
static inline void *
os_memblock_get(struct os_mempool *mp)
{
return btdm_memblock_get((struct btdm_mempool *)mp);
}
static inline os_error_t
os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr)
{
return btdm_memblock_put_from_cb((struct btdm_mempool *)mp, block_addr);
}
static inline os_error_t
os_memblock_put(struct os_mempool *mp, void *block_addr)
{
return btdm_memblock_put((struct btdm_mempool *)mp, block_addr);
}
static inline void
os_mempool_flags_set(struct os_mempool *mp, uint8_t flags)
{
btdm_mempool_flags_set((struct btdm_mempool *)mp, flags);
}
static inline void
os_mempool_flags_clear(struct os_mempool *mp, uint8_t flags)
{
btdm_mempool_flags_clear((struct btdm_mempool *)mp, flags);
}
#endif /* !CONFIG_BT_DUAL_MODE_ARCH */
#ifdef __cplusplus
}
File diff suppressed because it is too large Load Diff
@@ -16,6 +16,11 @@ int bredr_stack_enable(void);
void bredr_stack_disable(void);
int bredr_stack_reset(void);
int bredr_hci_cmd_rx_handler(uint16_t opcode, const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf,
uint8_t *rsplen);
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
esp_err_t sleep_modem_bredr_mac_modem_state_init(void);
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE
@@ -7,7 +7,7 @@
#define _BTDM_LP_H_
#include "esp_private/esp_modem_clock.h"
void btdm_lp_enable_clock(esp_btdm_controller_config_t *cfg);
void btdm_lp_enable_clock(esp_bt_ctrl_btdm_config_t *cfg);
void btdm_lp_disable_clock(void);
@@ -0,0 +1,81 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BTDM_MEM_DEBUG_H_
#define _BTDM_MEM_DEBUG_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable BTDM OSAL malloc/free leak tracking.
* Set to 0 to compile out the tracking hooks.
*/
#ifndef BTDM_MEM_DEBUG
#define BTDM_MEM_DEBUG 1
#endif
#if BTDM_MEM_DEBUG
/**
* @brief Record an allocation (address, size, and auto-incremented sequence).
*
* @param ptr Allocated memory address
* @param size Allocation size in bytes
*/
void btdm_mem_debug_record(void *ptr, uint32_t size);
/**
* @brief Clear the record for a freed address.
*
* @param ptr Memory address being freed
*/
void btdm_mem_debug_clear(void *ptr);
/**
* @brief Print all outstanding (not yet freed) allocations.
*
* Prints address, size and sequence number for each leak.
*/
void btdm_mem_debug_dump(void);
/**
* @brief Get number of currently tracked (unfreed) allocations.
*/
uint32_t btdm_mem_debug_get_count(void);
#else /* !BTDM_MEM_DEBUG */
static inline void btdm_mem_debug_record(void *ptr, uint32_t size)
{
(void)ptr;
(void)size;
}
static inline void btdm_mem_debug_clear(void *ptr)
{
(void)ptr;
}
static inline void btdm_mem_debug_dump(void)
{
}
static inline uint32_t btdm_mem_debug_get_count(void)
{
return 0;
}
#endif /* BTDM_MEM_DEBUG */
#ifdef __cplusplus
}
#endif
#endif /* _BTDM_MEM_DEBUG_H_ */
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -27,12 +27,15 @@
#define _BTDM_MEMPOOL_H_
#include "btdm_osal.h"
#include "btdm_user_cfg.h"
#include "queue.h"
#ifdef __cplusplus
extern "C" {
#endif
#define BTDM_MEMPOOL_EXT_FUNC(f) e_##f
/**
* A memory block structure. This simply contains a pointer to the free list
* chain and is only used when the block is on the free list. When the block
@@ -40,7 +43,7 @@ extern "C" {
* caller.
*/
struct btdm_memblock {
SLIST_ENTRY(btdm_memblock) mb_next;
SLIST_ENTRY(btdm_memblock) mb_next;
};
/* XXX: Change this structure so that we keep the first address in the pool? */
@@ -52,33 +55,31 @@ struct btdm_memblock {
* Memory pool
*/
struct btdm_mempool {
/** Size of the memory blocks, in bytes. */
uint32_t mp_block_size;
/** The number of memory blocks. */
uint16_t mp_num_blocks;
/** The number of free blocks left */
uint16_t mp_num_free;
/** The lowest number of free blocks seen */
uint16_t mp_min_free;
/** Bitmap of OS_MEMPOOL_F_[...] values. */
uint8_t mp_flags;
/** Address of memory buffer used by pool */
uint32_t mp_membuf_addr;
STAILQ_ENTRY(btdm_mempool) mp_list;
SLIST_HEAD(, btdm_memblock);
/** Name for memory block */
const char *name;
/** Size of the memory blocks, in bytes. */
uint32_t mp_block_size;
/** The number of memory blocks. */
uint16_t mp_num_blocks;
/** The number of free blocks left */
uint16_t mp_num_free;
/** The lowest number of free blocks seen */
uint16_t mp_min_free;
/** Bitmap of OS_MEMPOOL_F_[...] values. */
uint8_t mp_flags;
/** Address of memory buffer used by pool */
uint32_t mp_membuf_addr;
STAILQ_ENTRY(btdm_mempool) mp_list;
SLIST_HEAD(, btdm_memblock);
/** Name for memory block */
const char *name;
#if UC_BT_CTRL_MEMPOOL_BLOCK_REUSED
/** The number of allocated blocks. */
uint16_t mp_alloc_blocks;
#endif // UC_BT_CTRL_MEMPOOL_BLOCK_REUSED
};
/**
* Indicates an extended mempool. Address can be safely cast to
* (struct btdm_mempool_ext *).
*/
#define BTDM_MEMPOOL_F_EXT 0x01
#define BTDM_ALIGNMENT 4
#define BTDM_MEMPOOL_SIZE(n, blksize) \
((((blksize) + ((BTDM_ALIGNMENT) - 1)) / (BTDM_ALIGNMENT)) * (n))
#define BTDM_MEMPOOL_SIZE(n, blksize) \
((((blksize) + ((BTDM_ALIGNMENT)-1)) / (BTDM_ALIGNMENT)) * (n))
#if (BTDM_ALIGNMENT == 4)
typedef uint32_t btdm_membuf_t;
@@ -90,6 +91,69 @@ typedef __uint128_t btdm_membuf_t;
#error "Unhandled `BTDM_ALIGNMENT` for `btdm_membuf_t`"
#endif /* BTDM_ALIGNMENT == * */
/**
* Indicates an extended mempool. Address can be safely cast to
* (struct btdm_mempool_ext *).
*/
#define BTDM_MEMPOOL_F_EXT (1 << 0)
/* Flag to indicate runtime allocation mode */
#define BTDM_MEMPOOL_F_RUNTIME (1 << 1)
/* Flag to indicate reuse block for runtime allocation mode */
#define BTDM_MEMPOOL_F_REUSED (1 << 2)
/* Flag to indicate no address range comparison */
#define BTDM_MEMPOOL_F_FRAG (1 << 3)
/* Flag to indicate mempool source */
#define BTDM_MEMPOOL_F_CONTROLLER (1 << 4)
#define BTDM_MEMPOOL_F_LOW_PRIO (1 << 5)
#define BTDM_MEMPOOL_F_FORBID (1 << 6)
#define BTDM_MEMPOOL_F_COMBINATION (1 << 7)
struct btdm_mempool_ext;
/**
* Block put callback function. If configured, this callback gets executed
* whenever a block is freed to the corresponding extended mempool. Note: The
* os_memblock_put() function calls this callback instead of freeing the block
* itself. Therefore, it is the callback's responsibility to free the block
* via a call to os_memblock_put_from_cb().
*
* @param ome The extended mempool that a block is being
* freed back to.
* @param data The block being freed.
* @param arg Optional argument configured along with the
* callback.
*
* @return Indicates whether the block was successfully
* freed. A non-zero value should only be
* returned if the block was not successfully
* released back to its pool.
*/
typedef btdm_osal_error_t btdm_mempool_put_fn(struct btdm_mempool_ext *ome,
void *data, void *arg);
/**
* Block get callback function. If configured, this callback gets executed
* whenever a block is fetched from the corresponding extended mempool.
*
* @param ome The extended mempool that a block is being
* fetched.
* @param arg Optional argument configured along with the
* callback.
*
* @return void * pointer of block, return NULL if get failed
*/
typedef void *btdm_mempool_get_fn(struct btdm_mempool_ext *ome, void *arg);
struct btdm_mempool_ext {
struct btdm_mempool mpe_mp;
/* Callback that is executed immediately when a block is freed. */
btdm_mempool_put_fn *mpe_put_cb;
void *mpe_put_arg;
btdm_mempool_get_fn *mpe_get_cb;
void *mpe_get_arg;
};
/**
* Initialize a memory pool.
*
@@ -101,17 +165,11 @@ typedef __uint128_t btdm_membuf_t;
*
* @return btdm_osal_error_t
*/
static inline btdm_osal_error_t
btdm_mempool_init(struct btdm_mempool *mp, uint16_t blocks, uint32_t block_size, void *membuf,
const char *name)
{
extern btdm_osal_error_t r_btdm_os_mempool_init(struct btdm_mempool * mp, uint16_t blocks,
uint32_t block_size, void *membuf,
const char *name);
return r_btdm_os_mempool_init(mp, blocks, block_size, membuf, name);
}
btdm_osal_error_t e_btdm_mempool_init(struct btdm_mempool *mp, uint16_t blocks,
uint32_t block_size, void *membuf,
const char *name);
#define btdm_mempool_init BTDM_MEMPOOL_EXT_FUNC(btdm_mempool_init)
#if 0
/**
* Initializes an extended memory pool. Extended attributes (e.g., callbacks)
* are not specified when this function is called; they are assigned manually
@@ -125,16 +183,36 @@ btdm_mempool_init(struct btdm_mempool *mp, uint16_t blocks, uint32_t block_size,
*
* @return btdm_osal_error_t
*/
static inline btdm_osal_error_t
btdm_mempool_ext_init(struct btdm_mempool_ext *mpe, uint16_t blocks, uint32_t block_size,
void *membuf, const char *name)
{
extern btdm_osal_error_t r_btdm_os_mempool_ext_init(struct btdm_mempool_ext * mpe,
uint16_t blocks, uint32_t block_size,
void *membuf, const char *name);
return r_btdm_os_mempool_ext_init(mpe, blocks, block_size, membuf, name);
}
#endif
btdm_osal_error_t e_btdm_mempool_ext_init(struct btdm_mempool_ext *mpe,
uint16_t blocks, uint32_t block_size,
void *membuf, const char *name);
#define btdm_mempool_ext_init BTDM_MEMPOOL_EXT_FUNC(btdm_mempool_ext_init)
/**
* Assign the put and get callback for an extended memory pool.
*
* @param mpe The extended memory pool
* @param put_cb Block put callback function
* @param put_arg Argument for put callback
* @param get_cb Block put callback function
* @param get_arg Argument for get callback
*/
void e_btdm_mempool_ext_register_cb(struct btdm_mempool_ext *mpe, void *put_cb,
void *put_arg, void *get_cb, void *get_arg);
#define btdm_mempool_ext_register_cb \
BTDM_MEMPOOL_EXT_FUNC(btdm_mempool_ext_register_cb)
/**
* Removes the specified mempool from the list of initialized mempools.
*
* @param mp The mempool to unregister.
*
* @return 0 on success;
* OS_INVALID_PARM if the mempool is not
* registered.
*/
btdm_osal_error_t e_btdm_mempool_unregister(struct btdm_mempool *mp);
#define btdm_mempool_unregister BTDM_MEMPOOL_EXT_FUNC(btdm_mempool_unregister)
/**
* Clears a memory pool.
@@ -143,12 +221,18 @@ btdm_mempool_ext_init(struct btdm_mempool_ext *mpe, uint16_t blocks, uint32_t bl
*
* @return btdm_osal_error_t
*/
static inline btdm_osal_error_t
btdm_mempool_clear(struct btdm_mempool *mp)
{
extern btdm_osal_error_t r_btdm_os_mempool_clear(struct btdm_mempool * mp);
return r_btdm_os_mempool_clear(mp);
}
btdm_osal_error_t e_btdm_mempool_clear(struct btdm_mempool *mp);
#define btdm_mempool_clear BTDM_MEMPOOL_EXT_FUNC(btdm_mempool_clear)
/**
* Clears an extended memory pool.
*
* @param mpe The extended memory pool to clear.
*
* @return btdm_osal_error_t
*/
btdm_osal_error_t e_btdm_mempool_ext_clear(struct btdm_mempool_ext *mpe);
#define btdm_mempool_ext_clear BTDM_MEMPOOL_EXT_FUNC(btdm_mempool_ext_clear)
/**
* Performs an integrity check of the specified mempool. This function
@@ -160,12 +244,8 @@ btdm_mempool_clear(struct btdm_mempool *mp)
* check;
* false if the memory pool is corrupt.
*/
static inline bool
btdm_mempool_is_sane(const struct btdm_mempool *mp)
{
extern bool r_btdm_os_mempool_is_sane(const struct btdm_mempool *mp);
return r_btdm_os_mempool_is_sane(mp);
}
bool e_btdm_mempool_is_sane(const struct btdm_mempool *mp);
#define btdm_mempool_is_sane BTDM_MEMPOOL_EXT_FUNC(btdm_mempool_is_sane)
/**
* Checks if a memory block was allocated from the specified mempool.
@@ -176,12 +256,8 @@ btdm_mempool_is_sane(const struct btdm_mempool *mp)
* @return 0 if the block does not belong to the mempool;
* 1 if the block does belong to the mempool.
*/
static inline int
btdm_memblock_from(const struct btdm_mempool *mp, const void *block_addr)
{
extern int r_btdm_os_memblock_from(const struct btdm_mempool *mp, const void *block_addr);
return r_btdm_os_memblock_from(mp, block_addr);
}
int e_btdm_memblock_from(const struct btdm_mempool *mp, const void *block_addr);
#define btdm_memblock_from BTDM_MEMPOOL_EXT_FUNC(btdm_memblock_from)
/**
* Get a memory block from a memory pool
@@ -190,12 +266,8 @@ btdm_memblock_from(const struct btdm_mempool *mp, const void *block_addr)
*
* @return void* Pointer to block if available; NULL otherwise
*/
static inline void *
btdm_memblock_get(struct btdm_mempool *mp)
{
extern void *r_btdm_os_memblock_get(struct btdm_mempool * mp);
return r_btdm_os_memblock_get(mp);
}
void *e_btdm_memblock_get(struct btdm_mempool *mp);
#define btdm_memblock_get BTDM_MEMPOOL_EXT_FUNC(btdm_memblock_get)
/**
* Puts the memory block back into the pool, ignoring the put callback, if any.
@@ -207,13 +279,8 @@ btdm_memblock_get(struct btdm_mempool *mp)
*
* @return btdm_osal_error_t
*/
static inline btdm_osal_error_t
btdm_mempool_put_from_cb(struct btdm_mempool *mp, void *block_addr)
{
extern btdm_osal_error_t r_btdm_os_memblock_put_from_cb(struct btdm_mempool * mp,
void *block_addr);
return r_btdm_os_memblock_put_from_cb(mp, block_addr);
}
btdm_osal_error_t e_btdm_memblock_put_from_cb(struct btdm_mempool *mp, void *block_addr);
#define btdm_memblock_put_from_cb BTDM_MEMPOOL_EXT_FUNC(btdm_memblock_put_from_cb)
/**
* Puts the memory block back into the pool
@@ -223,19 +290,52 @@ btdm_mempool_put_from_cb(struct btdm_mempool *mp, void *block_addr)
*
* @return btdm_osal_error_t
*/
static inline btdm_osal_error_t
btdm_memblock_put(struct btdm_mempool *mp, void *block_addr)
{
extern btdm_osal_error_t r_btdm_os_memblock_put(struct btdm_mempool * mp, void *block_addr);
return r_btdm_os_memblock_put(mp, block_addr);
}
btdm_osal_error_t e_btdm_memblock_put(struct btdm_mempool *mp,
void *block_addr);
#define btdm_memblock_put BTDM_MEMPOOL_EXT_FUNC(btdm_memblock_put)
static inline uint16_t
btdm_memblock_free_num_get(struct btdm_mempool *mp)
{
extern uint16_t r_btdm_os_memblock_num_free(struct btdm_mempool * mp);
return r_btdm_os_memblock_num_free(mp);
}
/**
* Set the flags of a memory pool.
*
* @param mp Pointer to memory pool
* @param flags Flags value
*/
void e_btdm_mempool_flags_set(struct btdm_mempool *mp, uint8_t flags);
#define btdm_mempool_flags_set BTDM_MEMPOOL_EXT_FUNC(btdm_mempool_flags_set)
/**
* Clear the flags of a memory pool.
*
* @param mp Pointer to memory pool
* @param flags Flags value
*/
void e_btdm_mempool_flags_clear(struct btdm_mempool *mp, uint8_t flags);
#define btdm_mempool_flags_clear BTDM_MEMPOOL_EXT_FUNC(btdm_mempool_flags_clear)
/**
* Get the number of free blocks in a memory pool.
*
* @param mp Pointer to memory pool
*
* @return uint16_t Number of free blocks
*/
uint16_t e_btdm_mempool_free_blocks_num(struct btdm_mempool *mp);
#define btdm_mempool_free_blocks_num \
BTDM_MEMPOOL_EXT_FUNC(btdm_mempool_free_blocks_num)
/**
* Initialize the memory pool module.
*/
void e_btdm_mempool_module_init(void);
#define btdm_mempool_module_init BTDM_MEMPOOL_EXT_FUNC(btdm_mempool_module_init)
/**
* Deinitialize the memory pool module.
*
* @param is_controller Whether called from controller.
*/
void e_btdm_mempool_deinit(bool is_controller);
#define btdm_mempool_deinit BTDM_MEMPOOL_EXT_FUNC(btdm_mempool_deinit)
#ifdef __cplusplus
}
@@ -65,6 +65,11 @@ struct btdm_osal_sem {
void *sem;
};
#define BTDM_OSAL_ALIGN(__n, __a) \
((((__n) & ((__a)-1)) == 0) ? (__n) : ((__n) + ((__a) - ((__n) & ((__a)-1)))))
#define BTDM_OSAL_ALIGNMENT (sizeof(void *))
/*
* Type definitions for BTDM OSAL
*/
@@ -33,9 +33,9 @@ extern "C" {
#endif
struct btdm_osal_event_freertos {
bool queued;
void (*fn)(struct btdm_osal_event *ev);
void *arg;
bool queued;
};
struct btdm_osal_eventq_freertos {
@@ -107,6 +107,28 @@ extern "C" {
//TODO
#define UC_BT_CTRL_CONN_FC_ENABLE (1)
#ifdef CONFIG_BT_NIMBLE_STATIC_TO_DYNAMIC
#define UC_BT_CTRL_DYNAMIC_MEMPOOL (CONFIG_BT_NIMBLE_STATIC_TO_DYNAMIC)
#else
#define UC_BT_CTRL_DYNAMIC_MEMPOOL (0)
#endif
#ifdef CONFIG_BT_NIMBLE_MEMPOOL_RUNTIME_ALLOC
#define UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL (CONFIG_BT_NIMBLE_MEMPOOL_RUNTIME_ALLOC)
#else
#define UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL (0)
#endif
#ifdef CONFIG_BT_NIMBLE_MEMPOOL_BLOCK_REUSED
#define UC_BT_CTRL_MEMPOOL_BLOCK_REUSED (CONFIG_BT_NIMBLE_MEMPOOL_BLOCK_REUSED)
#else
#define UC_BT_CTRL_MEMPOOL_BLOCK_REUSED (0)
#endif
#define UC_BT_CTRL_MEMPOOL_CHECK (0)
#ifdef __cplusplus
}
#endif
@@ -161,7 +161,7 @@ wr_btdm_coex_iso_protect_frame_thres_get(void)
#endif /* CONFIG_SW_COEXIST_ENABLE */
}
void
void IRAM_ATTR
wr_btdm_coex_iso_start_int_handle(uint16_t handle, uint32_t duration)
{
#if CONFIG_SW_COEXIST_ENABLE && CONFIG_BT_LE_ISO_SUPPORT
@@ -169,7 +169,7 @@ wr_btdm_coex_iso_start_int_handle(uint16_t handle, uint32_t duration)
#endif /* CONFIG_SW_COEXIST_ENABLE */
}
void
void IRAM_ATTR
wr_btdm_coex_iso_end_int_handle(uint16_t handle, uint32_t duration)
{
#if CONFIG_SW_COEXIST_ENABLE && CONFIG_BT_LE_ISO_SUPPORT
@@ -177,7 +177,7 @@ wr_btdm_coex_iso_end_int_handle(uint16_t handle, uint32_t duration)
#endif /* CONFIG_SW_COEXIST_ENABLE */
}
void
void IRAM_ATTR
wr_btdm_coex_ble_idle_time_inform(uint32_t start_offset, uint32_t duration)
{
#if CONFIG_SW_COEXIST_ENABLE
@@ -188,7 +188,7 @@ wr_btdm_coex_ble_idle_time_inform(uint32_t start_offset, uint32_t duration)
int
wr_btdm_coex_register_ble_cb(uint32_t type, coex_funcs_ble_cb_t func)
{
#if CONFIG_SW_COEXIST_ENABLE
#if CONFIG_SW_COEXIST_ENABLE && CONFIG_BT_LE_ISO_SUPPORT
return coex_register_ble_cb(type, func);
#else
return ESP_OK;
@@ -17,9 +17,12 @@ wr_btdm_external_bb_get_tx_pwr_table(uint8_t *length, uint8_t modem_cfg)
assert(length != NULL);
assert (modem_cfg < TX_PWR_TABLE_MODEM_CFG_MAX);
#if UC_BT_CTRL_BR_EDR_IS_ENABLE
if (modem_cfg == TX_PWR_TABLE_MODEM_CFG_BREDR) {
return bt_bb_tx_pwr_table_get(length, modem_cfg);
} else {
} else
#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE
{
// TODO: replace with bt_bb_tx_pwr_table_get when all the targets(h4, s31, etc) support this API
return bt_bb_get_tx_pwr_table(length);
}
@@ -1,14 +1,48 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdbool.h>
#include "btdm_osal.h"
#include "sdkconfig.h"
#include "assert.h"
#include "esp_attr.h"
#include "esp_rom_sys.h"
#include "btdm_osal.h"
#include "esp_err.h"
#include "esp_log.h"
#if CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2
#include "ble_log.h"
#else /* !CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 */
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
#include "ble_log/ble_log_spi_out.h"
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
#if CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED
#include "ble_log/ble_log_uhci_out.h"
#endif // CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED
#endif /* CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 */
#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED
typedef void (*interface_func_t) (uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag);
enum {
BLE_LOG_INTERFACE_FLAG_CONTINUE = 0,
BLE_LOG_INTERFACE_FLAG_END,
};
/**
* @brief Select buffers
*/
typedef enum {
ESP_BLE_LOG_BUF_HCI = 0x02,
ESP_BLE_LOG_BUF_CONTROLLER = 0x05,
} esp_ble_log_buf_t;
#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED
/*
***************************************************************************************************
@@ -16,11 +50,321 @@
***************************************************************************************************
*/
#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED
void api_base_ll_dumpDebugStatus(void);
void r_btdm_sched_list_details_dump(void);
void r_ble_phy_hw_state_dump(uint8_t);
void esp_ble_controller_log_dump_all(bool);
void esp_panic_handler_feed_wdts(void);
void r_ble_log_async_output_dump_all(bool output);
int r_ble_log_init_async(interface_func_t interface, bool task_create, uint8_t buffers, uint32_t *bufs_size);
int r_ble_log_deinit_async(void);
int r_ble_log_init_simple(interface_func_t interface, void *handler);
void r_ble_log_deinit_simple(void);
void r_ble_log_async_select_dump_buffers(uint8_t buffers);
int r_ble_log_ctrl_level_and_mod(uint8_t log_level, uint32_t mod_switch);
int r_ble_ctrl_mod_type(uint16_t mod, uint32_t mod_type_switch);
#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED
/*
***************************************************************************************************
* Static Function Definitions
***************************************************************************************************
*/
#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED
static bool log_is_inited = false;
#if CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2
/* TODO: Remove event handler dependency in lib */
static void void_handler(void) {}
/* TODO: Declare public interfaces in a public header */
void esp_bt_controller_log_deinit(void)
{
log_is_inited = false;
r_ble_log_deinit_simple();
ble_log_deinit();
}
esp_err_t esp_bt_controller_log_init(void)
{
if (log_is_inited) {
return ESP_OK;
}
if (!ble_log_init()) {
goto exit;
}
if (r_ble_log_init_simple(ble_log_write_hex_ll, void_handler) != 0) {
goto exit;
}
if (r_ble_log_ctrl_level_and_mod(CONFIG_BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL,
CONFIG_BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH) != ESP_OK) {
goto exit;
}
log_is_inited = true;
return ESP_OK;
exit:
esp_bt_controller_log_deinit();
return ESP_FAIL;
}
#else /* !CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 */
const static uint32_t log_bufs_size[] = {CONFIG_BT_LE_LOG_CTRL_BUF1_SIZE, CONFIG_BT_LE_LOG_HCI_BUF_SIZE, CONFIG_BT_LE_LOG_CTRL_BUF2_SIZE};
#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE
#error "This function has been deprecated."
#include "esp_partition.h"
#include "hal/wdt_hal.h"
#define MAX_STORAGE_SIZE (CONFIG_BT_LE_CONTROLLER_LOG_PARTITION_SIZE)
#define BLOCK_SIZE (4096)
#define THRESHOLD (3072)
#define PARTITION_NAME "bt_ctrl_log"
static const esp_partition_t *log_partition;
static uint32_t write_index = 0;
static uint32_t next_erase_index = BLOCK_SIZE;
static bool block_erased = false;
static bool stop_write = false;
static bool is_filled = false;
static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void)
{
log_partition = NULL;
assert(MAX_STORAGE_SIZE % BLOCK_SIZE == 0);
// Find the partition map in the partition table
log_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, PARTITION_NAME);
assert(log_partition != NULL);
// Prepare data to be read later using the mapped address
ESP_ERROR_CHECK(esp_partition_erase_range(log_partition, 0, BLOCK_SIZE));
write_index = 0;
next_erase_index = BLOCK_SIZE;
block_erased = false;
is_filled = false;
stop_write = false;
}
static int esp_bt_controller_log_storage(uint32_t len, const uint8_t *addr, bool end)
{
if (len > MAX_STORAGE_SIZE) {
return -1;
}
if (stop_write) {
return 0;
}
if (((write_index) % BLOCK_SIZE) >= THRESHOLD && !block_erased) {
// esp_rom_printf("Ers nxt: %d,%d\n", next_erase_index, write_index);
esp_partition_erase_range(log_partition, next_erase_index, BLOCK_SIZE);
next_erase_index = (next_erase_index + BLOCK_SIZE) % MAX_STORAGE_SIZE;
block_erased = true;
}
if (((write_index + len) / BLOCK_SIZE) > (write_index / BLOCK_SIZE)) {
block_erased = false;
}
if (write_index + len <= MAX_STORAGE_SIZE) {
esp_partition_write(log_partition, write_index, addr, len);
write_index = (write_index + len) % MAX_STORAGE_SIZE;
} else {
uint32_t first_part_len = MAX_STORAGE_SIZE - write_index;
esp_partition_write(log_partition, write_index, addr, first_part_len);
esp_partition_write(log_partition, 0, addr + first_part_len, len - first_part_len);
write_index = len - first_part_len;
is_filled = true;
// esp_rom_printf("old idx: %d,%d\n",next_erase_index, write_index);
}
return 0;
}
void esp_bt_read_ctrl_log_from_flash(bool output)
{
esp_partition_mmap_handle_t mmap_handle;
uint32_t read_index;
const void *mapped_ptr;
const uint8_t *buffer;
uint32_t print_len;
uint32_t max_print_len;
esp_err_t err;
print_len = 0;
max_print_len = 4096;
err = esp_partition_mmap(log_partition, 0, MAX_STORAGE_SIZE, ESP_PARTITION_MMAP_DATA, &mapped_ptr, &mmap_handle);
if (err != ESP_OK) {
ESP_LOGE("FLASH", "Mmap failed: %s", esp_err_to_name(err));
return;
}
portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
portENTER_CRITICAL_SAFE(&spinlock);
esp_panic_handler_feed_wdts();
r_ble_log_async_output_dump_all(true);
esp_bt_controller_log_deinit();
stop_write = true;
buffer = (const uint8_t *)mapped_ptr;
esp_panic_handler_feed_wdts();
if (is_filled) {
read_index = next_erase_index;
} else {
read_index = 0;
}
esp_rom_printf("\r\nREAD_CHECK:%ld,%ld,%d\r\n",read_index, write_index, is_filled);
esp_rom_printf("\r\n[DUMP_START:");
while (read_index != write_index) {
esp_rom_printf("%02x ", buffer[read_index]);
if (print_len > max_print_len) {
esp_panic_handler_feed_wdts();
print_len = 0;
}
print_len++;
read_index = (read_index + 1) % MAX_STORAGE_SIZE;
}
esp_rom_printf(":DUMP_END]\r\n");
portEXIT_CRITICAL_SAFE(&spinlock);
esp_partition_munmap(mmap_handle);
err = esp_bt_controller_log_init();
assert(err == ESP_OK);
}
#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE
#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED && !CONFIG_BT_LE_CONTROLLER_LOG_UHCI_OUT_ENABLED
static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag)
{
bool end = (flag & (1 << BLE_LOG_INTERFACE_FLAG_END));
#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE
esp_bt_controller_log_storage(len, addr, end);
#else // !CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE
btdm_osal_hw_enter_critical();
esp_panic_handler_feed_wdts();
if (len && addr) {
for (int i = 0; i < len; i++) {
esp_rom_printf("%02x ", addr[i]);
}
}
if (len_append && addr_append) {
for (int i = 0; i < len_append; i++) {
esp_rom_printf("%02x ", addr_append[i]);
}
}
if (end) {
esp_rom_printf("\n");
}
btdm_osal_hw_exit_critical(0);
#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE
}
#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED && !CONFIG_BT_LE_CONTROLLER_LOG_UHCI_OUT_ENABLED
esp_err_t esp_bt_controller_log_init(void)
{
if (log_is_inited) {
return ESP_OK;
}
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
if (ble_log_spi_out_init() != 0) {
goto spi_out_init_failed;
}
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
#if CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED
if (ble_log_uhci_out_init() != 0) {
goto uhci_out_init_failed;
}
#endif // CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED
#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
if (r_ble_log_init_simple(ble_log_spi_out_ll_write, ble_log_spi_out_ll_log_ev_proc) != 0) {
goto log_init_failed;
}
#elif CONFIG_BT_LE_CONTROLLER_LOG_UHCI_OUT_ENABLED
if (r_ble_log_init_simple(ble_log_uhci_out_ll_write, ble_log_uhci_out_ll_log_ev_proc) != 0) {
goto log_init_failed;
}
#else
uint8_t buffers = 0;
#if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED
buffers |= ESP_BLE_LOG_BUF_CONTROLLER;
#endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED
#if CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED
buffers |= ESP_BLE_LOG_BUF_HCI;
#endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED
bool task_create = true;
#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY
task_create = false;
#elif CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE
esp_bt_ctrl_log_partition_get_and_erase_first_block();
#endif
if (r_ble_log_init_async(esp_bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size) != 0) {
goto log_init_failed;
}
#endif
if (r_ble_log_ctrl_level_and_mod(CONFIG_BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL, CONFIG_BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH) != ESP_OK) {
goto ctrl_level_init_failed;
}
log_is_inited = true;
return ESP_OK;
ctrl_level_init_failed:
#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
r_ble_log_deinit_simple();
#elif CONFIG_BT_LE_CONTROLLER_LOG_UHCI_OUT_ENABLED
r_ble_log_deinit_simple();
#else
r_ble_log_deinit_async();
#endif
log_init_failed:
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
ble_log_spi_out_deinit();
spi_out_init_failed:
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
#if CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED
ble_log_uhci_out_deinit();
uhci_out_init_failed:
#endif // CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED
return ESP_FAIL;
}
void esp_bt_controller_log_deinit(void)
{
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
ble_log_spi_out_deinit();
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
#if CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED
ble_log_uhci_out_deinit();
#endif // CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED
#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
r_ble_log_deinit_simple();
#elif CONFIG_BT_LE_CONTROLLER_LOG_UHCI_OUT_ENABLED
r_ble_log_deinit_simple();
#else
r_ble_log_deinit_async();
#endif
log_is_inited = false;
}
#endif /* CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 */
#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED
/*
***************************************************************************************************
* Public Function Definitions
@@ -102,7 +446,7 @@ void IRAM_ATTR
wr_btdm_assert(const char *file, int line, int p0, int p1, uint8_t type)
{
#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED
r_ble_phy_hw_state_dump(false);
api_base_ll_dumpDebugStatus();
r_btdm_sched_list_details_dump();
esp_ble_controller_log_dump_all(true);
#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED
@@ -111,6 +455,50 @@ wr_btdm_assert(const char *file, int line, int p0, int p1, uint8_t type)
assert(0);
}
#if CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE
void __real_esp_panic_handler(void *info);
void __wrap_esp_panic_handler (void *info)
{
esp_ble_controller_log_dump_all(true);
__real_esp_panic_handler(info);
}
#endif // CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE
#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED
#if CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2
void esp_ble_controller_log_dump_all(bool output)
{
ble_log_dump_to_console();
}
#else /* !CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 */
void esp_ble_controller_log_dump_all(bool output)
{
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
ble_log_spi_out_dump_all();
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE
esp_bt_read_ctrl_log_from_flash(output);
#elif !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
btdm_osal_hw_enter_critical();
esp_panic_handler_feed_wdts();
esp_rom_printf("\r\n[DUMP_START:");
r_ble_log_async_output_dump_all(output);
esp_rom_printf(":DUMP_END]\r\n");
btdm_osal_hw_exit_critical(0);
#endif
}
#endif // CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2
#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED
#if CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE
void esp_task_wdt_isr_user_handler(void)
{
esp_ble_controller_log_dump_all(true);
}
#endif // CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE
/*
***************************************************************************************************
* BTDM LOG Initialization
@@ -119,11 +507,21 @@ wr_btdm_assert(const char *file, int line, int p0, int p1, uint8_t type)
int
btdm_log_init(void)
{
#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED
esp_err_t ret;
ret = esp_bt_controller_log_init();
if (ret != ESP_OK) {
return ret;
}
#endif // CONFIG_BT_CONTROLLER_LOG_ENABLED
return 0;
}
void
btdm_log_deinit(void)
{
#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED
esp_bt_controller_log_deinit();
#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED
}
@@ -121,7 +121,7 @@ btdm_lp_rtc_slow_clk_select(uint8_t slow_clk_src)
}
static void
btdm_lp_timer_clk_init(esp_btdm_controller_config_t *cfg)
btdm_lp_timer_clk_init(esp_bt_ctrl_btdm_config_t *cfg)
{
if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_INVALID) {
#if CONFIG_BT_CTRL_LP_CLK_SRC_MAIN_XTAL
@@ -164,10 +164,10 @@ modem_clock_lpclk_src_t btdm_lp_get_lpclk_src(void)
return s_bt_lpclk_src;
}
extern esp_bt_controller_status_t esp_ble_controller_get_status(void);
void btdm_lp_set_lpclk_src(modem_clock_lpclk_src_t clk_src)
{
if (esp_ble_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
return;
}
@@ -187,7 +187,7 @@ void btdm_lp_set_lpclk_freq(uint32_t clk_freq)
{
uint32_t xtal_freq;
if (esp_ble_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
return;
}
@@ -209,21 +209,6 @@ btdm_lp_timer_clk_deinit(void)
modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE);
}
void IRAM_ATTR e_btdm_lp_modem_clock_set(bool enable)
{
if (enable) {
if (!s_btdm_lp_modem_clk_en) {
modem_clock_module_enable(PERIPH_BT_MODULE);
s_btdm_lp_modem_clk_en = 1;
}
} else {
if (!s_bt_active && s_btdm_lp_modem_clk_en) {
modem_clock_module_disable(PERIPH_BT_MODULE);
s_btdm_lp_modem_clk_en = 0;
}
}
}
void
btdm_lp_sleep_cb(uint32_t enable_tick, void *arg)
{
@@ -280,12 +265,12 @@ btdm_lp_modem_retention_create(void)
}
#if UC_BT_CTRL_BR_EDR_IS_ENABLE
// TODO: check the return value
// TODO: check the return value. Shouldn't invoke the upper layer function directly.
sleep_modem_bredr_mac_modem_state_init();
#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE
#if UC_BT_CTRL_BLE_IS_ENABLE
// TODO: check the return value
// TODO: check the return value. Shouldn't invoke the upper layer function directly.
sleep_modem_ble_mac_modem_state_init();
#endif // UC_BT_CTRL_BLE_IS_ENABLE
return err;
@@ -348,7 +333,7 @@ btdm_lp_modem_state_deinit(void)
***************************************************************************************************
*/
void
btdm_lp_enable_clock(esp_btdm_controller_config_t *cfg)
btdm_lp_enable_clock(esp_bt_ctrl_btdm_config_t *cfg)
{
if (!s_btdm_lp_modem_clk_en) {
modem_clock_module_enable(PERIPH_BT_MODULE);
@@ -477,3 +462,24 @@ btdm_lp_shutdown(void)
s_bt_active = false;
}
}
/*
***************************************************************************************************
* External Function Definitions for other modules
***************************************************************************************************
*/
void IRAM_ATTR
e_btdm_lp_modem_clock_set(bool enable)
{
if (enable) {
if (!s_btdm_lp_modem_clk_en) {
modem_clock_module_enable(PERIPH_BT_MODULE);
s_btdm_lp_modem_clk_en = 1;
}
} else {
if (!s_bt_active && s_btdm_lp_modem_clk_en) {
modem_clock_module_disable(PERIPH_BT_MODULE);
s_btdm_lp_modem_clk_en = 0;
}
}
}
@@ -0,0 +1,147 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "btdm_mem_debug.h"
#include <stdint.h>
#if BTDM_MEM_DEBUG
#include <stddef.h>
#include "esp_rom_sys.h"
#include "freertos/FreeRTOS.h"
#include "freertos/portmacro.h"
#include <string.h>
#define BTDM_MEM_DEBUG_MAX 1024 * 5
typedef struct {
void *ptr;
uint32_t size;
uint32_t seq;
} btdm_mem_debug_entry_t;
static btdm_mem_debug_entry_t s_mem_dbg_tbl[BTDM_MEM_DEBUG_MAX];
static uint32_t s_mem_dbg_seq;
static uint32_t s_mem_dbg_count;
static portMUX_TYPE s_mem_dbg_lock = portMUX_INITIALIZER_UNLOCKED;
void
btdm_mem_debug_record(void *ptr, uint32_t size)
{
int i;
if (ptr == NULL || size == 0) {
return;
}
portENTER_CRITICAL(&s_mem_dbg_lock);
for (i = 0; i < BTDM_MEM_DEBUG_MAX; i++) {
if (s_mem_dbg_tbl[i].ptr == NULL) {
s_mem_dbg_seq++;
s_mem_dbg_tbl[i].ptr = ptr;
s_mem_dbg_tbl[i].size = size;
s_mem_dbg_tbl[i].seq = s_mem_dbg_seq;
s_mem_dbg_count++;
portEXIT_CRITICAL(&s_mem_dbg_lock);
return;
}
}
portEXIT_CRITICAL(&s_mem_dbg_lock);
esp_rom_printf("[BTDM_MEM] record full, drop ptr=%p size=%u\n", ptr, (unsigned)size);
}
void
btdm_mem_debug_clear(void *ptr)
{
int i;
if (ptr == NULL) {
return;
}
portENTER_CRITICAL(&s_mem_dbg_lock);
for (i = 0; i < BTDM_MEM_DEBUG_MAX; i++) {
if (s_mem_dbg_tbl[i].ptr == ptr) {
s_mem_dbg_tbl[i].ptr = NULL;
s_mem_dbg_tbl[i].size = 0;
s_mem_dbg_tbl[i].seq = 0;
s_mem_dbg_count--;
portEXIT_CRITICAL(&s_mem_dbg_lock);
return;
}
}
portEXIT_CRITICAL(&s_mem_dbg_lock);
esp_rom_printf("[BTDM_MEM] clear miss ptr=%p\n", ptr);
}
void
btdm_mem_debug_dump(void)
{
int i;
void *ptr;
uint32_t size;
uint32_t seq;
uint32_t count = 0;
uint32_t total_size = 0;
esp_rom_printf("[BTDM_MEM] ===== unfreed dump begin =====\n");
for (i = 0; i < BTDM_MEM_DEBUG_MAX; i++) {
portENTER_CRITICAL(&s_mem_dbg_lock);
ptr = s_mem_dbg_tbl[i].ptr;
size = s_mem_dbg_tbl[i].size;
seq = s_mem_dbg_tbl[i].seq;
portEXIT_CRITICAL(&s_mem_dbg_lock);
if (ptr != NULL) {
esp_rom_printf("[BTDM_MEM] ptr=%p size=%u seq=%u\n",
ptr, (unsigned)size, (unsigned)seq);
count++;
total_size += size;
}
}
esp_rom_printf("[BTDM_MEM] unfreed count=%u total_size=%u\n",
(unsigned)count, (unsigned)total_size);
esp_rom_printf("[BTDM_MEM] ===== unfreed dump end =====\n");
portENTER_CRITICAL(&s_mem_dbg_lock);
memset(s_mem_dbg_tbl, 0, sizeof(s_mem_dbg_tbl));
s_mem_dbg_seq = 0;
s_mem_dbg_count = 0;
portEXIT_CRITICAL(&s_mem_dbg_lock);
}
uint32_t
btdm_mem_debug_get_count(void)
{
uint32_t count;
portENTER_CRITICAL(&s_mem_dbg_lock);
count = s_mem_dbg_count;
portEXIT_CRITICAL(&s_mem_dbg_lock);
return count;
}
uint32_t
btdm_mem_debug_get_seq_num(void)
{
uint32_t sequence;
portENTER_CRITICAL(&s_mem_dbg_lock);
sequence = s_mem_dbg_seq;
portEXIT_CRITICAL(&s_mem_dbg_lock);
return sequence;
}
#endif /* BTDM_MEM_DEBUG */
@@ -0,0 +1,608 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "btdm_mempool.h"
#define BTDM_MEM_TRUE_BLOCK_SIZE(bsize) BTDM_OSAL_ALIGN(bsize, BTDM_OSAL_ALIGNMENT)
#define BTDM_MEMPOOL_TRUE_BLOCK_SIZE(mp) BTDM_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size)
static STAILQ_HEAD(, btdm_mempool) s_btdm_osal_mempool_list = STAILQ_HEAD_INITIALIZER(s_btdm_osal_mempool_list);
#if UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL
static btdm_osal_error_t
e_btdm_mempool_mem_free(struct btdm_mempool *mp)
{
/* For runtime allocation mode, check whether all blocks have been freed */
if (!(mp->mp_flags & BTDM_MEMPOOL_F_RUNTIME)) {
return BTDM_OSAL_EINVAL;
}
/* NOTE: if mempool gets cleared before all mem block is retrieved, it may leads to mem trampling */
assert(mp->mp_num_free == mp->mp_num_blocks);
#if UC_BT_CTRL_MEMPOOL_BLOCK_REUSED
struct btdm_memblock *block_ptr;
/* For block reused mode, free all allocated blocks */
if (mp->mp_flags & BTDM_MEMPOOL_F_REUSED) {
uint16_t cnt;
for (cnt = 0; cnt < mp->mp_alloc_blocks; cnt ++) {
block_ptr = SLIST_FIRST(mp);
if (block_ptr) {
assert(block_ptr);
SLIST_REMOVE_HEAD(mp, mb_next);
btdm_osal_free(block_ptr);
}
}
mp->mp_alloc_blocks = 0;
}
#endif
/* Only reset statistics */
SLIST_FIRST(mp) = NULL;
mp->mp_min_free = mp->mp_num_blocks;
return BTDM_OSAL_OK;
}
#endif // UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL
static btdm_osal_error_t
e_btdm_mempool_init_internal(struct btdm_mempool *mp, uint16_t blocks,
uint32_t block_size, void *membuf, const char *name,
uint8_t flags)
{
int true_block_size;
int i;
uint8_t *block_addr;
struct btdm_memblock *block_ptr;
/* Check for valid parameters */
if (!mp || (block_size == 0)) {
return BTDM_OSAL_INVALID_PARM;
}
/* For runtime allocation mode, membuf can be NULL */
#if !UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL
if ((!membuf) && (blocks != 0)) {
return BTDM_OSAL_INVALID_PARM;
}
#endif
if (membuf != NULL) {
/* Blocks need to be sized properly and memory buffer should be
* aligned
*/
if (((uint32_t)(uintptr_t)membuf & (BTDM_OSAL_ALIGNMENT - 1)) != 0) {
return BTDM_OSAL_MEM_NOT_ALIGNED;
}
}
/* Initialize the memory pool structure */
mp->mp_block_size = block_size;
mp->mp_num_free = blocks;
mp->mp_min_free = blocks;
mp->mp_flags = flags;
mp->mp_num_blocks = blocks;
mp->mp_membuf_addr = (uint32_t)(uintptr_t)membuf;
mp->name = name;
SLIST_FIRST(mp) = membuf;
#if UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL
if (membuf == NULL) {
/* Runtime allocation mode */
mp->mp_membuf_addr = 0;
mp->mp_flags |= BTDM_MEMPOOL_F_RUNTIME;
#if UC_BT_CTRL_MEMPOOL_BLOCK_REUSED
mp->mp_flags |= BTDM_MEMPOOL_F_REUSED;
mp->mp_alloc_blocks = 0;
#endif
SLIST_FIRST(mp) = NULL;
/* Check if mempool is already in the list (reinitialization case) */
struct btdm_mempool *cur;
if (!STAILQ_EMPTY(&s_btdm_osal_mempool_list)) {
STAILQ_FOREACH(cur, &s_btdm_osal_mempool_list, mp_list) {
if (cur->name == mp->name) {
/* Mempool is already in the list, remove it first */
btdm_mempool_unregister(cur);
break;
}
}
}
STAILQ_INSERT_TAIL(&s_btdm_osal_mempool_list, mp, mp_list);
return BTDM_OSAL_OK;
}
#endif
if (blocks > 0) {
true_block_size = BTDM_MEMPOOL_TRUE_BLOCK_SIZE(mp);
/* Chain the memory blocks to the free list */
block_addr = (uint8_t *)membuf;
block_ptr = (struct btdm_memblock *)block_addr;
for (i = 1; i < blocks; i++) {
block_addr += true_block_size;
SLIST_NEXT(block_ptr, mb_next) = (struct btdm_memblock *)block_addr;
block_ptr = (struct btdm_memblock *)block_addr;
}
/* Last one in the list should be NULL */
SLIST_NEXT(block_ptr, mb_next) = NULL;
}
/* Check if mempool is already in the list (reinitialization case) */
struct btdm_mempool *cur;
if (!STAILQ_EMPTY(&s_btdm_osal_mempool_list)) {
STAILQ_FOREACH(cur, &s_btdm_osal_mempool_list, mp_list) {
if (cur->name == mp->name) {
/* Mempool is already in the list, remove it first */
btdm_mempool_unregister(cur);
break;
}
}
}
STAILQ_INSERT_TAIL(&s_btdm_osal_mempool_list, mp, mp_list);
return BTDM_OSAL_OK;
}
btdm_osal_error_t
e_btdm_mempool_init(struct btdm_mempool *mp, uint16_t blocks, uint32_t block_size,
void *membuf, const char *name)
{
return e_btdm_mempool_init_internal(mp, blocks, block_size, membuf, name, 0);
}
btdm_osal_error_t
e_btdm_mempool_ext_init(struct btdm_mempool_ext *mpe, uint16_t blocks,
uint32_t block_size, void *membuf, const char *name)
{
int rc;
rc = e_btdm_mempool_init_internal(&mpe->mpe_mp, blocks, block_size, membuf,
name, BTDM_MEMPOOL_F_EXT);
if (rc != 0) {
return rc;
}
mpe->mpe_put_cb = NULL;
mpe->mpe_put_arg = NULL;
mpe->mpe_get_cb = NULL;
mpe->mpe_get_arg = NULL;
return 0;
}
void
e_btdm_mempool_ext_register_cb(struct btdm_mempool_ext *mpe,
void *put_cb, void *put_arg,
void *get_cb, void *get_arg)
{
mpe->mpe_put_cb = put_cb;
mpe->mpe_put_arg = put_arg;
mpe->mpe_get_cb = get_cb;
mpe->mpe_get_arg = get_arg;
}
btdm_osal_error_t
e_btdm_mempool_unregister(struct btdm_mempool *mp)
{
struct btdm_mempool *cur;
/* Remove the mempool from the global stailq. This is done manually rather
* than with `STAILQ_REMOVE` to allow for a graceful failure if the mempool
* isn't found.
*/
cur = NULL;
if (!STAILQ_EMPTY(&s_btdm_osal_mempool_list)) {
STAILQ_FOREACH(cur, &s_btdm_osal_mempool_list, mp_list) {
if (cur == mp) {
break;
}
}
}
if (cur == NULL) {
return BTDM_OSAL_INVALID_PARM;
}
#if UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL
e_btdm_mempool_mem_free(cur);
#endif // UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL
STAILQ_REMOVE(&s_btdm_osal_mempool_list, cur, btdm_mempool, mp_list);
return 0;
}
btdm_osal_error_t
e_btdm_mempool_clear(struct btdm_mempool *mp)
{
struct btdm_memblock *block_ptr;
int true_block_size;
uint8_t *block_addr;
uint16_t blocks;
if (!mp) {
return BTDM_OSAL_INVALID_PARM;
}
#if UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL
if (e_btdm_mempool_mem_free(mp) == BTDM_OSAL_OK) {
return BTDM_OSAL_OK;
}
#endif // UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL
true_block_size = BTDM_MEMPOOL_TRUE_BLOCK_SIZE(mp);
/* cleanup the memory pool structure */
mp->mp_num_free = mp->mp_num_blocks;
mp->mp_min_free = mp->mp_num_blocks;
SLIST_FIRST(mp) = (void *)(uintptr_t)mp->mp_membuf_addr;
/* Chain the memory blocks to the free list */
block_addr = (uint8_t *)(uintptr_t)mp->mp_membuf_addr;
block_ptr = (struct btdm_memblock *)block_addr;
blocks = mp->mp_num_blocks;
while (blocks > 1) {
block_addr += true_block_size;
SLIST_NEXT(block_ptr, mb_next) = (struct btdm_memblock *)block_addr;
block_ptr = (struct btdm_memblock *)block_addr;
--blocks;
}
/* Last one in the list should be NULL */
SLIST_NEXT(block_ptr, mb_next) = NULL;
return BTDM_OSAL_OK;
}
btdm_osal_error_t
e_btdm_mempool_ext_clear(struct btdm_mempool_ext *mpe)
{
btdm_osal_error_t rc;
mpe->mpe_put_cb = NULL;
mpe->mpe_put_arg = NULL;
mpe->mpe_get_cb = NULL;
mpe->mpe_get_arg = NULL;
rc = btdm_mempool_clear(&mpe->mpe_mp);
#if UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL
mpe->mpe_mp.mp_flags &= ~BTDM_MEMPOOL_F_EXT;
#else
mpe->mpe_mp.mp_flags = 0;
#endif
return rc;
}
bool
e_btdm_mempool_is_sane(const struct btdm_mempool *mp)
{
struct btdm_memblock *block;
#if UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL
/* Runtime mode cannot verify sanity */
if (mp->mp_flags & BTDM_MEMPOOL_F_RUNTIME) {
assert(0);
}
#endif
/* Verify that each block in the free list belongs to the mempool. */
SLIST_FOREACH(block, mp, mb_next) {
if (!e_btdm_memblock_from(mp, block)) {
return false;
}
}
return true;
}
int
e_btdm_memblock_from(const struct btdm_mempool *mp, const void *block_addr)
{
uint32_t true_block_size;
uintptr_t baddr32;
uint32_t end;
#if UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL
/* Runtime allocation mode doesn't support from */
if (mp->mp_flags & BTDM_MEMPOOL_F_RUNTIME) {
assert(0);
}
#endif
static_assert(sizeof block_addr == sizeof baddr32,
"Pointer to void must be 32-bits.");
baddr32 = (uint32_t)(uintptr_t)block_addr;
true_block_size = BTDM_MEMPOOL_TRUE_BLOCK_SIZE(mp);
end = mp->mp_membuf_addr + (mp->mp_num_blocks * true_block_size);
/* Check that the block is in the memory buffer range. */
if ((baddr32 < mp->mp_membuf_addr) || (baddr32 >= end)) {
return 0;
}
/* All freed blocks should be on true block size boundaries! */
if (!(mp->mp_flags & BTDM_MEMPOOL_F_COMBINATION) &&
((baddr32 - mp->mp_membuf_addr) % true_block_size) != 0) {
return 0;
}
return 1;
}
void *
e_btdm_memblock_get(struct btdm_mempool *mp)
{
struct btdm_mempool_ext *mpe;
struct btdm_memblock *block;
/* Check to make sure they passed in a memory pool (or something) */
block = NULL;
if (mp && mp->mp_flags & BTDM_MEMPOOL_F_EXT) {
mpe = (struct btdm_mempool_ext *)mp;
if (mpe->mpe_get_cb != NULL) {
block = mpe->mpe_get_cb(mpe, mpe->mpe_get_arg);
return block;
}
}
#if UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL
/* Runtime allocation mode */
if (mp && mp->mp_flags & BTDM_MEMPOOL_F_RUNTIME) {
bool need_alloc = false;
void *allocated_block;
uint32_t alloc_size;
btdm_osal_hw_enter_critical();
if (mp->mp_num_free) {
#if UC_BT_CTRL_MEMPOOL_BLOCK_REUSED
if (mp->mp_flags & BTDM_MEMPOOL_F_REUSED) {
if (!SLIST_EMPTY(mp)) {
block = SLIST_FIRST(mp);
SLIST_REMOVE_HEAD(mp, mb_next);
} else {
assert(mp->mp_alloc_blocks < mp->mp_num_blocks);
need_alloc = true;
mp->mp_alloc_blocks++;
}
} else
#endif
{
need_alloc = true;
}
/* Decrement number free by 1 */
mp->mp_num_free--;
if (mp->mp_min_free > mp->mp_num_free) {
mp->mp_min_free = mp->mp_num_free;
}
}
btdm_osal_hw_exit_critical(0);
/* Allocate outside critical section to avoid holding lock too long */
if (need_alloc) {
alloc_size = BTDM_MEMPOOL_TRUE_BLOCK_SIZE(mp);
allocated_block = btdm_osal_malloc(alloc_size, BTDM_OSAL_MALLOC_F_INTERNAL);
if (allocated_block) {
/* Save mempool pointer for block */
block = (struct btdm_memblock *)(allocated_block);
} else {
// Should not happen
btdm_osal_hw_enter_critical();
mp->mp_num_free++;
#if UC_BT_CTRL_MEMPOOL_BLOCK_REUSED
if (mp->mp_flags & BTDM_MEMPOOL_F_REUSED) {
mp->mp_alloc_blocks--;
}
#endif
btdm_osal_hw_exit_critical(0);
}
}
return block;
}
#endif
if (mp) {
btdm_osal_hw_enter_critical();
/* Check for any free */
if (mp->mp_num_free) {
/* Get a free block */
block = SLIST_FIRST(mp);
/* Set new free list head */
SLIST_FIRST(mp) = SLIST_NEXT(block, mb_next);
/* Decrement number free by 1 */
mp->mp_num_free--;
if (mp->mp_min_free > mp->mp_num_free) {
mp->mp_min_free = mp->mp_num_free;
}
}
btdm_osal_hw_exit_critical(0);
}
return (void *)block;
}
btdm_osal_error_t
e_btdm_memblock_put_from_cb(struct btdm_mempool *mp, void *block_addr)
{
struct btdm_memblock *block;
#if UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL
bool need_free = true;
if (mp->mp_flags & BTDM_MEMPOOL_F_RUNTIME) {
/* Runtime allocation mode - free directly */
btdm_osal_hw_enter_critical();
#if UC_BT_CTRL_MEMPOOL_BLOCK_REUSED
if (mp->mp_flags & BTDM_MEMPOOL_F_REUSED) {
block = (struct btdm_memblock *)block_addr;
SLIST_INSERT_HEAD(mp, block, mb_next);
need_free = false;
}
#endif
mp->mp_num_free++;
assert(mp->mp_num_blocks >= mp->mp_num_free);
btdm_osal_hw_exit_critical(0);
/* Free outside critical section */
if (need_free) {
btdm_osal_free(block_addr);
}
return BTDM_OSAL_OK;
}
#endif
/* Validate that the block belongs to this mempool */
if (!(mp->mp_flags & BTDM_MEMPOOL_F_FRAG) &&
!e_btdm_memblock_from(mp, block_addr)) {
return BTDM_OSAL_INVALID_PARM;
}
block = (struct btdm_memblock *)block_addr;
btdm_osal_hw_enter_critical();
/* Check for duplicate free - verify block is not already in free list */
{
struct btdm_memblock *cur;
SLIST_FOREACH(cur, mp, mb_next) {
if (cur == block) {
btdm_osal_hw_exit_critical(0);
return BTDM_OSAL_INVALID_PARM;
}
}
}
/* Check that the number free doesn't exceed number blocks */
if (mp->mp_num_free >= mp->mp_num_blocks) {
btdm_osal_hw_exit_critical(0);
return BTDM_OSAL_INVALID_PARM;
}
/* Chain current free list pointer to this block; make this block head */
SLIST_NEXT(block, mb_next) = SLIST_FIRST(mp);
SLIST_FIRST(mp) = block;
/* Increment number free */
mp->mp_num_free++;
btdm_osal_hw_exit_critical(0);
return BTDM_OSAL_OK;
}
btdm_osal_error_t
e_btdm_memblock_put(struct btdm_mempool *mp, void *block_addr)
{
struct btdm_mempool_ext *mpe;
btdm_osal_error_t ret;
#if UC_BT_CTRL_MEMPOOL_CHECK
struct btdm_memblock *block;
#endif
/* Make sure parameters are valid */
if ((mp == NULL) || (block_addr == NULL)) {
ret = BTDM_OSAL_INVALID_PARM;
goto done;
}
#if UC_BT_CTRL_MEMPOOL_CHECK
#if UC_BT_CTRL_RUNTIME_ALLOC_MEMPOOL
if (!(mp->mp_flags & BTDM_MEMPOOL_F_RUNTIME))
#endif
{
/* Check that the block we are freeing is a valid block! */
assert(btdm_memblock_from(mp, block_addr));
}
/*
* Check for duplicate free.
*/
SLIST_FOREACH(block, mp, mb_next) {
assert(block != (struct btdm_memblock *)block_addr);
}
#endif
/* If this is an extended mempool with a put callback, call the callback
* instead of freeing the block directly.
*/
if (mp->mp_flags & BTDM_MEMPOOL_F_EXT) {
mpe = (struct btdm_mempool_ext *)mp;
if (mpe->mpe_put_cb != NULL) {
ret = mpe->mpe_put_cb(mpe, block_addr, mpe->mpe_put_arg);
goto done;
}
}
/* No callback; free the block. */
ret = btdm_memblock_put_from_cb(mp, block_addr);
done:
return ret;
}
void
e_btdm_mempool_flags_set(struct btdm_mempool *mp, uint8_t flags)
{
mp->mp_flags |= flags;
}
void
e_btdm_mempool_flags_clear(struct btdm_mempool *mp, uint8_t flags)
{
mp->mp_flags &= ~flags;
}
uint16_t
e_btdm_mempool_free_blocks_num(struct btdm_mempool *mp)
{
uint16_t free_blocks_num;
btdm_osal_hw_enter_critical();
free_blocks_num = mp->mp_num_free;
btdm_osal_hw_exit_critical(0);
return free_blocks_num;
}
void
e_btdm_mempool_module_init(void)
{
}
void
e_btdm_mempool_deinit(bool is_controller)
{
struct btdm_mempool *mp = NULL;
struct btdm_mempool *next = NULL;
mp = STAILQ_FIRST(&s_btdm_osal_mempool_list);
// All mempool blocks should be reclaimed and mempool removed from mempool list after nimble deinit
while (mp) {
if (is_controller == !!(mp->mp_flags & BTDM_MEMPOOL_F_CONTROLLER)) {
next = STAILQ_NEXT(mp, mp_list);
btdm_mempool_unregister(mp);
mp = next;
} else {
mp = STAILQ_NEXT(mp, mp_list);
}
}
}
@@ -30,12 +30,12 @@ extern int esp_rom_printf(const char *fmt, ...);
} \
} while (0)
#define BTDM_MEMPOOL_ALLOC (1)
#if (!defined(SOC_ESP_NIMBLE_CONTROLLER) || !SOC_ESP_NIMBLE_CONTROLLER)
#error "not defined SOC_ESP_NIMBLE_CONTROLLER or SOC_ESP_NIMBLE_CONTROLLER is zero"
#endif
#define BTDM_OSAL_DYNAMIC_ALLOC (1)
struct btdm_intr_alloc_params {
union {
struct {
@@ -54,18 +54,9 @@ static const char *TAG __attribute__((unused)) = "BTDM OSAL";
struct btdm_mempool s_btdm_osal_ev_pool;
static btdm_membuf_t *s_btdm_osal_ev_buf = NULL;
struct btdm_mempool s_btdm_osal_evq_pool;
static btdm_membuf_t *s_btdm_osal_evq_buf = NULL;
struct btdm_mempool s_btdm_osal_co_pool;
static btdm_membuf_t *s_btdm_osal_co_buf = NULL;
struct btdm_mempool s_btdm_osal_sem_pool;
static btdm_membuf_t *s_btdm_osal_sem_buf = NULL;
struct btdm_mempool s_btdm_osal_mutex_pool;
static btdm_membuf_t *s_btdm_osal_mutex_buf = NULL;
static uint16_t s_btdm_osal_evtq_deepth = 0;
static uint8_t s_btdm_osal_intr_nest = 0;
static portMUX_TYPE s_btsm_osal_intr_mutex = portMUX_INITIALIZER_UNLOCKED;
@@ -90,56 +81,36 @@ in_isr(void)
void
wr_btdm_osal_eventq_init(struct btdm_osal_eventq *evq)
{
struct btdm_osal_eventq_freertos *eventq = NULL;
struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq;
#if BTDM_MEMPOOL_ALLOC
if (!btdm_memblock_from(&s_btdm_osal_evq_pool, evq->eventq)) {
evq->eventq = btdm_memblock_get(&s_btdm_osal_evq_pool);
eventq = (struct btdm_osal_eventq_freertos *)evq->eventq;
BTDM_OSAL_ASSERT(eventq);
memset(eventq, 0, sizeof(*eventq));
eventq->q = xQueueCreate(s_btdm_osal_evtq_deepth, sizeof(struct btdm_osal_eventq *));
BTDM_OSAL_ASSERT(eventq->q);
} else {
eventq = (struct btdm_osal_eventq_freertos *)evq->eventq;
xQueueReset(eventq->q);
static_assert(sizeof(struct btdm_osal_eventq_freertos) == sizeof(struct btdm_osal_eventq),
"size of btdm_osal_eventq_freertos and btdm_osal_eventq must be the same");
if (eventq->q) {
return;
}
#else
if (!evq->eventq) {
evq->eventq = btdm_osal_malloc(sizeof(struct btdm_osal_eventq_freertos),
BTDM_OSAL_MALLOC_F_INTERNAL);
eventq = (struct btdm_osal_eventq_freertos *)evq->eventq;
BTDM_OSAL_ASSERT(eventq);
memset(eventq, 0, sizeof(*eventq));
eventq->q = xQueueCreate(s_btdm_osal_evtq_deepth, sizeof(struct btdm_osal_eventq *));
BTDM_OSAL_ASSERT(eventq->q);
} else {
eventq = (struct btdm_osal_eventq_freertos *)evq->eventq;
xQueueReset(eventq->q);
}
#endif
memset(eventq, 0, sizeof(*eventq));
eventq->q = xQueueCreate(s_btdm_osal_evtq_deepth, sizeof(struct btdm_osal_event *));
BTDM_OSAL_ASSERT(eventq->q);
}
void
wr_btdm_osal_eventq_deinit(struct btdm_osal_eventq *evq)
{
struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq->eventq;
struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq;
BTDM_OSAL_ASSERT(eventq);
BTDM_OSAL_ASSERT(eventq->q);
vQueueDelete(eventq->q);
#if BTDM_MEMPOOL_ALLOC
btdm_memblock_put(&s_btdm_osal_evq_pool, eventq);
#else
btdm_osal_free((void *)eventq);
#endif
evq->eventq = NULL;
eventq->q = NULL;
}
struct btdm_osal_event *IRAM_ATTR
wr_btdm_osal_eventq_get(struct btdm_osal_eventq *evq, btdm_osal_time_t tmo)
{
struct btdm_osal_event *ev = NULL;
struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq->eventq;
struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq;
BaseType_t woken;
BaseType_t ret;
@@ -169,7 +140,7 @@ wr_btdm_osal_eventq_put(struct btdm_osal_eventq *evq, struct btdm_osal_event *ev
{
BaseType_t woken;
BaseType_t ret;
struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq->eventq;
struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq;
struct btdm_osal_event_freertos *event = (struct btdm_osal_event_freertos *)ev->event;
if (event->queued) {
@@ -195,7 +166,7 @@ wr_btdm_osal_eventq_put_to_front(struct btdm_osal_eventq *evq, struct btdm_osal_
{
BaseType_t woken;
BaseType_t ret;
struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq->eventq;
struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq;
struct btdm_osal_event_freertos *event = (struct btdm_osal_event_freertos *)ev->event;
if (event->queued) {
@@ -224,7 +195,7 @@ wr_btdm_osal_eventq_remove(struct btdm_osal_eventq *evq, struct btdm_osal_event
int i;
int count;
BaseType_t woken, woken2;
struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq->eventq;
struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq;
struct btdm_osal_event_freertos *event = (struct btdm_osal_event_freertos *)ev->event;
if (!event->queued) {
@@ -263,7 +234,7 @@ wr_btdm_osal_eventq_remove(struct btdm_osal_eventq *evq, struct btdm_osal_event
/* RISK: For multi-core, this mutex can't protect the queue from being changed by other cores
* with wr_btdm_osal_eventq_put(). The count maybe less than the actual.
*/
portENTER_CRITICAL(&s_btsm_osal_intr_mutex);
portENTER_CRITICAL_SAFE(&s_btsm_osal_intr_mutex);
count = uxQueueMessagesWaiting(eventq->q);
for (i = 0; i < count; i++) {
@@ -278,7 +249,7 @@ wr_btdm_osal_eventq_remove(struct btdm_osal_eventq *evq, struct btdm_osal_event
BTDM_OSAL_ASSERT(ret == pdPASS);
}
portEXIT_CRITICAL(&s_btsm_osal_intr_mutex);
portEXIT_CRITICAL_SAFE(&s_btsm_osal_intr_mutex);
}
event->queued = 0;
@@ -287,7 +258,7 @@ wr_btdm_osal_eventq_remove(struct btdm_osal_eventq *evq, struct btdm_osal_event
bool IRAM_ATTR
wr_btdm_osal_eventq_is_empty(struct btdm_osal_eventq *evq)
{
struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq->eventq;
struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq;
return xQueueIsQueueEmptyFromISR(eventq->q);
}
@@ -308,16 +279,17 @@ wr_btdm_osal_event_init(struct btdm_osal_event *ev, btdm_osal_event_fn *fn, void
{
struct btdm_osal_event_freertos *event = NULL;
#if BTDM_MEMPOOL_ALLOC
if (!btdm_memblock_from(&s_btdm_osal_ev_pool, ev->event)) {
if (!ev->event) {
ev->event = btdm_memblock_get(&s_btdm_osal_ev_pool);
}
#else
#if BTDM_OSAL_DYNAMIC_ALLOC
if (!ev->event) {
ev->event = btdm_osal_malloc(sizeof(struct btdm_osal_event_freertos),
BTDM_OSAL_MALLOC_F_INTERNAL);
ev->event =
btdm_osal_malloc(sizeof(struct btdm_osal_event_freertos), BTDM_OSAL_MALLOC_F_INTERNAL);
}
#endif
#endif // BTDM_OSAL_DYNAMIC_ALLOC
event = (struct btdm_osal_event_freertos *)ev->event;
BTDM_OSAL_ASSERT(event);
@@ -329,16 +301,22 @@ wr_btdm_osal_event_init(struct btdm_osal_event *ev, btdm_osal_event_fn *fn, void
void IRAM_ATTR
wr_btdm_osal_event_deinit(struct btdm_osal_event *ev)
{
if (!ev->event) {
struct btdm_osal_event_freertos *event = (struct btdm_osal_event_freertos *)ev->event;
if (!event) {
return;
}
#if BTDM_MEMPOOL_ALLOC
btdm_memblock_put(&s_btdm_osal_ev_pool, ev->event);
#else
btdm_osal_free(ev->event);
#endif
ev->event = NULL;
#if BTDM_OSAL_DYNAMIC_ALLOC
if (!btdm_memblock_from(&s_btdm_osal_ev_pool, event)) {
btdm_osal_free(event);
return;
}
#endif
btdm_memblock_put(&s_btdm_osal_ev_pool, event);
}
void IRAM_ATTR
@@ -381,57 +359,29 @@ wr_btdm_osal_event_set_arg(struct btdm_osal_event *ev, void *arg)
btdm_osal_error_t
wr_btdm_osal_mutex_init(struct btdm_osal_mutex *mu)
{
struct btdm_osal_mutex_freertos *mutex = NULL;
#if BTDM_MEMPOOL_ALLOC
if (!btdm_memblock_from(&s_btdm_osal_mutex_pool, mu->mutex)) {
mu->mutex = btdm_memblock_get(&s_btdm_osal_mutex_pool);
mutex = (struct btdm_osal_mutex_freertos *)mu->mutex;
struct btdm_osal_mutex_freertos *mutex = (struct btdm_osal_mutex_freertos *)mu;
static_assert(sizeof(struct btdm_osal_mutex_freertos) == sizeof(struct btdm_osal_mutex),
"size of btdm_osal_mutex_freertos and btdm_osal_mutex must be the same");
if (!mutex) {
return BTDM_OSAL_INVALID_PARM;
}
mutex->handle = xSemaphoreCreateRecursiveMutex();
memset(mutex, 0, sizeof(*mutex));
mutex->handle = xSemaphoreCreateRecursiveMutex();
BTDM_OSAL_ASSERT(mutex->handle);
if (!mutex->handle) {
return BTDM_OSAL_ENOMEM;
}
#else
if (!mu->mutex) {
mu->mutex = btdm_osal_malloc(sizeof(struct btdm_osal_mutex_freertos),
BTDM_OSAL_MALLOC_F_INTERNAL);
mutex = (struct btdm_osal_mutex_freertos *)mu->mutex;
if (!mutex) {
return BTDM_OSAL_INVALID_PARM;
}
memset(mutex, 0, sizeof(*mutex));
mutex->handle = xSemaphoreCreateRecursiveMutex();
BTDM_OSAL_ASSERT(mutex->handle);
}
#endif
return BTDM_OSAL_OK;
}
btdm_osal_error_t
wr_btdm_osal_mutex_deinit(struct btdm_osal_mutex *mu)
{
struct btdm_osal_mutex_freertos *mutex = (struct btdm_osal_mutex_freertos *)mu->mutex;
struct btdm_osal_mutex_freertos *mutex = (struct btdm_osal_mutex_freertos *)mu;
if (!mutex) {
if (!mutex->handle) {
return BTDM_OSAL_INVALID_PARM;
}
BTDM_OSAL_ASSERT(mutex->handle);
vSemaphoreDelete(mutex->handle);
#if BTDM_MEMPOOL_ALLOC
btdm_memblock_put(&s_btdm_osal_mutex_pool, mutex);
#else
btdm_osal_free((void *)mutex);
#endif
mu->mutex = NULL;
mutex->handle = NULL;
return BTDM_OSAL_OK;
}
@@ -440,14 +390,12 @@ btdm_osal_error_t IRAM_ATTR
wr_btdm_osal_mutex_pend(struct btdm_osal_mutex *mu, btdm_osal_time_t timeout)
{
BaseType_t ret;
struct btdm_osal_mutex_freertos *mutex = (struct btdm_osal_mutex_freertos *)mu->mutex;
struct btdm_osal_mutex_freertos *mutex = (struct btdm_osal_mutex_freertos *)mu;
if (!mutex) {
if (!mutex->handle) {
return BTDM_OSAL_INVALID_PARM;
}
BTDM_OSAL_ASSERT(mutex->handle);
if (in_isr()) {
ret = pdFAIL;
BTDM_OSAL_ASSERT(0);
@@ -461,14 +409,12 @@ wr_btdm_osal_mutex_pend(struct btdm_osal_mutex *mu, btdm_osal_time_t timeout)
btdm_osal_error_t IRAM_ATTR
wr_btdm_osal_mutex_release(struct btdm_osal_mutex *mu)
{
struct btdm_osal_mutex_freertos *mutex = (struct btdm_osal_mutex_freertos *)mu->mutex;
struct btdm_osal_mutex_freertos *mutex = (struct btdm_osal_mutex_freertos *)mu;
if (!mutex) {
if (!mutex->handle) {
return BTDM_OSAL_INVALID_PARM;
}
BTDM_OSAL_ASSERT(mutex->handle);
if (in_isr()) {
BTDM_OSAL_ASSERT(0);
} else {
@@ -488,36 +434,15 @@ wr_btdm_osal_mutex_release(struct btdm_osal_mutex *mu)
btdm_osal_error_t
wr_btdm_osal_sem_init(struct btdm_osal_sem *sem, uint16_t tokens)
{
struct btdm_osal_sem_freertos *semaphore = NULL;
struct btdm_osal_sem_freertos *semaphore = (struct btdm_osal_sem_freertos *)sem;
#if BTDM_MEMPOOL_ALLOC
if (!btdm_memblock_from(&s_btdm_osal_sem_pool, sem->sem)) {
sem->sem = btdm_memblock_get(&s_btdm_osal_sem_pool);
semaphore = (struct btdm_osal_sem_freertos *)sem->sem;
static_assert(sizeof(struct btdm_osal_sem_freertos) == sizeof(struct btdm_osal_sem),
"size of btdm_osal_sem_freertos and btdm_osal_sem must be the same");
if (!semaphore) {
return BTDM_OSAL_INVALID_PARM;
}
memset(semaphore, 0, sizeof(*semaphore));
semaphore->handle = xSemaphoreCreateCounting(128, tokens);
BTDM_OSAL_ASSERT(semaphore->handle);
semaphore->handle = xSemaphoreCreateCounting(128, tokens);
if (!semaphore->handle) {
return BTDM_OSAL_ENOMEM;
}
#else
if (!sem->sem) {
sem->sem = btdm_osal_malloc(sizeof(struct btdm_osal_sem_freertos),
BTDM_OSAL_MALLOC_F_INTERNAL);
semaphore = (struct btdm_osal_sem_freertos *)sem->sem;
if (!semaphore) {
return BTDM_OSAL_INVALID_PARM;
}
memset(semaphore, 0, sizeof(*semaphore));
semaphore->handle = xSemaphoreCreateCounting(128, tokens);
BTDM_OSAL_ASSERT(semaphore->handle);
}
#endif
return BTDM_OSAL_OK;
}
@@ -525,21 +450,14 @@ wr_btdm_osal_sem_init(struct btdm_osal_sem *sem, uint16_t tokens)
btdm_osal_error_t
wr_btdm_osal_sem_deinit(struct btdm_osal_sem *sem)
{
struct btdm_osal_sem_freertos *semaphore = (struct btdm_osal_sem_freertos *)sem->sem;
struct btdm_osal_sem_freertos *semaphore = (struct btdm_osal_sem_freertos *)sem;
if (!semaphore) {
if (!semaphore->handle) {
return BTDM_OSAL_INVALID_PARM;
}
BTDM_OSAL_ASSERT(semaphore->handle);
vSemaphoreDelete(semaphore->handle);
#if BTDM_MEMPOOL_ALLOC
btdm_memblock_put(&s_btdm_osal_sem_pool, semaphore);
#else
btdm_osal_free((void *)semaphore);
#endif
sem->sem = NULL;
semaphore->handle = NULL;
return BTDM_OSAL_OK;
}
@@ -549,14 +467,12 @@ wr_btdm_osal_sem_pend(struct btdm_osal_sem *sem, btdm_osal_time_t timeout)
{
BaseType_t woken;
BaseType_t ret;
struct btdm_osal_sem_freertos *semaphore = (struct btdm_osal_sem_freertos *)sem->sem;
struct btdm_osal_sem_freertos *semaphore = (struct btdm_osal_sem_freertos *)sem;
if (!semaphore) {
if (!semaphore->handle) {
return BTDM_OSAL_INVALID_PARM;
}
BTDM_OSAL_ASSERT(semaphore->handle);
if (in_isr()) {
BTDM_OSAL_ASSERT(timeout == 0);
ret = xSemaphoreTakeFromISR(semaphore->handle, &woken);
@@ -575,14 +491,12 @@ wr_btdm_osal_sem_release(struct btdm_osal_sem *sem)
{
BaseType_t ret;
BaseType_t woken;
struct btdm_osal_sem_freertos *semaphore = (struct btdm_osal_sem_freertos *)sem->sem;
struct btdm_osal_sem_freertos *semaphore = (struct btdm_osal_sem_freertos *)sem;
if (!semaphore) {
if (!semaphore->handle) {
return BTDM_OSAL_INVALID_PARM;
}
BTDM_OSAL_ASSERT(semaphore->handle);
if (in_isr()) {
ret = xSemaphoreGiveFromISR(semaphore->handle, &woken);
if (woken == pdTRUE) {
@@ -599,7 +513,7 @@ wr_btdm_osal_sem_release(struct btdm_osal_sem *sem)
uint16_t IRAM_ATTR
wr_btdm_osal_sem_get_count(struct btdm_osal_sem *sem)
{
struct btdm_osal_sem_freertos *semaphore = (struct btdm_osal_sem_freertos *)sem->sem;
struct btdm_osal_sem_freertos *semaphore = (struct btdm_osal_sem_freertos *)sem;
return uxSemaphoreGetCount(semaphore->handle);
}
@@ -666,89 +580,58 @@ wr_btdm_osal_callout_init(struct btdm_osal_callout *co, struct btdm_osal_eventq
{
struct btdm_osal_callout_freertos *callout = NULL;
#if BTDM_MEMPOOL_ALLOC
if (!btdm_memblock_from(&s_btdm_osal_co_pool, co->co)) {
if (!co->co) {
co->co = btdm_memblock_get(&s_btdm_osal_co_pool);
callout = (struct btdm_osal_callout_freertos *)co->co;
BTDM_OSAL_ASSERT(callout);
memset(callout, 0, sizeof(*callout));
btdm_osal_event_init(&callout->ev, ev_cb, ev_arg);
#if BTDM_OSAL_USE_ESP_TIMER
callout->evq = evq;
esp_timer_create_args_t create_args = {
.callback = btdm_osal_event_fn_wrapper,
.arg = callout,
.name = "nimble_timer"
};
if (esp_timer_create(&create_args, &callout->handle) != ESP_OK) {
btdm_osal_event_deinit(&callout->ev);
btdm_memblock_put(&s_btdm_osal_co_pool, callout);
co->co = NULL;
return -1;
if (callout) {
memset(callout, 0, sizeof(struct btdm_osal_callout_freertos));
}
#else
callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb);
if (!callout->handle) {
btdm_osal_event_deinit(&callout->ev);
btdm_memblock_put(&s_btdm_osal_co_pool, callout);
co->co = NULL;
return -1;
}
#endif // BTDM_OSAL_USE_ESP_TIMER
} else {
callout = (struct btdm_osal_callout_freertos *)co->co;
BTDM_OSAL_ASSERT(callout);
callout->evq = evq;
btdm_osal_event_init(&callout->ev, ev_cb, ev_arg);
}
#else
#if BTDM_OSAL_DYNAMIC_ALLOC
if (!co->co) {
co->co = btdm_osal_malloc(sizeof(struct btdm_osal_callout_freertos),
BTDM_OSAL_MALLOC_F_INTERNAL);
callout = (struct btdm_osal_callout_freertos *)co->co;
if (!callout) {
return -1;
if (callout) {
memset(callout, 0, sizeof(struct btdm_osal_callout_freertos));
}
}
#endif
memset(callout, 0, sizeof(*callout));
btdm_osal_event_init(&callout->ev, ev_cb, ev_arg);
callout = (struct btdm_osal_callout_freertos *)co->co;
if (!callout) {
return BTDM_OSAL_ENOMEM;
}
btdm_osal_event_init(&callout->ev, ev_cb, ev_arg);
callout->evq = evq;
if (callout->handle) {
return BTDM_OSAL_OK;
}
#if BTDM_OSAL_USE_ESP_TIMER
callout->evq = evq;
esp_timer_create_args_t create_args = {
.callback = btdm_osal_event_fn_wrapper,
.arg = callout,
.name = "btdm_timer"
};
esp_timer_create_args_t create_args = {
.callback = btdm_osal_event_fn_wrapper, .arg = callout, .name = "nimble_timer"};
if (esp_timer_create(&create_args, &callout->handle) != ESP_OK) {
btdm_osal_event_deinit(&callout->ev);
btdm_osal_free((void *)callout);
co->co = NULL;
return -1;
}
#else
callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb);
if (!callout->handle) {
btdm_osal_event_deinit(&callout->ev);
btdm_osal_free((void *)callout);
co->co = NULL;
return -1;
}
#endif // BTDM_OSAL_USE_ESP_TIMER
} else {
callout = (struct btdm_osal_callout_freertos *)co->co;
BTDM_OSAL_ASSERT(callout);
callout->evq = evq;
btdm_osal_event_init(&callout->ev, ev_cb, ev_arg);
if (esp_timer_create(&create_args, &callout->handle) != ESP_OK) {
btdm_osal_callout_deinit(co);
return BTDM_OSAL_ENOMEM;
}
#endif // BTDM_MEMPOOL_ALLOC
return 0;
#else // BTDM_OSAL_USE_ESP_TIMER
callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb);
if (!callout->handle) {
btdm_osal_callout_deinit(co);
return BTDM_OSAL_ENOMEM;
}
#endif // BTDM_OSAL_USE_ESP_TIMER
return BTDM_OSAL_OK;
}
void
@@ -762,34 +645,36 @@ wr_btdm_osal_callout_deinit(struct btdm_osal_callout *co)
return;
}
if (!callout->handle) {
return;
if (callout->handle) {
#if BTDM_OSAL_USE_ESP_TIMER
esp_err_t err = esp_timer_stop(callout->handle);
if (err != ESP_OK) {
/* ESP_ERR_INVALID_STATE is expected when timer is already stopped */
if (err != ESP_ERR_INVALID_STATE) {
ESP_LOGD(TAG, "Timer not stopped");
}
}
err = esp_timer_delete(callout->handle);
if (err != ESP_OK) {
ESP_LOGW(TAG, "Timer not deleted");
}
#else
xTimerDelete(callout->handle, portMAX_DELAY);
#endif // BTDM_OSAL_USE_ESP_TIMER
}
btdm_osal_event_deinit(&callout->ev);
#if BTDM_OSAL_USE_ESP_TIMER
esp_err_t err = esp_timer_stop(callout->handle);
if (err != ESP_OK) {
/* ESP_ERR_INVALID_STATE is expected when timer is already stopped */
if (err != ESP_ERR_INVALID_STATE) {
ESP_LOGD(TAG, "Timer not stopped");
}
}
err = esp_timer_delete(callout->handle);
if (err != ESP_OK) {
ESP_LOGW(TAG, "Timer not deleted");
}
#else
xTimerDelete(callout->handle, portMAX_DELAY);
#endif // BTDM_OSAL_USE_ESP_TIMER
#if BTDM_MEMPOOL_ALLOC
btdm_memblock_put(&s_btdm_osal_co_pool, callout);
#else
btdm_osal_free((void *)callout);
#endif // BTDM_MEMPOOL_ALLOC
co->co = NULL;
memset(co, 0, sizeof(struct btdm_osal_callout));
#if BTDM_OSAL_DYNAMIC_ALLOC
if (!btdm_memblock_from(&s_btdm_osal_co_pool, callout)) {
btdm_osal_free((void *)callout);
return;
}
#endif
btdm_memblock_put(&s_btdm_osal_co_pool, callout);
}
btdm_osal_error_t IRAM_ATTR
@@ -1151,11 +1036,15 @@ wr_btdm_osal_intr_free(btdm_osal_intr_handle_t intr_handle)
void *
wr_btdm_osal_malloc(uint32_t size, btdm_osal_malloc_flag_t flags)
{
void *ptr;
if (flags == BTDM_OSAL_MALLOC_F_INTERNAL) {
return heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
ptr = heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
} else {
return heap_caps_malloc(size, MALLOC_CAP_8BIT);
ptr = heap_caps_malloc(size, MALLOC_CAP_8BIT);
}
return ptr;
}
void
@@ -1253,7 +1142,6 @@ wr_btdm_osal_rand(void)
int
btdm_osal_elem_mempool_init(btdm_osal_elem_num_t *elem_num)
{
#if BTDM_MEMPOOL_ALLOC
int rc;
s_btdm_osal_evtq_deepth = elem_num->evt_count;
@@ -1274,104 +1162,37 @@ btdm_osal_elem_mempool_init(btdm_osal_elem_num_t *elem_num)
}
}
if (elem_num->evtq_count) {
s_btdm_osal_evq_buf = btdm_osal_malloc(
BTDM_MEMPOOL_SIZE(elem_num->evtq_count, sizeof(struct btdm_osal_eventq_freertos)) *
sizeof(btdm_membuf_t),
BTDM_OSAL_MALLOC_F_INTERNAL);
if (!s_btdm_osal_evq_buf) {
return -3;
}
rc = btdm_mempool_init(&s_btdm_osal_evq_pool, elem_num->evtq_count,
sizeof(struct btdm_osal_eventq_freertos), s_btdm_osal_evq_buf,
"s_btdm_osal_evq_pool");
if (rc) {
return -4;
}
}
if (elem_num->co_count) {
s_btdm_osal_co_buf = btdm_osal_malloc(
BTDM_MEMPOOL_SIZE(elem_num->co_count, sizeof(struct btdm_osal_callout_freertos)) *
sizeof(btdm_membuf_t),
BTDM_OSAL_MALLOC_F_INTERNAL);
if (!s_btdm_osal_co_buf) {
return -5;
return -3;
}
rc = btdm_mempool_init(&s_btdm_osal_co_pool, elem_num->co_count,
sizeof(struct btdm_osal_callout_freertos), s_btdm_osal_co_buf,
"s_btdm_osal_co_pool");
if (rc) {
return -6;
}
}
if (elem_num->sem_count) {
s_btdm_osal_sem_buf = btdm_osal_malloc(
BTDM_MEMPOOL_SIZE(elem_num->sem_count, sizeof(struct btdm_osal_sem_freertos)) *
sizeof(btdm_membuf_t),
BTDM_OSAL_MALLOC_F_INTERNAL);
if (!s_btdm_osal_sem_buf) {
return -7;
}
rc = btdm_mempool_init(&s_btdm_osal_sem_pool, elem_num->sem_count,
sizeof(struct btdm_osal_sem_freertos),
s_btdm_osal_sem_buf, "s_btdm_osal_sem_pool");
if (rc) {
return -8;
}
}
if (elem_num->mutex_count) {
s_btdm_osal_mutex_buf = btdm_osal_malloc(
BTDM_MEMPOOL_SIZE(elem_num->mutex_count, sizeof(struct btdm_osal_mutex_freertos)) *
sizeof(btdm_membuf_t),
BTDM_OSAL_MALLOC_F_INTERNAL);
if (!s_btdm_osal_mutex_buf) {
return -9;
}
rc = btdm_mempool_init(&s_btdm_osal_mutex_pool, elem_num->mutex_count,
sizeof(struct btdm_osal_mutex_freertos), s_btdm_osal_mutex_buf,
"s_btdm_osal_mutex_pool");
if (rc) {
return -10;
return -4;
}
}
return 0;
#else
return 0;
#endif // BTDM_MEMPOOL_ALLOC
}
void
btdm_osal_elem_mempool_deinit(void)
{
#if BTDM_MEMPOOL_ALLOC
if (s_btdm_osal_ev_buf) {
BTDM_OSAL_ASSERT(s_btdm_osal_ev_pool.mp_num_free == s_btdm_osal_ev_pool.mp_num_blocks);
btdm_osal_free(s_btdm_osal_ev_buf);
s_btdm_osal_ev_buf = NULL;
}
if (s_btdm_osal_evq_buf) {
BTDM_OSAL_ASSERT(s_btdm_osal_evq_pool.mp_num_free == s_btdm_osal_evq_pool.mp_num_blocks);
btdm_osal_free(s_btdm_osal_evq_buf);
s_btdm_osal_evq_buf = NULL;
}
if (s_btdm_osal_co_buf) {
BTDM_OSAL_ASSERT(s_btdm_osal_co_pool.mp_num_free == s_btdm_osal_co_pool.mp_num_blocks);
btdm_osal_free(s_btdm_osal_co_buf);
s_btdm_osal_co_buf = NULL;
}
if (s_btdm_osal_sem_buf) {
BTDM_OSAL_ASSERT(s_btdm_osal_sem_pool.mp_num_free == s_btdm_osal_sem_pool.mp_num_blocks);
btdm_osal_free(s_btdm_osal_sem_buf);
s_btdm_osal_sem_buf = NULL;
}
if (s_btdm_osal_mutex_buf) {
BTDM_OSAL_ASSERT(s_btdm_osal_mutex_pool.mp_num_free == s_btdm_osal_mutex_pool.mp_num_blocks);
btdm_osal_free(s_btdm_osal_mutex_buf);
s_btdm_osal_mutex_buf = NULL;
}
#endif // BTDM_MEMPOOL_ALLOC
}
@@ -119,6 +119,8 @@ int r_ble_hci_trans_reset(void);
//!TODO: Should we initialize the hci layer in IDF ?
void esp_ble_hci_trans_init(uint8_t);
int hci_cmd_proc_init(void);
// ********************************************************************************************
// btdm common
// ********************************************************************************************
@@ -126,7 +128,9 @@ void esp_ble_hci_trans_init(uint8_t);
typedef int (*btdm_hci_trans_tx_func_t)(hci_driver_packet_t *pkt);
#define HCI_INTERNAL_CONN_MASK (0x0fff)
#define HCI_INTERNAL_CONN_IS_BLE(conn_handle) (!(conn_handle & 0x0800))
#define HCI_INTERNAL_CONN_IS_BLE(conn_handle) ((conn_handle & 0x0800) == 0x0000)
#define HCI_INTERNAL_CONN_IS_BLE_ACL(conn_handle) ((conn_handle & 0x0e00) == 0x0000)
#define HCI_INTERNAL_CONN_IS_BLE_ISO(conn_handle) ((conn_handle & 0x0e00) == 0x0200)
#define HCI_INTERNAL_CONN_IS_BREDR(conn_handle) (conn_handle & 0x0800)
#define HCI_INTERNAL_CONN_IS_BREDR_ACL(conn_handle) ((conn_handle & 0x0800) && (conn_handle & 0x000f))
#define HCI_INTERNAL_CONN_IS_BREDR_SYNC(conn_handle) ((conn_handle & 0x0800) && (conn_handle & 0x00f0))
File diff suppressed because it is too large Load Diff
@@ -245,6 +245,8 @@ hci_transport_init(uint8_t hci_transport_mode)
goto error;
}
hci_cmd_proc_init();
s_hci_transport_env.driver_ops = ops;
#if UC_BT_CTRL_BLE_IS_ENABLE
r_ble_hci_trans_cfg_hs((esp_hci_internal_rx_cmd_fn *)hci_transport_controller_le_evt_tx, NULL,
@@ -271,21 +273,21 @@ hci_transport_deinit(void)
{
hci_driver_ops_t *ops;
btdm_hci_trans_register_tx((btdm_hci_trans_tx_func_t *)hci_transport_controller_tx_dummy, false);
ops = s_hci_transport_env.driver_ops;
if (ops) {
btdm_hci_trans_register_tx((btdm_hci_trans_tx_func_t *)hci_transport_controller_tx_dummy, false);
#if UC_BT_CTRL_BLE_IS_ENABLE
r_ble_hci_trans_cfg_hs((esp_hci_internal_rx_cmd_fn *)hci_transport_controller_le_tx_dummy, NULL,
r_ble_hci_trans_cfg_hs((esp_hci_internal_rx_cmd_fn *)hci_transport_controller_le_tx_dummy, NULL,
(esp_hci_internal_rx_acl_fn *)hci_transport_controller_le_tx_dummy, NULL);
#if CONFIG_BT_LE_ISO_SUPPORT
ble_iso_trans_cfg_hs((esp_hci_internal_rx_iso_fn *)hci_transport_controller_le_iso_tx_dummy, NULL);
ble_iso_trans_cfg_hs((esp_hci_internal_rx_iso_fn *)hci_transport_controller_le_iso_tx_dummy, NULL);
#endif // CONFIG_BT_LE_ISO_SUPPORT
#endif // UC_BT_CTRL_BLE_IS_ENABLE
#if UC_BT_CTRL_BR_EDR_IS_ENABLE
bredr_hci_trans_register_tx((btdm_hci_trans_tx_func_t *)hci_transport_controller_bredr_tx_dummy,
(btdm_hci_trans_tx_func_t *)hci_transport_controller_bredr_tx_dummy,
(btdm_hci_trans_tx_func_t *)hci_transport_controller_bredr_tx_dummy);
bredr_hci_trans_register_tx((btdm_hci_trans_tx_func_t *)hci_transport_controller_bredr_tx_dummy,
(btdm_hci_trans_tx_func_t *)hci_transport_controller_bredr_tx_dummy,
(btdm_hci_trans_tx_func_t *)hci_transport_controller_bredr_tx_dummy);
#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE
ops = s_hci_transport_env.driver_ops;
if (ops) {
ops->hci_driver_deinit();
}
memset(&s_hci_transport_env, 0, sizeof(hci_transport_env_t));