Add WiFi/BLE Coexistence support

Co-authored-by: Gustavo Henrique Nihei <gustavo.nihei@espressif.com>
Co-authored-by: Abdelatif Guettouche <abdelatif.guettouche@espressif.com>
This commit is contained in:
Alan C. Assis 2021-12-02 10:53:19 -03:00 committed by Xiang Xiao
parent 509350a614
commit 01e4e249cc
10 changed files with 871 additions and 346 deletions

View File

@ -532,7 +532,7 @@ config ESP32_AES_ACCELERATOR
endmenu # ESP32 Peripheral Selection
menuconfig ESP32_WIFI_BT_COEXIST
config ESP32_WIFI_BT_COEXIST
bool "Wi-Fi and BT coexist"
default n
depends on ESP32_WIRELESS && ESP32_BLE

View File

@ -206,7 +206,7 @@ endif
ifeq ($(CONFIG_ESP32_WIRELESS),y)
WIRELESS_DRV_UNPACK = esp-wireless-drivers-3rdparty
WIRELESS_DRV_ID = 2b53111
WIRELESS_DRV_ID = 055f1ef
WIRELESS_DRV_ZIP = $(WIRELESS_DRV_ID).zip
WIRELESS_DRV_URL = https://github.com/espressif/esp-wireless-drivers-3rdparty/archive
@ -235,11 +235,18 @@ EXTRA_LIBS += -lcore -lrtc -lnet80211 -lpp -lsmartconfig -lespnow -lphy -lwpa_su
ifeq ($(CONFIG_ESP32_BLE),y)
CHIP_CSRCS += esp32_ble_adapter.c esp32_ble.c
EXTRA_LIBS += -lbtdm_app -lcoexist
EXTRA_LIBS += -lbtdm_app
ifeq ($(CONFIG_ESP32_WIFI_BT_COEXIST),y)
EXTRA_LIBS += -lcoexist
endif
endif
# Due to some Wi-Fi related libraries, the option is need to avoid linking too much
# unused functions.
LDFLAGS += --gc-sections
# Wireless interfaces.
CHIP_CSRCS += esp32_wireless.c
endif

View File

@ -55,10 +55,10 @@
#include "xtensa_attr.h"
#include "esp32_rt_timer.h"
#include "esp32_ble_adapter.h"
#include "esp32_wireless.h"
#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
# include "esp_coexist_internal.h"
# include "esp_coexist_adapter.h"
#endif
/****************************************************************************
@ -108,10 +108,6 @@ do {\
extern void btdm_controller_set_sleep_mode(uint8_t mode);
#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
extern void coex_pti_v2(void);
#endif
/****************************************************************************
* Private Types
****************************************************************************/
@ -437,6 +433,19 @@ int coex_bt_release_wrapper(uint32_t event);
uint32_t coex_bb_reset_lock_wrapper(void);
void coex_bb_reset_unlock_wrapper(uint32_t restore);
extern void coex_ble_adv_priority_high_set(bool high);
extern int coex_bt_request(uint32_t event,
uint32_t latency,
uint32_t duration);
extern int coex_bt_release(uint32_t event);
extern int coex_enable(void);
extern int coex_register_bt_cb(coex_func_cb_t cb);
extern int coex_schm_register_btdm_callback(void *callback);
extern int coex_register_wifi_channel_change_callback(void *cb);
extern int coex_wifi_channel_get(uint8_t *primary,
uint8_t *secondary);
extern int coex_register_bt_cb(coex_func_cb_t cb);
extern void coex_bb_reset_unlock(uint32_t restore);
extern uint32_t coex_bb_reset_lock(void);
extern char _bss_start_btdm;
extern char _bss_end_btdm;
@ -497,9 +506,6 @@ static DRAM_ATTR esp_timer_handle_t g_btdm_slp_tmr;
/* BT interrupt private data */
static irqstate_t g_inter_flags;
static uint32_t g_phy_clk_en_cnt;
static int64_t g_phy_rf_en_ts;
static uint8_t g_phy_access_ref;
/****************************************************************************
* Public Data
@ -627,47 +633,81 @@ static btdm_dram_available_region_t btdm_dram_available_region[] =
static int adapter_coex_register_bt_cb_wrapper(coex_func_cb_t cb)
{
return ESP_ERR_INVALID_STATE;
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_register_bt_cb(cb);
#else
return 0;
#endif
}
static int adapter_coex_schm_register_btdm_callback(void *callback)
{
return ESP_ERR_INVALID_STATE;
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_schm_register_btdm_callback(callback);
#else
return 0;
#endif
}
static int adapter_coex_register_wifi_channel_change_callback(void *cb)
{
return ESP_ERR_INVALID_STATE;
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_register_wifi_channel_change_callback(cb);
#else
return -1;
#endif
}
static int adapter_coex_wifi_channel_get(uint8_t *primary,
uint8_t *secondary)
{
return -ERROR;
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_wifi_channel_get(primary, secondary);
#else
return -1;
#endif
}
static void adapter_coex_schm_status_bit_clear(uint32_t type,
uint32_t status)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
coex_schm_status_bit_clear(type, status);
#endif
}
static void adapter_coex_schm_status_bit_set(uint32_t type, uint32_t status)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
coex_schm_status_bit_set(type, status);
#endif
}
static uint32_t adapter_coex_schm_interval_get(void)
{
return ESP_ERR_INVALID_STATE;
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_schm_interval_get();
#else
return 0;
#endif
}
static uint8_t adapter_coex_schm_curr_period_get(void)
{
return OK;
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_schm_interval_get();
#else
return 0;
#endif
}
static void *adapter_coex_schm_curr_phase_get(void)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_schm_curr_phase_get();
#else
return NULL;
#endif
}
/****************************************************************************
@ -2065,69 +2105,6 @@ int coexist_printf(const char *format, ...)
return 0;
}
/****************************************************************************
* Name: bt_phy_enable_clock
*
* Description:
* Enable BT clock.
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void bt_phy_enable_clock(void)
{
irqstate_t flags;
flags = enter_critical_section();
if (g_phy_clk_en_cnt == 0)
{
modifyreg32(DPORT_WIFI_CLK_EN_REG, 0,
DPORT_WIFI_CLK_WIFI_BT_COMMON_M);
}
g_phy_clk_en_cnt++;
leave_critical_section(flags);
}
/****************************************************************************
* Name: bt_phy_disable_clock
*
* Description:
* Disable BT clock.
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void bt_phy_disable_clock(void)
{
irqstate_t flags;
flags = enter_critical_section();
if (g_phy_clk_en_cnt)
{
g_phy_clk_en_cnt--;
if (!g_phy_clk_en_cnt)
{
modifyreg32(DPORT_WIFI_CLK_EN_REG,
DPORT_WIFI_CLK_WIFI_BT_COMMON_M,
0);
}
}
leave_critical_section(flags);
}
/****************************************************************************
* Name: bt_phy_disable
*
@ -2144,25 +2121,7 @@ static void bt_phy_disable_clock(void)
static void bt_phy_disable(void)
{
irqstate_t flags;
flags = enter_critical_section();
g_phy_access_ref--;
if (g_phy_access_ref == 0)
{
/* Disable PHY and RF. */
phy_close_rf();
/* Disable Wi-Fi/BT common peripheral clock.
* Do not disable clock for hardware RNG.
*/
bt_phy_disable_clock();
}
leave_critical_section(flags);
esp32_phy_disable();
}
/****************************************************************************
@ -2181,35 +2140,7 @@ static void bt_phy_disable(void)
static void bt_phy_enable(void)
{
irqstate_t flags;
esp_phy_calibration_data_t *cal_data;
cal_data = kmm_zalloc(sizeof(esp_phy_calibration_data_t));
if (cal_data == NULL)
{
wlerr("Failed to kmm_zalloc");
DEBUGASSERT(0);
}
flags = enter_critical_section();
if (g_phy_access_ref == 0)
{
/* Update time stamp */
g_phy_rf_en_ts = (int64_t)rt_timer_time_us();
bt_phy_enable_clock();
phy_set_wifi_mode_only(0);
register_chipv7_phy(&phy_init_data, cal_data, PHY_RF_CAL_NONE);
#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
coex_pti_v2();
#endif
}
g_phy_access_ref++;
leave_critical_section(flags);
kmm_free(cal_data);
esp32_phy_enable();
}
/****************************************************************************
@ -2933,21 +2864,35 @@ int coex_bt_request_wrapper(uint32_t event,
uint32_t latency,
uint32_t duration)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_bt_request(event, latency, duration);
#else
return 0;
#endif
}
int coex_bt_release_wrapper(uint32_t event)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_bt_release(event);
#else
return 0;
#endif
}
uint32_t coex_bb_reset_lock_wrapper(void)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_bb_reset_lock();
#else
return 0;
#endif
}
void coex_bb_reset_unlock_wrapper(uint32_t restore)
{
return;
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
coex_bb_reset_unlock(restore);
#endif
}

View File

@ -57,12 +57,17 @@
#include "hardware/esp32_emac.h"
#include "hardware/esp32_soc.h"
#include "esp32_irq.h"
#include "esp32_wireless.h"
#include "esp32_wifi_adapter.h"
#include "esp32_rt_timer.h"
#include "esp32_wifi_utils.h"
#ifdef CONFIG_PM
#include "esp32_pm.h"
# include "esp32_pm.h"
#endif
#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
# include "esp_coexist_internal.h"
#endif
#include "espidf_wifi.h"
@ -224,6 +229,13 @@ static void *esp_semphr_create(uint32_t max, uint32_t init);
static void esp_semphr_delete(void *semphr);
static int32_t esp_semphr_take(void *semphr, uint32_t block_time_tick);
static int32_t esp_semphr_give(void *semphr);
#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
static int32_t esp_semphr_take_from_isr(void *semphr, void *hptw);
static int32_t esp_semphr_give_from_isr(void *semphr, void *hptw);
static int wifi_is_in_isr(void);
#endif
static void *esp_thread_semphr_get(void);
static void *esp_mutex_create(void);
static void *esp_recursive_mutex_create(void);
@ -273,10 +285,6 @@ static void esp_dport_access_stall_other_cpu_start(void);
static void esp_dport_access_stall_other_cpu_end(void);
static void wifi_apb80m_request(void);
static void wifi_apb80m_release(void);
static void wifi_phy_disable(void);
static void wifi_phy_enable(void);
static void esp_phy_enable_clock(void);
static void esp_phy_disable_clock(void);
static int32_t wifi_phy_update_country_info(const char *country);
static int32_t esp_wifi_read_mac(uint8_t *mac, uint32_t type);
static void esp_timer_arm(void *timer, uint32_t tmout, bool repeat);
@ -371,20 +379,6 @@ void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num);
static pthread_key_t g_wifi_thread_key;
static bool g_wifi_tkey_init;
/* Wi-Fi sleep private data */
static uint32_t g_phy_clk_en_cnt;
/* Reference count of enabling PHY */
static uint8_t g_phy_access_ref;
/* time stamp updated when the PHY/RF is turned on */
static int64_t g_phy_rf_en_ts;
static uint32_t g_common_clock_disable_time;
/* Wi-Fi event private data */
static struct work_s g_wifi_evt_work;
@ -434,6 +428,35 @@ static wifi_txdone_cb_t g_softap_txdone_cb;
static spinlock_t g_lock;
/* Wi-Fi and BT coexistence OS adapter data */
#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
coex_adapter_funcs_t g_coex_adapter_funcs =
{
._version = COEX_ADAPTER_VERSION,
._spin_lock_create = esp_spin_lock_create,
._spin_lock_delete = esp_spin_lock_delete,
._int_enable = esp_wifi_int_restore,
._int_disable = esp_wifi_int_disable,
._task_yield_from_isr = esp_task_yield_from_isr,
._semphr_create = esp_semphr_create,
._semphr_delete = esp_semphr_delete,
._semphr_take_from_isr = esp_semphr_take_from_isr,
._semphr_give_from_isr = esp_semphr_give_from_isr,
._semphr_take = esp_semphr_take,
._semphr_give = esp_semphr_give,
._is_in_isr = wifi_is_in_isr,
._malloc_internal = esp_malloc_internal,
._free = esp_free,
._timer_disarm = esp_timer_disarm,
._timer_done = esp32_timer_done,
._timer_setfn = esp_timer_setfn,
._timer_arm_us = esp_timer_arm_us,
._esp_timer_get_time = esp_timer_get_time,
._magic = COEX_ADAPTER_MAGIC,
};
#endif
/****************************************************************************
* Public Data
****************************************************************************/
@ -496,10 +519,10 @@ wifi_osi_funcs_t g_wifi_osi_funcs =
esp_dport_access_stall_other_cpu_end,
._wifi_apb80m_request = wifi_apb80m_request,
._wifi_apb80m_release = wifi_apb80m_release,
._phy_disable = wifi_phy_disable,
._phy_enable = wifi_phy_enable,
._phy_common_clock_enable = esp_phy_enable_clock,
._phy_common_clock_disable = esp_phy_disable_clock,
._phy_disable = esp32_phy_disable,
._phy_enable = esp32_phy_enable,
._phy_common_clock_enable = esp32_phy_enable_clock,
._phy_common_clock_disable = esp32_phy_disable_clock,
._phy_update_country_info = wifi_phy_update_country_info,
._read_mac = esp_wifi_read_mac,
._timer_arm = esp_timer_arm,
@ -1164,6 +1187,70 @@ static int32_t esp_semphr_give(void *semphr)
return osi_errno_trans(ret);
}
#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
/****************************************************************************
* Name: esp_semphr_take_from_isr
*
* Description:
* Try to take semaphore from within an interrupt service routine.
*
* Input Parameters:
* semphr - Semaphore data pointer
*
* Returned Value:
* True if success or false if fail
*
****************************************************************************/
static int32_t esp_semphr_take_from_isr(void *semphr, void *hptw)
{
*(int *)hptw = 0;
return esp_semphr_take(semphr, 0);
}
/****************************************************************************
* Name: esp_semphr_give_from_isr
*
* Description:
* Post semaphore from within an interrupt service routine.
*
* Input Parameters:
* semphr - Semaphore data pointer
*
* Returned Value:
* True if success or false if fail
*
****************************************************************************/
static int32_t esp_semphr_give_from_isr(void *semphr, void *hptw)
{
*(int *)hptw = 0;
return esp_semphr_give(semphr);
}
/****************************************************************************
* Name: wifi_is_in_isr
*
* Description:
* Check whether current execution context is of an interrupt service
* routine.
*
* Input Parameters:
* None
*
* Returned Value:
* true if in interrupt or false if not
*
****************************************************************************/
static int IRAM_ATTR wifi_is_in_isr(void)
{
return up_interrupt_context();
}
#endif
/****************************************************************************
* Name: esp_thread_semphr_get
@ -2374,198 +2461,6 @@ static void wifi_apb80m_release(void)
#endif
}
/****************************************************************************
* Name: phy_update_wifi_mac_time
*
* Description:
* Update Wi-Fi mac timer.
*
* Input Parameters:
* en_clock_stopped - Check if clock is stopped
* now - time now
*
* Returned Value:
* NOne
*
****************************************************************************/
static void phy_update_wifi_mac_time(bool en_clock_stopped, int64_t now)
{
uint32_t diff;
if (en_clock_stopped)
{
g_common_clock_disable_time = (uint32_t)now;
}
else
{
if (g_common_clock_disable_time)
{
diff = (uint64_t)now - g_common_clock_disable_time;
esp_wifi_internal_update_mac_time(diff);
g_common_clock_disable_time = 0;
}
}
}
/****************************************************************************
* Name: wifi_phy_disable
*
* Description:
* Deinitialize PHY hardware
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void wifi_phy_disable(void)
{
irqstate_t flags;
flags = enter_critical_section();
g_phy_access_ref--;
if (g_phy_access_ref == 0)
{
/* Disable PHY and RF. */
phy_close_rf();
/* Update Wi-Fi MAC time before disabling it.
* Wi-Fi/BT common peripheral clock.
*/
phy_update_wifi_mac_time(true, esp_timer_get_time());
/* Disable Wi-Fi/BT common peripheral clock.
* Do not disable clock for hardware RNG.
*/
esp_phy_disable_clock();
}
leave_critical_section(flags);
}
/****************************************************************************
* Name: wifi_phy_enable
*
* Description:
* Initialize PHY hardware
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void wifi_phy_enable(void)
{
irqstate_t flags;
esp_phy_calibration_data_t *cal_data;
cal_data = kmm_zalloc(sizeof(esp_phy_calibration_data_t));
if (!cal_data)
{
wlerr("Failed to kmm_zalloc");
DEBUGASSERT(0);
}
flags = enter_critical_section();
if (g_phy_access_ref == 0)
{
/* Update time stamp */
g_phy_rf_en_ts = esp_timer_get_time();
/* Update Wi-Fi MAC time before Wi-Fi/BT common clock is enabled */
phy_update_wifi_mac_time(false, g_phy_rf_en_ts);
esp_phy_enable_clock();
phy_set_wifi_mode_only(0);
register_chipv7_phy(&phy_init_data, cal_data, PHY_RF_CAL_NONE);
coex_bt_high_prio();
}
g_phy_access_ref++;
leave_critical_section(flags);
kmm_free(cal_data);
}
/****************************************************************************
* Name: esp_phy_enable_clock
*
* Description:
* Enable PHY hardware clock
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void esp_phy_enable_clock(void)
{
irqstate_t flags;
flags = spin_lock_irqsave(&g_lock);
if (g_phy_clk_en_cnt == 0)
{
modifyreg32(DPORT_WIFI_CLK_EN_REG, 0,
DPORT_WIFI_CLK_WIFI_BT_COMMON_M);
}
g_phy_clk_en_cnt++;
spin_unlock_irqrestore(&g_lock, flags);
}
/****************************************************************************
* Name: esp_phy_disable_clock
*
* Description:
* Disable PHY hardware clock
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void esp_phy_disable_clock(void)
{
irqstate_t flags;
flags = spin_lock_irqsave(&g_lock);
if (g_phy_clk_en_cnt)
{
g_phy_clk_en_cnt--;
if (!g_phy_clk_en_cnt)
{
modifyreg32(DPORT_WIFI_CLK_EN_REG,
DPORT_WIFI_CLK_WIFI_BT_COMMON_M,
0);
}
}
spin_unlock_irqrestore(&g_lock, flags);
}
/****************************************************************************
* Name: wifi_phy_update_country_info
*
@ -3901,7 +3796,11 @@ static void esp_wifi_delete_queue(void *queue)
static int wifi_coex_init(void)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_init();
#else
return 0;
#endif
}
/****************************************************************************
@ -3914,6 +3813,9 @@ static int wifi_coex_init(void)
static void wifi_coex_deinit(void)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
coex_deinit();
#endif
}
/****************************************************************************
@ -3926,7 +3828,11 @@ static void wifi_coex_deinit(void)
static int wifi_coex_enable(void)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_enable();
#else
return 0;
#endif
}
/****************************************************************************
@ -3939,6 +3845,9 @@ static int wifi_coex_enable(void)
static void wifi_coex_disable(void)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
coex_disable();
#endif
}
/****************************************************************************
@ -3951,7 +3860,11 @@ static void wifi_coex_disable(void)
static uint32_t esp_coex_status_get(void)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_status_get();
#else
return 0;
#endif
}
/****************************************************************************
@ -3964,6 +3877,9 @@ static uint32_t esp_coex_status_get(void)
static void esp_coex_condition_set(uint32_t type, bool dissatisfy)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
coex_condition_set(type, dissatisfy);
#endif
}
/****************************************************************************
@ -3977,7 +3893,11 @@ static void esp_coex_condition_set(uint32_t type, bool dissatisfy)
static int32_t esp_coex_wifi_request(uint32_t event, uint32_t latency,
uint32_t duration)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_wifi_request(event, latency, duration);
#else
return 0;
#endif
}
/****************************************************************************
@ -3990,7 +3910,11 @@ static int32_t esp_coex_wifi_request(uint32_t event, uint32_t latency,
static int32_t esp_coex_wifi_release(uint32_t event)
{
return 0;
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_wifi_release(event);
#else
return 0;
#endif
}
/****************************************************************************
@ -4003,7 +3927,11 @@ static int32_t esp_coex_wifi_release(uint32_t event)
static int wifi_coex_wifi_set_channel(uint8_t primary, uint8_t secondary)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_wifi_channel_set(primary, secondary);
#else
return 0;
#endif
}
/****************************************************************************
@ -4016,7 +3944,11 @@ static int wifi_coex_wifi_set_channel(uint8_t primary, uint8_t secondary)
static int wifi_coex_get_event_duration(uint32_t event, uint32_t *duration)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_event_duration_get(event, duration);
#else
return 0;
#endif
}
/****************************************************************************
@ -4042,6 +3974,9 @@ static int wifi_coex_get_pti(uint32_t event, uint8_t *pti)
static void wifi_coex_clear_schm_status_bit(uint32_t type, uint32_t status)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
coex_schm_status_bit_clear(type, status);
#endif
}
/****************************************************************************
@ -4054,6 +3989,9 @@ static void wifi_coex_clear_schm_status_bit(uint32_t type, uint32_t status)
static void wifi_coex_set_schm_status_bit(uint32_t type, uint32_t status)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
coex_schm_status_bit_set(type, status);
#endif
}
/****************************************************************************
@ -4066,7 +4004,11 @@ static void wifi_coex_set_schm_status_bit(uint32_t type, uint32_t status)
static int wifi_coex_set_schm_interval(uint32_t interval)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_schm_interval_set(interval);
#else
return 0;
#endif
}
/****************************************************************************
@ -4079,7 +4021,11 @@ static int wifi_coex_set_schm_interval(uint32_t interval)
static uint32_t wifi_coex_get_schm_interval(void)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_schm_interval_get();
#else
return 0;
#endif
}
/****************************************************************************
@ -4092,7 +4038,11 @@ static uint32_t wifi_coex_get_schm_interval(void)
static uint8_t wifi_coex_get_schm_curr_period(void)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_schm_curr_period_get();
#else
return 0;
#endif
}
/****************************************************************************
@ -4105,7 +4055,11 @@ static uint8_t wifi_coex_get_schm_curr_period(void)
static void *wifi_coex_get_schm_curr_phase(void)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_schm_curr_phase_get();
#else
return NULL;
#endif
}
/****************************************************************************
@ -4118,7 +4072,11 @@ static void *wifi_coex_get_schm_curr_phase(void)
static int wifi_coex_set_schm_curr_phase_idx(int idx)
{
return -1;
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_schm_curr_phase_idx_set(idx);
#else
return 0;
#endif
}
/****************************************************************************
@ -4131,7 +4089,11 @@ static int wifi_coex_set_schm_curr_phase_idx(int idx)
static int wifi_coex_get_schm_curr_phase_idx(void)
{
#if defined(CONFIG_ESP32_WIFI_BT_COEXIST)
return coex_schm_curr_phase_idx_get();
#else
return 0;
#endif
}
/****************************************************************************
@ -4665,6 +4627,32 @@ void __assert_func(const char *file, int line,
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: esp32_wifi_bt_coexist_init
*
* Description:
* Initialize ESP32 Wi-Fi and BT coexistence module.
*
* Input Parameters:
* None
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
int esp32_wifi_bt_coexist_init(void)
{
coex_dbg_set_log_level(COEX_LOG_INFO);
esp_coex_adapter_register(&g_coex_adapter_funcs);
coex_pre_init();
return 0;
}
#endif
/****************************************************************************
* Name: esp_event_send_internal
*
@ -6791,4 +6779,5 @@ int esp_wifi_softap_rssi(struct iwreq *iwr, bool set)
{
return -ENOSYS;
}
#endif

View File

@ -63,6 +63,14 @@ extern "C"
#define MAC_LEN (6)
/* Needed to fix coex_adapter_funcs_t definition */
#define CONFIG_IDF_TARGET_ESP32 1
/* Define esp_err_t */
typedef int esp_err_t;
/* Wi-Fi event ID */
enum wifi_adpt_evt_e
@ -76,6 +84,16 @@ enum wifi_adpt_evt_e
WIFI_ADPT_EVT_MAX,
};
enum coex_log_level_e
{
COEX_LOG_NONE = 0,
COEX_LOG_ERROR,
COEX_LOG_WARN,
COEX_LOG_INFO,
COEX_LOG_DEBUG,
COEX_LOG_VERBOSE
};
/* Wi-Fi event callback function */
typedef void (*wifi_evt_cb_t)(void *p);
@ -84,6 +102,8 @@ typedef void (*wifi_evt_cb_t)(void *p);
typedef void (*wifi_txdone_cb_t)(uint8_t *data, uint16_t *len, bool status);
#define COEX_ADAPTER_FUNCS_TIME_BLOCKING 0xffffffff
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
@ -810,6 +830,26 @@ int esp_wifi_softap_country(struct iwreq *iwr, bool set);
****************************************************************************/
int esp_wifi_softap_rssi(struct iwreq *iwr, bool set);
#endif /* ESP32_WLAN_HAS_SOFTAP */
/****************************************************************************
* Name: esp32_wifi_bt_coexist_init
*
* Description:
* Initialize ESP32 Wi-Fi and BT coexistence module.
*
* Input Parameters:
* None
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
int esp32_wifi_bt_coexist_init(void);
void coex_dbg_set_log_level(int level);
#endif
#ifdef __cplusplus

View File

@ -0,0 +1,281 @@
/****************************************************************************
* arch/xtensa/src/esp32/esp32_wireless.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/kmalloc.h>
#include <debug.h>
#include <assert.h>
#include "xtensa.h"
#include "hardware/esp32_soc.h"
#include "hardware/esp32_dport.h"
#include "esp32_wireless.h"
#include "esp_phy_init.h"
#include "phy_init_data.h"
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static inline void phy_digital_regs_store(void);
static inline void phy_digital_regs_load(void);
/****************************************************************************
* Extern Functions declaration
****************************************************************************/
extern void coex_bt_high_prio(void);
extern void phy_wakeup_init(void);
extern void phy_close_rf(void);
extern void phy_dig_reg_backup(bool init, uint32_t *regs);
extern int register_chipv7_phy(const esp_phy_init_data_t *init_data,
esp_phy_calibration_data_t *cal_data,
esp_phy_calibration_mode_t cal_mode);
/****************************************************************************
* Private Data
****************************************************************************/
/* Wi-Fi sleep private data */
static uint32_t g_phy_clk_en_cnt;
/* Reference count of enabling PHY */
static uint8_t g_phy_access_ref;
/* Memory to store PHY digital registers */
static uint32_t *g_phy_digital_regs_mem = NULL;
/* Indicate PHY is calibrated or not */
static bool g_is_phy_calibrated = false;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: phy_digital_regs_store
*
* Description:
* Store PHY digital registers.
*
****************************************************************************/
static inline void phy_digital_regs_store(void)
{
if (g_phy_digital_regs_mem == NULL)
{
g_phy_digital_regs_mem = (uint32_t *)
kmm_malloc(SOC_PHY_DIG_REGS_MEM_SIZE);
}
DEBUGASSERT(g_phy_digital_regs_mem != NULL);
phy_dig_reg_backup(true, g_phy_digital_regs_mem);
}
/****************************************************************************
* Name: phy_digital_regs_load
*
* Description:
* Load PHY digital registers.
*
****************************************************************************/
static inline void phy_digital_regs_load(void)
{
if (g_phy_digital_regs_mem != NULL)
{
phy_dig_reg_backup(false, g_phy_digital_regs_mem);
}
}
/****************************************************************************
* Name: esp32_phy_enable_clock
*
* Description:
* Enable PHY hardware clock
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void esp32_phy_enable_clock(void)
{
irqstate_t flags;
flags = enter_critical_section();
if (g_phy_clk_en_cnt == 0)
{
modifyreg32(DPORT_WIFI_CLK_EN_REG, 0,
DPORT_WIFI_CLK_WIFI_BT_COMMON_M);
}
g_phy_clk_en_cnt++;
leave_critical_section(flags);
}
/****************************************************************************
* Name: esp32_phy_disable_clock
*
* Description:
* Disable PHY hardware clock
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void esp32_phy_disable_clock(void)
{
irqstate_t flags;
flags = enter_critical_section();
if (g_phy_clk_en_cnt > 0)
{
g_phy_clk_en_cnt--;
if (g_phy_clk_en_cnt == 0)
{
modifyreg32(DPORT_WIFI_CLK_EN_REG,
DPORT_WIFI_CLK_WIFI_BT_COMMON_M,
0);
}
}
leave_critical_section(flags);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: esp32_phy_disable
*
* Description:
* Deinitialize PHY hardware
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void esp32_phy_disable(void)
{
irqstate_t flags;
flags = enter_critical_section();
g_phy_access_ref--;
if (g_phy_access_ref == 0)
{
/* Disable PHY and RF. */
phy_close_rf();
/* Disable Wi-Fi/BT common peripheral clock.
* Do not disable clock for hardware RNG.
*/
esp32_phy_disable_clock();
}
leave_critical_section(flags);
}
/****************************************************************************
* Name: esp32_phy_enable
*
* Description:
* Initialize PHY hardware
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void esp32_phy_enable(void)
{
static bool debug = false;
irqstate_t flags;
esp_phy_calibration_data_t *cal_data;
if (debug == false)
{
char *phy_version = get_phy_version_str();
wlinfo("phy_version %s\n", phy_version);
debug = true;
}
cal_data = kmm_zalloc(sizeof(esp_phy_calibration_data_t));
if (!cal_data)
{
wlerr("ERROR: Failed to allocate PHY calibration data buffer.");
abort();
}
flags = enter_critical_section();
if (g_phy_access_ref == 0)
{
esp32_phy_enable_clock();
if (g_is_phy_calibrated == false)
{
register_chipv7_phy(&phy_init_data, cal_data, PHY_RF_CAL_NONE);
g_is_phy_calibrated = true;
}
else
{
phy_wakeup_init();
phy_digital_regs_load();
}
#ifdef CONFIG_ESP32_BLE
coex_bt_high_prio();
#endif
}
g_phy_access_ref++;
leave_critical_section(flags);
kmm_free(cal_data);
}

View File

@ -0,0 +1,110 @@
/****************************************************************************
* arch/xtensa/src/esp32/esp32_wireless.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_XTENSA_SRC_ESP32_ESP32_WIRELESS_H
#define __ARCH_XTENSA_SRC_ESP32_ESP32_WIRELESS_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Note: Don't remove these definitions, they are needed by the 3rdparty IDF
* headers
*/
#define CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN 0
#define CONFIG_MAC_BB_PD 0
#define SOC_COEX_HW_PTI 0
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: esp32_phy_enable
*
* Description:
* Initialize PHY hardware
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void esp32_phy_enable(void);
/****************************************************************************
* Name: esp32_phy_disable
*
* Description:
* Deinitialize PHY hardware
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void esp32_phy_disable(void);
/****************************************************************************
* Name: esp32_phy_enable_clock
*
* Description:
* Enable PHY clock
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void esp32_phy_enable_clock(void);
/****************************************************************************
* Name: esp32_phy_disable_clock
*
* Description:
* Disable PHY clock
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void esp32_phy_disable_clock(void);
#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_WIRELESS_H */

View File

@ -804,6 +804,10 @@ extern int rom_i2c_writereg(int block, int block_id, int reg_add,
#define INVALID_MMU_VAL 0x100
/* phy registers and memory size */
#define SOC_PHY_DIG_REGS_MEM_SIZE (21*4)
/****************************************************************************
* Inline Functions
****************************************************************************/

View File

@ -0,0 +1,136 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_ARCH_LEDS is not set
# CONFIG_DISABLE_ENVIRON is not set
# CONFIG_DISABLE_MQUEUE is not set
# CONFIG_DISABLE_POSIX_TIMERS is not set
# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set
# CONFIG_NSH_DISABLEBG is not set
# CONFIG_NSH_DISABLESCRIPT is not set
# CONFIG_NSH_DISABLE_ARP is not set
# CONFIG_NSH_DISABLE_BASENAME is not set
# CONFIG_NSH_DISABLE_CMP is not set
# CONFIG_NSH_DISABLE_DD is not set
# CONFIG_NSH_DISABLE_DF is not set
# CONFIG_NSH_DISABLE_DIRNAME is not set
# CONFIG_NSH_DISABLE_EXEC is not set
# CONFIG_NSH_DISABLE_GET is not set
# CONFIG_NSH_DISABLE_HEXDUMP is not set
# CONFIG_NSH_DISABLE_ITEF is not set
# CONFIG_NSH_DISABLE_LOOPS is not set
# CONFIG_NSH_DISABLE_LOSETUP is not set
# CONFIG_NSH_DISABLE_MKRD is not set
# CONFIG_NSH_DISABLE_MKSMARTFS is not set
# CONFIG_NSH_DISABLE_PUT is not set
# CONFIG_NSH_DISABLE_SEMICOLON is not set
# CONFIG_NSH_DISABLE_TIME is not set
# CONFIG_NSH_DISABLE_UNAME is not set
# CONFIG_NSH_DISABLE_WGET is not set
# CONFIG_NSH_DISABLE_XD is not set
CONFIG_ALLOW_BSD_COMPONENTS=y
CONFIG_ARCH="xtensa"
CONFIG_ARCH_BOARD="esp32-devkitc"
CONFIG_ARCH_BOARD_ESP32_DEVKITC=y
CONFIG_ARCH_CHIP="esp32"
CONFIG_ARCH_CHIP_ESP32=y
CONFIG_ARCH_CHIP_ESP32WROVER=y
CONFIG_ARCH_INTERRUPTSTACK=4096
CONFIG_ARCH_STACKDUMP=y
CONFIG_ARCH_XTENSA=y
CONFIG_BOARD_LOOPSPERMSEC=16717
CONFIG_BTSAK=y
CONFIG_BUILTIN=y
CONFIG_CLOCK_MONOTONIC=y
CONFIG_DEBUG_ERROR=y
CONFIG_DEBUG_FEATURES=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEBUG_WARN=y
CONFIG_DEBUG_WIRELESS=y
CONFIG_DEBUG_WIRELESS_ERROR=y
CONFIG_DEBUG_WIRELESS_INFO=y
CONFIG_DEBUG_WIRELESS_WARN=y
CONFIG_DEFAULT_SMALL=y
CONFIG_DEFAULT_TASK_STACKSIZE=4096
CONFIG_DEV_URANDOM=y
CONFIG_DRIVERS_BLUETOOTH=y
CONFIG_DRIVERS_IEEE80211=y
CONFIG_DRIVERS_WIRELESS=y
CONFIG_ESP32_BLE=y
CONFIG_ESP32_RT_TIMER_TASK_STACK_SIZE=4096
CONFIG_ESP32_SPIFLASH=y
CONFIG_ESP32_SPIFLASH_SMARTFS=y
CONFIG_ESP32_STORAGE_MTD_SIZE=0x80000
CONFIG_ESP32_UART0=y
CONFIG_ESP32_WIFI_BT_COEXIST=y
CONFIG_ESP32_WIFI_SAVE_PARAM=y
CONFIG_EXAMPLE_POWER_SAVE_MIN_MODEM=y
CONFIG_FS_LARGEFILE=y
CONFIG_FS_PROCFS=y
CONFIG_FS_SPIFFS=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_IDLETHREAD_STACKSIZE=3072
CONFIG_INTELHEX_BINARY=y
CONFIG_LIBC_LONG_LONG=y
CONFIG_MM_REGIONS=3
CONFIG_NAME_MAX=48
CONFIG_NETDB_DNSCLIENT=y
CONFIG_NETDB_DNSCLIENT_ENTRIES=8
CONFIG_NETDB_DNSCLIENT_NAMESIZE=64
CONFIG_NETDEVICES=y
CONFIG_NETDEV_LATEINIT=y
CONFIG_NETDEV_PHY_IOCTL=y
CONFIG_NETDEV_WIRELESS_IOCTL=y
CONFIG_NETUTILS_IPERF=y
CONFIG_NETUTILS_TELNETD=y
CONFIG_NET_BLUETOOTH=y
CONFIG_NET_BROADCAST=y
CONFIG_NET_ETH_PKTSIZE=1518
CONFIG_NET_ICMP=y
CONFIG_NET_ICMP_SOCKET=y
CONFIG_NET_NACTIVESOCKETS=32
CONFIG_NET_STATISTICS=y
CONFIG_NET_TCP=y
CONFIG_NET_TCP_DELAYED_ACK=y
CONFIG_NET_TCP_WRITE_BUFFERS=y
CONFIG_NET_UDP=y
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_LINELEN=300
CONFIG_NSH_TELNET=y
CONFIG_PTHREAD_MUTEX_ROBUST=y
CONFIG_PTHREAD_MUTEX_TYPES=y
CONFIG_RAM_SIZE=114688
CONFIG_RAM_START=0x20000000
CONFIG_RAW_BINARY=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_WAITPID=y
CONFIG_SDCLONE_DISABLE=y
CONFIG_SIG_DEFAULT=y
CONFIG_SMARTFS_ALIGNED_ACCESS=y
CONFIG_SMARTFS_MAXNAMLEN=48
CONFIG_SPI=y
CONFIG_SPIFFS_NAME_MAX=48
CONFIG_SPINLOCK=y
CONFIG_START_DAY=6
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2011
CONFIG_SYSTEM_DHCPC_RENEW=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_PING=y
CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048
CONFIG_TELNET_CHARACTER_MODE=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=2048
CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_USER_ENTRYPOINT="nsh_main"
CONFIG_WIRELESS=y
CONFIG_WIRELESS_BLUETOOTH=y
CONFIG_WIRELESS_WAPI=y
CONFIG_WIRELESS_WAPI_CMDTOOL=y

View File

@ -73,6 +73,10 @@
# include "esp32_board_wlan.h"
#endif
#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
# include "esp32_wifi_adapter.h"
#endif
#ifdef CONFIG_ESP32_I2C
# include "esp32_board_i2c.h"
#endif
@ -223,6 +227,15 @@ int esp32_bringup(void)
}
#endif
#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
ret = esp32_wifi_bt_coexist_init();
if (ret)
{
syslog(LOG_ERR, "ERROR: Failed to initialize Wi-Fi and BT "
"coexistence support\n");
}
#endif
#ifdef CONFIG_ESP32_BLE
ret = esp32_ble_initialize();
if (ret)