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:41 UTC

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

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();