You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2021/06/29 04:14:40 UTC

[incubator-nuttx] branch master updated (c89c11a -> 5fd3eca)

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from c89c11a  drivers: wireless: Fix error handling in gs2200m_ioctl_send()
     new 8b96edc  riscv/esp32c3: Add esp32c3 BLE driver
     new 145d917  riscv/esp32c3: Add Wi-Fi and BLE coexist
     new 5fd3eca  riscv/esp32c3: Support BLE sleep mode

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 arch/risc-v/include/esp32c3/irq.h                  |    2 +
 arch/risc-v/src/esp32c3/Kconfig                    |   53 +-
 arch/risc-v/src/esp32c3/Make.defs                  |   15 +-
 arch/risc-v/src/esp32c3/esp32c3_ble.c              |  337 +++
 .../risc-v/src/esp32c3/esp32c3_ble.h               |   24 +-
 arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c      | 2474 ++++++++++++++++++++
 .../src/esp32c3/esp32c3_ble_adapter.h}             |  127 +-
 arch/risc-v/src/esp32c3/esp32c3_irq.c              |    9 +
 arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c     |  265 ++-
 arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.h     |   19 +
 arch/risc-v/src/esp32c3/esp32c3_wlan.c             |    4 +-
 arch/risc-v/src/esp32c3/esp32c3_wlan.h             |    4 +-
 .../esp32c3-devkit/configs/autopm/defconfig        |    2 +-
 .../configs/{sotest => ble}/defconfig              |   27 +-
 .../esp32c3-devkit/configs/sta_softap/defconfig    |    2 +-
 .../esp32c3/esp32c3-devkit/configs/wapi/defconfig  |    2 +-
 .../esp32c3/esp32c3-devkit/src/esp32c3_bringup.c   |   27 +
 17 files changed, 3285 insertions(+), 108 deletions(-)
 create mode 100644 arch/risc-v/src/esp32c3/esp32c3_ble.c
 copy libs/libc/unistd/lib_getuid.c => arch/risc-v/src/esp32c3/esp32c3_ble.h (82%)
 create mode 100644 arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c
 copy arch/{arm/src/cxd56xx/cxd56_gpio.h => risc-v/src/esp32c3/esp32c3_ble_adapter.h} (58%)
 copy boards/risc-v/esp32c3/esp32c3-devkit/configs/{sotest => ble}/defconfig (74%)

[incubator-nuttx] 03/03: riscv/esp32c3: Support BLE sleep mode

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 5fd3eca9c9956a046de15436201469adab1c41b2
Author: xiewenxiang <xi...@espressif.com>
AuthorDate: Wed Jun 2 17:20:19 2021 +0800

    riscv/esp32c3: Support BLE sleep mode
---
 arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c      | 490 ++++++++++++++++++++-
 arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c     |  17 +-
 .../esp32c3-devkit/configs/sta_softap/defconfig    |   2 +-
 3 files changed, 471 insertions(+), 38 deletions(-)

diff --git a/arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c b/arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c
index bcf8b51..406686c 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c
@@ -65,9 +65,18 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
-#define OSI_FUNCS_TIME_BLOCKING  0xffffffff
-#define OSI_VERSION              0x00010006
-#define OSI_MAGIC_VALUE          0xfadebead
+#define OSI_FUNCS_TIME_BLOCKING          0xffffffff
+#define OSI_VERSION                      0x00010006
+#define OSI_MAGIC_VALUE                  0xfadebead
+
+#ifdef CONFIG_PM
+#define BTDM_MIN_TIMER_UNCERTAINTY_US    (1800)
+
+/* Sleep and wakeup interval control */
+
+#define BTDM_MIN_SLEEP_DURATION          (24) /* threshold of interval in half slots to allow to fall into modem sleep */
+#define BTDM_MODEM_WAKE_UP_DELAY         (8)  /* delay in half slots of modem wake up procedure, including re-enable PHY/RF */
+#endif
 
 /****************************************************************************
  * Private Types
@@ -92,32 +101,47 @@ struct irq_adpt_s
 
 /* BLE low power control struct */
 
+typedef enum btdm_lpclk_sel_e
+{
+  BTDM_LPCLK_SEL_XTAL     = 0,
+  BTDM_LPCLK_SEL_XTAL32K  = 1,
+  BTDM_LPCLK_SEL_RTC_SLOW = 2,
+  BTDM_LPCLK_SEL_8M       = 3,
+} btdm_lpclk_sel_t;
+
+typedef enum btdm_vnd_ol_sig_e
+{
+  BTDM_VND_OL_SIG_WAKEUP_TMR,
+  BTDM_VND_OL_SIG_NUM,
+} btdm_vnd_ol_sig_t;
+
 typedef struct btdm_lpcntl_s
 {
-  uint32_t enable;                  /* whether low power mode is required */
-  uint32_t lpclk_sel;               /* low power clock source */
-  uint32_t mac_bb_pd;               /* whether hardware(MAC, BB) force-power-down is required during sleep */
-  uint32_t wakeup_timer_required;   /* whether system timer is needed */
-  uint32_t no_light_sleep;          /* do not allow system to enter light sleep after bluetooth is enabled */
+  bool enable;                  /* whether low power mode is required */
+  bool wakeup_timer_required;   /* whether system timer is needed */
+  btdm_lpclk_sel_t lpclk_sel;   /* low power clock source */
 } btdm_lpcntl_t;
 
 /* low power control status */
 
 typedef struct btdm_lpstat_s
 {
-  uint32_t pm_lock_released        /* whether power management lock is released */
-  uint32_t mac_bb_pd               /* whether hardware(MAC, BB) is powered down */
-  uint32_t phy_enabled             /* whether phy is switched on */
-  uint32_t wakeup_timer_started    /* whether wakeup timer is started */
+  bool pm_lock_released;        /* whether power management lock is released */
+  bool phy_enabled;             /* whether phy is switched on */
+  bool wakeup_timer_started;    /* whether wakeup timer is started */
 } btdm_lpstat_t;
 
-/* vendor dependent signals to be posted to controller task */
+#ifdef CONFIG_PM
+/* wakeup request sources */
 
-typedef enum
+enum btdm_wakeup_src_e
 {
-  BTDM_VND_OL_SIG_WAKEUP_TMR,
-  BTDM_VND_OL_SIG_NUM,
-} btdm_vnd_ol_sig_t;
+  BTDM_ASYNC_WAKEUP_SRC_VHCI,
+  BTDM_ASYNC_WAKEUP_SRC_DISA,
+  BTDM_ASYNC_WAKEUP_SRC_TMR,
+  BTDM_ASYNC_WAKEUP_SRC_MAX,
+};
+#endif
 
 /* prototype of function to handle vendor dependent signals */
 
@@ -257,6 +281,13 @@ static int queue_recv_wrapper(void *queue, void *item,
                               uint32_t block_time_ms);
 static void queue_delete_wrapper(void *queue);
 
+#ifdef CONFIG_PM
+static bool IRAM_ATTR btdm_sleep_check_duration(int32_t *half_slot_cnt);
+static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles);
+static void btdm_sleep_enter_phase2_wrapper(void);
+static void btdm_sleep_exit_phase3_wrapper(void);
+#endif
+
 /****************************************************************************
  * Extern Functions declaration and value
  ****************************************************************************/
@@ -361,6 +392,16 @@ static DRAM_ATTR uint32_t g_btdm_lpcycle_us = 0;
 
 static DRAM_ATTR uint8_t g_btdm_lpcycle_us_frac = 0;
 
+#ifdef CONFIG_PM
+/* semaphore used for blocking VHCI API to wait for controller to wake up */
+
+static DRAM_ATTR void * g_wakeup_req_sem  = NULL;
+
+/* wakeup timer */
+
+static DRAM_ATTR esp_timer_handle_t g_btdm_slp_tmr;
+#endif
+
 /* BT interrupt private data */
 
 static bool g_ble_irq_bind;
@@ -413,6 +454,12 @@ static struct osi_funcs_s g_osi_funcs =
   ._rand = rand_wrapper,
   ._btdm_lpcycles_2_hus = btdm_lpcycles_2_hus,
   ._btdm_hus_2_lpcycles = btdm_hus_2_lpcycles,
+#ifdef CONFIG_PM
+  ._btdm_sleep_check_duration = btdm_sleep_check_duration,
+  ._btdm_sleep_enter_phase1 = btdm_sleep_enter_phase1_wrapper,
+  ._btdm_sleep_enter_phase2 = btdm_sleep_enter_phase2_wrapper,
+  ._btdm_sleep_exit_phase3 = btdm_sleep_exit_phase3_wrapper,
+#endif
   ._coex_wifi_sleep_set = coex_wifi_sleep_set_hook,
   ._coex_core_ble_conn_dyn_prio_get = coex_core_ble_conn_dyn_prio_get,
   ._coex_schm_status_bit_set = coex_schm_status_bit_set_wrapper,
@@ -1345,6 +1392,225 @@ static uint32_t IRAM_ATTR btdm_hus_2_lpcycles(uint32_t us)
   return (uint32_t)cycles;
 }
 
+#ifdef CONFIG_PM
+/****************************************************************************
+ * Name: btdm_sleep_exit_phase0
+ *
+ * Description:
+ *   acquire PM lock and stop esp timer.
+ *
+ * Input Parameters:
+ *   param - wakeup event
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR btdm_sleep_exit_phase0(void *param)
+{
+  DEBUGASSERT(g_lp_cntl.enable == true);
+
+  if (g_lp_stat.pm_lock_released)
+    {
+      esp32c3_pm_lockacquire();
+      g_lp_stat.pm_lock_released = false;
+    }
+
+  int event = (int) param;
+
+  if (event == BTDM_ASYNC_WAKEUP_SRC_VHCI ||
+      event == BTDM_ASYNC_WAKEUP_SRC_DISA)
+    {
+      btdm_wakeup_request();
+    }
+
+  if (g_lp_cntl.wakeup_timer_required && g_lp_stat.wakeup_timer_started)
+    {
+      esp_timer_stop(g_btdm_slp_tmr);
+      g_lp_stat.wakeup_timer_started = false;
+    }
+
+  if (event == BTDM_ASYNC_WAKEUP_SRC_VHCI ||
+      event == BTDM_ASYNC_WAKEUP_SRC_DISA)
+    {
+      semphr_give_wrapper(g_wakeup_req_sem);
+    }
+}
+
+/****************************************************************************
+ * Name: btdm_slp_tmr_callback
+ *
+ * Description:
+ *   Esp ble sleep callback function.
+ *
+ * Input Parameters:
+ *   arg - Unused
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR btdm_slp_tmr_callback(void *arg)
+{
+  btdm_vnd_offload_post(BTDM_VND_OL_SIG_WAKEUP_TMR,
+                        (void *)BTDM_ASYNC_WAKEUP_SRC_TMR);
+}
+
+/****************************************************************************
+ * Name: btdm_sleep_check_duration
+ *
+ * Description:
+ *   Wake up in advance considering the delay in enabling PHY/RF.
+ *
+ * Input Parameters:
+ *   half_slot_cnt - half slots to allow to fall into modem sleep
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static bool IRAM_ATTR btdm_sleep_check_duration(int32_t *half_slot_cnt)
+{
+  if (*half_slot_cnt < BTDM_MIN_SLEEP_DURATION)
+    {
+      return false;
+    }
+
+  *half_slot_cnt -= BTDM_MODEM_WAKE_UP_DELAY;
+  return true;
+}
+
+/****************************************************************************
+ * Name: btdm_sleep_enter_phase1_wrapper
+ *
+ * Description:
+ *   ESP32C3 BLE lightsleep callback function.
+ *
+ * Input Parameters:
+ *   lpcycles - light sleep cycles
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles)
+{
+  if (g_lp_cntl.wakeup_timer_required == false)
+    {
+      return;
+    }
+
+  /* start a timer to wake up and acquire the pm_lock before sleep awakes */
+
+  uint32_t us_to_sleep = btdm_lpcycles_2_hus(lpcycles, NULL) >> 1;
+
+  DEBUGASSERT(us_to_sleep > BTDM_MIN_TIMER_UNCERTAINTY_US);
+  uint32_t uncertainty = (us_to_sleep >> 11);
+
+  if (uncertainty < BTDM_MIN_TIMER_UNCERTAINTY_US)
+    {
+      uncertainty = BTDM_MIN_TIMER_UNCERTAINTY_US;
+    }
+
+  DEBUGASSERT(g_lp_stat.wakeup_timer_started == false);
+
+  if (esp_timer_start_once(g_btdm_slp_tmr,
+                           us_to_sleep - uncertainty) == ESP_OK)
+    {
+      g_lp_stat.wakeup_timer_started = true;
+    }
+  else
+    {
+      wlerr("timer start failed");
+      DEBUGASSERT(0);
+    }
+}
+
+/****************************************************************************
+ * Name: btdm_sleep_enter_phase2_wrapper
+ *
+ * Description:
+ *   ESP32C3 BLE lightsleep callback function.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void btdm_sleep_enter_phase2_wrapper(void)
+{
+  if (btdm_controller_get_sleep_mode() == ESP_BT_SLEEP_MODE_1)
+    {
+      if (g_lp_stat.phy_enabled)
+        {
+          bt_phy_disable();
+          g_lp_stat.phy_enabled = false;
+        }
+      else
+        {
+          DEBUGASSERT(0);
+        }
+
+      if (g_lp_stat.pm_lock_released == false)
+        {
+          esp32c3_pm_lockrelease();
+          g_lp_stat.pm_lock_released = true;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: btdm_sleep_exit_phase3_wrapper
+ *
+ * Description:
+ *   ESP32C3 BLE lightsleep callback function..
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void btdm_sleep_exit_phase3_wrapper(void)
+{
+  if (g_lp_stat.pm_lock_released)
+    {
+      esp32c3_pm_lockacquire();
+      g_lp_stat.pm_lock_released = false;
+    }
+
+  if (btdm_sleep_clock_sync())
+    {
+      wlerr("sleep eco state err\n");
+      DEBUGASSERT(0);
+    }
+
+  if (btdm_controller_get_sleep_mode() == ESP_BT_SLEEP_MODE_1)
+    {
+      if (g_lp_stat.phy_enabled == false)
+        {
+          bt_phy_enable();
+          g_lp_stat.phy_enabled = true;
+        }
+    }
+
+  if (g_lp_cntl.wakeup_timer_required && g_lp_stat.wakeup_timer_started)
+    {
+      esp_timer_stop(g_btdm_slp_tmr);
+      g_lp_stat.wakeup_timer_started = false;
+    }
+}
+#endif
+
 /****************************************************************************
  * Name: coex_schm_status_bit_set_wrapper
  *
@@ -1754,6 +2020,10 @@ int esp32c3_bt_controller_init(void)
 {
   esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
   esp_bt_controller_config_t *cfg = &bt_cfg;
+#ifdef CONFIG_PM
+  bool select_src_ret;
+  bool set_div_ret;
+#endif
 
   if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE)
     {
@@ -1795,6 +2065,95 @@ int esp32c3_bt_controller_init(void)
   wlinfo("BT controller compile version [%s]\n",
                               btdm_controller_get_compile_version());
 
+#ifdef CONFIG_PM
+  /* init low-power control resources */
+
+  memset(&g_lp_cntl, 0x0, sizeof(btdm_lpcntl_t));
+  memset(&g_lp_stat, 0x0, sizeof(btdm_lpstat_t));
+  g_wakeup_req_sem = NULL;
+  g_btdm_slp_tmr = NULL;
+
+  /* configure and initialize resources */
+
+  g_lp_cntl.enable = (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) ? true : false;
+
+  if (g_lp_cntl.enable)
+    {
+      g_lp_cntl.wakeup_timer_required = true;
+      g_wakeup_req_sem = semphr_create_wrapper(1, 0);
+
+      if (g_wakeup_req_sem == NULL)
+        {
+          goto error;
+        }
+
+      btdm_vnd_offload_task_register(BTDM_VND_OL_SIG_WAKEUP_TMR,
+                                     btdm_sleep_exit_phase0);
+    }
+
+  if (g_lp_cntl.wakeup_timer_required)
+    {
+      esp_timer_create_args_t create_args =
+        {
+          .callback = btdm_slp_tmr_callback,
+          .arg = NULL,
+          .name = "btSlp",
+        };
+
+      if ((err = esp_timer_create(&create_args, &g_btdm_slp_tmr)) != ESP_OK)
+        {
+          goto error;
+        }
+    }
+
+  g_btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
+  g_btdm_lpcycle_us = 2 << (g_btdm_lpcycle_us_frac);
+
+  if (esp32c3_rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_32K_XTAL)
+    {
+      g_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL32K;
+    }
+  else
+    {
+      wlwarn("32.768kHz XTAL not detected");
+      g_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL;
+    }
+
+  if (g_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL)
+    {
+      select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL);
+      set_div_ret = btdm_lpclk_set_div(esp32c3_rtc_clk_xtal_freq_get() * 2);
+      DEBUGASSERT(select_src_ret && set_div_ret);
+      g_btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
+      g_btdm_lpcycle_us = 2 << (g_btdm_lpcycle_us_frac);
+    }
+  else if (g_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL32K)
+    {
+      select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K);
+      set_div_ret = btdm_lpclk_set_div(0);
+      DEBUGASSERT(select_src_ret && set_div_ret);
+      g_btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
+      g_btdm_lpcycle_us = (RTC_CLK_CAL_FRACT > 15) ?
+          (1000000 << (RTC_CLK_CAL_FRACT - 15)) :
+          (1000000 >> (15 - RTC_CLK_CAL_FRACT));
+      DEBUGASSERT(g_btdm_lpcycle_us != 0);
+    }
+  else if (g_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_RTC_SLOW)
+    {
+      select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
+      set_div_ret = btdm_lpclk_set_div(0);
+      DEBUGASSERT(select_src_ret && set_div_ret);
+      g_btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
+      g_btdm_lpcycle_us = esp_clk_slowclk_cal_get_wrapper();
+    }
+  else
+    {
+      goto error;
+    }
+
+  g_lp_stat.pm_lock_released = true;
+#endif
+
 #ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
   coex_init();
 #endif
@@ -1802,18 +2161,48 @@ int esp32c3_bt_controller_init(void)
   modifyreg32(SYSTEM_WIFI_CLK_EN_REG, 0, UINT32_MAX);
 
   bt_phy_enable();
-  g_lp_stat.phy_enabled = 1;
+  g_lp_stat.phy_enabled = true;
 
   if (btdm_controller_init(cfg) != 0)
     {
       bt_phy_disable();
-      g_lp_stat.phy_enabled = 0;
+      g_lp_stat.phy_enabled = false;
       return -EIO;
     }
 
   btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
 
   return 0;
+
+#ifdef CONFIG_PM
+error:
+  if (g_lp_stat.phy_enabled)
+    {
+      bt_phy_disable();
+      g_lp_stat.phy_enabled = false;
+    }
+
+  g_lp_stat.pm_lock_released = false;
+
+  if (g_lp_cntl.wakeup_timer_required && g_btdm_slp_tmr != NULL)
+    {
+      esp_timer_delete(g_btdm_slp_tmr);
+      g_btdm_slp_tmr = NULL;
+    }
+
+  if (g_lp_cntl.enable)
+    {
+      btdm_vnd_offload_task_deregister(BTDM_VND_OL_SIG_WAKEUP_TMR);
+
+      if (g_wakeup_req_sem != NULL)
+        {
+          semphr_delete_wrapper(g_wakeup_req_sem);
+          g_wakeup_req_sem = NULL;
+        }
+    }
+
+  return ENOMEM;
+#endif
 }
 
 /****************************************************************************
@@ -1841,13 +2230,38 @@ int esp32c3_bt_controller_deinit(void)
   if (g_lp_stat.phy_enabled)
     {
       bt_phy_disable();
-      g_lp_stat.phy_enabled = 0;
+      g_lp_stat.phy_enabled = false;
     }
-    else
+  else
     {
-      assert(0);
+      DEBUGASSERT(0);
     }
 
+#ifdef CONFIG_PM
+  /* deinit low power control resources */
+
+  g_lp_stat.pm_lock_released = false;
+
+  if (g_lp_cntl.wakeup_timer_required)
+    {
+      if (g_lp_stat.wakeup_timer_started)
+        {
+          esp_timer_stop(g_btdm_slp_tmr);
+        }
+
+      g_lp_stat.wakeup_timer_started = false;
+      esp_timer_delete(g_btdm_slp_tmr);
+      g_btdm_slp_tmr = NULL;
+    }
+
+  if (g_lp_cntl.enable)
+    {
+      btdm_vnd_offload_task_deregister(BTDM_VND_OL_SIG_WAKEUP_TMR);
+      semphr_delete_wrapper(g_wakeup_req_sem);
+      g_wakeup_req_sem = NULL;
+    }
+#endif
+
   btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
   g_btdm_lpcycle_us = 0;
   return 0;
@@ -1886,6 +2300,20 @@ int esp32c3_bt_controller_disable(void)
 
   btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
 
+#ifdef CONFIG_PM
+  /* disable low power mode */
+
+  if (g_lp_stat.pm_lock_released == false)
+    {
+      esp32c3_pm_lockrelease();
+      g_lp_stat.pm_lock_released = true;
+    }
+  else
+    {
+      DEBUGASSERT(0);
+    }
+#endif
+
   return 0;
 }
 
@@ -1922,8 +2350,18 @@ int esp32c3_bt_controller_enable(esp_bt_mode_t mode)
   coex_enable();
 #endif
 
+#ifdef CONFIG_PM
   /* enable low power mode */
 
+  esp32c3_pm_lockacquire();
+  g_lp_stat.pm_lock_released = false;
+
+  if (g_lp_cntl.enable)
+    {
+      btdm_controller_enable_sleep(true);
+    }
+#endif
+
   if (g_lp_cntl.enable)
     {
         btdm_controller_enable_sleep(true);
@@ -1945,6 +2383,14 @@ error:
 
   btdm_controller_enable_sleep(false);
 
+#ifdef CONFIG_PM
+  if (g_lp_stat.pm_lock_released == false)
+    {
+      esp32c3_pm_lockrelease();
+      g_lp_stat.pm_lock_released = true;
+    }
+#endif
+
   return ret;
 }
 
diff --git a/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c
index ee3daab..3f55826 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c
@@ -4624,19 +4624,6 @@ int esp_mesh_send_event_internal(int32_t event_id,
 }
 
 /****************************************************************************
- * Name: esp_mesh_get_topology
- *
- * Description:
- *   Don't support
- *
- ****************************************************************************/
-
-void *esp_mesh_get_topology(void)
-{
-  return NULL;
-}
-
-/****************************************************************************
  * Functions needed by libwpa_supplicant.a
  ****************************************************************************/
 
@@ -4880,7 +4867,7 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
       return ret;
     }
 
-#if SOC_WIFI_HW_TSF
+#ifdef CONFIG_PM
   ret = esp32c3_pm_register_skip_sleep_callback(
                     esp_wifi_internal_is_tsf_active);
   if (ret != OK)
@@ -4935,7 +4922,7 @@ esp_err_t esp_wifi_deinit(void)
       return ret;
     }
 
-#if SOC_WIFI_HW_TSF
+#ifdef CONFIG_PM
     esp32c3_pm_unregister_skip_sleep_callback(
                     esp_wifi_internal_is_tsf_active);
     esp32c3_pm_unregister_inform_out_sleep_overhead_callback(
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/sta_softap/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/sta_softap/defconfig
index aca1681..7e59d55 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/configs/sta_softap/defconfig
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/sta_softap/defconfig
@@ -30,9 +30,9 @@ CONFIG_DRIVERS_WIRELESS=y
 CONFIG_ESP32C3_MTD_OFFSET=0x110000
 CONFIG_ESP32C3_MTD_SIZE=0xf0000
 CONFIG_ESP32C3_SPIFLASH=y
+CONFIG_ESP32C3_WIFI=y
 CONFIG_ESP32C3_WIFI_SAVE_PARAM=y
 CONFIG_ESP32C3_WIFI_STATION_SOFTAP_COEXISTENCE=y
-CONFIG_ESP32C3_WIFI=y
 CONFIG_EXAMPLES_DHCPD=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_FS_PROCFS=y

[incubator-nuttx] 01/03: riscv/esp32c3: Add esp32c3 BLE driver

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 8b96edc3a5b62e76b8c1ff22063321a08de1361e
Author: xiewenxiang <xi...@espressif.com>
AuthorDate: Fri Apr 2 16:05:30 2021 +0800

    riscv/esp32c3: Add esp32c3 BLE driver
---
 arch/risc-v/include/esp32c3/irq.h                  |    2 +
 arch/risc-v/src/esp32c3/Kconfig                    |   48 +-
 arch/risc-v/src/esp32c3/Make.defs                  |   15 +-
 arch/risc-v/src/esp32c3/esp32c3_ble.c              |  337 ++++
 .../src/esp32c3/{esp32c3_wlan.h => esp32c3_ble.h}  |   58 +-
 arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c      | 2007 ++++++++++++++++++++
 arch/risc-v/src/esp32c3/esp32c3_ble_adapter.h      |  161 ++
 arch/risc-v/src/esp32c3/esp32c3_irq.c              |    9 +
 arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c     |   11 +
 arch/risc-v/src/esp32c3/esp32c3_wlan.c             |    4 +-
 arch/risc-v/src/esp32c3/esp32c3_wlan.h             |    4 +-
 .../esp32c3-devkit/configs/autopm/defconfig        |    2 +-
 .../esp32c3-devkit/configs/{wapi => ble}/defconfig |   30 +-
 .../esp32c3-devkit/configs/sta_softap/defconfig    |    2 +-
 .../esp32c3/esp32c3-devkit/configs/wapi/defconfig  |    2 +-
 .../esp32c3/esp32c3-devkit/src/esp32c3_bringup.c   |   16 +-
 16 files changed, 2622 insertions(+), 86 deletions(-)

diff --git a/arch/risc-v/include/esp32c3/irq.h b/arch/risc-v/include/esp32c3/irq.h
index 89334e2..1b44758 100644
--- a/arch/risc-v/include/esp32c3/irq.h
+++ b/arch/risc-v/include/esp32c3/irq.h
@@ -133,6 +133,8 @@
 /* Reserved CPU interrupt for specific drivers */
 
 #define ESP32C3_CPUINT_WMAC            1  /* Wi-Fi MAC */
+#define ESP32C3_CPUINT_BT_BB           5  /* BT BB */
+#define ESP32C3_CPUINT_RWBLE           8  /* RW BLE */
 
 /* IRQ numbers. */
 
diff --git a/arch/risc-v/src/esp32c3/Kconfig b/arch/risc-v/src/esp32c3/Kconfig
index 45c9713..791b087 100644
--- a/arch/risc-v/src/esp32c3/Kconfig
+++ b/arch/risc-v/src/esp32c3/Kconfig
@@ -162,6 +162,12 @@ config ESP32C3_RTC_HEAP
 	select ARCH_HAVE_EXTRA_HEAPS
 	default n
 
+config ESP32C3_WIRELESS
+	bool
+	default n
+	select ESP32C3_RT_TIMER
+	select ESP32C3_TIMER0
+
 menu "ESP32-C3 Peripheral Support"
 
 config ESP32C3_ADC
@@ -328,6 +334,22 @@ config ESP32C3_RSA_ACCELERATOR
 	---help---
 		Enable ESP32-C3 RSA accelerator support.
 
+config ESP32C3_WIFI
+	bool "Wi-Fi"
+	default n
+	select NET
+	select ARCH_PHY_INTERRUPT
+	select ESP32C3_WIRELESS
+	---help---
+		Enable Wi-Fi support
+
+config ESP32C3_BLE
+	bool "BLE"
+	default n
+	select ESP32C3_WIRELESS
+	---help---
+		Enable BLE support
+
 endmenu # ESP32-C3 Peripheral Support
 
 menu "I2C Configuration"
@@ -641,7 +663,7 @@ endif # ESP32C3_ADC1
 endmenu # ADC Configuration
 
 menu "Wi-Fi configuration"
-	depends on ESP32C3_WIRELESS
+	depends on ESP32C3_WIFI
 
 choice
 	prompt "ESP32-C3 Wi-Fi mode"
@@ -763,7 +785,29 @@ config ESP32C3_WIFI_RECONNECT
 	---help---
 		Select this option to enable Wi-Fi to reconnect for station when disconnected.
 
-endmenu # ESP32C3_WIRELESS
+endmenu # Wi-Fi configuration
+
+menu "BLE Configuration"
+	depends on ESP32C3_BLE
+
+config ESP32C3_BLE_PKTBUF_NUM
+	int "BLE netcard packet buffer number per netcard"
+	default 16
+
+config ESP32C3_BLE_TTY_NAME
+	string "BLE TTY device name"
+	default "/dev/ttyHCI0"
+	depends on UART_BTH4
+
+config ESP32C3_BLE_TASK_STACK_SIZE
+	int "Controller task stack size"
+	default 4096
+
+config ESP32C3_BLE_TASK_PRIORITY
+	int "Controller task priority"
+	default 110
+
+endmenu # BLE Configuration
 
 menu "SPI Flash configuration"
 	depends on ESP32C3_SPIFLASH
diff --git a/arch/risc-v/src/esp32c3/Make.defs b/arch/risc-v/src/esp32c3/Make.defs
index bd62279..df1b047 100644
--- a/arch/risc-v/src/esp32c3/Make.defs
+++ b/arch/risc-v/src/esp32c3/Make.defs
@@ -178,7 +178,7 @@ endif
 
 ifeq ($(CONFIG_ESP32C3_WIRELESS),y)
 WIRELESS_DRV_UNPACK  = esp-wireless-drivers-3rdparty
-WIRELESS_DRV_ID      = 2b53111
+WIRELESS_DRV_ID      = df1f8c1
 WIRELESS_DRV_ZIP     = $(WIRELESS_DRV_ID).zip
 WIRELESS_DRV_URL     = https://github.com/espressif/esp-wireless-drivers-3rdparty/archive
 
@@ -200,13 +200,22 @@ clean_context::
 
 INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)include)
 INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)include$(DELIM)esp32c3)
-CHIP_CSRCS += esp32c3_wlan.c esp32c3_wifi_utils.c esp32c3_wifi_adapter.c
 
 EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)libs$(DELIM)esp32c3
-EXTRA_LIBS += -lcore -lnet80211 -lpp -lsmartconfig -lcoexist -lespnow -lphy -lwpa_supplicant -lwapi
+EXTRA_LIBS += -lphy
 
 # Due to some Wi-Fi related libraries, the option is need to avoid linking too much
 # unused functions.
 
 LDFLAGS += --gc-sections
 endif
+
+ifeq ($(CONFIG_ESP32C3_WIFI),y)
+CHIP_CSRCS += esp32c3_wlan.c esp32c3_wifi_utils.c esp32c3_wifi_adapter.c
+EXTRA_LIBS += -lcore -lnet80211 -lpp -lsmartconfig -lcoexist -lespnow -lwpa_supplicant -lwapi
+endif
+
+ifeq ($(CONFIG_ESP32C3_BLE),y)
+CHIP_CSRCS += esp32c3_ble_adapter.c esp32c3_ble.c
+EXTRA_LIBS +=  -lbtbb -lbtdm_app
+endif
diff --git a/arch/risc-v/src/esp32c3/esp32c3_ble.c b/arch/risc-v/src/esp32c3/esp32c3_ble.c
new file mode 100644
index 0000000..b655b73
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp32c3_ble.c
@@ -0,0 +1,337 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp32c3_ble.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 <sys/types.h>
+
+#include <sys/socket.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <queue.h>
+#include <debug.h>
+
+#include <nuttx/nuttx.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/net/bluetooth.h>
+#include <nuttx/wireless/bluetooth/bt_driver.h>
+#include <nuttx/wireless/bluetooth/bt_uart.h>
+
+#if defined(CONFIG_UART_BTH4)
+  #include <nuttx/serial/uart_bth4.h>
+#endif
+
+#include "esp32c3_ble_adapter.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* BLE packet buffer max number */
+
+#define BLE_BUF_NUM       CONFIG_ESP32C3_BLE_PKTBUF_NUM
+
+/* BLE packet buffer max size */
+
+#define BLE_BUF_SIZE      1024
+
+/* Low-priority work queue process RX/TX */
+
+#define BLE_WORK          LPWORK
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct esp32c3_ble_priv_s
+{
+  struct bt_driver_s drv;         /* NuttX BT/BLE driver data */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int esp32c3_ble_open(struct bt_driver_s *drv);
+static int esp32c3_ble_send(struct bt_driver_s *drv,
+                            enum bt_buf_type_e type,
+                            void *data, size_t len);
+static void esp32c3_ble_close(struct bt_driver_s *drv);
+
+static void esp32c3_ble_send_ready(void);
+static int esp32c3_ble_recv_cb(uint8_t *data, uint16_t len);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct esp32c3_ble_priv_s g_ble_priv =
+{
+  .drv =
+    {
+      .head_reserve = H4_HEADER_SIZE,
+      .open         = esp32c3_ble_open,
+      .send         = esp32c3_ble_send,
+      .close        = esp32c3_ble_close
+    }
+};
+
+static esp_vhci_host_callback_t vhci_host_cb =
+{
+  .notify_host_send_available = esp32c3_ble_send_ready,
+  .notify_host_recv           = esp32c3_ble_recv_cb
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32c3_ble_send_ready
+ *
+ * Description:
+ *   If the controller could send HCI comand will callback this function.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void esp32c3_ble_send_ready(void)
+{
+}
+
+/****************************************************************************
+ * Name: esp32c3_ble_recv_cb
+ *
+ * Description:
+ *   BLE receive callback function when BLE hardware receive packet
+ *
+ * Input Parameters:
+ *   data - BLE packet data pointer
+ *   len  - BLE packet length
+ *
+ * Returned Value:
+ *   0 on success or a negated value on failure.
+ *
+ ****************************************************************************/
+
+static int esp32c3_ble_recv_cb(uint8_t *data, uint16_t len)
+{
+  int ret;
+  bool valid;
+  enum bt_buf_type_e type;
+  struct esp32c3_ble_priv_s *priv = &g_ble_priv;
+
+  switch (data[0])
+    {
+      case H4_EVT:
+        type = BT_EVT;
+        valid = true;
+        break;
+      case H4_ACL:
+        type = BT_ACL_IN;
+        valid = true;
+        break;
+      case H4_ISO:
+        type = BT_ISO_IN;
+        valid = true;
+        break;
+      default:
+        valid = false;
+        break;
+    }
+
+  if (!valid)
+    {
+      ret = ERROR;
+    }
+  else
+    {
+      /* send packet to host */
+
+      ret = bt_netdev_receive(&priv->drv, type,
+                              &data[H4_HEADER_SIZE],
+                              len - H4_HEADER_SIZE);
+      if (ret < 0)
+        {
+          wlerr("Failed to receive ret=%d\n", ret);
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32c3_ble_send
+ *
+ * Description:
+ *   ESP32-C3 BLE send callback function for BT driver.
+ *
+ * Input Parameters:
+ *   drv  - BT driver pointer
+ *   type - BT packet type
+ *   data - BT packte data buffer pointer
+ *   len  - BT packte length
+ *
+ * Returned Value:
+ *   Sent bytes on success or a negated value on failure.
+ *
+ ****************************************************************************/
+
+static int esp32c3_ble_send(struct bt_driver_s *drv,
+                            enum bt_buf_type_e type,
+                            void *data, size_t len)
+{
+  uint8_t *hdr = (uint8_t *)data - drv->head_reserve;
+
+  if ((len + H4_HEADER_SIZE) > BLE_BUF_SIZE)
+    {
+      return -EINVAL;
+    }
+
+  if (type == BT_CMD)
+    {
+      *hdr = H4_CMD;
+    }
+  else if (type == BT_ACL_OUT)
+    {
+      *hdr = H4_ACL;
+    }
+  else if (type == BT_ISO_OUT)
+    {
+      *hdr = H4_ISO;
+    }
+  else
+    {
+      return -EINVAL;
+    }
+
+  if (esp32c3_vhci_host_check_send_available())
+    {
+      esp32c3_vhci_host_send_packet(hdr, len + drv->head_reserve);
+    }
+
+  return len;
+}
+
+/****************************************************************************
+ * Name: esp32c3_ble_close
+ *
+ * Description:
+ *   ESP32-C3 BLE close callback function for BT driver.
+ *
+ * Input Parameters:
+ *   drv  - BT driver pointer
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void esp32c3_ble_close(struct bt_driver_s *drv)
+{
+}
+
+/****************************************************************************
+ * Name: esp32c3_ble_open
+ *
+ * Description:
+ *   ESP32-C3 BLE open callback function for BT driver.
+ *
+ * Input Parameters:
+ *   drv - BT driver pointer
+ *
+ * Returned Value:
+ *   OK on success or a negated value on failure.
+ *
+ ****************************************************************************/
+
+static int esp32c3_ble_open(struct bt_driver_s *drv)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32c3_ble_initialize
+ *
+ * Description:
+ *   Init BT controller
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   success or fail
+ *
+ ****************************************************************************/
+
+int esp32c3_ble_initialize(void)
+{
+  int ret;
+
+  ret = esp32c3_bt_controller_init();
+  if (ret)
+    {
+      wlerr("Failed to initialize BLE ret=%d\n", ret);
+      return ERROR;
+    }
+
+  ret = esp32c3_bt_controller_enable(ESP_BT_MODE_BLE);
+  if (ret)
+    {
+      wlerr("Failed to Enable BLE ret=%d\n", ret);
+      return ERROR;
+    }
+
+  ret = esp32c3_vhci_register_callback(&vhci_host_cb);
+  if (ret)
+    {
+      wlerr("Failed to register BLE callback ret=%d\n", ret);
+      return ERROR;
+    }
+
+#if defined(CONFIG_UART_BTH4)
+  ret = uart_bth4_register(CONFIG_BT_UART_ON_DEV_NAME, &g_ble_priv.drv);
+#else
+  ret = bt_netdev_register(&g_ble_priv.drv);
+#endif
+  if (ret < 0)
+    {
+      wlerr("bt_netdev_register error: %d\n", ret);
+      return ret;
+    }
+
+  return OK;
+}
diff --git a/arch/risc-v/src/esp32c3/esp32c3_wlan.h b/arch/risc-v/src/esp32c3/esp32c3_ble.h
similarity index 57%
copy from arch/risc-v/src/esp32c3/esp32c3_wlan.h
copy to arch/risc-v/src/esp32c3/esp32c3_ble.h
index 54cdf9a..d1cd2c9 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_wlan.h
+++ b/arch/risc-v/src/esp32c3/esp32c3_ble.h
@@ -1,5 +1,5 @@
 /****************************************************************************
- * arch/risc-v/src/esp32c3/esp32c3_wlan.h
+ * arch/risc-v/src/esp32c3/esp32c3_ble.h
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -18,8 +18,8 @@
  *
  ****************************************************************************/
 
-#ifndef __ARCH_RISCV_SRC_ESP32C3_ESP32C3_WLAN_H
-#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_WLAN_H
+#ifndef __ARCH_RISCV_SRC_ESP32C3_ESP32C3_BLE_H
+#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_BLE_H
 
 /****************************************************************************
  * Included Files
@@ -27,66 +27,24 @@
 
 #include <nuttx/config.h>
 
-#include "esp32c3_wifi_adapter.h"
-
-#ifndef __ASSEMBLY__
-
-#undef EXTERN
-#if defined(__cplusplus)
-#define EXTERN extern "C"
-extern "C"
-{
-#else
-#define EXTERN extern
-#endif
-
-#ifdef CONFIG_ESP32C3_WIRELESS
-
 /****************************************************************************
  * Public Function Prototypes
  ****************************************************************************/
 
 /****************************************************************************
- * Name: esp32c3_wlan_sta_initialize
+ * Name: esp32c3_ble_initialize
  *
  * Description:
- *   Initialize the ESP32-C3 WLAN station netcard driver
+ *   Init BT controller
  *
  * Input Parameters:
  *   None
  *
  * Returned Value:
- *   OK on success; Negated errno on failure.
+ *   success or fail
  *
  ****************************************************************************/
 
-#ifdef ESP32C3_WLAN_HAS_STA
-int esp32c3_wlan_sta_initialize(void);
-#endif
-
-/****************************************************************************
- * Name: esp32c3_wlan_softap_initialize
- *
- * Description:
- *   Initialize the ESP32-C3 WLAN softAP netcard driver
- *
- * Input Parameters:
- *   None
- *
- * Returned Value:
- *   OK on success; Negated errno on failure.
- *
- ****************************************************************************/
-
-#ifdef ESP32C3_WLAN_HAS_SOFTAP
-int esp32c3_wlan_softap_initialize(void);
-#endif
-
-#endif /* CONFIG_ESP32C3_WIRELESS */
-#ifdef __cplusplus
-}
-#endif
-#undef EXTERN
+int esp32c3_ble_initialize(void);
 
-#endif /* __ASSEMBLY__ */
-#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_WLAN_H */
+#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_BLE_H */
diff --git a/arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c b/arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c
new file mode 100644
index 0000000..561cffb
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c
@@ -0,0 +1,2007 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp32c3_ble_adapter.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 <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <debug.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <clock/clock.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mqueue.h>
+#include <nuttx/spinlock.h>
+#include <nuttx/irq.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/kthread.h>
+#include <nuttx/wdog.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/sched.h>
+#include <nuttx/signal.h>
+
+#include "hardware/esp32c3_syscon.h"
+#include "espidf_wifi.h"
+#include "esp32c3.h"
+#include "esp32c3_attr.h"
+#include "esp32c3_irq.h"
+#include "esp32c3_rt_timer.h"
+#include "esp32c3_ble_adapter.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define OSI_FUNCS_TIME_BLOCKING  0xffffffff
+#define OSI_VERSION              0x00010006
+#define OSI_MAGIC_VALUE          0xfadebead
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* BLE message queue private data */
+
+struct mq_adpt_s
+{
+  struct file mq;           /* Message queue handle */
+  uint32_t    msgsize;      /* Message size */
+  char        name[16];     /* Message queue name */
+};
+
+/* BLE interrupt adapter private data */
+
+struct irq_adpt_s
+{
+  void (*func)(void *arg);  /* Interrupt callback function */
+  void *arg;                /* Interrupt private data */
+};
+
+/* BLE low power control struct */
+
+typedef struct btdm_lpcntl_s
+{
+  uint32_t enable;                  /* whether low power mode is required */
+  uint32_t lpclk_sel;               /* low power clock source */
+  uint32_t mac_bb_pd;               /* whether hardware(MAC, BB) force-power-down is required during sleep */
+  uint32_t wakeup_timer_required;   /* whether system timer is needed */
+  uint32_t no_light_sleep;          /* do not allow system to enter light sleep after bluetooth is enabled */
+} btdm_lpcntl_t;
+
+/* low power control status */
+
+typedef struct btdm_lpstat_s
+{
+  uint32_t pm_lock_released        /* whether power management lock is released */
+  uint32_t mac_bb_pd               /* whether hardware(MAC, BB) is powered down */
+  uint32_t phy_enabled             /* whether phy is switched on */
+  uint32_t wakeup_timer_started    /* whether wakeup timer is started */
+} btdm_lpstat_t;
+
+/* vendor dependent signals to be posted to controller task */
+
+typedef enum
+{
+  BTDM_VND_OL_SIG_WAKEUP_TMR,
+  BTDM_VND_OL_SIG_NUM,
+} btdm_vnd_ol_sig_t;
+
+/* prototype of function to handle vendor dependent signals */
+
+typedef void (* btdm_vnd_ol_task_func_t)(void *param);
+
+/* VHCI function interface */
+
+typedef struct vhci_host_callback_s
+{
+  void (*notify_host_send_available)(void);               /* callback used to notify that the host can send packet to controller */
+  int (*notify_host_recv)(uint8_t *data, uint16_t len);   /* callback used to notify that the controller has a packet to send to the host */
+} vhci_host_callback_t;
+
+/* DRAM region */
+
+typedef struct btdm_dram_available_region_s
+{
+  esp_bt_mode_t mode;
+  intptr_t start;
+  intptr_t end;
+} btdm_dram_available_region_t;
+
+typedef void (* osi_intr_handler)(void);
+
+/* BLE OS function */
+
+struct osi_funcs_s
+{
+  uint32_t _magic;
+  uint32_t _version;
+  void (*_interrupt_set)(int cpu_no, int intr_source,
+                         int interrupt_no, int interrpt_prio);
+  void (*_interrupt_clear)(int interrupt_source, int interrupt_no);
+  void (*_interrupt_handler_set)(int interrupt_no, void * fn, void *arg);
+  void (*_interrupt_disable)(void);
+  void (*_interrupt_restore)(void);
+  void (*_task_yield)(void);
+  void (*_task_yield_from_isr)(void);
+  void *(*_semphr_create)(uint32_t max, uint32_t init);
+  void (*_semphr_delete)(void *semphr);
+  int (*_semphr_take_from_isr)(void *semphr, void *hptw);
+  int (*_semphr_give_from_isr)(void *semphr, void *hptw);
+  int (*_semphr_take)(void *semphr, uint32_t block_time_ms);
+  int (*_semphr_give)(void *semphr);
+  void *(*_mutex_create)(void);
+  void (*_mutex_delete)(void *mutex);
+  int (*_mutex_lock)(void *mutex);
+  int (*_mutex_unlock)(void *mutex);
+  void *(* _queue_create)(uint32_t queue_len, uint32_t item_size);
+  void (* _queue_delete)(void *queue);
+  int (* _queue_send)(void *queue, void *item, uint32_t block_time_ms);
+  int (* _queue_send_from_isr)(void *queue, void *item, void *hptw);
+  int (* _queue_recv)(void *queue, void *item, uint32_t block_time_ms);
+  int (* _queue_recv_from_isr)(void *queue, void *item, void *hptw);
+  int (* _task_create)(void *task_func, const char *name,
+                       uint32_t stack_depth, void *param, uint32_t prio,
+                       void *task_handle, uint32_t core_id);
+  void (* _task_delete)(void *task_handle);
+  bool (* _is_in_isr)(void);
+  int (* _cause_sw_intr_to_core)(int core_id, int intr_no);
+  void *(* _malloc)(size_t size);
+  void *(* _malloc_internal)(size_t size);
+  void (* _free)(void *p);
+  int (* _read_efuse_mac)(uint8_t mac[6]);
+  void (* _srand)(unsigned int seed);
+  int (* _rand)(void);
+  uint32_t (* _btdm_lpcycles_2_hus)(uint32_t cycles, uint32_t *error_corr);
+  uint32_t (* _btdm_hus_2_lpcycles)(uint32_t us);
+  bool (* _btdm_sleep_check_duration)(int32_t *slot_cnt);
+  void (* _btdm_sleep_enter_phase1)(uint32_t lpcycles);  /* called when interrupt is disabled */
+  void (* _btdm_sleep_enter_phase2)(void);
+  void (* _btdm_sleep_exit_phase1)(void);  /* called from ISR */
+  void (* _btdm_sleep_exit_phase2)(void);  /* called from ISR */
+  void (* _btdm_sleep_exit_phase3)(void);  /* called from task */
+  void (* _coex_wifi_sleep_set)(bool sleep);
+  int (* _coex_core_ble_conn_dyn_prio_get)(bool *low, bool *high);
+  void (* _coex_schm_status_bit_set)(uint32_t type, uint32_t status);
+  void (* _coex_schm_status_bit_clear)(uint32_t type, uint32_t status);
+  void (* _interrupt_on)(int intr_num);
+  void (* _interrupt_off)(int intr_num);
+  void (* _esp_hw_power_down)(void);
+  void (* _esp_hw_power_up)(void);
+  void (* _ets_backup_dma_copy)(uint32_t reg,
+                                uint32_t mem_addr, uint32_t num,
+                                bool to_rem);
+};
+
+/****************************************************************************
+ * Private Function
+ ****************************************************************************/
+
+static void interrupt_set_wrapper(int cpu_no, int intr_source,
+                                  int intr_num, int intr_prio);
+static void interrupt_clear_wrapper(int intr_source, int intr_num);
+static void interrupt_handler_set_wrapper(int n, void *fn, void *arg);
+static void IRAM_ATTR interrupt_disable(void);
+static void IRAM_ATTR interrupt_restore(void);
+static void IRAM_ATTR task_yield_from_isr(void);
+static void *semphr_create_wrapper(uint32_t max, uint32_t init);
+static void semphr_delete_wrapper(void *semphr);
+static int IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw);
+static int IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw);
+static int  semphr_take_wrapper(void *semphr, uint32_t block_time_ms);
+static int  semphr_give_wrapper(void *semphr);
+static void *mutex_create_wrapper(void);
+static void mutex_delete_wrapper(void *mutex);
+static int mutex_lock_wrapper(void *mutex);
+static int mutex_unlock_wrapper(void *mutex);
+static int IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item,
+                                                 void *hptw);
+static int IRAM_ATTR queue_recv_from_isr_wrapper(void *queue, void *item,
+                                                 void *hptw);
+static int task_create_wrapper(void *task_func, const char *name,
+                               uint32_t stack_depth, void *param,
+                               uint32_t prio, void *task_handle,
+                               uint32_t core_id);
+static void task_delete_wrapper(void *task_handle);
+static bool IRAM_ATTR is_in_isr_wrapper(void);
+static void *malloc_wrapper(size_t size);
+static void *malloc_internal_wrapper(size_t size);
+static int IRAM_ATTR read_mac_wrapper(uint8_t mac[6]);
+static void IRAM_ATTR srand_wrapper(unsigned int seed);
+static int IRAM_ATTR rand_wrapper(void);
+static uint32_t IRAM_ATTR btdm_lpcycles_2_hus(uint32_t cycles,
+                                              uint32_t *error_corr);
+static uint32_t IRAM_ATTR btdm_hus_2_lpcycles(uint32_t us);
+static void coex_wifi_sleep_set_hook(bool sleep);
+static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status);
+static void coex_schm_status_bit_clear_wrapper(uint32_t type,
+                                               uint32_t status);
+static void interrupt_on_wrapper(int intr_num);
+static void interrupt_off_wrapper(int intr_num);
+static void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size);
+static int queue_send_wrapper(void *queue, void *item,
+                              uint32_t block_time_ms);
+static int queue_recv_wrapper(void *queue, void *item,
+                              uint32_t block_time_ms);
+static void queue_delete_wrapper(void *queue);
+
+/****************************************************************************
+ * Extern Functions declaration and value
+ ****************************************************************************/
+
+extern int btdm_osi_funcs_register(void *osi_funcs);
+extern void btdm_controller_rom_data_init(void);
+
+/* Initialise and De-initialise */
+
+extern int btdm_controller_init(esp_bt_controller_config_t *config_opts);
+extern void btdm_controller_deinit(void);
+extern int btdm_controller_enable(esp_bt_mode_t mode);
+extern void btdm_controller_disable(void);
+extern uint8_t btdm_controller_get_mode(void);
+extern const char *btdm_controller_get_compile_version(void);
+extern void btdm_rf_bb_init_phase2(void); /* shall be called after PHY/RF is enabled */
+
+/* Sleep */
+
+extern void btdm_controller_enable_sleep(bool enable);
+extern uint8_t btdm_controller_get_sleep_mode(void);
+extern bool btdm_power_state_active(void);
+extern void btdm_wakeup_request(void);
+extern void btdm_in_wakeup_requesting_set(bool in_wakeup_requesting);
+
+/* vendor dependent tasks to be posted and handled by controller task */
+
+extern int btdm_vnd_offload_task_register(btdm_vnd_ol_sig_t sig,
+                                          btdm_vnd_ol_task_func_t func);
+extern int btdm_vnd_offload_task_deregister(btdm_vnd_ol_sig_t sig);
+extern int btdm_vnd_offload_post_from_isr(btdm_vnd_ol_sig_t sig,
+                                          void *param, bool need_yield);
+extern int btdm_vnd_offload_post(btdm_vnd_ol_sig_t sig, void *param);
+
+/* Low Power Clock */
+
+extern bool btdm_lpclk_select_src(uint32_t sel);
+extern bool btdm_lpclk_set_div(uint32_t div);
+extern int btdm_hci_tl_io_event_post(int event);
+
+/* VHCI */
+
+extern bool API_vhci_host_check_send_available(void); /* Functions in bt lib */
+extern void API_vhci_host_send_packet(uint8_t * data, uint16_t len);
+extern int API_vhci_host_register_callback(const vhci_host_callback_t
+                                           *callback);
+
+/* TX power */
+
+extern int ble_txpwr_set(int power_type, int power_level);
+extern int ble_txpwr_get(int power_type);
+
+extern uint16_t l2c_ble_link_get_tx_buf_num(void);
+extern int coex_core_ble_conn_dyn_prio_get(bool *low, bool *high);
+
+extern bool btdm_deep_sleep_mem_init(void);
+extern void btdm_deep_sleep_mem_deinit(void);
+extern void btdm_ble_power_down_dma_copy(bool copy);
+extern uint8_t btdm_sleep_clock_sync(void);
+
+extern char _bss_start_btdm;
+extern char _bss_end_btdm;
+extern char _data_start_btdm;
+extern char _data_end_btdm;
+extern uint32_t _data_start_btdm_rom;
+extern uint32_t _data_end_btdm_rom;
+
+extern uint32_t _bt_bss_start;
+extern uint32_t _bt_bss_end;
+extern uint32_t _btdm_bss_start;
+extern uint32_t _btdm_bss_end;
+extern uint32_t _bt_data_start;
+extern uint32_t _bt_data_end;
+extern uint32_t _btdm_data_start;
+extern uint32_t _btdm_data_end;
+
+extern char _bt_tmp_bss_start;
+extern char _bt_tmp_bss_end;
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Controller status */
+
+static DRAM_ATTR esp_bt_controller_status_t btdm_controller_status =
+                        ESP_BT_CONTROLLER_STATUS_IDLE;
+
+/* low power control struct */
+
+static DRAM_ATTR btdm_lpcntl_t g_lp_cntl;
+
+/* low power status struct */
+
+static DRAM_ATTR btdm_lpstat_t g_lp_stat;
+
+/* measured average low power clock period in micro seconds */
+
+static DRAM_ATTR uint32_t g_btdm_lpcycle_us = 0;
+
+/* number of fractional bit for g_btdm_lpcycle_us */
+
+static DRAM_ATTR uint8_t g_btdm_lpcycle_us_frac = 0;
+
+/* BT interrupt private data */
+
+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
+ ****************************************************************************/
+
+/* BLE OS adapter data */
+
+static struct osi_funcs_s g_osi_funcs =
+{
+  ._magic = OSI_MAGIC_VALUE,
+  ._version = OSI_VERSION,
+  ._interrupt_set = interrupt_set_wrapper,
+  ._interrupt_clear = interrupt_clear_wrapper,
+  ._interrupt_handler_set = interrupt_handler_set_wrapper,
+  ._interrupt_disable = interrupt_disable,
+  ._interrupt_restore = interrupt_restore,
+  ._task_yield = task_yield_from_isr,
+  ._task_yield_from_isr = task_yield_from_isr,
+  ._semphr_create = semphr_create_wrapper,
+  ._semphr_delete = semphr_delete_wrapper,
+  ._semphr_take_from_isr = semphr_take_from_isr_wrapper,
+  ._semphr_give_from_isr = semphr_give_from_isr_wrapper,
+  ._semphr_take = semphr_take_wrapper,
+  ._semphr_give = semphr_give_wrapper,
+  ._mutex_create = mutex_create_wrapper,
+  ._mutex_delete = mutex_delete_wrapper,
+  ._mutex_lock = mutex_lock_wrapper,
+  ._mutex_unlock = mutex_unlock_wrapper,
+  ._queue_create = queue_create_wrapper,
+  ._queue_delete = queue_delete_wrapper,
+  ._queue_send = queue_send_wrapper,
+  ._queue_send_from_isr = queue_send_from_isr_wrapper,
+  ._queue_recv = queue_recv_wrapper,
+  ._queue_recv_from_isr = queue_recv_from_isr_wrapper,
+  ._task_create = task_create_wrapper,
+  ._task_delete = task_delete_wrapper,
+  ._is_in_isr = is_in_isr_wrapper,
+  ._malloc = malloc_wrapper,
+  ._malloc_internal = malloc_internal_wrapper,
+  ._free = free,
+  ._read_efuse_mac = read_mac_wrapper,
+  ._srand = srand_wrapper,
+  ._rand = rand_wrapper,
+  ._btdm_lpcycles_2_hus = btdm_lpcycles_2_hus,
+  ._btdm_hus_2_lpcycles = btdm_hus_2_lpcycles,
+  ._coex_wifi_sleep_set = coex_wifi_sleep_set_hook,
+  ._coex_core_ble_conn_dyn_prio_get = coex_core_ble_conn_dyn_prio_get,
+  ._coex_schm_status_bit_set = coex_schm_status_bit_set_wrapper,
+  ._coex_schm_status_bit_clear = coex_schm_status_bit_clear_wrapper,
+  ._interrupt_on = interrupt_on_wrapper,
+  ._interrupt_off = interrupt_off_wrapper,
+};
+
+/****************************************************************************
+ * Private Functions and Public Functions only used by libraries
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_errno_trans
+ *
+ * Description:
+ *   Transform from nuttx error code to Wi-Fi adapter error code
+ *
+ * Input Parameters:
+ *   ret - NuttX error code
+ *
+ * Returned Value:
+ *   Wi-Fi adapter error code
+ *
+ ****************************************************************************/
+
+static inline int32_t esp_errno_trans(int ret)
+{
+  if (!ret)
+  {
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+/****************************************************************************
+ * Name: esp_task_create_pinned_to_core
+ *
+ * Description:
+ *   Create task and bind it to target CPU, the task will run when it
+ *   is created
+ *
+ * Input Parameters:
+ *   entry       - Task entry
+ *   name        - Task name
+ *   stack_depth - Task stack size
+ *   param       - Task private data
+ *   prio        - Task priority
+ *   task_handle - Task handle pointer which is used to pause, resume
+ *                 and delete the task
+ *   core_id     - CPU which the task runs in
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int32_t esp_task_create_pinned_to_core(void *entry,
+                                              const char *name,
+                                              uint32_t stack_depth,
+                                              void *param,
+                                              uint32_t prio,
+                                              void *task_handle,
+                                              uint32_t core_id)
+{
+  int pid;
+#ifdef CONFIG_SMP
+  int ret;
+  cpu_set_t cpuset;
+#endif
+
+  pid = kthread_create(name, prio, stack_depth, entry,
+                      (char * const *)param);
+  if (pid > 0)
+    {
+      if (task_handle)
+        {
+          *((int *)task_handle) = pid;
+        }
+
+#ifdef CONFIG_SMP
+      if (core_id < CONFIG_SMP_NCPUS)
+        {
+          CPU_ZERO(&cpuset);
+          CPU_SET(core_id, &cpuset);
+          ret = nxsched_set_affinity(pid, sizeof(cpuset), &cpuset);
+          if (ret)
+            {
+              wlerr("Failed to set affinity error=%d\n", ret);
+              return false;
+            }
+        }
+#endif
+    }
+  else
+    {
+      wlerr("Failed to create task\n");
+    }
+
+  return pid > 0 ? true : false;
+}
+
+/****************************************************************************
+ * Name: interrupt_set_wrapper
+ *
+ * Description:
+ *   Bind IRQ and resource with given parameters.
+ *
+ * Input Parameters:
+ *     cpu_no      - The CPU which the interrupt number belongs.
+ *     intr_source - The interrupt hardware source number.
+ *     intr_num    - The interrupt number CPU.
+ *     intr_prio   - The interrupt priority.
+ *
+ * Returned Value:
+ *     None
+ *
+ ****************************************************************************/
+
+static void interrupt_set_wrapper(int cpu_no,
+                                  int intr_source,
+                                  int intr_num,
+                                  int intr_prio)
+{
+    wlinfo("cpu_no=%d , intr_source=%d , intr_num=%d, intr_prio=%d\n",
+                        cpu_no, intr_source, intr_num, intr_prio);
+    esp32c3_bind_irq(intr_num, intr_source, intr_prio, ESP32C3_INT_LEVEL);
+}
+
+/****************************************************************************
+ * Name: interrupt_clear_wrapper
+ *
+ * Description:
+ *   Not supported
+ *
+ ****************************************************************************/
+
+static void interrupt_clear_wrapper(int intr_source, int intr_num)
+{
+}
+
+/****************************************************************************
+ * Name: esp_int_adpt_cb
+ *
+ * Description:
+ *   BT interrupt adapter callback function
+ *
+ * Input Parameters:
+ *   arg - interrupt adapter private data
+ *
+ * Returned Value:
+ *   NuttX error code
+ *
+ ****************************************************************************/
+
+static int esp_int_adpt_cb(int irq, void *context, FAR void *arg)
+{
+  struct irq_adpt_s *adapter = (struct irq_adpt_s *)arg;
+
+  adapter->func(adapter->arg);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: interrupt_handler_set_wrapper
+ *
+ * Description:
+ *   Register interrupt function
+ *
+ * Input Parameters:
+ *   n   - Interrupt ID
+ *   f   - Interrupt function
+ *   arg - Function private data
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void interrupt_handler_set_wrapper(int n, void *fn, void *arg)
+{
+  int ret;
+  struct irq_adpt_s *adapter;
+
+    if (g_ble_irq_bind)
+      {
+        return;
+      }
+
+  adapter = kmm_malloc(sizeof(struct irq_adpt_s));
+  DEBUGASSERT(adapter);
+
+  adapter->func = fn;
+  adapter->arg = arg;
+
+  ret = irq_attach(n + ESP32C3_IRQ_FIRSTPERIPH, esp_int_adpt_cb, adapter);
+  DEBUGASSERT(ret == OK);
+
+  g_ble_irq_bind = true;
+}
+
+/****************************************************************************
+ * Name: esp32c3_ints_on
+ *
+ * Description:
+ *   Enable Wi-Fi interrupt
+ *
+ * Input Parameters:
+ *   intr_num - No mean
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void interrupt_on_wrapper(int intr_num)
+{
+  up_enable_irq(intr_num);
+}
+
+/****************************************************************************
+ * Name: esp32c3_ints_off
+ *
+ * Description:
+ *   Disable Wi-Fi interrupt
+ *
+ * Input Parameters:
+ *   intr_num - No mean
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void interrupt_off_wrapper(int intr_num)
+{
+  up_disable_irq(intr_num);
+}
+
+/****************************************************************************
+ * Name: interrupt_disable
+ *
+ * Description:
+ *   Enter critical section by disabling interrupts and taking the spin lock
+ *   if in SMP mode.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR interrupt_disable(void)
+{
+  enter_critical_section();
+}
+
+/****************************************************************************
+ * Name: interrupt_restore
+ *
+ * Description:
+ *   Exit from critical section by enabling interrupts and releasing the spin
+ *   lock if in SMP mode.
+ *
+ * Input Parameters:
+ *  None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR interrupt_restore(void)
+{
+  leave_critical_section(g_inter_flags);
+}
+
+/****************************************************************************
+ * Name: task_yield_from_isr
+ *
+ * Description:
+ *   Do nothing in NuttX
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR task_yield_from_isr(void)
+{
+}
+
+/****************************************************************************
+ * Name: semphr_create_wrapper
+ *
+ * Description:
+ *   Create and initialize semaphore
+ *
+ * Input Parameters:
+ *   max  - Unused
+ *   init - semaphore initialization value
+ *
+ * Returned Value:
+ *   Semaphore data pointer
+ *
+ ****************************************************************************/
+
+static void *semphr_create_wrapper(uint32_t max, uint32_t init)
+{
+  int ret;
+  sem_t *sem;
+  int tmp;
+
+  tmp = sizeof(sem_t);
+  sem = kmm_malloc(tmp);
+  DEBUGASSERT(sem);
+
+  ret = sem_init(sem, 0, init);
+  DEBUGASSERT(ret == OK);
+
+  return sem;
+}
+
+/****************************************************************************
+ * Name: semphr_delete_wrapper
+ *
+ * Description:
+ *   Delete semaphore
+ *
+ * Input Parameters:
+ *   semphr - Semaphore data pointer
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void semphr_delete_wrapper(void *semphr)
+{
+  sem_t *sem = (sem_t *)semphr;
+  sem_destroy(sem);
+  kmm_free(sem);
+}
+
+/****************************************************************************
+ * Name: semphr_take_from_isr_wrapper
+ *
+ * Description:
+ *   take a semaphore from an ISR
+ *
+ * Input Parameters:
+ *   semphr - Semaphore data pointer
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw)
+{
+  return semphr_take_wrapper(semphr, 0);
+}
+
+/****************************************************************************
+ * Name: semphr_give_from_isr_wrapper
+ *
+ * Description:
+ *   Post semaphore
+ *
+ * Input Parameters:
+ *   semphr - Semaphore data pointer
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw)
+{
+  return semphr_give_wrapper(semphr);
+}
+
+/****************************************************************************
+ * Name: esp_update_time
+ *
+ * Description:
+ *   Transform ticks to time and add this time to timespec value
+ *
+ * Input Parameters:
+ *   timespec - Input timespec data pointer
+ *   ticks    - System ticks
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void esp_update_time(struct timespec *timespec, uint32_t ticks)
+{
+  uint32_t tmp;
+
+  tmp = TICK2SEC(ticks);
+  timespec->tv_sec += tmp;
+
+  ticks -= SEC2TICK(tmp);
+  tmp = TICK2NSEC(ticks);
+
+  timespec->tv_nsec += tmp;
+}
+
+/****************************************************************************
+ * Name: semphr_take_wrapper
+ *
+ * Description:
+ *   Wait semaphore within a certain period of time
+ *
+ * Input Parameters:
+ *   semphr         - Semaphore data pointer
+ *   block_time_ms  - Wait time
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int semphr_take_wrapper(void *semphr, uint32_t block_time_ms)
+{
+  int ret;
+  struct timespec timeout;
+  sem_t *sem = (sem_t *)semphr;
+
+  if (block_time_ms == OSI_FUNCS_TIME_BLOCKING)
+    {
+      ret = sem_wait(sem);
+      if (ret)
+        {
+          wlerr("Failed to wait sem\n");
+        }
+    }
+  else
+    {
+      ret = clock_gettime(CLOCK_REALTIME, &timeout);
+      if (ret < 0)
+        {
+          wlerr("Failed to get time\n");
+          return false;
+        }
+
+      if (block_time_ms)
+        {
+          esp_update_time(&timeout, MSEC2TICK(block_time_ms));
+        }
+
+      ret = sem_timedwait(sem, &timeout);
+    }
+
+  return esp_errno_trans(ret);
+}
+
+/****************************************************************************
+ * Name: semphr_give_wrapper
+ *
+ * Description:
+ *   Post semaphore
+ *
+ * Input Parameters:
+ *   semphr - Semaphore data pointer
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int semphr_give_wrapper(void *semphr)
+{
+  int ret;
+  sem_t *sem = (sem_t *)semphr;
+
+  ret = sem_post(sem);
+  if (ret)
+    {
+      wlerr("Failed to post sem error=%d\n", ret);
+    }
+
+  return esp_errno_trans(ret);
+}
+
+/****************************************************************************
+ * Name: mutex_create_wrapper
+ *
+ * Description:
+ *   Create mutex
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Mutex data pointer
+ *
+ ****************************************************************************/
+
+static void *mutex_create_wrapper(void)
+{
+  int ret;
+  pthread_mutex_t *mutex;
+  int tmp;
+
+  tmp = sizeof(pthread_mutex_t);
+  mutex = kmm_malloc(tmp);
+  DEBUGASSERT(mutex);
+
+  ret = pthread_mutex_init(mutex, NULL);
+  if (ret)
+    {
+      wlerr("Failed to initialize mutex error=%d\n", ret);
+      kmm_free(mutex);
+      return NULL;
+    }
+
+  return mutex;
+}
+
+/****************************************************************************
+ * Name: mutex_delete_wrapper
+ *
+ * Description:
+ *   Delete mutex
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Mutex data pointer
+ *
+ ****************************************************************************/
+
+static void mutex_delete_wrapper(void *mutex)
+{
+  pthread_mutex_destroy(mutex);
+  kmm_free(mutex);
+}
+
+/****************************************************************************
+ * Name: mutex_lock_wrapper
+ *
+ * Description:
+ *   Lock mutex
+ *
+ * Input Parameters:
+ *   mutex_data - mutex data pointer
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int mutex_lock_wrapper(void *mutex)
+{
+  int ret;
+
+  ret = pthread_mutex_lock(mutex);
+  if (ret)
+    {
+      wlerr("Failed to lock mutex error=%d\n", ret);
+    }
+
+  return esp_errno_trans(ret);
+}
+
+/****************************************************************************
+ * Name: mutex_unlock_wrapper
+ *
+ * Description:
+ *   Unlock mutex
+ *
+ * Input Parameters:
+ *   mutex_data - mutex data pointer
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int mutex_unlock_wrapper(void *mutex)
+{
+  int ret;
+
+  ret = pthread_mutex_unlock(mutex);
+  if (ret)
+    {
+      wlerr("Failed to unlock mutex error=%d\n", ret);
+    }
+
+  return esp_errno_trans(ret);
+}
+
+/****************************************************************************
+ * Name: esp_queue_send_generic
+ *
+ * Description:
+ *   Generic send message to queue within a certain period of time
+ *
+ * Input Parameters:
+ *   queue - Message queue data pointer
+ *   item  - Message data pointer
+ *   ticks - Wait ticks
+ *   prio  - Message priority
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int32_t esp_queue_send_generic(void *queue, void *item,
+                                      uint32_t ticks, int prio)
+{
+  int ret;
+  struct timespec timeout;
+  struct mq_adpt_s *mq_adpt = (struct mq_adpt_s *)queue;
+
+  if (ticks == OSI_FUNCS_TIME_BLOCKING || ticks == 0)
+    {
+      /**
+       * BLE interrupt function will call this adapter function to send
+       * message to message queue, so here we should call kernel API
+       * instead of application API
+       */
+
+      ret = file_mq_send(&mq_adpt->mq, (const char *)item,
+                         mq_adpt->msgsize, prio);
+      if (ret < 0)
+        {
+          wlerr("Failed to send message to mqueue error=%d\n", ret);
+        }
+    }
+  else
+    {
+      ret = clock_gettime(CLOCK_REALTIME, &timeout);
+      if (ret < 0)
+        {
+          wlerr("Failed to get time\n");
+          return false;
+        }
+
+      if (ticks)
+        {
+          esp_update_time(&timeout, ticks);
+        }
+
+      ret = file_mq_timedsend(&mq_adpt->mq, (const char *)item,
+                              mq_adpt->msgsize, prio, &timeout);
+      if (ret < 0)
+        {
+          wlerr("Failed to timedsend message to mqueue error=%d\n", ret);
+        }
+    }
+
+  return esp_errno_trans(ret);
+}
+
+/****************************************************************************
+ * Name: queue_send_from_isr_wrapper
+ *
+ * Description:
+ *   Send message of low priority to queue in ISR within
+ *   a certain period of time
+ *
+ * Input Parameters:
+ *   queue - Message queue data pointer
+ *   item  - Message data pointer
+ *   hptw  - Unused
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR queue_send_from_isr_wrapper(void *queue,
+                                                 void *item,
+                                                 void *hptw)
+{
+  return esp_queue_send_generic(queue, item, 0, 0);
+}
+
+/****************************************************************************
+ * Name: queue_recv_from_isr_wrapper
+ *
+ * Description:
+ *   Receive message from queue within a certain period of time
+ *
+ * Input Parameters:
+ *   queue - Message queue data pointer
+ *   item  - Message data pointer
+ *   hptw - Unused
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR queue_recv_from_isr_wrapper(void *queue,
+                                                 void *item,
+                                                 void *hptw)
+{
+  return 0;
+}
+
+/****************************************************************************
+ * Name: task_create_wrapper
+ *
+ * Description:
+ *   Create task and the task will run when it is created
+ *
+ * Input Parameters:
+ *   entry       - Task entry
+ *   name        - Task name
+ *   stack_depth - Task stack size
+ *   param       - Task private data
+ *   prio        - Task priority
+ *   task_handle - Task handle pointer which is used to pause, resume
+ *                 and delete the task
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int task_create_wrapper(void *task_func, const char *name,
+                               uint32_t stack_depth, void *param,
+                               uint32_t prio, void *task_handle,
+                               uint32_t core_id)
+{
+  return esp_task_create_pinned_to_core(task_func, name,
+                                        stack_depth, param,
+                                        prio, task_handle, UINT32_MAX);
+}
+
+/****************************************************************************
+ * Name: task_delete_wrapper
+ *
+ * Description:
+ *   Delete the target task
+ *
+ * Input Parameters:
+ *   task_handle - Task handle pointer which is used to pause, resume
+ *                 and delete the task
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void task_delete_wrapper(void *task_handle)
+{
+  pid_t pid = (pid_t)((uintptr_t)task_handle);
+  kthread_delete(pid);
+}
+
+/****************************************************************************
+ * Name: is_in_isr_wrapper
+ *
+ * Description:
+ *
+ * Input Parameters:
+ *  None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static bool IRAM_ATTR is_in_isr_wrapper(void)
+{
+  return false;
+}
+
+/****************************************************************************
+ * Name: malloc_wrapper
+ *
+ * Description:
+ *   Malloc buffer
+ *
+ * Input Parameters:
+ *  szie - buffer size
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void *malloc_wrapper(size_t size)
+{
+  void * p = NULL;
+
+  p = kmm_malloc(size);
+  DEBUGASSERT(p);
+
+  return p;
+}
+
+/****************************************************************************
+ * Name: malloc_internal_wrapper
+ *
+ * Description:
+ *   Malloc buffer in DRAM
+ *
+ * Input Parameters:
+ *  szie - buffer size
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void *malloc_internal_wrapper(size_t size)
+{
+  void * p = NULL;
+
+  p = kmm_malloc(size);
+  DEBUGASSERT(p);
+
+  return p;
+}
+
+/****************************************************************************
+ * Name: read_mac_wrapper
+ *
+ * Description:
+ *   Get Mac Address
+ *
+ * Input Parameters:
+ *  mac - mac address
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR read_mac_wrapper(uint8_t mac[6])
+{
+  return 0;
+}
+
+/****************************************************************************
+ * Name: srand_wrapper
+ *
+ * Description:
+ *
+ * Input Parameters:
+ *  None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR srand_wrapper(unsigned int seed)
+{
+  /* empty function */
+}
+
+/****************************************************************************
+ * Name: rand_wrapper
+ *
+ * Description:
+ *    Get random value
+ * Input Parameters:
+ *  None
+ *
+ * Returned Value:
+ *   Random value
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR rand_wrapper(void)
+{
+  return random();
+}
+
+/****************************************************************************
+ * Name: btdm_lpcycles_2_hus
+ *
+ * Description:
+ * Converts a number of low power clock cycles into a duration in half us.
+ *
+ * Input Parameters:
+ *  cycles
+ * error_corr
+ *
+ * Returned Value:
+ *   us
+ *
+ ****************************************************************************/
+
+static uint32_t IRAM_ATTR btdm_lpcycles_2_hus(uint32_t cycles,
+                                              uint32_t *error_corr)
+{
+  uint64_t us = (uint64_t)g_btdm_lpcycle_us * cycles;
+  us = (us + (1 << (g_btdm_lpcycle_us_frac - 1))) >> g_btdm_lpcycle_us_frac;
+  return (uint32_t)us;
+}
+
+/****************************************************************************
+ * Name: btdm_hus_2_lpcycles
+ *
+ * Description:
+ * Converts a duration in half us into a number of low power clock cycles.
+ *
+ * Input Parameters:
+ *  us
+ *
+ * Returned Value:
+ *   cycles
+ *
+ ****************************************************************************/
+
+static uint32_t IRAM_ATTR btdm_hus_2_lpcycles(uint32_t us)
+{
+  uint64_t cycles;
+  cycles = ((uint64_t)(us) << g_btdm_lpcycle_us_frac) / g_btdm_lpcycle_us;
+  return (uint32_t)cycles;
+}
+
+/****************************************************************************
+ * Name: coex_schm_status_bit_set_wrapper
+ *
+ * Description:
+ *
+ * Input Parameters:
+ *  type
+ * status
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status)
+{
+  /* empty function */
+}
+
+/****************************************************************************
+ * Name: coex_schm_status_bit_clear_wrapper
+ *
+ * Description:
+ *
+ * Input Parameters:
+ *  szie
+ *  status
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void coex_schm_status_bit_clear_wrapper(uint32_t type,
+                          uint32_t status)
+{
+  /* empty function */
+}
+
+/****************************************************************************
+ * Name: btdm_controller_mem_init
+ *
+ * Description:
+ *    Initialize BT controller to allocate task and other resource.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+static void btdm_controller_mem_init(void)
+{
+  btdm_controller_rom_data_init();
+}
+
+/****************************************************************************
+ * Name: phy_printf
+ *
+ * Description:
+ *   Output format string and its arguments
+ *
+ * Input Parameters:
+ *   format - format string
+ *
+ * Returned Value:
+ *   0
+ *
+ ****************************************************************************/
+
+int phy_printf(const char *format, ...)
+{
+#ifdef CONFIG_DEBUG_WIRELESS_INFO
+  va_list arg;
+
+  va_start(arg, format);
+  vsyslog(LOG_INFO, format, arg);
+  va_end(arg);
+#endif
+
+  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(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
+ *
+ * Description:
+ *    Disable BT phy.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+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);
+}
+
+/****************************************************************************
+ * Name: bt_phy_enable
+ *
+ * Description:
+ *    Enable BT phy.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+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);
+}
+
+static void coex_wifi_sleep_set_hook(bool sleep)
+{
+}
+
+/****************************************************************************
+ * Name: queue_create_wrapper
+ *
+ * Description:
+ *   Create message queue
+ *
+ * Input Parameters:
+ *   queue_len - queue message number
+ *   item_size - message size
+ *
+ * Returned Value:
+ *   Message queue data pointer
+ *
+ ****************************************************************************/
+
+static void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size)
+{
+  struct mq_attr attr;
+  struct mq_adpt_s *mq_adpt;
+  int ret;
+
+  mq_adpt = kmm_malloc(sizeof(struct mq_adpt_s));
+  DEBUGASSERT(mq_adpt);
+
+  snprintf(mq_adpt->name, sizeof(mq_adpt->name), "/tmp/%p", mq_adpt);
+
+  attr.mq_maxmsg  = queue_len;
+  attr.mq_msgsize = item_size;
+  attr.mq_curmsgs = 0;
+  attr.mq_flags   = 0;
+
+  ret = file_mq_open(&mq_adpt->mq, mq_adpt->name,
+                          O_RDWR | O_CREAT, 0644, &attr);
+
+  if (ret < 0)
+    {
+      wlerr("Failed to create mqueue\n");
+      kmm_free(mq_adpt);
+      return NULL;
+    }
+
+  mq_adpt->msgsize = item_size;
+  return (void *)mq_adpt;
+}
+
+/****************************************************************************
+ * Name: queue_send_wrapper
+ *
+ * Description:
+ *   Generic send message to queue within a certain period of time
+ *
+ * Input Parameters:
+ *   queue         - Message queue data pointer
+ *   item          - Message data pointerint
+ *   block_time_ms - Wait time
+ *
+ * Returned Value:uint32_t
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int queue_send_wrapper(void *queue, void *item,
+                              uint32_t block_time_ms)
+{
+  return esp_queue_send_generic(queue, item, block_time_ms, 0);
+}
+
+/****************************************************************************
+ * Name: queue_recv_wrapper
+ *
+ * Description:
+ *   Receive message from queue within a certain period of time
+ *
+ * Input Parameters:
+ *   queue         - Message queue data pointer
+ *   item          - Message data pointer
+ *   block_time_ms - Wait time
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int queue_recv_wrapper(void *queue, void *item,
+                              uint32_t block_time_ms)
+{
+  ssize_t ret;
+  struct timespec timeout;
+  unsigned int prio;
+  struct mq_adpt_s *mq_adpt = (struct mq_adpt_s *)queue;
+
+  if (block_time_ms == OSI_FUNCS_TIME_BLOCKING)
+    {
+      ret = file_mq_receive(&mq_adpt->mq, (char *)item,
+                            mq_adpt->msgsize, &prio);
+
+      if (ret < 0)
+        {
+          wlerr("Failed to receive from mqueue error=%d\n", ret);
+        }
+    }
+  else
+    {
+      ret = clock_gettime(CLOCK_REALTIME, &timeout);
+
+      if (ret < 0)
+        {
+          wlerr("Failed to get time\n");
+          return false;
+        }
+
+      if (block_time_ms)
+        {
+          esp_update_time(&timeout, MSEC2TICK(block_time_ms));
+        }
+
+      ret = file_mq_timedreceive(&mq_adpt->mq, (char *)item,
+                                 mq_adpt->msgsize, &prio, &timeout);
+
+      if (ret < 0)
+        {
+          wlerr("Failed to timedreceive from mqueue error=%d\n", ret);
+        }
+    }
+
+  return ret > 0 ? true : false;
+}
+
+/****************************************************************************
+ * Name: queue_delete_wrapper
+ *
+ * Description:
+ *   Delete message queue
+ *
+ * Input Parameters:
+ *   queue - Message queue data pointer
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void queue_delete_wrapper(void *queue)
+{
+  struct mq_adpt_s *mq_adpt = (struct mq_adpt_s *)queue;
+
+  file_mq_close(&mq_adpt->mq);
+  file_mq_unlink(mq_adpt->name);
+  kmm_free(mq_adpt);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32c3_bt_controller_init
+ *
+ * Description:
+ *    Init  BT controller.
+ *
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32c3_bt_controller_init(void)
+{
+  esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
+  esp_bt_controller_config_t *cfg = &bt_cfg;
+
+  if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE)
+    {
+      wlerr("Invalid controller status");
+      return -1;
+    }
+
+  cfg->controller_task_stack_size       = CONFIG_ESP32C3_BLE_TASK_STACK_SIZE;
+  cfg->controller_task_prio             = CONFIG_ESP32C3_BLE_TASK_PRIORITY;
+
+  cfg->controller_task_run_cpu          = 0;
+  cfg->ble_max_act                      = 10;
+  cfg->sleep_mode                       = 0;
+  cfg->coex_phy_coded_tx_rx_time_limit  = 0;
+  cfg->bluetooth_mode                   = 1;
+  cfg->sleep_clock                      = 0;
+  cfg->ble_st_acl_tx_buf_nb             = 0;
+  cfg->ble_hw_cca_check                 = 0;
+  cfg->ble_adv_dup_filt_max             = 30;
+  cfg->ce_len_type                      = 0;
+  cfg->hci_tl_type                      = 1;
+  cfg->hci_tl_funcs                     = NULL;
+  cfg->txant_dft                        = 0;
+  cfg->rxant_dft                        = 0;
+  cfg->txpwr_dft                        = 7;
+  cfg->cfg_mask                         = 1;
+  cfg->scan_duplicate_mode              = 0;
+  cfg->scan_duplicate_type              = 0;
+  cfg->normal_adv_size                  = 20;
+  cfg->mesh_adv_size                    = 0;
+
+  btdm_controller_mem_init();
+
+  if (btdm_osi_funcs_register(&g_osi_funcs) != 0)
+    {
+      return -EINVAL;
+    }
+
+  wlinfo("BT controller compile version [%s]\n",
+                              btdm_controller_get_compile_version());
+
+  modifyreg32(SYSTEM_WIFI_CLK_EN_REG, 0, UINT32_MAX);
+
+  bt_phy_enable();
+  g_lp_stat.phy_enabled = 1;
+
+  if (btdm_controller_init(cfg) != 0)
+    {
+      bt_phy_disable();
+      g_lp_stat.phy_enabled = 0;
+      return -EIO;
+    }
+
+  btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32c3_bt_controller_deinit
+ *
+ * Description:
+ *    Deinit  BT controller.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32c3_bt_controller_deinit(void)
+{
+  if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED)
+    {
+      return -1;
+    }
+
+  btdm_controller_deinit();
+
+  if (g_lp_stat.phy_enabled)
+    {
+      bt_phy_disable();
+      g_lp_stat.phy_enabled = 0;
+    }
+    else
+    {
+      assert(0);
+    }
+
+  btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
+  g_btdm_lpcycle_us = 0;
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32c3_bt_controller_disable
+ *
+ * Description:
+ *    disable  BT controller.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32c3_bt_controller_disable(void)
+{
+  if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED)
+    {
+      return -1;
+    }
+
+  while (!btdm_power_state_active())
+    {
+      usleep(1000); /* wait */
+    }
+
+  btdm_controller_disable();
+
+  btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32c3_bt_controller_enable
+ *
+ * Description:
+ *    Enable  BT controller.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32c3_bt_controller_enable(esp_bt_mode_t mode)
+{
+  int ret = 0;
+
+  if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED)
+    {
+      return -1;
+    }
+
+  if (mode != btdm_controller_get_mode())
+    {
+      wlerr("invalid mode %d, controller support mode is %d",
+                                  mode, btdm_controller_get_mode());
+      return -1;
+    }
+
+  /* enable low power mode */
+
+  if (g_lp_cntl.enable)
+    {
+        btdm_controller_enable_sleep(true);
+    }
+
+  if (btdm_controller_enable(mode) != 0)
+    {
+      ret = -1;
+      goto error;
+    }
+
+  btdm_controller_status = ESP_BT_CONTROLLER_STATUS_ENABLED;
+
+  return ret;
+
+error:
+
+  /* disable low power mode */
+
+  btdm_controller_enable_sleep(false);
+
+  return ret;
+}
+
+esp_bt_controller_status_t esp32c3_bt_controller_get_status(void)
+{
+  return btdm_controller_status;
+}
+
+/****************************************************************************
+ * Name: esp32c3_vhci_host_check_send_available
+ *
+ * Description:
+ *   Check if the host can send packet to controller or not.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   bool - true or false
+ *
+ ****************************************************************************/
+
+bool esp32c3_vhci_host_check_send_available(void)
+{
+  if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED)
+    {
+      return false;
+    }
+
+  return API_vhci_host_check_send_available();
+}
+
+/****************************************************************************
+ * Name: esp32c3_vhci_host_send_packet
+ *
+ * Description:
+ *    host send packet to controller.
+ * Input Parameters:
+ *  data - the packet point
+ *  len - the packet length
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_vhci_host_send_packet(uint8_t *data, uint16_t len)
+{
+  if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED)
+    {
+      return;
+    }
+
+  API_vhci_host_send_packet(data, len);
+}
+
+/****************************************************************************
+ * Name: esp32c3_vhci_register_callback
+ *
+ * Description:
+ *    register the vhci reference callback.
+ * Input Parameters:
+ *  callback - struct defined by vhci_host_callback structure.
+ *
+ * Returned Value:
+ *   status - success or fail
+ *
+ ****************************************************************************/
+
+int esp32c3_vhci_register_callback(const esp_vhci_host_callback_t *callback)
+{
+  int ret = -1;
+  if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED)
+    {
+      return ret;
+    }
+
+  ret = API_vhci_host_register_callback(
+            (const vhci_host_callback_t *)callback) == 0 ? 0 : -1;
+  return ret;
+}
diff --git a/arch/risc-v/src/esp32c3/esp32c3_ble_adapter.h b/arch/risc-v/src/esp32c3/esp32c3_ble_adapter.h
new file mode 100644
index 0000000..7026035
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp32c3_ble_adapter.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp32c3_ble_adapter.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_BLE_ADAPTER_H
+#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_BLE_ADAPTER_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "esp_bt.h"
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32c3_bt_controller_init
+ *
+ * Description:
+ *    Init  BT controller.
+ *
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32c3_bt_controller_init(void);
+
+/****************************************************************************
+ * Name: esp32c3_bt_controller_deinit
+ *
+ * Description:
+ *    Deinit  BT controller.
+ * Input Parameters:
+ *    cfg -  Initial configuration of BT controller.
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32c3_bt_controller_deinit(void);
+
+/****************************************************************************
+ * Name: esp32c3_bt_controller_enable
+ *
+ * Description:
+ *    disable  BT controller.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32c3_bt_controller_enable(esp_bt_mode_t mode);
+
+/****************************************************************************
+ * Name: esp32c3_bt_controller_disable
+ *
+ * Description:
+ *    disable  BT controller.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32c3_bt_controller_disable(void);
+
+/****************************************************************************
+ * Name: esp32c3_bt_controller_enable
+ *
+ * Description:
+ *    Enable  BT controller.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+esp_bt_controller_status_t esp32c3_bt_controller_get_status(void);
+
+/****************************************************************************
+ * Name: esp32c3_vhci_host_check_send_available
+ *
+ * Description:
+ * used for check actively if the host can send packet to controller or not.
+ * Input Parameters:
+ *  None
+ *
+ * Returned Value:
+ *   bool - true or false
+ *
+ ****************************************************************************/
+
+bool esp32c3_vhci_host_check_send_available(void);
+
+/****************************************************************************
+ * Name: esp32c3_vhci_host_send_packet
+ *
+ * Description:
+ *    host send packet to controller.
+ * Input Parameters:
+ *  data - the packet point
+ *  len - the packet length
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_vhci_host_send_packet(uint8_t *data, uint16_t len);
+
+/****************************************************************************
+ * Name: esp32c3_vhci_register_callback
+ *
+ * Description:
+ *    register the vhci reference callback.
+ * Input Parameters:
+ *  callback - struct defined by vhci_host_callback structure.
+ *
+ * Returned Value:
+ *   status - success or fail
+ *
+ ****************************************************************************/
+
+int esp32c3_vhci_register_callback(
+                            const esp_vhci_host_callback_t *callback);
+
+#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_BLE_ADAPTER_H */
diff --git a/arch/risc-v/src/esp32c3/esp32c3_irq.c b/arch/risc-v/src/esp32c3/esp32c3_irq.c
index 734a74e..23e57c7 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_irq.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_irq.c
@@ -88,10 +88,19 @@ void up_irqinitialize(void)
    *   Object  |  CPU INT  |  Peripheral
    *           |           |
    *    Wi-Fi  |     1     |      1
+   *    BT BB  |     5     |      5
+   *    RW BLE |     8     |      8
    */
 
 #ifdef CONFIG_ESP32C3_WIRELESS
+#  ifdef CONFIG_ESP32C3_WIFI
   g_cpuint_map[ESP32C3_CPUINT_WMAC] = ESP32C3_PERIPH_WIFI_MAC_NMI;
+#  endif
+
+#  ifdef CONFIG_ESP32C3_BLE
+  g_cpuint_map[ESP32C3_CPUINT_BT_BB] = ESP32C3_PERIPH_BT_BB;
+  g_cpuint_map[ESP32C3_CPUINT_RWBLE] = ESP32C3_PERIPH_RWBLE_IRQ;
+#  endif
 #endif
 
   /* Clear all peripheral interrupts from "bootloader" */
diff --git a/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c
index 9c44b81..8d73dba 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c
@@ -354,6 +354,14 @@ static int wifi_coex_set_schm_curr_phase_idx(int idx);
 static int wifi_coex_get_schm_curr_phase_idx(void);
 
 /****************************************************************************
+ * Extern Functions declaration
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32C3_BLE
+extern void coex_pti_v2(void);
+#endif
+
+/****************************************************************************
  * Public Functions declaration
  ****************************************************************************/
 
@@ -2456,6 +2464,9 @@ static void wifi_phy_enable(void)
       esp_phy_enable_clock();
       phy_set_wifi_mode_only(0);
       register_chipv7_phy(&phy_init_data, cal_data, PHY_RF_CAL_NONE);
+#ifdef CONFIG_ESP32C3_BLE
+      coex_pti_v2();
+#endif
     }
 
   g_phy_access_ref++;
diff --git a/arch/risc-v/src/esp32c3/esp32c3_wlan.c b/arch/risc-v/src/esp32c3/esp32c3_wlan.c
index bdfb8ff..6cdf9dd 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_wlan.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_wlan.c
@@ -24,7 +24,7 @@
 
 #include <nuttx/config.h>
 
-#ifdef CONFIG_ESP32C3_WIRELESS
+#ifdef CONFIG_ESP32C3_WIFI
 
 #include <queue.h>
 #include <assert.h>
@@ -2026,4 +2026,4 @@ int esp32c3_wlan_softap_initialize(void)
 }
 #endif
 
-#endif  /* CONFIG_ESP32C3_WIRELESS */
+#endif  /* CONFIG_ESP32C3_WIFI */
diff --git a/arch/risc-v/src/esp32c3/esp32c3_wlan.h b/arch/risc-v/src/esp32c3/esp32c3_wlan.h
index 54cdf9a..ce4e06f 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_wlan.h
+++ b/arch/risc-v/src/esp32c3/esp32c3_wlan.h
@@ -40,7 +40,7 @@ extern "C"
 #define EXTERN extern
 #endif
 
-#ifdef CONFIG_ESP32C3_WIRELESS
+#ifdef CONFIG_ESP32C3_WIFI
 
 /****************************************************************************
  * Public Function Prototypes
@@ -82,7 +82,7 @@ int esp32c3_wlan_sta_initialize(void);
 int esp32c3_wlan_softap_initialize(void);
 #endif
 
-#endif /* CONFIG_ESP32C3_WIRELESS */
+#endif /* CONFIG_ESP32C3_WIFI */
 #ifdef __cplusplus
 }
 #endif
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/autopm/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/autopm/defconfig
index af32cc2..588fbc6 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/configs/autopm/defconfig
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/autopm/defconfig
@@ -22,7 +22,7 @@ CONFIG_BUILTIN=y
 CONFIG_DRIVERS_IEEE80211=y
 CONFIG_DRIVERS_WIRELESS=y
 CONFIG_ESP32C3_AUTO_SLEEP=y
-CONFIG_ESP32C3_WIRELESS=y
+CONFIG_ESP32C3_WIFI=y
 CONFIG_EXAMPLE_POWER_SAVE_MIN_MODEM=y
 CONFIG_FS_PROCFS=y
 CONFIG_HAVE_CXX=y
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/ble/defconfig
similarity index 65%
copy from boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig
copy to boards/risc-v/esp32c3/esp32c3-devkit/configs/ble/defconfig
index 96f6cbf..fb1bb17 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/ble/defconfig
@@ -5,9 +5,6 @@
 # You can then do "make savedefconfig" to generate a new defconfig file that includes your
 # modifications.
 #
-# CONFIG_NSH_ARGCAT is not set
-# CONFIG_NSH_CMDOPT_HEXDUMP is not set
-# CONFIG_NSH_CMDPARMS is not set
 CONFIG_ARCH="risc-v"
 CONFIG_ARCH_BOARD="esp32c3-devkit"
 CONFIG_ARCH_BOARD_ESP32C3_DEVKIT=y
@@ -18,27 +15,21 @@ CONFIG_ARCH_INTERRUPTSTACK=1536
 CONFIG_ARCH_RISCV=y
 CONFIG_ARCH_STACKDUMP=y
 CONFIG_BOARD_LOOPSPERMSEC=16717
+CONFIG_BTSAK=y
 CONFIG_BUILTIN=y
+CONFIG_DRIVERS_BLUETOOTH=y
 CONFIG_DRIVERS_IEEE80211=y
 CONFIG_DRIVERS_WIRELESS=y
-CONFIG_ESP32C3_WIRELESS=y
+CONFIG_ESP32C3_BLE=y
 CONFIG_FS_PROCFS=y
 CONFIG_HAVE_CXX=y
 CONFIG_HAVE_CXXINITIALIZE=y
 CONFIG_IDLETHREAD_STACKSIZE=3072
 CONFIG_INTELHEX_BINARY=y
-CONFIG_LIBC_FLOATINGPOINT=y
 CONFIG_NAME_MAX=48
-CONFIG_NETDB_DNSCLIENT=y
-CONFIG_NETDEV_LATEINIT=y
-CONFIG_NETDEV_PHY_IOCTL=y
-CONFIG_NETDEV_WIRELESS_IOCTL=y
-CONFIG_NET_BROADCAST=y
-CONFIG_NET_ETH_PKTSIZE=1514
-CONFIG_NET_ICMP=y
-CONFIG_NET_ICMP_SOCKET=y
+CONFIG_NET_BLUETOOTH=y
+CONFIG_NET_SOCKOPTS=y
 CONFIG_NET_TCP=y
-CONFIG_NET_UDP=y
 CONFIG_NSH_ARCHINIT=y
 CONFIG_NSH_BUILTIN_APPS=y
 CONFIG_NSH_FILEIOSIZE=512
@@ -48,18 +39,11 @@ CONFIG_PREALLOC_TIMERS=4
 CONFIG_PTHREAD_MUTEX_TYPES=y
 CONFIG_RAW_BINARY=y
 CONFIG_RR_INTERVAL=200
-CONFIG_SCHED_LPWORK=y
 CONFIG_SCHED_WAITPID=y
 CONFIG_SIG_DEFAULT=y
-CONFIG_START_DAY=6
-CONFIG_START_MONTH=12
-CONFIG_START_YEAR=2011
-CONFIG_SYSTEM_DHCPC_RENEW=y
+CONFIG_SPINLOCK=y
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYSTEM_PING=y
 CONFIG_UART0_SERIAL_CONSOLE=y
 CONFIG_USER_ENTRYPOINT="nsh_main"
 CONFIG_WIRELESS=y
-CONFIG_WIRELESS_WAPI=y
-CONFIG_WIRELESS_WAPI_CMDTOOL=y
-CONFIG_WIRELESS_WAPI_STACKSIZE=4096
+CONFIG_WIRELESS_BLUETOOTH=y
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/sta_softap/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/sta_softap/defconfig
index 12f0332..aca1681 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/configs/sta_softap/defconfig
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/sta_softap/defconfig
@@ -32,7 +32,7 @@ CONFIG_ESP32C3_MTD_SIZE=0xf0000
 CONFIG_ESP32C3_SPIFLASH=y
 CONFIG_ESP32C3_WIFI_SAVE_PARAM=y
 CONFIG_ESP32C3_WIFI_STATION_SOFTAP_COEXISTENCE=y
-CONFIG_ESP32C3_WIRELESS=y
+CONFIG_ESP32C3_WIFI=y
 CONFIG_EXAMPLES_DHCPD=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_FS_PROCFS=y
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig
index 96f6cbf..acff433 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig
@@ -21,7 +21,7 @@ CONFIG_BOARD_LOOPSPERMSEC=16717
 CONFIG_BUILTIN=y
 CONFIG_DRIVERS_IEEE80211=y
 CONFIG_DRIVERS_WIRELESS=y
-CONFIG_ESP32C3_WIRELESS=y
+CONFIG_ESP32C3_WIFI=y
 CONFIG_FS_PROCFS=y
 CONFIG_HAVE_CXX=y
 CONFIG_HAVE_CXXINITIALIZE=y
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
index 550a133..15297a7 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
@@ -67,6 +67,10 @@
 #  include "esp32c3_rtc_lowerhalf.h"
 #endif
 
+#ifdef CONFIG_ESP32C3_BLE
+#  include "esp32c3_ble.h"
+#endif
+
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
@@ -303,10 +307,20 @@ int esp32c3_bringup(void)
   if (ret < 0)
     {
       syslog(LOG_ERR, "Failed to initialize RT timer: %d\n", ret);
+      return ret;
+    }
+#endif
+
+#ifdef CONFIG_ESP32C3_BLE
+  ret = esp32c3_ble_initialize();
+  if (ret)
+    {
+      syslog(LOG_ERR, "ERROR: Failed to initialize BLE\n");
+      return ret;
     }
 #endif
 
-#ifdef CONFIG_ESP32C3_WIRELESS
+#ifdef CONFIG_ESP32C3_WIFI
 
 #ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM
   ret = esp32c3_init_wifi_storage();

[incubator-nuttx] 02/03: riscv/esp32c3: Add Wi-Fi and BLE coexist

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 145d9175872148632db4db4dc5fccf71d181144c
Author: xiewenxiang <xi...@espressif.com>
AuthorDate: Wed Jun 2 11:52:57 2021 +0800

    riscv/esp32c3: Add Wi-Fi and BLE coexist
---
 arch/risc-v/src/esp32c3/Kconfig                    |   5 +
 arch/risc-v/src/esp32c3/Make.defs                  |   2 +-
 arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c      |  25 ++-
 arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c     | 237 ++++++++++++++++++++-
 arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.h     |  19 ++
 .../esp32c3/esp32c3-devkit/src/esp32c3_bringup.c   |  13 ++
 6 files changed, 297 insertions(+), 4 deletions(-)

diff --git a/arch/risc-v/src/esp32c3/Kconfig b/arch/risc-v/src/esp32c3/Kconfig
index 791b087..f5ba513 100644
--- a/arch/risc-v/src/esp32c3/Kconfig
+++ b/arch/risc-v/src/esp32c3/Kconfig
@@ -352,6 +352,11 @@ config ESP32C3_BLE
 
 endmenu # ESP32-C3 Peripheral Support
 
+menuconfig ESP32C3_WIFI_BT_COEXIST
+	bool "Wi-Fi and BT coexist"
+	default n
+	depends on ESP32C3_WIFI && ESP32C3_BLE
+
 menu "I2C Configuration"
 	depends on ESP32C3_I2C
 
diff --git a/arch/risc-v/src/esp32c3/Make.defs b/arch/risc-v/src/esp32c3/Make.defs
index df1b047..9866ee4 100644
--- a/arch/risc-v/src/esp32c3/Make.defs
+++ b/arch/risc-v/src/esp32c3/Make.defs
@@ -212,7 +212,7 @@ endif
 
 ifeq ($(CONFIG_ESP32C3_WIFI),y)
 CHIP_CSRCS += esp32c3_wlan.c esp32c3_wifi_utils.c esp32c3_wifi_adapter.c
-EXTRA_LIBS += -lcore -lnet80211 -lpp -lsmartconfig -lcoexist -lespnow -lwpa_supplicant -lwapi
+EXTRA_LIBS += -lcore -lnet80211 -lpp -lsmartconfig -lcoexist -lespnow -lwpa_supplicant -lwapi -lmesh
 endif
 
 ifeq ($(CONFIG_ESP32C3_BLE),y)
diff --git a/arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c b/arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c
index 561cffb..bcf8b51 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c
@@ -56,6 +56,11 @@
 #include "esp32c3_rt_timer.h"
 #include "esp32c3_ble_adapter.h"
 
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+#  include "esp_coexist_internal.h"
+#  include "esp_coexist_adapter.h"
+#endif
+
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
@@ -1356,7 +1361,9 @@ static uint32_t IRAM_ATTR btdm_hus_2_lpcycles(uint32_t us)
 
 static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status)
 {
-  /* empty function */
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  coex_schm_status_bit_set(type, status);
+#endif
 }
 
 /****************************************************************************
@@ -1376,7 +1383,9 @@ static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status)
 static void coex_schm_status_bit_clear_wrapper(uint32_t type,
                           uint32_t status)
 {
-  /* empty function */
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  coex_schm_status_bit_clear(type, status);
+#endif
 }
 
 /****************************************************************************
@@ -1786,6 +1795,10 @@ int esp32c3_bt_controller_init(void)
   wlinfo("BT controller compile version [%s]\n",
                               btdm_controller_get_compile_version());
 
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  coex_init();
+#endif
+
   modifyreg32(SYSTEM_WIFI_CLK_EN_REG, 0, UINT32_MAX);
 
   bt_phy_enable();
@@ -1867,6 +1880,10 @@ int esp32c3_bt_controller_disable(void)
 
   btdm_controller_disable();
 
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  coex_disable();
+#endif
+
   btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
 
   return 0;
@@ -1901,6 +1918,10 @@ int esp32c3_bt_controller_enable(esp_bt_mode_t mode)
       return -1;
     }
 
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  coex_enable();
+#endif
+
   /* enable low power mode */
 
   if (g_lp_cntl.enable)
diff --git a/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c
index 8d73dba..ee3daab 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c
@@ -65,6 +65,11 @@
 
 #include "espidf_wifi.h"
 
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+#  include "esp_coexist_internal.h"
+#  include "esp_coexist_adapter.h"
+#endif
+
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
@@ -227,6 +232,11 @@ 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_ESP32C3_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);
@@ -443,6 +453,27 @@ static bool g_softap_started;
 static wifi_txdone_cb_t g_softap_txdone_cb;
 #endif
 
+/* Wi-Fi and BT coexistance OS adapter data */
+
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+coex_adapter_funcs_t g_coex_adapter_funcs =
+{
+  ._version = COEX_ADAPTER_VERSION,
+  ._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,
+  ._esp_timer_get_time = esp_timer_get_time,
+  ._magic = COEX_ADAPTER_MAGIC,
+};
+#endif
+
 /****************************************************************************
  * Public Data
  ****************************************************************************/
@@ -1139,6 +1170,69 @@ static int32_t esp_semphr_give(void *semphr)
 }
 
 /****************************************************************************
+ * Name: esp_semphr_take_from_isr
+ *
+ * Description:
+ *   Try to task semaphore in interrupt
+ *
+ * Input Parameters:
+ *   semphr - Semaphore data pointer
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+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 in interrupt
+ *
+ * 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 current is in interrupt
+ *
+ * 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
  *
  * Description:
@@ -3812,7 +3906,11 @@ static void esp_wifi_delete_queue(void *queue)
 
 static int wifi_coex_init(void)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  return coex_init();
+#else
   return 0;
+#endif
 }
 
 /****************************************************************************
@@ -3825,6 +3923,9 @@ static int wifi_coex_init(void)
 
 static void wifi_coex_deinit(void)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  coex_deinit();
+#endif
 }
 
 /****************************************************************************
@@ -3837,7 +3938,11 @@ static void wifi_coex_deinit(void)
 
 static int wifi_coex_enable(void)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  return coex_enable();
+#else
   return 0;
+#endif
 }
 
 /****************************************************************************
@@ -3850,6 +3955,9 @@ static int wifi_coex_enable(void)
 
 static void wifi_coex_disable(void)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  coex_disable();
+#endif
 }
 
 /****************************************************************************
@@ -3862,7 +3970,11 @@ static void wifi_coex_disable(void)
 
 static uint32_t esp_coex_status_get(void)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  return coex_status_get();
+#else
   return 0;
+#endif
 }
 
 /****************************************************************************
@@ -3875,6 +3987,9 @@ static uint32_t esp_coex_status_get(void)
 
 static void esp_coex_condition_set(uint32_t type, bool dissatisfy)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  coex_condition_set(type, dissatisfy);
+#endif
 }
 
 /****************************************************************************
@@ -3886,9 +4001,13 @@ static void esp_coex_condition_set(uint32_t type, bool dissatisfy)
  ****************************************************************************/
 
 static int esp_coex_wifi_request(uint32_t event, uint32_t latency,
-                                     uint32_t duration)
+                                 uint32_t duration)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  return coex_wifi_request(event, latency, duration);
+#else
   return 0;
+#endif
 }
 
 /****************************************************************************
@@ -3901,7 +4020,11 @@ static int esp_coex_wifi_request(uint32_t event, uint32_t latency,
 
 static int esp_coex_wifi_release(uint32_t event)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  return coex_wifi_release(event);
+#else
   return 0;
+#endif
 }
 
 /****************************************************************************
@@ -3914,7 +4037,11 @@ static int esp_coex_wifi_release(uint32_t event)
 
 static int wifi_coex_wifi_set_channel(uint8_t primary, uint8_t secondary)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  return coex_wifi_channel_set(primary, secondary);
+#else
   return 0;
+#endif
 }
 
 /****************************************************************************
@@ -3927,7 +4054,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)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  return coex_event_duration_get(event, duration);
+#else
   return 0;
+#endif
 }
 
 /****************************************************************************
@@ -3940,7 +4071,11 @@ static int wifi_coex_get_event_duration(uint32_t event, uint32_t *duration)
 
 static int wifi_coex_get_pti(uint32_t event, uint8_t *pti)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  return coex_pti_get(event, pti);
+#else
   return 0;
+#endif
 }
 
 /****************************************************************************
@@ -3953,6 +4088,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)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  coex_schm_status_bit_clear(type, status);
+#endif
 }
 
 /****************************************************************************
@@ -3965,6 +4103,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)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  coex_schm_status_bit_set(type, status);
+#endif
 }
 
 /****************************************************************************
@@ -3977,7 +4118,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)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  return coex_schm_interval_set(interval);
+#else
   return 0;
+#endif
 }
 
 /****************************************************************************
@@ -3990,7 +4135,11 @@ static int wifi_coex_set_schm_interval(uint32_t interval)
 
 static uint32_t wifi_coex_get_schm_interval(void)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  return coex_schm_interval_get();
+#else
   return 0;
+#endif
 }
 
 /****************************************************************************
@@ -4003,7 +4152,11 @@ static uint32_t wifi_coex_get_schm_interval(void)
 
 static uint8_t wifi_coex_get_schm_curr_period(void)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  return coex_schm_curr_period_get();
+#else
   return 0;
+#endif
 }
 
 /****************************************************************************
@@ -4016,7 +4169,11 @@ static uint8_t wifi_coex_get_schm_curr_period(void)
 
 static void *wifi_coex_get_schm_curr_phase(void)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  return coex_schm_curr_phase_get();
+#else
   return NULL;
+#endif
 }
 
 /****************************************************************************
@@ -4030,6 +4187,11 @@ 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
+  return 0;
+#endif
 }
 
 /****************************************************************************
@@ -4042,7 +4204,11 @@ static int wifi_coex_set_schm_curr_phase_idx(int idx)
 
 static int wifi_coex_get_schm_curr_phase_idx(void)
 {
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  return coex_schm_curr_phase_idx_get();
+#else
   return 0;
+#endif
 }
 
 /****************************************************************************
@@ -4379,6 +4545,35 @@ int pp_printf(const char *format, ...)
 }
 
 /****************************************************************************
+ * Name: coexist_printf
+ *
+ * Description:
+ *   Output format string and its arguments
+ *
+ * Input Parameters:
+ *   format - format string
+ *
+ * Returned Value:
+ *   0
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+int coexist_printf(const char * format, ...)
+{
+#ifdef CONFIG_DEBUG_WIRELESS_INFO
+  va_list arg;
+
+  va_start(arg, format);
+  vsyslog(LOG_INFO, format, arg);
+  va_end(arg);
+#endif
+
+  return 0;
+}
+#endif
+
+/****************************************************************************
  * Functions needed by libnet80211.a
  ****************************************************************************/
 
@@ -4655,10 +4850,22 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
 {
   esp_err_t ret;
 
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  ret = coex_init();
+  if (ret)
+    {
+      wlerr("ERROR: Failed to initialize coex error=%d\n", ret);
+      return ret;
+    }
+#endif
+
   ret = esp_wifi_init_internal(config);
   if (ret)
     {
       wlerr("ERROR: Failed to initialize Wi-Fi error=%d\n", ret);
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+      coex_deinit();
+#endif
       return ret;
     }
 
@@ -4667,6 +4874,9 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
     {
       wlerr("ERROR: Failed to initialize WPA supplicant error=%d\n", ret);
       esp_wifi_deinit_internal();
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+      coex_deinit();
+#endif
       return ret;
     }
 
@@ -6776,3 +6986,28 @@ int esp_wifi_softap_rssi(struct iwreq *iwr, bool set)
   return -ENOSYS;
 }
 #endif
+
+/****************************************************************************
+ * Name: esp32c3_wifi_bt_coexist_init
+ *
+ * Description:
+ *   Initialize ESP32-C3 Wi-Fi and BT coexistance module.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   OK on success (positive non-zero values are cmd-specific)
+ *   Negated errno returned on failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+int esp32c3_wifi_bt_coexist_init(void)
+{
+  esp_coex_adapter_register(&g_coex_adapter_funcs);
+  coex_pre_init();
+
+  return 0;
+}
+#endif
diff --git a/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.h b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.h
index 159dc49..0e9e840 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.h
+++ b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.h
@@ -817,6 +817,25 @@ int esp_wifi_softap_country(struct iwreq *iwr, bool set);
 int esp_wifi_softap_rssi(struct iwreq *iwr, bool set);
 #endif
 
+/****************************************************************************
+ * Name: esp32c3_wifi_bt_coexist_init
+ *
+ * Description:
+ *   Initialize ESP32-C3 Wi-Fi and BT coexistance module.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   OK on success (positive non-zero values are cmd-specific)
+ *   Negated errno returned on failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+int esp32c3_wifi_bt_coexist_init(void);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
index 15297a7..320753f 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
@@ -311,6 +311,17 @@ int esp32c3_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_ESP32C3_WIRELESS
+
+#ifdef CONFIG_ESP32C3_WIFI_BT_COEXIST
+  ret = esp32c3_wifi_bt_coexist_init();
+  if (ret)
+    {
+      syslog(LOG_ERR, "ERROR: Failed to initialize Wi-Fi and BT coexist\n");
+      return ret;
+    }
+#endif
+
 #ifdef CONFIG_ESP32C3_BLE
   ret = esp32c3_ble_initialize();
   if (ret)
@@ -353,6 +364,8 @@ int esp32c3_bringup(void)
 
 #endif
 
+#endif /* CONFIG_ESP32C3_WIRELESS */
+
 #ifdef CONFIG_ESP32C3_LEDC
   ret = esp32c3_pwm_setup();
   if (ret < 0)