risc-v/esp32c3: Fix Wi-Fi & BLE coexist issue

1. Wi-Fi and BLE use common PHY functions.
  2. Fix Wi-Fi & BLE coexist adapter error.
  3. Update esp-wireless-drivers-3rdparty, provide coexist protection for connection.
This commit is contained in:
ChenWen 2021-10-26 15:50:47 +08:00 committed by Alan Carvalho de Assis
parent 65d7f4bfb3
commit 440787c0c1
6 changed files with 367 additions and 360 deletions

View File

@ -174,7 +174,7 @@ endif
ifeq ($(CONFIG_ESP32C3_WIRELESS),y)
WIRELESS_DRV_UNPACK = esp-wireless-drivers-3rdparty
WIRELESS_DRV_ID = 024420d
WIRELESS_DRV_ID = 055f1ef
WIRELESS_DRV_ZIP = $(WIRELESS_DRV_ID).zip
WIRELESS_DRV_URL = https://github.com/espressif/esp-wireless-drivers-3rdparty/archive
@ -204,6 +204,10 @@ EXTRA_LIBS += -lphy
# unused functions.
LDFLAGS += --gc-sections
# Wireless interfaces.
CHIP_CSRCS += esp32c3_wireless.c
endif
ifeq ($(CONFIG_ESP32C3_WIFI),y)

View File

@ -55,6 +55,7 @@
#include "esp32c3_irq.h"
#include "esp32c3_rt_timer.h"
#include "esp32c3_ble_adapter.h"
#include "esp32c3_wireless.h"
#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
# include "esp_coexist_internal.h"
@ -406,9 +407,6 @@ static DRAM_ATTR esp_timer_handle_t g_btdm_slp_tmr;
static bool g_ble_irq_bind;
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
@ -1683,69 +1681,6 @@ int phy_printf(const char *format, ...)
}
#endif
/****************************************************************************
* 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(SYSTEM_WIFI_CLK_EN_REG, 0,
SYSTEM_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(SYSTEM_WIFI_CLK_EN_REG,
SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M,
0);
}
}
leave_critical_section(flags);
}
/****************************************************************************
* Name: bt_phy_disable
*
@ -1761,25 +1696,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);
esp32c3_phy_disable();
}
/****************************************************************************
@ -1797,36 +1714,17 @@ 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)
{
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);
extern void coex_pti_v2(void);
coex_pti_v2();
}
g_phy_access_ref++;
leave_critical_section(flags);
kmm_free(cal_data);
esp32c3_phy_enable();
}
/****************************************************************************
* Name: coex_wifi_sleep_set_hook
*
* Description:
* Don't support
*
****************************************************************************/
static void coex_wifi_sleep_set_hook(bool sleep)
{
}

View File

@ -62,6 +62,7 @@
#include "esp32c3_wifi_utils.h"
#include "esp32c3_wlan.h"
#include "esp32c3_ble_adapter.h"
#include "esp32c3_wireless.h"
#include "esp32c3_clockconfig.h"
#ifdef CONFIG_PM
@ -314,10 +315,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 int wifi_phy_update_country_info(const char *country);
static int esp_wifi_read_mac(uint8_t *mac, uint32_t type);
static void wifi_reset_mac(void);
@ -392,14 +389,6 @@ static int esp_wifi_sta_connect_wrapper(void);
#endif
static void esp_wifi_set_debug_log(void);
/****************************************************************************
* Extern Functions declaration
****************************************************************************/
#ifdef CONFIG_ESP32C3_BLE
extern void coex_pti_v2(void);
#endif
/****************************************************************************
* Public Functions declaration
****************************************************************************/
@ -424,18 +413,6 @@ uint8_t esp_crc8(const uint8_t *p, uint32_t len);
static bool g_wifi_irq_bind;
/* 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;
/* Wi-Fi event private data */
static struct work_s g_wifi_evt_work;
@ -447,14 +424,6 @@ static sem_t g_wifiexcl_sem = SEM_INITIALIZER(1);
static int g_wifi_ref = 0;
/* 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;
#ifdef ESP32C3_WLAN_HAS_STA
/* If reconnect automatically */
@ -576,8 +545,8 @@ 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_disable = esp32c3_phy_disable,
._phy_enable = esp32c3_phy_enable,
._phy_update_country_info = wifi_phy_update_country_info,
._read_mac = esp_wifi_read_mac,
._timer_arm = ets_timer_arm,
@ -2670,214 +2639,6 @@ static void wifi_apb80m_release(void)
#endif
}
/****************************************************************************
* 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: 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)
{
/* Store PHY digital register. */
phy_digital_regs_store();
/* Disable PHY and RF. */
phy_close_rf();
phy_xpd_tsens();
/* 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)
{
static bool debug = false;
irqstate_t flags;
esp_phy_calibration_data_t *cal_data;
char *phy_version = get_phy_version_str();
if (debug == false)
{
debug = true;
wlinfo("phy_version %s\n", phy_version);
}
cal_data = kmm_zalloc(sizeof(esp_phy_calibration_data_t));
if (!cal_data)
{
wlerr("ERROR: 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();
esp_phy_enable_clock();
if (g_is_phy_calibrated == false)
{
register_chipv7_phy(&phy_init_data, cal_data, PHY_RF_CAL_FULL);
g_is_phy_calibrated = true;
}
else
{
phy_wakeup_init();
phy_digital_regs_load();
}
#ifdef CONFIG_ESP32C3_BLE
coex_pti_v2();
#endif
}
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 = enter_critical_section();
if (g_phy_clk_en_cnt == 0)
{
modifyreg32(SYSTEM_WIFI_CLK_EN_REG, 0,
SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M);
}
g_phy_clk_en_cnt++;
leave_critical_section(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 = enter_critical_section();
if (g_phy_clk_en_cnt)
{
g_phy_clk_en_cnt--;
if (!g_phy_clk_en_cnt)
{
modifyreg32(SYSTEM_WIFI_CLK_EN_REG,
SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M,
0);
}
}
leave_critical_section(flags);
}
/****************************************************************************
* Name: wifi_phy_update_country_info
*
@ -4464,7 +4225,6 @@ static void *wifi_coex_get_schm_curr_phase(void)
static int wifi_coex_set_schm_curr_phase_idx(int idx)
{
return -1;
#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
return coex_schm_curr_phase_idx_set(idx);
#else

View File

@ -0,0 +1,282 @@
/****************************************************************************
* arch/risc-v/src/esp32c3/esp32c3_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 "hardware/esp32c3_soc.h"
#include "hardware/esp32c3_syscon.h"
#include "esp32c3.h"
#include "espidf_wifi.h"
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static inline void phy_digital_regs_store(void);
static inline void phy_digital_regs_load(void);
static void esp32c3_phy_enable_clock(void);
static void esp32c3_phy_disable_clock(void);
/****************************************************************************
* Extern Functions declaration
****************************************************************************/
#ifdef CONFIG_ESP32C3_BLE
extern void coex_pti_v2(void);
#endif
/****************************************************************************
* 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: esp32c3_phy_enable_clock
*
* Description:
* Enable PHY hardware clock
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void esp32c3_phy_enable_clock(void)
{
irqstate_t flags;
flags = enter_critical_section();
if (g_phy_clk_en_cnt == 0)
{
modifyreg32(SYSTEM_WIFI_CLK_EN_REG, 0,
SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M);
}
g_phy_clk_en_cnt++;
leave_critical_section(flags);
}
/****************************************************************************
* Name: esp32c3_phy_disable_clock
*
* Description:
* Disable PHY hardware clock
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void esp32c3_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(SYSTEM_WIFI_CLK_EN_REG,
SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M,
0);
}
}
leave_critical_section(flags);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: esp32c3_phy_disable
*
* Description:
* Deinitialize PHY hardware
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void esp32c3_phy_disable(void)
{
irqstate_t flags;
flags = enter_critical_section();
g_phy_access_ref--;
if (g_phy_access_ref == 0)
{
/* Store PHY digital register. */
phy_digital_regs_store();
/* Disable PHY and RF. */
phy_close_rf();
phy_xpd_tsens();
/* Disable Wi-Fi/BT common peripheral clock.
* Do not disable clock for hardware RNG.
*/
esp32c3_phy_disable_clock();
}
leave_critical_section(flags);
}
/****************************************************************************
* Name: esp32c3_phy_enable
*
* Description:
* Initialize PHY hardware
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void esp32c3_phy_enable(void)
{
static bool debug = false;
irqstate_t flags;
esp_phy_calibration_data_t *cal_data;
char *phy_version = get_phy_version_str();
if (debug == false)
{
debug = true;
wlinfo("phy_version %s\n", phy_version);
}
cal_data = kmm_zalloc(sizeof(esp_phy_calibration_data_t));
if (!cal_data)
{
wlerr("ERROR: Failed to kmm_zalloc");
DEBUGASSERT(0);
}
flags = enter_critical_section();
if (g_phy_access_ref == 0)
{
esp32c3_phy_enable_clock();
if (g_is_phy_calibrated == false)
{
register_chipv7_phy(&phy_init_data, cal_data, PHY_RF_CAL_FULL);
g_is_phy_calibrated = true;
}
else
{
phy_wakeup_init();
phy_digital_regs_load();
}
#ifdef CONFIG_ESP32C3_BLE
coex_pti_v2();
#endif
}
g_phy_access_ref++;
leave_critical_section(flags);
kmm_free(cal_data);
}

View File

@ -0,0 +1,66 @@
/****************************************************************************
* arch/risc-v/src/esp32c3/esp32c3_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_RISCV_SRC_ESP32C3_ESP32C3_WIRELESS_H
#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_WIRELESS_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: esp32c3_phy_enable
*
* Description:
* Initialize PHY hardware
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void esp32c3_phy_enable(void);
/****************************************************************************
* Name: esp32c3_phy_disable
*
* Description:
* Deinitialize PHY hardware
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void esp32c3_phy_disable(void);
#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_WIRELESS_H */

View File

@ -1591,7 +1591,6 @@ ppTask = 0x40001720;
ppTxPkt = 0x40001724;
ppTxProtoProc = 0x40001728;
ppTxqUpdateBitmap = 0x4000172c;
pp_coex_tx_request = 0x40001730;
pp_hdrsize = 0x40001734;
pp_post = 0x40001738;
pp_process_hmac_waiting_txq = 0x4000173c;
@ -1762,12 +1761,10 @@ esp_coex_rom_version_get = 0x400018ac;
coex_bt_release = 0x400018b0;
coex_bt_request = 0x400018b4;
coex_core_ble_conn_dyn_prio_get = 0x400018b8;
coex_core_event_duration_get = 0x400018bc;
coex_core_pti_get = 0x400018c0;
coex_core_release = 0x400018c4;
coex_core_request = 0x400018c8;
coex_core_status_get = 0x400018cc;
coex_core_timer_idx_get = 0x400018d0;
coex_event_duration_get = 0x400018d4;
coex_hw_timer_disable = 0x400018d8;
coex_hw_timer_enable = 0x400018dc;