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 2024/10/18 13:34:03 UTC

(nuttx) branch master updated: esp32[c3]: Add BLE support

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/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 05ba822c41 esp32[c3]: Add BLE support
05ba822c41 is described below

commit 05ba822c4141c064ffb4fa3ad1df1dcf960f5496
Author: Eren Terzioglu <er...@espressif.com>
AuthorDate: Fri Jul 19 16:10:15 2024 +0200

    esp32[c3]: Add BLE support
---
 .../esp32c3/boards/esp32c3-generic/index.rst       |   68 +
 arch/risc-v/src/common/espressif/Kconfig           |   39 +
 arch/risc-v/src/common/espressif/Make.defs         |    6 +-
 arch/risc-v/src/common/espressif/Wireless.mk       |    1 +
 arch/risc-v/src/common/espressif/esp_wifi_utils.c  |    6 +
 arch/risc-v/src/common/espressif/esp_wifi_utils.h  |    4 +
 arch/risc-v/src/esp32c3/Make.defs                  |    5 +
 arch/risc-v/src/esp32c3/esp_ble.c                  |  328 ++
 arch/risc-v/src/esp32c3/esp_ble.h                  |   50 +
 arch/risc-v/src/esp32c3/esp_ble_adapter.c          | 3443 ++++++++++++++++++++
 arch/risc-v/src/esp32c3/esp_ble_adapter.h          |  175 +
 arch/risc-v/src/esp32c3/esp_wireless.c             |  370 +++
 arch/risc-v/src/esp32c3/esp_wireless.h             |  198 ++
 .../esp32c3/common/scripts/esp32c3_flat_memory.ld  |    1 +
 .../esp32c3/esp32c3-generic/configs/ble/defconfig  |   67 +
 .../esp32c3/esp32c3-generic/src/esp32c3_bringup.c  |   33 +-
 16 files changed, 4781 insertions(+), 13 deletions(-)

diff --git a/Documentation/platforms/risc-v/esp32c3/boards/esp32c3-generic/index.rst b/Documentation/platforms/risc-v/esp32c3/boards/esp32c3-generic/index.rst
index 64c42bbde1..4f74029fe8 100644
--- a/Documentation/platforms/risc-v/esp32c3/boards/esp32c3-generic/index.rst
+++ b/Documentation/platforms/risc-v/esp32c3/boards/esp32c3-generic/index.rst
@@ -53,6 +53,74 @@ All of the configurations presented below can be tested by running the following
 Where <config_name> is the name of board configuration you want to use, i.e.: nsh, buttons, wifi...
 Then use a serial console terminal like ``picocom`` configured to 115200 8N1.
 
+ble
+---
+
+This configuration is used to enable the Bluetooth Low Energy (BLE) of
+ESP32-C3 chip.
+
+To test it, just run the following commands below.
+
+Confirm that bnep interface exist::
+
+    nsh> ifconfig
+    bnep0   Link encap:UNSPEC at DOWN
+        inet addr:0.0.0.0 DRaddr:0.0.0.0 Mask:0.0.0.0
+
+Get basic information from it::
+
+    nsh> bt bnep0 info
+    Device: bnep0
+    BDAddr: 86:f7:03:09:41:4d
+    Flags:  0000
+    Free:   20
+      ACL:  20
+      SCO:  0
+    Max:
+      ACL:  24
+      SCO:  0
+    MTU:
+      ACL:  70
+      SCO:  70
+    Policy: 0
+    Type:   0
+
+Start the scanning process::
+
+    nsh> bt bnep0 scan start
+
+Wait a little bit before stopping it.
+
+Then after some minutes stop it::
+
+    nsh> bt bnep0 scan stop
+
+Get the list of BLE devices found around you::
+
+    nsh> bt bnep0 scan get
+    Scan result:
+    1.     addr:           d7:c4:e6:xx:xx:xx type: 0
+           rssi:            -62
+           response type:   4
+           advertiser data: 10 09 4d 69 20 XX XX XX XX XX XX XX XX XX XX 20                      e
+    2.     addr:           cb:23:18:xx:xx:xx type: 0
+           rssi:            -60
+           response type:   0
+           advertiser data: 02 01 06 1b ff XX XX XX ff ff ff ff ff ff ff ff                      8
+    3.     addr:           cb:23:18:xx:xx:xx type: 0
+           rssi:            -60
+           response type:   4
+           advertiser data: 10 09 4d 69 20 XX XX XX XX XX XX XX XX XX XX 20                      e
+    4.     addr:           d7:c4:e6:xx:xx:xx type: 0
+           rssi:            -62
+           response type:   0
+           advertiser data: 02 01 06 1b ff XX XX XX ff ff ff ff ff ff ff ff                      e
+    5.     addr:           d7:c4:e6:xx:xx:xx type: 0
+           rssi:            -62
+           response type:   4
+           advertiser data: 10 09 4d 69 20 XX XX XX XX XX XX XX XX XX XX 20                      e
+    nsh>
+
 bmp180
 ------
 
diff --git a/arch/risc-v/src/common/espressif/Kconfig b/arch/risc-v/src/common/espressif/Kconfig
index 23c03ac6f6..f83d01071f 100644
--- a/arch/risc-v/src/common/espressif/Kconfig
+++ b/arch/risc-v/src/common/espressif/Kconfig
@@ -465,6 +465,14 @@ config ESPRESSIF_WIFI
 	---help---
 		Enable Wi-Fi support
 
+config ESPRESSIF_BLE
+	bool "BLE"
+	depends on ESPRESSIF_ESP32C3
+	default n
+	select ESP_WIRELESS
+	---help---
+		Enable BLE support
+
 config ESP_COEX_SW_COEXIST_ENABLE
 	bool "Software WiFi/Bluetooth/IEEE 802.15.4 coexistence"
 	depends on (ESPRESSIF_WIFI && ESPRESSIF_BLE) || \
@@ -478,6 +486,13 @@ config ESP_COEX_SW_COEXIST_ENABLE
 		If only Bluetooth is used, it is recommended to disable this option to reduce binary file
 		size.
 
+menuconfig ESPRESSIF_WIFI_BT_COEXIST
+	bool "Wi-Fi and BT coexist"
+	default y if ESPRESSIF_WIFI && ESPRESSIF_BLE
+	default n
+	depends on ESPRESSIF_WIFI && ESPRESSIF_BLE
+	select ESPRESSIF_WIFI_STA_DISCONNECT_PM
+
 config ESP_MCPWM
 	bool "Motor Control PWM (MCPWM)"
 	default n
@@ -933,6 +948,30 @@ endchoice # ESP_POWER_SAVE_MODE
 
 endmenu # ESPRESSIF_WIFI
 
+menu "BLE Configuration"
+	depends on ESPRESSIF_BLE
+
+config ESPRESSIF_BLE_TTY_NAME
+	string "BLE TTY device name"
+	default "/dev/ttyHCI0"
+	depends on UART_BTH4
+
+config ESPRESSIF_BLE_TASK_STACK_SIZE
+	int "Controller task stack size"
+	default 4096
+
+config ESPRESSIF_BLE_TASK_PRIORITY
+	int "Controller task priority"
+	default 253
+
+config ESPRESSIF_BLE_INTERRUPT_SAVE_STATUS
+	int "Number of interrupt save status"
+	default 3
+	---help---
+		Number of interrupt save status variables to keep track. Increase it if any related bug is found.
+
+endmenu # BLE Configuration
+
 menu "UART Configuration"
 	depends on ESPRESSIF_UART
 
diff --git a/arch/risc-v/src/common/espressif/Make.defs b/arch/risc-v/src/common/espressif/Make.defs
index 97b24aa1c2..af6ae2f4d3 100644
--- a/arch/risc-v/src/common/espressif/Make.defs
+++ b/arch/risc-v/src/common/espressif/Make.defs
@@ -120,8 +120,8 @@ ifeq ($(CONFIG_ESP_WIRELESS),y)
 	ifeq ($(CONFIG_ESPRESSIF_WIFI),y)
 		CHIP_CSRCS += esp_wifi_init.c
 		CHIP_CSRCS += esp_wlan.c
-		CHIP_CSRCS += esp_wifi_utils.c
 	endif
+	CHIP_CSRCS += esp_wifi_utils.c
 endif
 
 ifeq ($(CONFIG_ESP_MCPWM),y)
@@ -136,7 +136,7 @@ endif
 
 ESP_HAL_3RDPARTY_REPO   = esp-hal-3rdparty
 ifndef ESP_HAL_3RDPARTY_VERSION
-	ESP_HAL_3RDPARTY_VERSION = b4c723a119344b4b71d69819019d55637fb570fd
+	ESP_HAL_3RDPARTY_VERSION = ca869dd97ed2c01187b85b759c0d6edb27c12c21
 endif
 
 ifndef ESP_HAL_3RDPARTY_URL
@@ -168,7 +168,7 @@ chip/$(ESP_HAL_3RDPARTY_REPO):
 	$(Q) git -C chip/$(ESP_HAL_3RDPARTY_REPO) checkout --quiet $(ESP_HAL_3RDPARTY_VERSION)
 ifeq ($(CONFIG_ESP_WIRELESS),y)
 	$(Q) echo "Espressif HAL for 3rd Party Platforms: initializing submodules..."
-	$(Q) git -C chip/$(ESP_HAL_3RDPARTY_REPO) submodule --quiet update --init $(GIT_DEPTH_PARAMETER) components/mbedtls/mbedtls components/esp_phy/lib components/esp_wifi/lib components/esp_coex/lib
+	$(Q) git -C chip/$(ESP_HAL_3RDPARTY_REPO) submodule --quiet update --init $(GIT_DEPTH_PARAMETER) components/mbedtls/mbedtls components/esp_phy/lib components/esp_wifi/lib components/bt/controller/lib_esp32c3_family components/esp_coex/lib
 	$(Q) git -C chip/$(ESP_HAL_3RDPARTY_REPO)/components/mbedtls/mbedtls reset --quiet --hard
 	$(Q) echo "Applying patches..."
 	$(Q) cd chip/$(ESP_HAL_3RDPARTY_REPO)/components/mbedtls/mbedtls && git apply ../../../nuttx/patches/components/mbedtls/mbedtls/*.patch
diff --git a/arch/risc-v/src/common/espressif/Wireless.mk b/arch/risc-v/src/common/espressif/Wireless.mk
index 9783ac1c5f..c63e1d190f 100644
--- a/arch/risc-v/src/common/espressif/Wireless.mk
+++ b/arch/risc-v/src/common/espressif/Wireless.mk
@@ -24,6 +24,7 @@ INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY
 INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)$(CHIP_SERIES)$(DELIM)include
 INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)include$(DELIM)esp_wifi
 
+EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)bt$(DELIM)controller$(DELIM)lib_esp32c3_family$(DELIM)$(CHIP_SERIES)
 EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_coex$(DELIM)lib$(DELIM)$(CHIP_SERIES)
 EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_phy$(DELIM)lib$(DELIM)$(CHIP_SERIES)
 EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_wifi$(DELIM)lib$(DELIM)$(CHIP_SERIES)
diff --git a/arch/risc-v/src/common/espressif/esp_wifi_utils.c b/arch/risc-v/src/common/espressif/esp_wifi_utils.c
index 21019a78f4..506cc2ceb5 100644
--- a/arch/risc-v/src/common/espressif/esp_wifi_utils.c
+++ b/arch/risc-v/src/common/espressif/esp_wifi_utils.c
@@ -33,6 +33,7 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/wireless/wireless.h>
 
+#ifdef CONFIG_ESPRESSIF_WIFI
 #include "esp_wifi_adapter.h"
 
 #include "esp_log.h"
@@ -44,7 +45,9 @@
 #include "esp_wpa.h"
 #include "rom/ets_sys.h"
 #include "soc/soc_caps.h"
+#endif /* CONFIG_ESPRESSIF_WIFI */
 
+#include "esp_err.h"
 #include "esp_wifi_utils.h"
 
 /****************************************************************************
@@ -104,6 +107,8 @@ static uint8_t g_channel_list[CHANNEL_MAX_NUM];
  * Public Functions
  ****************************************************************************/
 
+#ifdef CONFIG_ESPRESSIF_WIFI
+
 /****************************************************************************
  * Name: esp_wifi_start_scan
  *
@@ -573,6 +578,7 @@ scan_result_full:
   priv->scan_status = ESP_SCAN_DONE;
   nxsem_post(&priv->scan_signal);
 }
+#endif /* CONFIG_ESPRESSIF_WIFI */
 
 /****************************************************************************
  * Name: esp_wifi_to_errno
diff --git a/arch/risc-v/src/common/espressif/esp_wifi_utils.h b/arch/risc-v/src/common/espressif/esp_wifi_utils.h
index 738fbbed08..488011cd9e 100644
--- a/arch/risc-v/src/common/espressif/esp_wifi_utils.h
+++ b/arch/risc-v/src/common/espressif/esp_wifi_utils.h
@@ -45,6 +45,8 @@ extern "C"
  * Public Function Prototypes
  ****************************************************************************/
 
+#ifdef CONFIG_ESPRESSIF_WIFI
+
 /****************************************************************************
  * Name: esp_wifi_start_scan
  *
@@ -95,6 +97,8 @@ int esp_wifi_get_scan_results(struct iwreq *iwr);
 
 void esp_wifi_scan_event_parse(void);
 
+#endif
+
 /****************************************************************************
  * Name: esp_wifi_to_errno
  *
diff --git a/arch/risc-v/src/esp32c3/Make.defs b/arch/risc-v/src/esp32c3/Make.defs
index 97e5963f4b..c5fde77370 100644
--- a/arch/risc-v/src/esp32c3/Make.defs
+++ b/arch/risc-v/src/esp32c3/Make.defs
@@ -28,4 +28,9 @@ CHIP_CSRCS += esp_coex_adapter.c esp_wifi_adapter.c
 EXTRA_LIBS += -lcore -lnet80211 -lpp
 endif
 
+ifeq ($(CONFIG_ESPRESSIF_BLE),y)
+CHIP_CSRCS += esp_ble.c esp_ble_adapter.c esp_wireless.c
+EXTRA_LIBS +=  -lbtbb -lbtdm_app
+endif
+
 CFLAGS += ${DEFINE_PREFIX}_RETARGETABLE_LOCKING
diff --git a/arch/risc-v/src/esp32c3/esp_ble.c b/arch/risc-v/src/esp32c3/esp_ble.c
new file mode 100644
index 0000000000..8b5bd34357
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp_ble.c
@@ -0,0 +1,328 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp_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 <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 "esp_ble_adapter.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* BLE packet buffer max size */
+
+#define BLE_BUF_SIZE      1024
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct esp_ble_priv_s
+{
+  struct bt_driver_s drv;   /* NuttX BT/BLE driver data */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int esp_ble_open(struct bt_driver_s *drv);
+static int esp_ble_send(struct bt_driver_s *drv,
+                        enum bt_buf_type_e type,
+                        void *data, size_t len);
+static void esp_ble_close(struct bt_driver_s *drv);
+static void esp_ble_send_ready(void);
+static int esp_ble_recv_cb(uint8_t *data, uint16_t len);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct esp_ble_priv_s g_ble_priv =
+{
+  .drv =
+    {
+      .head_reserve = H4_HEADER_SIZE,
+      .open         = esp_ble_open,
+      .send         = esp_ble_send,
+      .close        = esp_ble_close
+    }
+};
+
+static esp_vhci_host_callback_t vhci_host_cb =
+{
+  .notify_host_send_available = esp_ble_send_ready,
+  .notify_host_recv           = esp_ble_recv_cb
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_ble_send_ready
+ *
+ * Description:
+ *   If the controller could send HCI comand will callback this function.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void esp_ble_send_ready(void)
+{
+}
+
+/****************************************************************************
+ * Name: esp_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 esp_ble_recv_cb(uint8_t *data, uint16_t len)
+{
+  int ret;
+  bool valid;
+  enum bt_buf_type_e type;
+  struct esp_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: esp_ble_send
+ *
+ * Description:
+ *   ESP32-C3 BLE send callback function for BT driver.
+ *
+ * Input Parameters:
+ *   drv  - BT driver pointer
+ *   type - BT packet type
+ *   data - BT packet data buffer pointer
+ *   len  - BT packet length
+ *
+ * Returned Value:
+ *   Sent bytes on success or a negated value on failure.
+ *
+ ****************************************************************************/
+
+static int esp_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 (esp_vhci_host_check_send_available())
+    {
+      esp_vhci_host_send_packet(hdr, len + drv->head_reserve);
+    }
+
+  return len;
+}
+
+/****************************************************************************
+ * Name: esp_ble_close
+ *
+ * Description:
+ *   ESP32-C3 BLE close callback function for BT driver.
+ *
+ * Input Parameters:
+ *   drv - BT driver pointer
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void esp_ble_close(struct bt_driver_s *drv)
+{
+}
+
+/****************************************************************************
+ * Name: esp_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 esp_ble_open(struct bt_driver_s *drv)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_ble_initialize
+ *
+ * Description:
+ *   Init BT controller
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   success or fail
+ *
+ ****************************************************************************/
+
+int esp_ble_initialize(void)
+{
+  int ret;
+
+  ret = esp_bt_controller_init();
+  if (ret)
+    {
+      wlerr("Failed to initialize BLE ret=%d\n", ret);
+      return ERROR;
+    }
+
+  ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
+  if (ret)
+    {
+      wlerr("Failed to Enable BLE ret=%d\n", ret);
+      return ERROR;
+    }
+
+  ret = esp_vhci_register_callback(&vhci_host_cb);
+  if (ret)
+    {
+      esp_bt_controller_disable();
+      wlerr("Failed to register BLE callback ret=%d\n", ret);
+      return ERROR;
+    }
+
+#if defined(CONFIG_UART_BTH4)
+  ret = uart_bth4_register(CONFIG_ESPRESSIF_BLE_TTY_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/esp_ble.h b/arch/risc-v/src/esp32c3/esp_ble.h
new file mode 100644
index 0000000000..537fdb3271
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp_ble.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp_ble.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_ESP_BLE_H
+#define __ARCH_RISCV_SRC_ESP32C3_ESP_BLE_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_ble_initialize
+ *
+ * Description:
+ *   Init BT controller
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   success or fail
+ *
+ ****************************************************************************/
+
+int esp_ble_initialize(void);
+
+#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP_BLE_H */
diff --git a/arch/risc-v/src/esp32c3/esp_ble_adapter.c b/arch/risc-v/src/esp32c3/esp_ble_adapter.c
new file mode 100644
index 0000000000..5122aa6a59
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp_ble_adapter.c
@@ -0,0 +1,3443 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp_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 <nuttx/wireless/wireless.h>
+#include <nuttx/irq.h>
+#include <irq/irq.h>
+
+#include "riscv_internal.h"
+#include "soc/rtc_cntl_reg.h"
+#include "hal/rtc_cntl_ll.h"
+#include "esp_private/esp_clk.h"
+#include "esp_bt.h"
+#include "esp_log.h"
+#include "esp_mac.h"
+#include "esp_private/phy.h"
+#include "esp_private/wifi.h"
+#include "esp_random.h"
+#include "esp_timer.h"
+#include "periph_ctrl.h"
+#include "rom/ets_sys.h"
+#include "soc/soc_caps.h"
+#include "esp_hr_timer.h"
+
+#include "esp_attr.h"
+#include "espressif/esp_irq.h"
+#include "esp_hr_timer.h"
+#include "espressif/esp_rtc.h"
+#include "esp_wireless.h"
+#include "espressif/esp_spiflash.h"
+#include "esp_phy_init.h"
+#include "espressif/esp_wifi_utils.h"
+#ifdef CONFIG_ESPRESSIF_WIFI_BT_COEXIST
+#  include "esp_coexist_internal.h"
+#  include "esp_coexist_adapter.h"
+#endif
+#include "esp_intr_alloc.h"
+#include "esp_ble_adapter.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#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 sleep mode */
+#define BTDM_MODEM_WAKE_UP_DELAY         (8)  /* delay in half slots of modem wake up procedure, including re-enable PHY/RF */
+
+/* Low Power Clock Selection */
+
+#define BTDM_LPCLK_SEL_XTAL              (0)
+#define BTDM_LPCLK_SEL_XTAL32K           (1)
+#define BTDM_LPCLK_SEL_RTC_SLOW          (2)
+#define BTDM_LPCLK_SEL_8M                (3)
+
+#define OSI_FUNCS_TIME_BLOCKING          0xffffffff
+#define OSI_VERSION                      0x00010009
+#define OSI_MAGIC_VALUE                  0xfadebead
+
+#ifdef CONFIG_ESPRESSIF_SPIFLASH
+#  define BLE_TASK_EVENT_QUEUE_ITEM_SIZE  8
+#  define BLE_TASK_EVENT_QUEUE_LEN        8
+#endif
+
+#ifdef CONFIG_ESPRESSIF_BLE_INTERRUPT_SAVE_STATUS
+#  define NR_IRQSTATE_FLAGS   CONFIG_ESPRESSIF_BLE_INTERRUPT_SAVE_STATUS
+#else
+#  define NR_IRQSTATE_FLAGS   3
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* Pack using bitfields for better memory use */
+
+typedef struct vector_desc_s vector_desc_t;
+
+struct vector_desc_s
+{
+  int flags: 16;
+  unsigned int cpu: 1;
+  unsigned int intno: 5;
+  int source: 8;
+  void *shared_vec_info;
+  vector_desc_t *next;
+};
+
+/** Interrupt handler associated data structure */
+
+struct intr_handle_data_t
+{
+  vector_desc_t *vector_desc;
+  void *shared_vector_desc;
+};
+
+/* 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;
+
+typedef struct
+{
+  int source;               /* ISR source */
+  int flags;                /* ISR alloc flag */
+  void (*fn)(void *);       /* ISR function */
+  void *arg;                /* ISR function args */
+  intr_handle_t *handle;    /* ISR handle */
+  esp_err_t ret;
+} btdm_isr_alloc_t;
+
+/* BLE OS function */
+
+struct osi_funcs_s
+{
+  uint32_t _magic;
+  uint32_t _version;
+  int (* _interrupt_alloc)(int cpu_id,
+                           int source,
+                           intr_handler_t handler,
+                           void *arg,
+                           void **ret_handle);
+  int (* _interrupt_free)(void *handle);
+  void (*_interrupt_handler_set_rsv)(int interrupt_no,
+                                     intr_handler_t fn,
+                                     void *arg);
+  void (*_global_intr_disable)(void);
+  void (*_global_intr_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);
+  int (* _coex_schm_register_btdm_callback)(void *callback);
+  void (* _coex_schm_status_bit_set)(uint32_t type, uint32_t status);
+  void (* _coex_schm_status_bit_clear)(uint32_t type, uint32_t status);
+  uint32_t (* _coex_schm_interval_get)(void);
+  uint8_t (* _coex_schm_curr_period_get)(void);
+  void *(* _coex_schm_curr_phase_get)(void);
+  int (* _interrupt_enable)(void *handle);
+  int (* _interrupt_disable)(void *handle);
+  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);
+  void (* _ets_delay_us)(uint32_t us);
+  void (* _btdm_rom_table_ready)(void);
+  bool (* _coex_bt_wakeup_request)(void);
+  void (* _coex_bt_wakeup_request_end)(void);
+};
+
+/* 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 */
+};
+
+typedef enum btdm_vnd_ol_sig_e
+{
+  BTDM_VND_OL_SIG_WAKEUP_TMR,
+  BTDM_VND_OL_SIG_NUM,
+} btdm_vnd_ol_sig_t;
+
+/* low power control struct */
+
+typedef union
+{
+  struct
+  {
+    uint32_t enable                  :  1; /* whether low power mode is required */
+    uint32_t lpclk_sel               :  3; /* low power clock source */
+    uint32_t mac_bb_pd               :  1; /* whether hardware(MAC, BB) force-power-down is required during sleep */
+    uint32_t wakeup_timer_required   :  1; /* whether system timer is needed */
+    uint32_t no_light_sleep          :  1; /* do not allow system to enter light sleep after bluetooth is enabled */
+    uint32_t main_xtal_pu            :  1; /* power up main XTAL */
+    uint32_t reserved                : 24; /* reserved */
+  };
+  uint32_t val;
+} btdm_lpcntl_t;
+
+/* low power control status */
+
+typedef union
+{
+  struct
+  {
+    uint32_t pm_lock_released        :  1; /* whether power management lock is released */
+    uint32_t mac_bb_pd               :  1; /* whether hardware(MAC, BB) is powered down */
+    uint32_t phy_enabled             :  1; /* whether phy is switched on */
+    uint32_t wakeup_timer_started    :  1; /* whether wakeup timer is started */
+    uint32_t reserved                : 28; /* reserved */
+  };
+  uint32_t val;
+} btdm_lpstat_t;
+
+/* wakeup request sources */
+
+enum btdm_wakeup_src_e
+{
+  BTDM_ASYNC_WAKEUP_SRC_VHCI,
+  BTDM_ASYNC_WAKEUP_REQ_COEX,
+  BTDM_ASYNC_WAKEUP_SRC_DISA,
+  BTDM_ASYNC_WAKEUP_SRC_TMR,
+  BTDM_ASYNC_WAKEUP_SRC_MAX,
+};
+
+/* Superseded semaphore definition */
+
+struct bt_sem_s
+{
+  sem_t sem;
+#ifdef CONFIG_ESPRESSIF_SPIFLASH
+  struct esp_semcache_s sc;
+#endif
+};
+
+/* prototype of function to handle vendor dependent signals */
+
+typedef void (*btdm_vnd_ol_task_func_t)(void *param);
+
+typedef void (*osi_intr_handler)(void);
+
+/* List of nested IRQ status flags */
+
+struct irqstate_list_s
+{
+  struct irqstate_list_s *flink;
+  irqstate_t flags;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Functions to be registered to struct osi_funcs_s
+ ****************************************************************************/
+
+static int interrupt_alloc_wrapper(int cpu_id,
+                                   int source,
+                                   intr_handler_t handler,
+                                   void *arg,
+                                   void **ret_handle);
+static int interrupt_free_wrapper(void *handle);
+static void IRAM_ATTR global_interrupt_disable(void);
+static void IRAM_ATTR global_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 void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size);
+static void queue_delete_wrapper(void *queue);
+static int queue_send_wrapper(void *queue, void *item,
+                              uint32_t block_time_ms);
+static int IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item,
+                                                 void *hptw);
+static int queue_recv_wrapper(void *queue, void *item,
+                              uint32_t block_time_ms);
+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 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);
+static void coex_wifi_sleep_set_hook(bool sleep);
+static int coex_schm_register_btdm_callback_wrapper(void *callback);
+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 uint32_t coex_schm_interval_get_wrapper(void);
+static uint8_t coex_schm_curr_period_get_wrapper(void);
+static void * coex_schm_curr_phase_get_wrapper(void);
+static int interrupt_enable_wrapper(void *handle);
+static int interrupt_disable_wrapper(void *handle);
+static void btdm_hw_mac_power_down_wrapper(void);
+static void btdm_hw_mac_power_up_wrapper(void);
+static void btdm_backup_dma_copy_wrapper(uint32_t reg, uint32_t mem_addr,
+                                  uint32_t num,  bool to_mem);
+static void btdm_funcs_table_ready_wrapper(void);
+static bool coex_bt_wakeup_request(void);
+static void coex_bt_wakeup_request_end(void);
+
+/****************************************************************************
+ * Other functions
+ ****************************************************************************/
+
+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);
+static IRAM_ATTR int32_t esp_queue_send_generic(void *queue,
+                                                void *item,
+                                                uint32_t ticks,
+                                                int prio);
+static void esp_update_time(struct timespec *timespec, uint32_t ticks);
+static void IRAM_ATTR btdm_slp_tmr_callback(void *arg);
+static int IRAM_ATTR esp_int_adpt_cb(int irq, void *context, void *arg);
+static void IRAM_ATTR btdm_sleep_exit_phase0(void *param);
+#if CONFIG_MAC_BB_PD
+static void IRAM_ATTR btdm_mac_bb_power_down_cb(void);
+static void IRAM_ATTR btdm_mac_bb_power_up_cb(void);
+#endif
+static void btdm_controller_mem_init(void);
+static void bt_controller_deinit_internal(void);
+static void btdm_low_power_mode_deinit(void);
+static bool async_wakeup_request(int event);
+static void async_wakeup_request_end(int event);
+
+/****************************************************************************
+ * Extern Functions declaration and value
+ ****************************************************************************/
+
+extern int btdm_osi_funcs_register(void *osi_funcs);
+
+/* 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 r_btdm_vnd_offload_post_from_isr(btdm_vnd_ol_sig_t sig,
+                                          void *param, bool need_yield);
+extern int r_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 void coex_pti_v2(void);
+
+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 void sdk_config_extend_set_pll_track(bool enable);
+
+#if CONFIG_MAC_BB_PD
+extern void esp_mac_bb_power_down(void);
+extern void esp_mac_bb_power_up(void);
+extern void ets_backup_dma_copy(uint32_t reg, uint32_t mem_addr,
+                                uint32_t num, bool to_mem);
+#endif
+
+#ifdef CONFIG_ESPRESSIF_SPIFLASH
+extern bool spi_flash_cache_enabled(void);
+#endif
+
+extern void btdm_cca_feature_enable(void);
+
+extern uint8_t _bt_bss_start[];
+extern uint8_t _bt_bss_end[];
+extern uint8_t _bt_controller_bss_start[];
+extern uint8_t _bt_controller_bss_end[];
+extern uint8_t _bt_data_start[];
+extern uint8_t _bt_data_end[];
+extern uint8_t _bt_controller_data_start[];
+extern uint8_t _bt_controller_data_end[];
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* BLE OS adapter data */
+
+static struct osi_funcs_s g_osi_funcs =
+{
+  ._magic = OSI_MAGIC_VALUE,
+  ._version = OSI_VERSION,
+  ._interrupt_alloc = interrupt_alloc_wrapper,
+  ._interrupt_free = interrupt_free_wrapper,
+  ._interrupt_handler_set_rsv = NULL,
+  ._global_intr_disable = global_interrupt_disable,
+  ._global_intr_restore = global_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,
+  ._cause_sw_intr_to_core = NULL,
+  ._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,
+  ._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_phase1 = NULL,
+  ._btdm_sleep_exit_phase2 = NULL,
+  ._btdm_sleep_exit_phase3 = btdm_sleep_exit_phase3_wrapper,
+  ._coex_wifi_sleep_set = coex_wifi_sleep_set_hook,
+  ._coex_core_ble_conn_dyn_prio_get = NULL,
+  ._coex_schm_register_btdm_callback =
+      coex_schm_register_btdm_callback_wrapper,
+  ._coex_schm_status_bit_set = coex_schm_status_bit_set_wrapper,
+  ._coex_schm_status_bit_clear = coex_schm_status_bit_clear_wrapper,
+  ._coex_schm_interval_get = coex_schm_interval_get_wrapper,
+  ._coex_schm_curr_period_get = coex_schm_curr_period_get_wrapper,
+  ._coex_schm_curr_phase_get = coex_schm_curr_phase_get_wrapper,
+  ._interrupt_enable = interrupt_enable_wrapper,
+  ._interrupt_disable = interrupt_disable_wrapper,
+  ._esp_hw_power_down = btdm_hw_mac_power_down_wrapper,
+  ._esp_hw_power_up = btdm_hw_mac_power_up_wrapper,
+  ._ets_backup_dma_copy = btdm_backup_dma_copy_wrapper,
+  ._ets_delay_us = esp_rom_delay_us,
+  ._btdm_rom_table_ready = btdm_funcs_table_ready_wrapper,
+  ._coex_bt_wakeup_request = coex_bt_wakeup_request,
+  ._coex_bt_wakeup_request_end = coex_bt_wakeup_request_end,
+};
+
+static DRAM_ATTR struct osi_funcs_s *g_osi_funcs_p;
+
+/* Controller status */
+
+static DRAM_ATTR esp_bt_controller_status_t g_btdm_controller_status =
+    ESP_BT_CONTROLLER_STATUS_IDLE;
+
+/* 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;
+
+/* low power status struct */
+
+static DRAM_ATTR btdm_lpstat_t g_lp_stat;
+
+/* low power control struct */
+
+static DRAM_ATTR btdm_lpcntl_t g_lp_cntl;
+
+/* 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;
+
+#ifdef CONFIG_PM
+
+/* pm_lock to prevent light sleep due to incompatibility currently */
+
+static DRAM_ATTR void * g_light_sleep_pm_lock;
+#endif
+
+/* BT interrupt private data */
+
+static sq_queue_t g_ble_int_flags_free;
+
+static sq_queue_t g_ble_int_flags_used;
+
+static struct irqstate_list_s g_ble_int_flags[NR_IRQSTATE_FLAGS];
+
+/* Cached queue control variables */
+
+#ifdef CONFIG_ESPRESSIF_SPIFLASH
+static struct esp_queuecache_s g_esp_queuecache;
+static uint8_t g_esp_queuecache_buffer[BLE_TASK_EVENT_QUEUE_ITEM_SIZE];
+#endif
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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)
+{
+  return ret == 0;
+}
+
+/****************************************************************************
+ * Functions to be registered to struct osi_funcs_s
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_bt_power_domain_on
+ *
+ * Description:
+ *   Power up the BT domain
+ *
+ * Input Parameters:
+ *   none
+ *
+ * Returned Value:
+ *   none
+ *
+ ****************************************************************************/
+
+static IRAM_ATTR void esp_bt_power_domain_on(void)
+{
+#if SOC_PM_SUPPORT_BT_PD
+  modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD, 0);
+  modifyreg32(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO, 0);
+#endif
+  esp_wifi_bt_power_domain_on();
+}
+
+/****************************************************************************
+ * Name: esp_bt_power_domain_off
+ *
+ * Description:
+ *   Power down the BT domain
+ *
+ * Input Parameters:
+ *   none
+ *
+ * Returned Value:
+ *   none
+ *
+ ****************************************************************************/
+
+static IRAM_ATTR void esp_bt_power_domain_off(void)
+{
+#if SOC_PM_SUPPORT_BT_PD
+  modifyreg32(RTC_CNTL_DIG_ISO_REG, 0, RTC_CNTL_BT_FORCE_ISO);
+  modifyreg32(RTC_CNTL_DIG_PWC_REG, 0, RTC_CNTL_BT_FORCE_PD);
+#endif
+  esp_wifi_bt_power_domain_off();
+}
+
+/****************************************************************************
+ * Name: interrupt_alloc_wrapper
+ *
+ * Description:
+ *   This function allocates an interrupt. It first allocates memory for the
+ *   interrupt and its handle. If this fails, it returns an error. Then, it
+ *   sets up the interrupt and gets its IRQ. If this fails, it returns an
+ *   error. Finally, it attaches the interrupt to the IRQ. If this fails, it
+ *   returns an error.
+ *
+ * Input Parameters:
+ *   cpu_id - The ID of the CPU where the interrupt will be allocated.
+ *   source - The source of the interrupt.
+ *   handler - The handler function for the interrupt.
+ *   arg - The argument for the handler function.
+ *   ret_handle - A pointer to the handle of the interrupt.
+ *
+ * Returned Value:
+ *   ESP_OK on success, or ESP_ERR_INVALID_ARG on failure.
+ *
+ ****************************************************************************/
+
+static int interrupt_alloc_wrapper(int cpu_id,
+                                   int source,
+                                   intr_handler_t handler,
+                                   void *arg,
+                                   void **ret_handle)
+{
+  btdm_isr_alloc_t *p;
+  intr_handle_data_t *handle;
+  vector_desc_t *vd;
+  int ret = OK;
+  int cpuint;
+  int irq;
+
+  wlinfo("cpu_id=%d , source=%d , handler=%p, arg=%p, ret_handle=%p\n",
+         cpu_id, source, handler, arg, ret_handle);
+
+  p = kmm_calloc(1, sizeof(btdm_isr_alloc_t));
+  if (p == NULL)
+    {
+      return ESP_ERR_NOT_FOUND;
+    }
+
+  handle = kmm_calloc(1, sizeof(intr_handle_data_t));
+  if (handle == NULL)
+    {
+      free(p);
+      return ESP_ERR_NOT_FOUND;
+    }
+
+  p->source = source;
+  p->flags = ESP_INTR_FLAG_LEVEL2 | ESP_INTR_FLAG_IRAM;
+  p->fn = handler;
+  p->arg = arg;
+  p->handle = (intr_handle_t *)ret_handle;
+
+  cpuint = esp_setup_irq(source, 2, ESP_IRQ_TRIGGER_LEVEL);
+  if (cpuint < 0)
+    {
+      kmm_free(handle);
+      return ESP_ERR_NOT_FOUND;
+    }
+
+  vd = kmm_calloc(1, sizeof(vector_desc_t));
+  if (vd == NULL)
+    {
+      kmm_free(handle);
+      return ESP_ERR_NOT_FOUND;
+    }
+
+  vd->intno = cpuint;
+  vd->cpu = cpu_id;
+  vd->source = source;
+
+  irq = esp_get_irq(cpuint);
+
+  handle->vector_desc = vd;
+  handle->shared_vector_desc = vd->shared_vec_info;
+
+  *(p->handle) = handle;
+
+  ret = irq_attach(irq, esp_int_adpt_cb, p);
+  if (ret != OK)
+    {
+      kmm_free(p);
+      kmm_free(handle);
+      return ESP_ERR_NOT_FOUND;
+    }
+
+  return ESP_OK;
+}
+
+/****************************************************************************
+ * Name: interrupt_free_wrapper
+ *
+ * Description:
+ *   Not supported. Clear previously bound interrupt IRQ.
+ *
+ * Input Parameters:
+ *   handle - A pointer to the interrupt handle.
+ *
+ * Returned Value:
+ *   NuttX error code
+ *
+ ****************************************************************************/
+
+static int interrupt_free_wrapper(void *handle)
+{
+  DEBUGPANIC();
+
+  return ESP_FAIL;
+}
+
+/****************************************************************************
+ * Name: global_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 global_interrupt_disable(void)
+{
+  struct irqstate_list_s *irqstate;
+
+  irqstate = (struct irqstate_list_s *)sq_remlast(&g_ble_int_flags_free);
+
+  ASSERT(irqstate != NULL);
+
+  irqstate->flags = enter_critical_section();
+
+  sq_addlast((sq_entry_t *)irqstate, &g_ble_int_flags_used);
+}
+
+/****************************************************************************
+ * Name: global_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 global_interrupt_restore(void)
+{
+  struct irqstate_list_s *irqstate;
+
+  irqstate = (struct irqstate_list_s *)sq_remlast(&g_ble_int_flags_used);
+
+  ASSERT(irqstate != NULL);
+
+  leave_critical_section(irqstate->flags);
+
+  sq_addlast((sq_entry_t *)irqstate, &g_ble_int_flags_free);
+}
+
+/****************************************************************************
+ * Name: task_yield_from_isr
+ *
+ * Description:
+ *   Perform a solicited context switch on FreeRTOS. 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;
+  struct bt_sem_s *bt_sem;
+  int tmp;
+
+  tmp = sizeof(struct bt_sem_s);
+  bt_sem = kmm_malloc(tmp);
+  DEBUGASSERT(bt_sem);
+  if (!bt_sem)
+    {
+      wlerr("ERROR: Failed to alloc %d memory\n", tmp);
+      return NULL;
+    }
+
+  ret = nxsem_init(&bt_sem->sem, 0, init);
+  DEBUGASSERT(ret == OK);
+  if (ret)
+    {
+      wlerr("ERROR: Failed to initialize sem error=%d\n", ret);
+      kmm_free(bt_sem);
+      return NULL;
+    }
+
+#ifdef CONFIG_ESPRESSIF_SPIFLASH
+  esp_init_semcache(&bt_sem->sc, &bt_sem->sem);
+#endif
+
+  return bt_sem;
+}
+
+/****************************************************************************
+ * Name: semphr_delete_wrapper
+ *
+ * Description:
+ *   Delete semaphore
+ *
+ * Input Parameters:
+ *   semphr - Semaphore data pointer
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void semphr_delete_wrapper(void *semphr)
+{
+  struct bt_sem_s *bt_sem = (struct bt_sem_s *)semphr;
+  nxsem_destroy(&bt_sem->sem);
+  kmm_free(bt_sem);
+}
+
+/****************************************************************************
+ * Name: semphr_take_from_isr_wrapper
+ *
+ * Description:
+ *   Take a semaphore from an ISR
+ *
+ * Input Parameters:
+ *   semphr - Semaphore data pointer.
+ *   hptw   - Unused.
+ *
+ * Returned Value:
+ *   True
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw)
+{
+  *(int *)hptw = 0;
+
+  DEBUGPANIC();
+  return 0;
+}
+
+/****************************************************************************
+ * Name: semphr_give_from_isr_wrapper
+ *
+ * Description:
+ *   Post semaphore
+ *
+ * Input Parameters:
+ *   semphr - Semaphore data pointer
+ *   hptw   - Unused.
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw)
+{
+  int ret;
+  struct bt_sem_s *bt_sem = (struct bt_sem_s *)semphr;
+
+#ifdef CONFIG_ESPRESSIF_SPIFLASH
+  if (spi_flash_cache_enabled())
+    {
+      ret = semphr_give_wrapper(bt_sem);
+    }
+  else
+    {
+      esp_post_semcache(&bt_sem->sc);
+      ret = 0;
+    }
+#else
+  ret = semphr_give_wrapper(bt_sem);
+#endif
+
+  return esp_errno_trans(ret);
+}
+
+/****************************************************************************
+ * 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 bt_sem_s *bt_sem = (struct bt_sem_s *)semphr;
+
+  if (block_time_ms == OSI_FUNCS_TIME_BLOCKING)
+    {
+      ret = nxsem_wait(&bt_sem->sem);
+    }
+  else
+    {
+      if (block_time_ms > 0)
+        {
+          ret = nxsem_tickwait(&bt_sem->sem, MSEC2TICK(block_time_ms));
+        }
+      else
+        {
+          ret = nxsem_trywait(&bt_sem->sem);
+        }
+    }
+
+  if (ret)
+    {
+      wlerr("ERROR: Failed to wait sem in %lu ticks. Error=%d\n",
+            MSEC2TICK(block_time_ms), ret);
+    }
+
+  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;
+  struct bt_sem_s *bt_sem = (struct bt_sem_s *)semphr;
+
+  ret = nxsem_post(&bt_sem->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: 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 %d\n", ret);
+      kmm_free(mq_adpt);
+      return NULL;
+    }
+
+  mq_adpt->msgsize = item_size;
+
+#ifdef CONFIG_ESPRESSIF_SPIFLASH
+  if (queue_len <= BLE_TASK_EVENT_QUEUE_LEN &&
+      item_size == BLE_TASK_EVENT_QUEUE_ITEM_SIZE)
+    {
+      esp_init_queuecache(&g_esp_queuecache,
+                          &mq_adpt->mq,
+                          g_esp_queuecache_buffer,
+                          BLE_TASK_EVENT_QUEUE_ITEM_SIZE);
+    }
+  else
+    {
+      wlerr("Failed to create queue cache."
+            " Please incresase BLE_TASK_EVENT_QUEUE_LEN to, at least, %ld",
+            queue_len);
+      return NULL;
+    }
+#endif
+
+  return (void *)mq_adpt;
+}
+
+/****************************************************************************
+ * 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);
+}
+
+/****************************************************************************
+ * Name: queue_send_wrapper
+ *
+ * Description:
+ *   Generic send message to queue within a certain period of time
+ *
+ * Input Parameters:
+ *   queue         - Message queue data pointer
+ *   item          - Item to be sent.
+ *   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_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_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 %d\n", ret);
+          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 && ret != -ETIMEDOUT)
+        {
+          wlerr("Failed to timedreceive from mqueue error=%d\n", ret);
+        }
+    }
+
+  return ret > 0 ? true : false;
+}
+
+/****************************************************************************
+ * 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)
+{
+  DEBUGPANIC();
+  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, core_id);
+}
+
+/****************************************************************************
+ * 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:
+ *   Check current is in interrupt
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   true if in interrupt or false if not
+ *
+ ****************************************************************************/
+
+static bool IRAM_ATTR is_in_isr_wrapper(void)
+{
+  return up_interrupt_context();
+}
+
+/****************************************************************************
+ * Name: malloc_wrapper
+ *
+ * Description:
+ *   Malloc buffer
+ *
+ * Input Parameters:
+ *   size - buffer size
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void *malloc_wrapper(size_t size)
+{
+  void * p = kmm_malloc(size);
+  DEBUGASSERT(p);
+
+  return p;
+}
+
+/****************************************************************************
+ * Name: malloc_internal_wrapper
+ *
+ * Description:
+ *   Malloc buffer in DRAM
+ *
+ * Input Parameters:
+ *   size - 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:
+ *   Zero (OK) is returned on success. Otherwise, -1 (ERROR) is returned.
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR read_mac_wrapper(uint8_t mac[6])
+{
+  return esp_read_mac(mac, ESP_MAC_BT);
+}
+
+/****************************************************************************
+ * Name: srand_wrapper
+ *
+ * Description:
+ *   Get random value with seed input. Not implemented.
+ *
+ * Input Parameters:
+ *   seed - Value to be used as seed.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR srand_wrapper(unsigned int seed)
+{
+}
+
+/****************************************************************************
+ * Name: rand_wrapper
+ *
+ * Description:
+ *   Get random value.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Random value
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR rand_wrapper(void)
+{
+  return esp_random();
+}
+
+/****************************************************************************
+ * Name: btdm_lpcycles_2_hus
+ *
+ * Description:
+ *   Converts a number of low power clock cycles into a duration in half us.
+ *
+ * Input Parameters:
+ *   cycles     - number of CPU cycles
+ *   error_corr - local error corr
+ *
+ * Returned Value:
+ *   res - value equivalent to the CPU cycles
+ *
+ ****************************************************************************/
+
+static uint32_t IRAM_ATTR btdm_lpcycles_2_hus(uint32_t cycles,
+                                              uint32_t *error_corr)
+{
+  uint64_t local_error_corr;
+  uint64_t res;
+
+  local_error_corr = (error_corr == NULL) ? 0 : (uint64_t)(*error_corr);
+  res = (uint64_t)g_btdm_lpcycle_us * cycles * 2;
+
+  local_error_corr += res;
+  res = (local_error_corr >> g_btdm_lpcycle_us_frac);
+  local_error_corr -= (res << g_btdm_lpcycle_us_frac);
+  if (error_corr)
+    {
+      *error_corr = (uint32_t)local_error_corr;
+    }
+
+  return (uint32_t)res;
+}
+
+/****************************************************************************
+ * Name: btdm_hus_2_lpcycles
+ *
+ * Description:
+ *   Converts a duration in half us into a number of low power clock cycles.
+ *
+ * Input Parameters:
+ *   hus - sleep duration (us)
+ *
+ * Returned Value:
+ *   cycles
+ *
+ ****************************************************************************/
+
+static uint32_t IRAM_ATTR btdm_hus_2_lpcycles(uint32_t hus)
+{
+  /* The number of sleep duration(us) should not lead to overflow. Thrs: 100s
+   * Compute the sleep duration in us to low power clock cycles, with
+   * calibration result applied clock measurement is conducted
+   */
+
+  uint64_t cycles;
+
+  cycles = ((uint64_t)(hus) << g_btdm_lpcycle_us_frac) / g_btdm_lpcycle_us;
+  cycles >>= 1;
+
+  return (uint32_t)cycles;
+}
+
+/****************************************************************************
+ * 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:
+ *   ESP32-C3 BLE lightsleep callback function.
+ *
+ * Input Parameters:
+ *   lpcycles - light sleep cycles
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles)
+{
+  uint32_t us_to_sleep;
+  uint32_t uncertainty;
+
+  if (g_lp_cntl.wakeup_timer_required == 0)
+    {
+      return;
+    }
+
+  /* start a timer to wake up and acquire the pm_lock before sleep awakes */
+
+  us_to_sleep = btdm_lpcycles_2_hus(lpcycles, NULL) >> 1;
+
+  DEBUGASSERT(us_to_sleep > BTDM_MIN_TIMER_UNCERTAINTY_US);
+  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 == 0);
+
+  ets_timer_arm_us((void *)&g_btdm_slp_tmr,
+                   us_to_sleep - uncertainty,
+                   false);
+  g_lp_stat.wakeup_timer_started = true;
+}
+
+/****************************************************************************
+ * Name: btdm_sleep_enter_phase2_wrapper
+ *
+ * Description:
+ *   ESP32-C3 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)
+        {
+          esp_phy_disable(PHY_MODEM_BT);
+          g_lp_stat.phy_enabled = 0;
+        }
+      else
+        {
+          DEBUGPANIC();
+        }
+
+#ifdef CONFIG_PM
+      if (g_lp_stat.pm_lock_released == 0)
+        {
+          g_lp_stat.pm_lock_released = 1;
+        }
+#endif
+    }
+}
+
+/****************************************************************************
+ * Name: btdm_sleep_exit_phase3_wrapper
+ *
+ * Description:
+ *   ESP32-C3 BLE lightsleep callback function..
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void btdm_sleep_exit_phase3_wrapper(void)
+{
+#ifdef CONFIG_PM
+  if (g_lp_stat.pm_lock_released)
+    {
+      g_lp_stat.pm_lock_released = 0;
+    }
+#endif
+
+  if (btdm_controller_get_sleep_mode() == ESP_BT_SLEEP_MODE_1)
+    {
+      if (g_lp_stat.phy_enabled == 0)
+        {
+          esp_phy_enable(PHY_MODEM_BT);
+          g_lp_stat.phy_enabled = 1;
+        }
+    }
+
+  if (g_lp_cntl.wakeup_timer_required && g_lp_stat.wakeup_timer_started)
+    {
+      ets_timer_disarm((void *)&g_btdm_slp_tmr);
+      g_lp_stat.wakeup_timer_started = 0;
+    }
+
+  while (btdm_sleep_clock_sync());
+}
+
+/****************************************************************************
+ * Name: coex_wifi_sleep_set_hook
+ *
+ * Description:
+ *   Set Wi-Fi/BT coexistence sleep.
+ *
+ * Input Parameters:
+ *   sleep - True to set sleep, false otherwise.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void coex_wifi_sleep_set_hook(bool sleep)
+{
+}
+
+/****************************************************************************
+ * Name: coex_schm_register_btdm_callback_wrapper
+ *
+ * Description:
+ *   This is a wrapper for registering a BTDM callback with the coexistence
+ *   scheme. If the Wi-Fi and Bluetooth coexistence feature is enabled
+ *   (CONFIG_ESPRESSIF_WIFI_BT_COEXIST), it calls the
+ *   coex_schm_register_callback function with COEX_SCHM_CALLBACK_TYPE_BT
+ *   and the provided callback. If the feature is not enabled, it returns 0.
+ *
+ * Input Parameters:
+ *   callback - The callback function to register.
+ *
+ * Returned Value:
+ *   If the coexistence feature is enabled, it returns the result of the
+ *   coex_schm_register_callback function. Otherwise, it returns 0.
+ *
+ ****************************************************************************/
+
+static int coex_schm_register_btdm_callback_wrapper(void *callback)
+{
+#if CONFIG_ESPRESSIF_WIFI_BT_COEXIST
+  return coex_schm_register_callback(COEX_SCHM_CALLBACK_TYPE_BT, callback);
+#else
+  return 0;
+#endif
+}
+
+/****************************************************************************
+ * Name: coex_schm_status_bit_set_wrapper
+ *
+ * Description:
+ *   Set coexistence status.
+ *
+ * Input Parameters:
+ *   type   - Coexistence status type
+ *   status - Coexistence status
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status)
+{
+#ifdef CONFIG_ESPRESSIF_WIFI_BT_COEXIST
+  coex_schm_status_bit_set(type, status);
+#endif
+}
+
+/****************************************************************************
+ * Name: coex_schm_status_bit_clear_wrapper
+ *
+ * Description:
+ *   Clear coexistence status.
+ *
+ * Input Parameters:
+ *   type   - Coexistence status type
+ *   status - Coexistence status
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void coex_schm_status_bit_clear_wrapper(uint32_t type,
+                                               uint32_t status)
+{
+#ifdef CONFIG_ESPRESSIF_WIFI_BT_COEXIST
+  coex_schm_status_bit_clear(type, status);
+#endif
+}
+
+/****************************************************************************
+ * Name: coex_schm_interval_get_wrapper
+ *
+ * Description:
+ *   This is a wrapper for coex_schm_interval_get. If the WiFi and Bluetooth
+ *   coexistence feature is enabled (CONFIG_ESPRESSIF_WIFI_BT_COEXIST), it
+ *   calls the function and returns its result. If not enabled, it returns 0.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   If the coexistence feature is enabled, it returns the result of the
+ *   coex_schm_interval_get function. Otherwise, it returns 0.
+ *
+ ****************************************************************************/
+
+static uint32_t coex_schm_interval_get_wrapper(void)
+{
+#if CONFIG_ESPRESSIF_WIFI_BT_COEXIST
+  return coex_schm_interval_get();
+#else
+  return 0;
+#endif
+}
+
+/****************************************************************************
+ * Name: coex_schm_curr_period_get_wrapper
+ *
+ * Description:
+ *   This is a wrapper for coex_schm_curr_period_get. If the WiFi and
+ *   Bluetooth coexistence feature is enabled
+ *   (CONFIG_ESPRESSIF_WIFI_BT_COEXIST), it calls the function and returns
+ *   its result. If the feature is not enabled, it returns 1.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   If the coexistence feature is enabled, it returns the result of the
+ *   coex_schm_curr_period_get function. Otherwise, it returns 1.
+ *
+ ****************************************************************************/
+
+static uint8_t coex_schm_curr_period_get_wrapper(void)
+{
+#if CONFIG_ESPRESSIF_WIFI_BT_COEXIST
+  return coex_schm_curr_period_get();
+#else
+  return 1;
+#endif
+}
+
+/****************************************************************************
+ * Name: coex_schm_curr_phase_get_wrapper
+ *
+ * Description:
+ *   This is a wrapper for coex_schm_curr_phase_get. If the WiFi and
+ *   Bluetooth coexistence feature is enabled
+ *   (CONFIG_ESPRESSIF_WIFI_BT_COEXIST), it calls the function and returns
+ *   its result. If the feature is not enabled, it returns NULL.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   If the coexistence feature is enabled, it returns the result of the
+ *   coex_schm_curr_phase_get function. Otherwise, it returns NULL.
+ *
+ ****************************************************************************/
+
+static void * coex_schm_curr_phase_get_wrapper(void)
+{
+#if CONFIG_ESPRESSIF_WIFI_BT_COEXIST
+  return coex_schm_curr_phase_get();
+#else
+  return NULL;
+#endif
+}
+
+/****************************************************************************
+ * Name: interrupt_enable_wrapper
+ *
+ * Description:
+ *   This function enables an interrupt. It first retrieves the interrupt
+ *   number and checks if it's valid. If it's not, it returns an error.
+ *   Then, it sets the interrupt to be handled in IRAM. If this fails, it
+ *   returns an error. Finally, it enables the interrupt. If this fails, it
+ *   returns an error.
+ *
+ * Input Parameters:
+ *   handle - A pointer to the interrupt handle.
+ *
+ * Returned Value:
+ *   ESP_OK on success, or ESP_ERR_INVALID_ARG on failure.
+ *
+ ****************************************************************************/
+
+static int interrupt_enable_wrapper(void *handle)
+{
+  intr_handle_t isr = (intr_handle_t)handle;
+  int ret = ESP_OK;
+  int cpuint;
+  int irq;
+
+  cpuint = isr->vector_desc->intno;
+
+  irq = esp_get_irq(cpuint);
+  if (irq == 127)
+    {
+      wlerr("CPU interrupt is not assigned!\n");
+      return ESP_ERR_INVALID_ARG;
+    }
+
+  ret = esp_irq_set_iram_isr(irq);
+  if (ret != ESP_OK)
+    {
+      wlerr("Failed to set IRAM ISR\n");
+      return ESP_ERR_INVALID_ARG;
+    }
+
+  up_enable_irq(irq);
+
+  return ret == OK ? ESP_OK : ESP_ERR_INVALID_ARG;
+}
+
+/****************************************************************************
+ * Name: interrupt_disable_wrapper
+ *
+ * Description:
+ *   This function disables an interrupt. It first retrieves the interrupt
+ *   number and checks if it's valid. If it's not, it returns an error.
+ *   Then, it disables the interrupt. If this fails, it returns an error.
+ *
+ * Input Parameters:
+ *   handle - A pointer to the interrupt handle.
+ *
+ * Returned Value:
+ *   ESP_OK on success, or ESP_ERR_INVALID_ARG on failure.
+ *
+ ****************************************************************************/
+
+static int interrupt_disable_wrapper(void *handle)
+{
+  intr_handle_t isr = (intr_handle_t)handle;
+  int ret = ESP_OK;
+  int cpuint;
+  int irq;
+
+  cpuint = isr->vector_desc->intno;
+
+  irq = esp_get_irq(cpuint);
+  if (irq == 127)
+    {
+      wlerr("CPU interrupt is not assigned!\n");
+      return ESP_ERR_INVALID_ARG;
+    }
+
+  up_disable_irq(irq);
+
+  return ret == OK ? ESP_OK : ESP_ERR_INVALID_ARG;
+}
+
+/****************************************************************************
+ * Name: btdm_hw_mac_power_down_wrapper
+ *
+ * Description:
+ *   Power down MAC and baseband of Wi-Fi and Bluetooth when PHY is disabled
+ *
+ * Input Parameters:
+ *   none
+ *
+ * Returned Value:
+ *   none
+ *
+ ****************************************************************************/
+
+void IRAM_ATTR btdm_hw_mac_power_down_wrapper(void)
+{
+}
+
+/****************************************************************************
+ * Name: btdm_hw_mac_power_up_wrapper
+ *
+ * Description:
+ *   Power up MAC and baseband of Wi-Fi and Bluetooth when PHY is disabled
+ *
+ * Input Parameters:
+ *   none
+ *
+ * Returned Value:
+ *   none
+ *
+ ****************************************************************************/
+
+void IRAM_ATTR btdm_hw_mac_power_up_wrapper(void)
+{
+}
+
+/****************************************************************************
+ * Name: btdm_backup_dma_copy_wrapper
+ *
+ * Description:
+ *   Copy btdm backup DMA when PHY is disabled
+ *
+ * Input Parameters:
+ *   none
+ *
+ * Returned Value:
+ *   none
+ *
+ ****************************************************************************/
+
+void IRAM_ATTR btdm_backup_dma_copy_wrapper(uint32_t reg, uint32_t mem_addr,
+                                            uint32_t num,  bool to_mem)
+{
+}
+
+/****************************************************************************
+ * Other functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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;
+
+  DEBUGASSERT(task_handle != NULL);
+
+  pid = kthread_create(name, prio, stack_depth, entry,
+                       (char * const *)param);
+  if (pid > 0)
+    {
+      if (task_handle)
+        {
+          *((int *)task_handle) = pid;
+        }
+    }
+  else
+    {
+      wlerr("Failed to create task, error %d\n", pid);
+    }
+
+  return pid > 0;
+}
+
+/****************************************************************************
+ * 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 IRAM_ATTR 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;
+
+#ifdef CONFIG_ESPRESSIF_SPIFLASH
+  if (!spi_flash_cache_enabled())
+    {
+      esp_send_queuecache(&g_esp_queuecache, item, mq_adpt->msgsize);
+      return esp_errno_trans(OK);
+    }
+#endif
+
+  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 %d\n", ret);
+          return esp_errno_trans(ret);
+        }
+
+      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: esp_update_time
+ *
+ * Description:
+ *   Transform ticks to time and add this time to timespec value
+ *
+ * Input Parameters:
+ *   ticks - System ticks
+ *
+ * Output Parameters:
+ *   timespec - Input timespec data pointer
+ *
+ * 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: btdm_slp_tmr_callback
+ *
+ * Description:
+ *   ESP-C3 BLE sleep callback function.
+ *
+ * Input Parameters:
+ *   arg - Unused
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR btdm_slp_tmr_callback(void *arg)
+{
+#ifdef CONFIG_PM
+  btdm_vnd_offload_post(BTDM_VND_OL_SIG_WAKEUP_TMR,
+                        (void *)BTDM_ASYNC_WAKEUP_SRC_TMR);
+#endif
+}
+
+/****************************************************************************
+ * 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 IRAM_ATTR esp_int_adpt_cb(int irq, void *context, void *arg)
+{
+  btdm_isr_alloc_t *p = (btdm_isr_alloc_t *)arg;
+
+  p->fn(p->arg);
+
+  return OK;
+}
+
+/****************************************************************************
+ * 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);
+
+#ifdef CONFIG_PM
+  if (g_lp_stat.pm_lock_released)
+    {
+      g_lp_stat.pm_lock_released = 0;
+    }
+#endif
+
+  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)
+    {
+      ets_timer_disarm((void *)&g_btdm_slp_tmr);
+      g_lp_stat.wakeup_timer_started = 0;
+    }
+
+  if (event == BTDM_ASYNC_WAKEUP_SRC_VHCI ||
+      event == BTDM_ASYNC_WAKEUP_SRC_DISA)
+    {
+      semphr_give_wrapper(g_wakeup_req_sem);
+    }
+}
+
+#if CONFIG_MAC_BB_PD
+
+/****************************************************************************
+ * Name: btdm_mac_bb_power_down_cb
+ *
+ * Description:
+ *   This function is a callback that powers down the MAC and baseband (BB)
+ *   of the Bluetooth module. It first checks if the power down control for
+ *   the MAC and BB is enabled and if they are not already powered down. If
+ *   these conditions are met, it powers down the DMA and sets the MAC and BB
+ *   as powered down.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR btdm_mac_bb_power_down_cb(void)
+{
+  if (g_lp_cntl.mac_bb_pd && g_lp_stat.mac_bb_pd == 0)
+    {
+      btdm_ble_power_down_dma_copy(true);
+      g_lp_stat.mac_bb_pd = 1;
+    }
+}
+
+/****************************************************************************
+ * Name: btdm_mac_bb_power_up_cb
+ *
+ * Description:
+ *   This function is a callback that powers up the MAC and baseband (BB)
+ *   of the Bluetooth module. It first checks if the power down control for
+ *   the MAC and BB is enabled and if they are currently powered down. If
+ *   these conditions are met, it powers up the DMA and sets the MAC and BB
+ *   as powered up.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR btdm_mac_bb_power_up_cb(void)
+{
+  if (g_lp_cntl.mac_bb_pd && g_lp_stat.mac_bb_pd)
+    {
+      btdm_ble_power_down_dma_copy(false);
+      g_lp_stat.mac_bb_pd = 0;
+    }
+}
+#endif
+
+static esp_err_t btdm_low_power_mode_init(esp_bt_controller_config_t *cfg)
+{
+  esp_err_t err = ESP_OK;
+  bool select_src_ret;
+  bool set_div_ret;
+
+  do
+    {
+      /* set default values for global states or resources */
+
+      g_lp_stat.val = 0;
+      g_lp_cntl.val = 0;
+      g_lp_cntl.main_xtal_pu = 0;
+      g_wakeup_req_sem = NULL;
+      g_btdm_slp_tmr = NULL;
+      g_lp_cntl.wakeup_timer_required = 0;
+
+      /* configure and initialize resources */
+
+      g_lp_cntl.enable = (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) ? 1 : 0;
+      g_lp_cntl.lpclk_sel = (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) ? \
+                            cfg->sleep_clock : ESP_BT_SLEEP_CLOCK_MAIN_XTAL;
+      g_lp_cntl.no_light_sleep = 0;
+
+      if (g_lp_cntl.enable)
+        {
+#if CONFIG_MAC_BB_PD
+          if (!btdm_deep_sleep_mem_init())
+            {
+              err = ESP_ERR_NO_MEM;
+              break;
+            }
+
+          g_lp_cntl.mac_bb_pd = 1;
+#endif
+#ifdef CONFIG_PM
+          g_lp_cntl.wakeup_timer_required = 1;
+#endif
+          /* async wakeup semaphore for VHCI */
+
+          g_wakeup_req_sem = semphr_create_wrapper(1, 0);
+          if (g_wakeup_req_sem == NULL)
+            {
+              err = ESP_ERR_NO_MEM;
+              break;
+            }
+
+          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",
+                };
+
+              ets_timer_setfn((void *)&g_btdm_slp_tmr,
+                              (void *)btdm_slp_tmr_callback,
+                              &create_args);
+            }
+
+          /* set default bluetooth sleep clock cycle and its
+           * fractional bits
+           */
+
+          g_btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
+          g_btdm_lpcycle_us = 2 << (g_btdm_lpcycle_us_frac);
+
+          /* External 32 kHz XTAL */
+
+          if (g_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL)
+            {
+              /* check whether or not EXT_CRYS is working */
+
+              if (rtc_clk_slow_freq_get() !=
+                  SOC_RTC_SLOW_CLK_SRC_XTAL32K)
+                {
+                  wlwarn("32.768kHz XTAL not detected, fall back to main"
+                         "XTAL as Bluetooth sleep clock");
+                  g_lp_cntl.lpclk_sel = ESP_BT_SLEEP_CLOCK_MAIN_XTAL;
+#if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
+                  g_lp_cntl.no_light_sleep = 1;
+#endif
+                }
+            }
+          else if (g_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_RTC_SLOW)
+            {
+              /* Internal 136kHz RC oscillator */
+
+              if (rtc_clk_slow_freq_get() ==
+                  SOC_RTC_SLOW_CLK_SRC_RC_SLOW)
+                {
+                  wlwarn("Internal 136kHz RC oscillator. The accuracy of "
+                         "this clock is a lot larger than 500ppm which is "
+                         "required in Bluetooth communication, so don't "
+                         "select this option in scenarios such as BLE "
+                         "connection state.");
+                }
+              else
+                {
+                  wlwarn("Internal 136kHz RC oscillator not detected.");
+                  PANIC();
+                }
+            }
+          else if (g_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL)
+            {
+              wlinfo("Bluetooth will use main XTAL as sleep clock.");
+  #if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
+              g_lp_cntl.no_light_sleep = 1;
+  #endif
+            }
+        }
+      else
+        {
+          g_lp_cntl.no_light_sleep = 1;
+        }
+
+      if (g_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL)
+        {
+#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
+          ASSERT(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON));
+          g_lp_cntl.main_xtal_pu = 1;
+#endif
+          select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL);
+          set_div_ret = btdm_lpclk_set_div(esp_clk_xtal_freq() / MHZ);
+          assert(select_src_ret && set_div_ret);
+          g_btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
+          g_btdm_lpcycle_us = 1 << (g_btdm_lpcycle_us_frac);
+        }
+      else if (g_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL)
+        {
+          select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K);
+          set_div_ret = btdm_lpclk_set_div(0);
+          assert(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));
+          assert(g_btdm_lpcycle_us != 0);
+        }
+      else if (g_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_RTC_SLOW)
+        {
+          select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
+          set_div_ret = btdm_lpclk_set_div(0);
+          assert(select_src_ret && set_div_ret);
+          g_btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
+          g_btdm_lpcycle_us = esp_clk_slowclk_cal_get();
+        }
+      else
+        {
+          UNUSED(select_src_ret);
+          UNUSED(set_div_ret);
+          err = ESP_ERR_INVALID_ARG;
+          break;
+        }
+
+#if CONFIG_ESPRESSIF_WIFI_BT_COEXIST
+      coex_update_lpclk_interval();
+#endif
+
+#ifdef CONFIG_PM
+      g_lp_stat.pm_lock_released = 1;
+#endif
+    }
+  while (0);
+
+  return err;
+}
+
+/****************************************************************************
+ * 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)
+{
+  extern void btdm_controller_rom_data_init(void);
+  btdm_controller_rom_data_init();
+}
+
+/****************************************************************************
+ * Name: bt_controller_deinit_internal
+ *
+ * Description:
+ *   Deinit BT internal controller.
+ *
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+static void bt_controller_deinit_internal(void)
+{
+  periph_module_disable(PERIPH_BT_MODULE);
+
+  btdm_low_power_mode_deinit();
+
+  esp_bt_power_domain_off();
+#if CONFIG_MAC_BB_PD
+  esp_mac_bb_pd_mem_deinit();
+#endif
+  esp_phy_modem_deinit();
+
+  if (g_osi_funcs_p != NULL)
+    {
+    free(g_osi_funcs_p);
+    g_osi_funcs_p = NULL;
+    }
+
+  g_btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
+}
+
+/****************************************************************************
+ * Name: btdm_low_power_mode_deinit
+ *
+ * Description:
+ *   This function deinitializes the low power control resources. It checks
+ *   various conditions and if they are met, it performs the corresponding
+ *   deinitialization actions such as stopping and deleting timers,
+ *   deregistering tasks, deleting semaphores, and updating the low power
+ *   clock interval.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void btdm_low_power_mode_deinit(void)
+{
+#if CONFIG_MAC_BB_PD
+  if (g_lp_cntl.mac_bb_pd)
+    {
+      btdm_deep_sleep_mem_deinit();
+      g_lp_cntl.mac_bb_pd = 0;
+    }
+#endif
+
+#ifdef CONFIG_PM
+  if (g_lp_cntl.no_light_sleep)
+    {
+      if (g_light_sleep_pm_lock != NULL)
+        {
+          g_light_sleep_pm_lock = NULL;
+        }
+    }
+#endif
+
+  if (g_lp_cntl.wakeup_timer_required && g_btdm_slp_tmr != NULL)
+    {
+      if (g_lp_stat.wakeup_timer_started)
+        {
+          ets_timer_disarm((void *)&g_btdm_slp_tmr);
+        }
+
+      g_lp_stat.wakeup_timer_started = 0;
+      ets_timer_done((void *)&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;
+        }
+    }
+
+  if (g_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL)
+    {
+#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
+      if (g_lp_cntl.main_xtal_pu)
+        {
+          ASSERT(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF));
+          g_lp_cntl.main_xtal_pu = 0;
+        }
+#endif
+
+      btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
+      btdm_lpclk_set_div(0);
+#if CONFIG_ESPRESSIF_WIFI_BT_COEXIST
+      coex_update_lpclk_interval();
+#endif
+    }
+
+  g_btdm_lpcycle_us = 0;
+}
+
+/****************************************************************************
+ * Name: async_wakeup_request
+ *
+ * Description:
+ *   Request the BLE Controller to wakeup
+ *
+ * Input Parameters:
+ *   event - the event that triggered the wakeup
+ *
+ * Returned Value:
+ *   true if request lock is needed, false otherwise
+ *
+ ****************************************************************************/
+
+static bool async_wakeup_request(int event)
+{
+  bool do_wakeup_request = false;
+
+  if (g_lp_cntl.enable == 0)
+    {
+      return false;
+    }
+
+  switch (event)
+    {
+      case BTDM_ASYNC_WAKEUP_SRC_VHCI:
+      case BTDM_ASYNC_WAKEUP_SRC_DISA:
+        btdm_in_wakeup_requesting_set(true);
+
+        if (btdm_power_state_active() == false)
+          {
+            r_btdm_vnd_offload_post(BTDM_VND_OL_SIG_WAKEUP_TMR,
+                                    (void *)event);
+            do_wakeup_request = true;
+            semphr_take_wrapper(g_wakeup_req_sem, OSI_FUNCS_TIME_BLOCKING);
+          }
+        break;
+      case BTDM_ASYNC_WAKEUP_REQ_COEX:
+        if (!btdm_power_state_active())
+          {
+            do_wakeup_request = true;
+#if CONFIG_PM
+            if (g_lp_stat.pm_lock_released)
+              {
+                g_lp_stat.pm_lock_released = 0;
+              }
+#endif
+
+            btdm_wakeup_request();
+
+            if (g_lp_cntl.wakeup_timer_required &&
+                g_lp_stat.wakeup_timer_started)
+              {
+                ets_timer_disarm((void *)&g_btdm_slp_tmr);
+                g_lp_stat.wakeup_timer_started = 0;
+              }
+          }
+
+      default:
+        return false;
+    }
+
+  return do_wakeup_request;
+}
+
+/****************************************************************************
+ * Name: async_wakeup_request_end
+ *
+ * Description:
+ *   Finish a wakeup request
+ *
+ * Input Parameters:
+ *   event - the event that triggered the wakeup
+ *
+ * Returned Value:
+ *   true if request lock is needed, false otherwise
+ *
+ ****************************************************************************/
+
+static void async_wakeup_request_end(int event)
+{
+  bool allow_to_sleep;
+
+  if (g_lp_cntl.enable == 0)
+    {
+      return;
+    }
+
+  switch (event)
+    {
+      case BTDM_ASYNC_WAKEUP_SRC_VHCI:
+      case BTDM_ASYNC_WAKEUP_SRC_DISA:
+        allow_to_sleep = true;
+        break;
+      case BTDM_ASYNC_WAKEUP_REQ_COEX:
+        allow_to_sleep = false;
+        break;
+      default:
+        allow_to_sleep = true;
+        break;
+    }
+
+  if (allow_to_sleep)
+    {
+      btdm_in_wakeup_requesting_set(false);
+    }
+}
+
+/****************************************************************************
+ * Name: btdm_funcs_table_ready_wrapper
+ *
+ * Description:
+ *   This is a wrapper for preparing the BTDM functions table. If the BT_BLE
+ *   CCA mode is set to 2, it enables the CCA feature by calling the
+ *   btdm_cca_feature_enable function.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void btdm_funcs_table_ready_wrapper(void)
+{
+#if BT_BLE_CCA_MODE == 2
+  btdm_cca_feature_enable();
+#endif
+}
+
+/****************************************************************************
+ * Name: bt_async_wakeup_request
+ *
+ * Description:
+ *   This function requests an asynchronous wakeup for the Bluetooth
+ *   controller. It calls the async_wakeup_request function with
+ *   BTDM_ASYNC_WAKEUP_SRC_VHCI as the argument.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   The result of the async_wakeup_request function.
+ *
+ ****************************************************************************/
+
+bool bt_async_wakeup_request(void)
+{
+  return async_wakeup_request(BTDM_ASYNC_WAKEUP_SRC_VHCI);
+}
+
+/****************************************************************************
+ * Name: bt_wakeup_request_end
+ *
+ * Description:
+ *   This function ends a wakeup request for the Bluetooth controller. It
+ *   calls the async_wakeup_request_end function with
+ *   BTDM_ASYNC_WAKEUP_SRC_VHCI as the argument.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void bt_wakeup_request_end(void)
+{
+  async_wakeup_request_end(BTDM_ASYNC_WAKEUP_SRC_VHCI);
+}
+
+/****************************************************************************
+ * Name: coex_bt_wakeup_request
+ *
+ * Description:
+ *   This function requests a coexistence Bluetooth wakeup. It calls the
+ *   async_wakeup_request function with BTDM_ASYNC_WAKEUP_REQ_COEX as the
+ *   argument.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   The result of the async_wakeup_request function.
+ *
+ ****************************************************************************/
+
+static bool coex_bt_wakeup_request(void)
+{
+  return async_wakeup_request(BTDM_ASYNC_WAKEUP_REQ_COEX);
+}
+
+/****************************************************************************
+ * Name: coex_bt_wakeup_request_end
+ *
+ * Description:
+ *   This function ends a coexistence Bluetooth wakeup request. It calls the
+ *   async_wakeup_request_end function with BTDM_ASYNC_WAKEUP_REQ_COEX as the
+ *   argument.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void coex_bt_wakeup_request_end(void)
+{
+  async_wakeup_request_end(BTDM_ASYNC_WAKEUP_REQ_COEX);
+  return;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_bt_controller_init
+ *
+ * Description:
+ *   Init BT controller.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned
+ *   on failure.
+ *
+ ****************************************************************************/
+
+int esp_bt_controller_init(void)
+{
+  esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
+  esp_bt_controller_config_t *cfg = &bt_cfg;
+  int i;
+  int err;
+
+  sq_init(&g_ble_int_flags_free);
+  sq_init(&g_ble_int_flags_used);
+
+  for (i = 0; i < NR_IRQSTATE_FLAGS; i++)
+    {
+      sq_addlast((sq_entry_t *)&g_ble_int_flags[i], &g_ble_int_flags_free);
+    }
+
+  if (g_btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE)
+    {
+      wlerr("Invalid controller status");
+      return ERROR;
+    }
+
+  if (cfg == NULL)
+    {
+      return -EINVAL;
+    }
+
+  if (cfg->controller_task_prio != ESP_TASK_BT_CONTROLLER_PRIO ||
+      cfg->controller_task_stack_size < ESP_TASK_BT_CONTROLLER_STACK)
+    {
+      wlerr("Invalid controller task prioriy or stack size");
+      return -EINVAL;
+    }
+
+  if (cfg->bluetooth_mode != ESP_BT_MODE_BLE)
+    {
+      wlerr("Controller only support BLE only mode");
+      return ERROR;
+    }
+
+  if (cfg->bluetooth_mode & ESP_BT_MODE_BLE)
+    {
+      if ((cfg->ble_max_act <= 0) ||
+          (cfg->ble_max_act > BT_CTRL_BLE_MAX_ACT_LIMIT))
+        {
+          wlerr("Invalid value of ble_max_act");
+          return -EINVAL;
+        }
+    }
+
+  if (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1)
+    {
+      if (cfg->sleep_clock == ESP_BT_SLEEP_CLOCK_NONE)
+        {
+          wlerr("SLEEP_MODE_1 enabled but sleep clock not configured");
+          return ERROR;
+        }
+
+      if (cfg->sleep_clock > ESP_BT_SLEEP_CLOCK_RTC_SLOW)
+        {
+          wlerr("SLEEP_MODE_1 is enabled but this sleep clock is not "
+                "supported");
+          return ERROR;
+        }
+    }
+
+  cfg->controller_task_stack_size = CONFIG_ESPRESSIF_BLE_TASK_STACK_SIZE;
+  cfg->controller_task_prio       = CONFIG_ESPRESSIF_BLE_TASK_PRIORITY;
+  cfg->controller_task_run_cpu    = CONFIG_BT_CTRL_PINNED_TO_CORE;
+  cfg->magic                      = ESP_BT_CTRL_CONFIG_MAGIC_VAL;
+
+#if CONFIG_MAC_BB_PD
+  esp_mac_bb_pd_mem_init();
+#endif
+
+  esp_phy_modem_init();
+
+  esp_bt_power_domain_on();
+
+  btdm_controller_mem_init();
+
+  g_osi_funcs_p = kmm_malloc(sizeof(struct osi_funcs_s));
+  if (g_osi_funcs_p == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  memcpy(g_osi_funcs_p, &g_osi_funcs, sizeof(struct osi_funcs_s));
+  if (btdm_osi_funcs_register(g_osi_funcs_p) != 0)
+    {
+      wlerr("Error, probably invalid OSI Functions\n");
+      return -EINVAL;
+    }
+
+  wlinfo("BT controller compile version [%s]\n",
+         btdm_controller_get_compile_version());
+
+  if ((err = btdm_low_power_mode_init(cfg)) != ESP_OK)
+    {
+      wlerr("Low power module initialization failed\n");
+      goto error;
+    }
+
+#ifdef CONFIG_ESPRESSIF_WIFI_BT_COEXIST
+  coex_init();
+#endif
+
+  periph_module_enable(PERIPH_BT_MODULE);
+  periph_module_reset(PERIPH_BT_MODULE);
+
+  if (btdm_controller_init(cfg) != 0)
+    {
+      err = -ENOMEM;
+      goto error;
+    }
+
+  g_btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
+
+#ifdef CONFIG_ESPRESSIF_SPIFLASH
+  if (esp_wireless_init() != OK)
+    {
+      return -EIO;
+    }
+#endif
+
+  return OK;
+
+error:
+
+  bt_controller_deinit_internal();
+
+  return esp_wifi_to_errno(err);
+}
+
+/****************************************************************************
+ * Name: esp_bt_controller_deinit
+ *
+ * Description:
+ *   Deinit BT controller.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. Otherwise, -1 (ERROR) is returned.
+ *
+ ****************************************************************************/
+
+int esp_bt_controller_deinit(void)
+{
+  if (g_btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED)
+    {
+      return ERROR;
+    }
+
+  btdm_controller_deinit();
+
+  bt_controller_deinit_internal();
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: esp_bt_controller_enable
+ *
+ * Description:
+ *   Enable BT controller.
+ *
+ * Input Parameters:
+ *   mode - the mode(BLE/BT/BTDM) to enable. For compatible of API, retain
+ *   this argument. This mode must be equal as the mode in "cfg" of
+ *   esp_bt_controller_init().
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned
+ *   on failure.
+ *
+ ****************************************************************************/
+
+int esp_bt_controller_enable(esp_bt_mode_t mode)
+{
+  int ret = OK;
+
+  if (g_btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED)
+    {
+      return ERROR;
+    }
+
+  if (mode != btdm_controller_get_mode())
+    {
+      wlerr("invalid mode %d, controller support mode is %d",
+            mode, btdm_controller_get_mode());
+      return ERROR;
+    }
+
+  /* Enable PHY when enabling controller to reduce power dissipation after
+   * controller init. Notice the init order: esp_phy_enable() ->
+   * bt_bb_v2_init_cmplx() -> coex_pti_v2()
+   */
+
+  esp_phy_enable(PHY_MODEM_BT);
+  g_lp_stat.phy_enabled = 1;
+
+#ifdef CONFIG_ESPRESSIF_WIFI_BT_COEXIST
+  coex_enable();
+#endif
+
+#ifdef CONFIG_PM
+  /* enable low power mode */
+
+  g_lp_stat.pm_lock_released = 0;
+#endif
+
+#if CONFIG_MAC_BB_PD
+  if (esp_register_mac_bb_pd_callback(btdm_mac_bb_power_down_cb) != 0)
+    {
+      err = -EINVAL;
+      goto error;
+    }
+
+  if (esp_register_mac_bb_pu_callback(btdm_mac_bb_power_up_cb) != 0)
+    {
+      err = -EINVAL;
+      goto error;
+    }
+#endif
+
+  if (g_lp_cntl.enable)
+    {
+        btdm_controller_enable_sleep(true);
+    }
+
+  /* Disable pll track by default in BLE controller on ESP32-C3 and
+   * ESP32-C3.
+   */
+
+  sdk_config_extend_set_pll_track(false);
+
+  if (btdm_controller_enable(mode) != 0)
+    {
+      ret = ERROR;
+      goto error;
+    }
+
+  coex_pti_v2();
+
+  g_btdm_controller_status = ESP_BT_CONTROLLER_STATUS_ENABLED;
+
+  return ret;
+
+error:
+
+#if CONFIG_MAC_BB_PD
+  esp_unregister_mac_bb_pd_callback(btdm_mac_bb_power_down_cb);
+  esp_unregister_mac_bb_pu_callback(btdm_mac_bb_power_up_cb);
+#endif
+
+  /* disable low power mode */
+
+  btdm_controller_enable_sleep(false);
+
+#ifdef CONFIG_PM
+  if (g_lp_stat.pm_lock_released == 0)
+    {
+      g_lp_stat.pm_lock_released = 1;
+    }
+#endif
+
+#if CONFIG_ESPRESSIF_WIFI_BT_COEXIST
+    coex_disable();
+#endif
+  if (g_lp_stat.phy_enabled)
+    {
+      esp_phy_disable(PHY_MODEM_BT);
+      g_lp_stat.phy_enabled = 0;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp_bt_controller_disable
+ *
+ * Description:
+ *   Disable BT controller.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned
+ *   on failure.
+ *
+ ****************************************************************************/
+
+int esp_bt_controller_disable(void)
+{
+  if (g_btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED)
+    {
+      return ERROR;
+    }
+
+  async_wakeup_request(BTDM_ASYNC_WAKEUP_SRC_DISA);
+  while (!btdm_power_state_active())
+    {
+      nxsig_usleep(1000); /* wait */
+    }
+
+  btdm_controller_disable();
+
+  async_wakeup_request_end(BTDM_ASYNC_WAKEUP_SRC_DISA);
+
+#ifdef CONFIG_ESPRESSIF_WIFI_BT_COEXIST
+  coex_disable();
+#endif
+
+  if (g_lp_stat.phy_enabled)
+    {
+      esp_phy_disable(PHY_MODEM_BT);
+      g_lp_stat.phy_enabled = 0;
+    }
+
+  g_btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
+
+  /* disable low power mode */
+
+#if CONFIG_MAC_BB_PD
+  esp_unregister_mac_bb_pd_callback(btdm_mac_bb_power_down_cb);
+  esp_unregister_mac_bb_pu_callback(btdm_mac_bb_power_up_cb);
+#endif
+
+#ifdef CONFIG_PM
+  if (g_lp_stat.pm_lock_released == 0)
+    {
+      g_lp_stat.pm_lock_released = 1;
+    }
+  else
+    {
+      DEBUGPANIC();
+    }
+#endif
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: esp_bt_controller_get_status
+ *
+ * Description:
+ *   Returns the status of the BT Controller
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   The current status (type esp_bt_controller_status_t)
+ *
+ ****************************************************************************/
+
+esp_bt_controller_status_t esp_bt_controller_get_status(void)
+{
+  return g_btdm_controller_status;
+}
+
+/****************************************************************************
+ * Name: esp_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 esp_vhci_host_check_send_available(void)
+{
+  if (g_btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED)
+    {
+      return false;
+    }
+
+  return api_vhci_host_check_send_available();
+}
+
+/****************************************************************************
+ * Name: esp_vhci_host_send_packet
+ *
+ * Description:
+ *   Host send packet to controller.
+ *
+ * Input Parameters:
+ *   data - the packet pointer
+ *   len  - the packet length
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp_vhci_host_send_packet(uint8_t *data, uint16_t len)
+{
+  if (g_btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED)
+    {
+      return;
+    }
+
+  async_wakeup_request(BTDM_ASYNC_WAKEUP_SRC_VHCI);
+
+  api_vhci_host_send_packet(data, len);
+
+  async_wakeup_request_end(BTDM_ASYNC_WAKEUP_SRC_VHCI);
+}
+
+/****************************************************************************
+ * Name: esp_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 esp_vhci_register_callback(const esp_vhci_host_callback_t *callback)
+{
+  int ret = ERROR;
+  if (g_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;
+}
+
+/****************************************************************************
+ * Name: esp_bt_get_lpclk_src
+ *
+ * Description:
+ *   This function returns the source of the low power clock for the ESP
+ *   Bluetooth controller. If the controller is not initialized or enabled,
+ *   it returns ESP_BT_SLEEP_CLOCK_NONE. Otherwise, it returns the current
+ *   low power clock selection.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   The source of the low power clock for the ESP Bluetooth controller.
+ *
+ ****************************************************************************/
+
+esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void)
+{
+  if (g_btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED &&
+      g_btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED)
+    {
+      return ESP_BT_SLEEP_CLOCK_NONE;
+    }
+
+  return g_lp_cntl.lpclk_sel;
+}
diff --git a/arch/risc-v/src/esp32c3/esp_ble_adapter.h b/arch/risc-v/src/esp32c3/esp_ble_adapter.h
new file mode 100644
index 0000000000..f3b20d79b1
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp_ble_adapter.h
@@ -0,0 +1,175 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp_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_ESP_BLE_ADAPTER_H
+#define __ARCH_RISCV_SRC_ESP32C3_ESP_BLE_ADAPTER_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "esp_bt.h"
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_bt_controller_init
+ *
+ * Description:
+ *   Init  BT controller.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned
+ *   on failure.
+ *
+ ****************************************************************************/
+
+int esp_bt_controller_init(void);
+
+/****************************************************************************
+ * Name: esp_bt_controller_deinit
+ *
+ * Description:
+ *   Deinit BT controller.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. Otherwise, -1 (ERROR) is returned.
+ *
+ ****************************************************************************/
+
+int esp_bt_controller_deinit(void);
+
+/****************************************************************************
+ * Name: esp_bt_controller_enable
+ *
+ * Description:
+ *   Enable BT controller.
+ *
+ * Input Parameters:
+ *   mode - the mode(BLE/BT/BTDM) to enable. For compatible of API, retain
+ *   this argument. This mode must be equal as the mode in "cfg" of
+ *   esp_bt_controller_init().
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned
+ *   on failure.
+ *
+ ****************************************************************************/
+
+int esp_bt_controller_enable(esp_bt_mode_t mode);
+
+/****************************************************************************
+ * Name: esp_bt_controller_disable
+ *
+ * Description:
+ *   Disable BT controller.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned
+ *   on failure.
+ *
+ ****************************************************************************/
+
+int esp_bt_controller_disable(void);
+
+/****************************************************************************
+ * Name: esp_bt_controller_get_status
+ *
+ * Description:
+ *   Enable BT controller.
+ *
+ * Input Parameters:
+ *   mode - the mode(BLE/BT/BTDM) to enable. For compatible of API, retain
+ *   this argument. This mode must be equal as the mode in "cfg" of
+ *   esp_bt_controller_init().
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned
+ *   on failure.
+ *
+ ****************************************************************************/
+
+esp_bt_controller_status_t esp_bt_controller_get_status(void);
+
+/****************************************************************************
+ * Name: esp_vhci_host_check_send_available
+ *
+ * Description:
+ *   Check if the host can send packet to controller or not.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   True if returned on success. Otherwise, false is returned.
+ *
+ ****************************************************************************/
+
+bool esp_vhci_host_check_send_available(void);
+
+/****************************************************************************
+ * Name: esp_vhci_host_send_packet
+ *
+ * Description:
+ *   Host send packet to controller.
+ *
+ * Input Parameters:
+ *   data - the packet pointer
+ *   len  - the packet length
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp_vhci_host_send_packet(uint8_t *data, uint16_t len);
+
+/****************************************************************************
+ * Name: esp_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 esp_vhci_register_callback(const esp_vhci_host_callback_t *callback);
+
+#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP_BLE_ADAPTER_H */
diff --git a/arch/risc-v/src/esp32c3/esp_wireless.c b/arch/risc-v/src/esp32c3/esp_wireless.c
new file mode 100644
index 0000000000..b64d2d21a0
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp_wireless.c
@@ -0,0 +1,370 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp_wireless.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/mqueue.h>
+
+#include <debug.h>
+#include <assert.h>
+#include <netinet/in.h>
+#include <sys/param.h>
+
+#include "soc/system_reg.h"
+#include "espressif/esp_irq.h"
+#include "riscv_internal.h"
+#include "esp_private/phy.h"
+#include "espressif/esp_hr_timer.h"
+
+#include "esp_private/phy.h"
+
+#include "periph_ctrl.h"
+#include "esp_phy_init.h"
+#include "phy_init_data.h"
+
+#include "esp_wireless.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Software Interrupt */
+
+#define SWI_IRQ       ESP_IRQ_FROM_CPU_INTR0
+#define SWI_PERIPH    FROM_CPU_INTR0_SOURCE
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* Wireless Private Data */
+
+struct esp_wireless_priv_s
+{
+  volatile int ref;               /* Reference count */
+
+  int cpuint;                     /* CPU interrupt assigned to SWI */
+
+  struct list_node sc_list;       /* Semaphore cache list */
+  struct list_node qc_list;       /* Queue cache list */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int esp_swi_irq(int irq, void *context, void *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Private data of the wireless common interface */
+
+static struct esp_wireless_priv_s g_esp_wireless_priv;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_swi_irq
+ *
+ * Description:
+ *   Wireless software interrupt callback function.
+ *
+ * Parameters:
+ *   cpuint  - CPU interrupt index
+ *   context - Context data from the ISR
+ *   arg     - NULL
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned on
+ *   failure.
+ *
+ ****************************************************************************/
+
+static int esp_swi_irq(int irq, void *context, void *arg)
+{
+  int i;
+  int ret;
+  struct esp_semcache_s *sc;
+  struct esp_semcache_s *sc_tmp;
+  struct esp_queuecache_s *qc;
+  struct esp_queuecache_s *qc_tmp;
+  struct esp_wireless_priv_s *priv = &g_esp_wireless_priv;
+
+  putreg32(0, SYSTEM_CPU_INTR_FROM_CPU_0_REG);
+
+  list_for_every_entry_safe(&priv->sc_list, sc, sc_tmp,
+                            struct esp_semcache_s, node)
+    {
+      for (i = 0; i < sc->count; i++)
+        {
+          ret = nxsem_post(sc->sem);
+          if (ret < 0)
+            {
+              wlerr("ERROR: Failed to post sem ret=%d\n", ret);
+            }
+        }
+
+      sc->count = 0;
+      list_delete(&sc->node);
+    }
+
+  list_for_every_entry_safe(&priv->qc_list, qc, qc_tmp,
+                            struct esp_queuecache_s, node)
+    {
+      ret = file_mq_send(qc->mq_ptr, (const char *)qc->buffer, qc->size, 0);
+      if (ret < 0)
+        {
+          wlerr("ERROR: Failed to send queue ret=%d\n", ret);
+        }
+
+      list_delete(&qc->node);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_init_semcache
+ *
+ * Description:
+ *   Initialize semaphore cache.
+ *
+ * Parameters:
+ *   sc  - Semaphore cache data pointer
+ *   sem - Semaphore data pointer
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void esp_init_semcache(struct esp_semcache_s *sc, sem_t *sem)
+{
+  sc->sem   = sem;
+  sc->count = 0;
+  list_initialize(&sc->node);
+}
+
+/****************************************************************************
+ * Name: esp_post_semcache
+ *
+ * Description:
+ *   Store posting semaphore action into semaphore cache.
+ *
+ * Parameters:
+ *   sc  - Semaphore cache data pointer
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+IRAM_ATTR void esp_post_semcache(struct esp_semcache_s *sc)
+{
+  struct esp_wireless_priv_s *priv = &g_esp_wireless_priv;
+
+  if (!sc->count)
+    {
+      list_add_tail(&priv->sc_list, &sc->node);
+    }
+
+  sc->count++;
+
+  /* Enable CPU interrupt. This will generate an IRQ as soon as non-IRAM
+   * are (re)enabled.
+   */
+
+  putreg32(SYSTEM_CPU_INTR_FROM_CPU_0_M, SYSTEM_CPU_INTR_FROM_CPU_0_REG);
+}
+
+/****************************************************************************
+ * Name: esp_init_queuecache
+ *
+ * Description:
+ *   Initialize queue cache.
+ *
+ * Parameters:
+ *   qc     - Queue cache data pointer
+ *   mq_ptr - Queue data pointer
+ *   buffer - Queue cache buffer pointer
+ *   size   - Queue cache buffer size
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void esp_init_queuecache(struct esp_queuecache_s *qc,
+                         struct file *mq_ptr,
+                         uint8_t *buffer,
+                         size_t size)
+{
+  qc->mq_ptr = mq_ptr;
+  qc->size   = size;
+  qc->buffer = buffer;
+  list_initialize(&qc->node);
+}
+
+/****************************************************************************
+ * Name: esp_send_queuecache
+ *
+ * Description:
+ *   Store posting queue action and data into queue cache.
+ *
+ * Parameters:
+ *   qc     - Queue cache data pointer
+ *   buffer - Data buffer
+ *   size   - Buffer size
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+IRAM_ATTR void esp_send_queuecache(struct esp_queuecache_s *qc,
+                                   uint8_t *buffer,
+                                   int size)
+{
+  struct esp_wireless_priv_s *priv = &g_esp_wireless_priv;
+
+  DEBUGASSERT(qc->size == size);
+
+  list_add_tail(&priv->qc_list, &qc->node);
+  memcpy(qc->buffer, buffer, size);
+
+  /* Enable CPU 0 interrupt. This will generate an IRQ as soon as non-IRAM
+   * are (re)enabled.
+   */
+
+  putreg32(SYSTEM_CPU_INTR_FROM_CPU_0_M, SYSTEM_CPU_INTR_FROM_CPU_0_REG);
+}
+
+/****************************************************************************
+ * Name: esp_wireless_init
+ *
+ * Description:
+ *   Initialize ESP32-C3 wireless common components for both BT and Wi-Fi.
+ *
+ * Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned on
+ *   failure.
+ *
+ ****************************************************************************/
+
+int esp_wireless_init(void)
+{
+  int ret;
+  irqstate_t flags;
+  struct esp_wireless_priv_s *priv = &g_esp_wireless_priv;
+
+  flags = enter_critical_section();
+  if (priv->ref != 0)
+    {
+      priv->ref++;
+      leave_critical_section(flags);
+      return OK;
+    }
+
+  priv->cpuint = esp_setup_irq(SWI_PERIPH, ESP_IRQ_PRIORITY_DEFAULT, 0);
+  if (priv->cpuint < 0)
+    {
+      /* Failed to allocate a CPU interrupt of this type. */
+
+      wlerr("ERROR: Failed to attach IRQ ret=%d\n", ret);
+      ret = priv->cpuint;
+      leave_critical_section(flags);
+
+      return ret;
+    }
+
+  ret = irq_attach(SWI_IRQ, esp_swi_irq, NULL);
+  if (ret < 0)
+    {
+      esp_teardown_irq(SWI_PERIPH, priv->cpuint);
+      leave_critical_section(flags);
+      wlerr("ERROR: Failed to attach IRQ ret=%d\n", ret);
+
+      return ret;
+    }
+
+  list_initialize(&priv->sc_list);
+  list_initialize(&priv->qc_list);
+
+  up_enable_irq(SWI_IRQ);
+
+  priv->ref++;
+
+  leave_critical_section(flags);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: esp_wireless_deinit
+ *
+ * Description:
+ *   De-initialize ESP32-C3 wireless common components.
+ *
+ * Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned on
+ *   failure.
+ *
+ ****************************************************************************/
+
+int esp_wireless_deinit(void)
+{
+  irqstate_t flags;
+  struct esp_wireless_priv_s *priv = &g_esp_wireless_priv;
+
+  flags = enter_critical_section();
+
+  if (priv->ref > 0)
+    {
+      priv->ref--;
+      if (priv->ref == 0)
+        {
+          up_disable_irq(SWI_IRQ);
+          irq_detach(SWI_IRQ);
+          esp_teardown_irq(SWI_PERIPH, priv->cpuint);
+        }
+    }
+
+  leave_critical_section(flags);
+
+  return OK;
+}
diff --git a/arch/risc-v/src/esp32c3/esp_wireless.h b/arch/risc-v/src/esp32c3/esp_wireless.h
new file mode 100644
index 0000000000..b2b74d60d9
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp_wireless.h
@@ -0,0 +1,198 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp_wireless.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_XTENSA_SRC_ESP32C3_ESP_WIRELESS_H
+#define __ARCH_XTENSA_SRC_ESP32C3_ESP_WIRELESS_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <semaphore.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <nuttx/config.h>
+#include <nuttx/list.h>
+
+#include "esp_attr.h"
+
+#include "esp_log.h"
+#include "esp_mac.h"
+#include "esp_private/phy.h"
+#include "esp_private/wifi.h"
+#include "esp_random.h"
+#include "esp_timer.h"
+#include "rom/ets_sys.h"
+#include "soc/soc_caps.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Note: Don't remove these definitions, they are needed by the 3rdparty IDF
+ * headers
+ */
+
+#define CONFIG_MAC_BB_PD                              (0)
+#define MAC_LEN                                       (6)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Semaphore Cache Data */
+
+struct esp_semcache_s
+{
+  struct list_node node;
+
+  sem_t *sem;
+  uint32_t count;
+};
+
+/* Queue Cache Data */
+
+struct esp_queuecache_s
+{
+  struct list_node node;
+
+  struct file *mq_ptr;
+  size_t size;
+  uint8_t *buffer;
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Functions needed by libphy.a
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_init_semcache
+ *
+ * Description:
+ *   Initialize semaphore cache.
+ *
+ * Parameters:
+ *   sc  - Semaphore cache data pointer
+ *   sem - Semaphore data pointer
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void esp_init_semcache(struct esp_semcache_s *sc, sem_t *sem);
+
+/****************************************************************************
+ * Name: esp_post_semcache
+ *
+ * Description:
+ *   Store posting semaphore action into semaphore cache.
+ *
+ * Parameters:
+ *   sc  - Semaphore cache data pointer
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void esp_post_semcache(struct esp_semcache_s *sc);
+
+/****************************************************************************
+ * Name: esp_init_queuecache
+ *
+ * Description:
+ *   Initialize queue cache.
+ *
+ * Parameters:
+ *   qc     - Queue cache data pointer
+ *   mq_ptr - Queue data pointer
+ *   buffer - Queue cache buffer pointer
+ *   size   - Queue cache buffer size
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void esp_init_queuecache(struct esp_queuecache_s *qc,
+                         struct file *mq_ptr,
+                         uint8_t *buffer,
+                         size_t size);
+
+/****************************************************************************
+ * Name: esp32_wl_send_queuecache
+ *
+ * Description:
+ *   Store posting queue action and data into queue cache.
+ *
+ * Parameters:
+ *   qc     - Queue cache data pointer
+ *   buffer - Data buffer
+ *   size   - Buffer size
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void esp_send_queuecache(struct esp_queuecache_s *qc,
+                         uint8_t *buffer,
+                         int size);
+
+/****************************************************************************
+ * Name: esp_wireless_init
+ *
+ * Description:
+ *   Initialize ESP32 wireless common components for both BT and Wi-Fi.
+ *
+ * Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned on
+ *   failure.
+ *
+ ****************************************************************************/
+
+int esp_wireless_init(void);
+
+/****************************************************************************
+ * Name: esp_wireless_deinit
+ *
+ * Description:
+ *   De-initialize ESP32 wireless common components.
+ *
+ * Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned on
+ *   failure.
+ *
+ ****************************************************************************/
+
+int esp_wireless_deinit(void);
+
+#endif /* __ARCH_XTENSA_SRC_ESP32C3_ESP_WIRELESS_H */
diff --git a/boards/risc-v/esp32c3/common/scripts/esp32c3_flat_memory.ld b/boards/risc-v/esp32c3/common/scripts/esp32c3_flat_memory.ld
index 2ae8fa2d8f..e308f85da1 100644
--- a/boards/risc-v/esp32c3/common/scripts/esp32c3_flat_memory.ld
+++ b/boards/risc-v/esp32c3/common/scripts/esp32c3_flat_memory.ld
@@ -30,6 +30,7 @@
  ****************************************************************************/
 
 #include "common.ld"
+#include "esp32c3_aliases.ld"
 
 #define SRAM_IRAM_START     0x4037c000
 #define SRAM_DRAM_START     0x3fc7c000
diff --git a/boards/risc-v/esp32c3/esp32c3-generic/configs/ble/defconfig b/boards/risc-v/esp32c3/esp32c3-generic/configs/ble/defconfig
new file mode 100644
index 0000000000..78d12364c5
--- /dev/null
+++ b/boards/risc-v/esp32c3/esp32c3-generic/configs/ble/defconfig
@@ -0,0 +1,67 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+CONFIG_ALLOW_BSD_COMPONENTS=y
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_BOARD="esp32c3-generic"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_ESP32C3_GENERIC=y
+CONFIG_ARCH_CHIP="esp32c3"
+CONFIG_ARCH_CHIP_ESP32C3_GENERIC=y
+CONFIG_ARCH_INTERRUPTSTACK=1536
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LOOPSPERMSEC=15000
+CONFIG_BTSAK=y
+CONFIG_BUILTIN=y
+CONFIG_DEV_ZERO=y
+CONFIG_DRIVERS_BLUETOOTH=y
+CONFIG_DRIVERS_IEEE80211=y
+CONFIG_DRIVERS_WIRELESS=y
+CONFIG_ESPRESSIF_BLE=y
+CONFIG_FS_PROCFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_NAME_MAX=48
+CONFIG_NETDEV_LATEINIT=y
+CONFIG_NET_BLUETOOTH=y
+CONFIG_NET_SOCKOPTS=y
+CONFIG_NET_TCP=y
+CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_DISABLE_DATE=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_NSH_STRERROR=y
+CONFIG_PREALLOC_MQ_MSGS=32
+CONFIG_PREALLOC_TIMERS=0
+CONFIG_PTHREAD_MUTEX_TYPES=y
+CONFIG_RR_INTERVAL=200
+CONFIG_RTC_ALARM=y
+CONFIG_SCHED_BACKTRACE=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_SIG_DEFAULT=y
+CONFIG_START_DAY=29
+CONFIG_START_MONTH=11
+CONFIG_START_YEAR=2019
+CONFIG_SYSTEM_DUMPSTACK=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_TESTING_GETPRIME=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_BLUETOOTH=y
diff --git a/boards/risc-v/esp32c3/esp32c3-generic/src/esp32c3_bringup.c b/boards/risc-v/esp32c3/esp32c3-generic/src/esp32c3_bringup.c
index af3e766898..134427f3b0 100644
--- a/boards/risc-v/esp32c3/esp32c3-generic/src/esp32c3_bringup.c
+++ b/boards/risc-v/esp32c3/esp32c3-generic/src/esp32c3_bringup.c
@@ -84,6 +84,10 @@
 #  include "esp_board_wlan.h"
 #endif
 
+#ifdef CONFIG_ESPRESSIF_BLE
+#  include "esp_ble.h"
+#endif
+
 #ifdef CONFIG_SPI_SLAVE_DRIVER
 #  include "espressif/esp_spi.h"
 #  include "esp_board_spislavedev.h"
@@ -232,6 +236,25 @@ int esp_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_RTC_DRIVER
+  /* Initialize the RTC driver */
+
+  ret = esp_rtc_driverinit();
+  if (ret < 0)
+    {
+      _err("Failed to initialize the RTC driver: %d\n", ret);
+    }
+#endif
+
+#ifdef CONFIG_ESPRESSIF_BLE
+  ret = esp_ble_initialize();
+  if (ret)
+    {
+      syslog(LOG_ERR, "ERROR: Failed to initialize BLE\n");
+      return ret;
+    }
+#endif
+
 #if defined(CONFIG_SPI_SLAVE_DRIVER) && defined(CONFIG_ESPRESSIF_SPI2)
   ret = board_spislavedev_initialize(ESPRESSIF_SPI2);
   if (ret < 0)
@@ -263,16 +286,6 @@ int esp_bringup(void)
     }
 #endif
 
-#ifdef CONFIG_RTC_DRIVER
-  /* Initialize the RTC driver */
-
-  ret = esp_rtc_driverinit();
-  if (ret < 0)
-    {
-      _err("Failed to initialize the RTC driver: %d\n", ret);
-    }
-#endif
-
 #if defined(CONFIG_I2C_DRIVER)
   /* Configure I2C peripheral interfaces */