You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gu...@apache.org on 2021/10/04 18:10:43 UTC

[incubator-nuttx] branch master updated: esp32: Add initial support to Bluetooth Low Energy

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 867c6d0  esp32: Add initial support to Bluetooth Low Energy
867c6d0 is described below

commit 867c6d0636c105781107fc0a46a411dd69f5a607
Author: Alan C. Assis <ac...@gmail.com>
AuthorDate: Fri Sep 10 10:36:11 2021 -0300

    esp32: Add initial support to Bluetooth Low Energy
    
    Co-authored-by: saramonteiro <sa...@gmail.com>
    Co-authored-by: Gustavo Henrique Nihei <gu...@gmail.com>
---
 arch/xtensa/include/esp32/irq.h                    |    2 +-
 arch/xtensa/src/esp32/Kconfig                      |   41 +-
 arch/xtensa/src/esp32/Make.defs                    |    7 +-
 arch/xtensa/src/esp32/esp32_allocateheap.c         |    2 +-
 arch/xtensa/src/esp32/esp32_ble.c                  |  346 +++
 arch/xtensa/src/esp32/esp32_ble.h                  |   50 +
 arch/xtensa/src/esp32/esp32_ble_adapter.c          | 2953 ++++++++++++++++++++
 arch/xtensa/src/esp32/esp32_ble_adapter.h          |  200 ++
 arch/xtensa/src/esp32/esp32_irq.c                  |   29 +-
 arch/xtensa/src/esp32/esp32_wifi_adapter.c         |   21 +-
 arch/xtensa/src/esp32/esp32_wifi_adapter.h         |    1 +
 arch/xtensa/src/esp32/hardware/esp32_dport.h       |    3 +-
 boards/xtensa/esp32/common/scripts/esp32.ld        |   20 +
 .../xtensa/esp32/common/scripts/esp32.template.ld  |    1 +
 .../xtensa/esp32/common/scripts/esp32_aliases.ld   |   31 +
 boards/xtensa/esp32/common/scripts/esp32_rom.ld    |  192 +-
 .../esp32/esp32-devkitc/configs/ble/defconfig      |   60 +
 boards/xtensa/esp32/esp32-devkitc/src/Make.defs    |    2 +-
 .../xtensa/esp32/esp32-devkitc/src/esp32_bringup.c |   12 +
 .../esp32/esp32-ethernet-kit/src/esp32_bringup.c   |   12 +
 .../esp32/esp32-wrover-kit/src/esp32_bringup.c     |   12 +
 .../esp32/ttgo_lora_esp32/src/esp32_bringup.c      |   12 +
 22 files changed, 3999 insertions(+), 10 deletions(-)

diff --git a/arch/xtensa/include/esp32/irq.h b/arch/xtensa/include/esp32/irq.h
index 66d330f..f85eccb 100644
--- a/arch/xtensa/include/esp32/irq.h
+++ b/arch/xtensa/include/esp32/irq.h
@@ -396,7 +396,7 @@
 
 #define ESP32_NCPUINTS              32
 #define ESP32_CPUINT_MAX            (ESP32_NCPUINTS - 1)
-#define ESP32_CPUINT_PERIPHSET      0xdffe773f
+#define ESP32_CPUINT_PERIPHSET      0xdffe741f
 #define ESP32_CPUINT_INTERNALSET    0x200188c0
 
 /* Priority 1:   0-10, 12-13, 17-18    (15)
diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig
index 204cca9..6b2e60d 100644
--- a/arch/xtensa/src/esp32/Kconfig
+++ b/arch/xtensa/src/esp32/Kconfig
@@ -509,6 +509,13 @@ config ESP32_WIRELESS
 	---help---
 		Enable Wireless support
 
+config ESP32_BLE
+	bool "BLE"
+	default n
+	select ESP32_WIRELESS
+	---help---
+		Enable BLE support
+
 config ESP32_I2C0
 	bool "I2C 0"
 	default n
@@ -525,11 +532,16 @@ config ESP32_AES_ACCELERATOR
 
 endmenu # ESP32 Peripheral Selection
 
+menuconfig ESP32_WIFI_BT_COEXIST
+	bool "Wi-Fi and BT coexist"
+	default n
+	depends on ESP32_WIRELESS && ESP32_BLE
+
 menu "Memory Configuration"
 
 config ESP32_BT_RESERVE_DRAM
 	int "Reserved BT DRAM"
-	default 0
+	default 65536
 
 config ESP32_TRACEMEM_RESERVE_DRAM
 	int "Reserved trace memory DRAM"
@@ -1170,6 +1182,33 @@ endchoice
 
 endmenu # ESP32_WIRELESS
 
+menu "BLE Configuration"
+	depends on ESP32_BLE
+
+config ESP32_BLE_PKTBUF_NUM
+	int "BLE netcard packet buffer number per netcard"
+	default 16
+
+config ESP32_BLE_TTY_NAME
+	string "BLE TTY device name"
+	default "/dev/ttyHCI0"
+	depends on UART_BTH4
+
+config ESP32_BLE_TASK_STACK_SIZE
+	int "Controller task stack size"
+	default 4096
+
+config ESP32_BLE_TASK_PRIORITY
+	int "Controller task priority"
+	default 110
+
+config ESP32_BLE_MAX_CONN
+	int "Maximum BLE simultaneous connections"
+	range 1 3
+	default 1
+
+endmenu # BLE Configuration
+
 menu "Real-Time Timer"
 	depends on ESP32_RT_TIMER
 
diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs
index 9ac87e3..da00928 100644
--- a/arch/xtensa/src/esp32/Make.defs
+++ b/arch/xtensa/src/esp32/Make.defs
@@ -231,7 +231,12 @@ INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wire
 CHIP_CSRCS += esp32_wlan.c esp32_wifi_utils.c esp32_wifi_adapter.c
 
 EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)libs$(DELIM)esp32
-EXTRA_LIBS += -lcore -lrtc -lnet80211 -lpp -lsmartconfig -lcoexist -lespnow -lphy -lwpa_supplicant
+EXTRA_LIBS += -lcore -lrtc -lnet80211 -lpp -lsmartconfig -lespnow -lphy -lwpa_supplicant
+
+ifeq ($(CONFIG_ESP32_BLE),y)
+CHIP_CSRCS += esp32_ble_adapter.c esp32_ble.c
+EXTRA_LIBS += -lbtdm_app -lcoexist
+endif
 
 # Due to some Wi-Fi related libraries, the option is need to avoid linking too much
 # unused functions.
diff --git a/arch/xtensa/src/esp32/esp32_allocateheap.c b/arch/xtensa/src/esp32/esp32_allocateheap.c
index a43ae4e..7757512 100644
--- a/arch/xtensa/src/esp32/esp32_allocateheap.c
+++ b/arch/xtensa/src/esp32/esp32_allocateheap.c
@@ -133,7 +133,7 @@ void xtensa_add_region(void)
 #endif
 #endif
 
-#ifndef CONFIG_ESP32_QEMU_IMAGE
+#if !defined(CONFIG_ESP32_QEMU_IMAGE) && !defined(CONFIG_ESP32_BLE)
   start = (void *)HEAP_REGION0_START;
   size  = (size_t)(HEAP_REGION0_END - HEAP_REGION0_START);
   umm_addregion(start, size);
diff --git a/arch/xtensa/src/esp32/esp32_ble.c b/arch/xtensa/src/esp32/esp32_ble.c
new file mode 100644
index 0000000..e6cb85d
--- /dev/null
+++ b/arch/xtensa/src/esp32/esp32_ble.c
@@ -0,0 +1,346 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32/esp32_ble.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+
+#include <sys/socket.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <queue.h>
+#include <debug.h>
+
+#include <nuttx/nuttx.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/net/bluetooth.h>
+#include <nuttx/wireless/bluetooth/bt_driver.h>
+#include <nuttx/wireless/bluetooth/bt_uart.h>
+
+#if defined(CONFIG_UART_BTH4)
+  #include <nuttx/serial/uart_bth4.h>
+#endif
+
+#include "esp32_ble_adapter.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* BLE packet buffer max number */
+
+#define BLE_BUF_NUM       CONFIG_ESP32_BLE_PKTBUF_NUM
+
+/* BLE packet buffer max size */
+
+#define BLE_BUF_SIZE      1024
+
+/* Low-priority work queue process RX/TX */
+
+#define BLE_WORK          LPWORK
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct esp32_ble_priv_s
+{
+  struct bt_driver_s drv;         /* NuttX BT/BLE driver data */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int esp32_ble_open(struct bt_driver_s *drv);
+static int esp32_ble_send(struct bt_driver_s *drv,
+                          enum bt_buf_type_e type,
+                          void *data, size_t len);
+static void esp32_ble_close(struct bt_driver_s *drv);
+
+static void esp32_ble_send_ready(void);
+static int esp32_ble_recv_cb(uint8_t *data, uint16_t len);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct esp32_ble_priv_s g_ble_priv =
+{
+  .drv =
+    {
+      .head_reserve = H4_HEADER_SIZE,
+      .open         = esp32_ble_open,
+      .send         = esp32_ble_send,
+      .close        = esp32_ble_close
+    }
+};
+
+static esp_vhci_host_callback_t vhci_host_cb =
+{
+  .notify_host_send_available = esp32_ble_send_ready,
+  .notify_host_recv           = esp32_ble_recv_cb
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32_ble_send_ready
+ *
+ * Description:
+ *   If the controller could send an HCI command, this function is called.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void esp32_ble_send_ready(void)
+{
+}
+
+/****************************************************************************
+ * Name: esp32_ble_recv_cb
+ *
+ * Description:
+ *   BLE receive callback function when BLE hardware receives a 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 esp32_ble_recv_cb(uint8_t *data, uint16_t len)
+{
+  int ret;
+  bool valid;
+  enum bt_buf_type_e type;
+  struct esp32_ble_priv_s *priv = &g_ble_priv;
+
+  wlinfo("len = %d\n", len);
+  wlinfo("host recv pkt: ");
+  for (uint16_t i = 0; i < len; i++)
+    {
+      wlinfo("%02x\n", data[i]);
+    }
+
+  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)
+    {
+      wlerr("Invalid H4 header \n");
+      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: esp32_ble_send
+ *
+ * Description:
+ *   ESP32 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 esp32_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 -EOVERFLOW;
+    }
+
+  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
+    {
+      wlerr("Unknown BT packet type 0x%x\n", type);
+      return -EINVAL;
+    }
+
+  if (esp32_vhci_host_check_send_available())
+    {
+      esp32_vhci_host_send_packet(hdr, len + drv->head_reserve);
+    }
+
+  return len;
+}
+
+/****************************************************************************
+ * Name: esp32_ble_close
+ *
+ * Description:
+ *   ESP32-C3 BLE close callback function for BT driver.
+ *
+ * Input Parameters:
+ *   drv  - BT driver pointer
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void esp32_ble_close(struct bt_driver_s *drv)
+{
+}
+
+/****************************************************************************
+ * Name: esp32_ble_open
+ *
+ * Description:
+ *   ESP32-C3 BLE open callback function for BT driver.
+ *
+ * Input Parameters:
+ *   drv - BT driver pointer
+ *
+ * Returned Value:
+ *   OK
+ *
+ ****************************************************************************/
+
+static int esp32_ble_open(struct bt_driver_s *drv)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32_ble_initialize
+ *
+ * Description:
+ *   Init BT controller
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   OK on success or a negated value on failure.
+ *
+ ****************************************************************************/
+
+int esp32_ble_initialize(void)
+{
+  int ret;
+
+  ret = esp32_bt_controller_init();
+  if (ret)
+    {
+      wlerr("Failed to initialize BLE ret=%d\n", ret);
+      return ERROR;
+    }
+
+  ret = esp32_bt_controller_enable(ESP_BT_MODE_BLE);
+  if (ret)
+    {
+      wlerr("Failed to Enable BLE ret=%d\n", ret);
+      return ERROR;
+    }
+
+  ret = esp32_vhci_register_callback(&vhci_host_cb);
+  if (ret)
+    {
+      wlerr("Failed to register BLE callback ret=%d\n", ret);
+      return ERROR;
+    }
+
+#if defined(CONFIG_UART_BTH4)
+  ret = uart_bth4_register(CONFIG_BT_UART_ON_DEV_NAME, &g_ble_priv.drv);
+#else
+  ret = bt_netdev_register(&g_ble_priv.drv);
+#endif
+  if (ret < 0)
+    {
+      wlerr("bt_netdev_register or uart_bth4_register error: %d\n", ret);
+      return ret;
+    }
+
+  return OK;
+}
diff --git a/arch/xtensa/src/esp32/esp32_ble.h b/arch/xtensa/src/esp32/esp32_ble.h
new file mode 100644
index 0000000..736edc5
--- /dev/null
+++ b/arch/xtensa/src/esp32/esp32_ble.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32/esp32_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_XTENSA_SRC_ESP32_ESP32_BLE_H
+#define __ARCH_XTENSA_SRC_ESP32_ESP32_BLE_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32_ble_initialize
+ *
+ * Description:
+ *   Init BT controller
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   success or fail
+ *
+ ****************************************************************************/
+
+int esp32_ble_initialize(void);
+
+#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_BLE_H */
diff --git a/arch/xtensa/src/esp32/esp32_ble_adapter.c b/arch/xtensa/src/esp32/esp32_ble_adapter.c
new file mode 100644
index 0000000..ad25f82
--- /dev/null
+++ b/arch/xtensa/src/esp32/esp32_ble_adapter.c
@@ -0,0 +1,2953 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32/esp32_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 <irq/irq.h>
+
+#include "hardware/esp32_dport.h"
+#include "espidf_wifi.h"
+#include "xtensa.h"
+#include "xtensa_attr.h"
+#include "esp32_rt_timer.h"
+#include "esp32_ble_adapter.h"
+
+#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
+#  include "esp_coexist_internal.h"
+#  include "esp_coexist_adapter.h"
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+typedef void (*xt_handler)(void *);
+typedef void (*coex_func_cb_t)(uint32_t event, int sched_cnt);
+
+#define XTHAL_SET_INTSET(v) \
+do {\
+  int __interrupt = (int)(v);\
+  __asm__ __volatile__("wsr.intset %0" :: "a"(__interrupt):"memory");\
+} while(0)
+
+#define MSG_QUEUE_NAME_SIZE    16
+
+#define ESP_ERR_INVALID_STATE       0x103
+
+#define OSI_FUNCS_TIME_BLOCKING          0xffffffff
+#define OSI_VERSION                      0x00010002
+#define OSI_MAGIC_VALUE                  0xfadebead
+
+#define BTDM_ASYNC_WAKEUP_REQ_HCI   0
+#define BTDM_ASYNC_WAKEUP_REQ_COEX  1
+#define BTDM_ASYNC_WAKEUP_REQMAX    2
+
+#ifdef CONFIG_PM
+#define BTDM_MIN_TIMER_UNCERTAINTY_US    (1800)
+
+/* 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)
+
+/* 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 */
+#endif
+
+#define BTDM_MODEM_SLEEP_MODE_NONE 0
+
+#define ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL  0x20200622
+
+extern void btdm_controller_set_sleep_mode(uint8_t mode);
+
+#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
+extern void coex_pti_v2(void);
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* Number of fractional bits in values returned by rtc_clk_cal */
+
+#define RTC_CLK_CAL_FRACT  19
+
+/* BLE message queue private data */
+
+struct mq_adpt_s
+{
+  struct file mq;                        /* Message queue handle */
+  uint32_t    msgsize;                   /* Message size */
+  char        name[MSG_QUEUE_NAME_SIZE]; /* Message queue name */
+};
+
+/* BLE interrupt adapter private data */
+
+struct irq_adpt_s
+{
+  void (*func)(void *arg);  /* Interrupt callback function */
+  void *arg;                /* Interrupt private data */
+};
+
+/* BLE low power control struct */
+
+typedef struct btdm_lpcntl_s
+{
+  bool enable;                  /* whether low power mode is required */
+  bool lpclk_sel;               /* low power clock source */
+  bool mac_bb_pd;               /* whether hardware(MAC, BB) force-power-down is required during sleep */
+  bool wakeup_timer_required;   /* whether system timer is needed */
+  bool no_light_sleep;          /* do not allow system to enter light sleep after bluetooth is enabled */
+} btdm_lpcntl_t;
+
+/* low power control status */
+
+typedef struct btdm_lpstat_s
+{
+  bool pm_lock_released;        /* whether power management lock is released */
+  bool mac_bb_pd;               /* whether hardware(MAC, BB) is powered down */
+  bool phy_enabled;             /* whether phy is switched on */
+  bool wakeup_timer_started;    /* whether wakeup timer is started */
+} btdm_lpstat_t;
+
+/* vendor dependent signals to be posted to controller task */
+
+typedef enum
+{
+  BTDM_VND_OL_SIG_WAKEUP_TMR,
+  BTDM_VND_OL_SIG_NUM,
+} btdm_vnd_ol_sig_t;
+
+#ifdef CONFIG_PM
+/* wakeup request sources */
+
+typedef enum
+{
+  BTDM_ASYNC_WAKEUP_SRC_VHCI,
+  BTDM_ASYNC_WAKEUP_SRC_DISA,
+  BTDM_ASYNC_WAKEUP_SRC_TMR,
+  BTDM_ASYNC_WAKEUP_SRC_MAX,
+} btdm_wakeup_src_t;
+#endif
+
+typedef enum
+{
+  PERIPH_LEDC_MODULE = 0,
+  PERIPH_UART0_MODULE,
+  PERIPH_UART1_MODULE,
+  PERIPH_UART2_MODULE,
+  PERIPH_I2C0_MODULE,
+  PERIPH_I2C1_MODULE,
+  PERIPH_I2S0_MODULE,
+  PERIPH_I2S1_MODULE,
+  PERIPH_TIMG0_MODULE,
+  PERIPH_TIMG1_MODULE,
+  PERIPH_PWM0_MODULE,
+  PERIPH_PWM1_MODULE,
+  PERIPH_PWM2_MODULE,
+  PERIPH_PWM3_MODULE,
+  PERIPH_UHCI0_MODULE,
+  PERIPH_UHCI1_MODULE,
+  PERIPH_RMT_MODULE,
+  PERIPH_PCNT_MODULE,
+  PERIPH_SPI_MODULE,
+  PERIPH_HSPI_MODULE,
+  PERIPH_VSPI_MODULE,
+  PERIPH_SPI_DMA_MODULE,
+  PERIPH_SDMMC_MODULE,
+  PERIPH_SDIO_SLAVE_MODULE,
+  PERIPH_CAN_MODULE,
+  PERIPH_EMAC_MODULE,
+  PERIPH_RNG_MODULE,
+  PERIPH_WIFI_MODULE,
+  PERIPH_BT_MODULE,
+  PERIPH_WIFI_BT_COMMON_MODULE,
+  PERIPH_BT_BASEBAND_MODULE,
+  PERIPH_BT_LC_MODULE,
+  PERIPH_AES_MODULE,
+  PERIPH_SHA_MODULE,
+  PERIPH_RSA_MODULE,
+} periph_module_e;
+
+/* prototype of function to handle vendor dependent signals */
+
+typedef void (*btdm_vnd_ol_task_func_t)(void *param);
+
+/* VHCI function interface */
+
+typedef struct vhci_host_callback_s
+{
+  void (*notify_host_send_available)(void);               /* callback used to notify that the host can send packet to controller */
+  int (*notify_host_recv)(uint8_t *data, uint16_t len);   /* callback used to notify that the controller has a packet to send to the host */
+} vhci_host_callback_t;
+
+/* DRAM region */
+
+typedef struct btdm_dram_available_region_s
+{
+  esp_bt_mode_t mode;
+  intptr_t start;
+  intptr_t end;
+} btdm_dram_available_region_t;
+
+typedef void (*osi_intr_handler)(void);
+
+/* BLE OS function */
+
+struct osi_funcs_s
+{
+    uint32_t _version;
+    xt_handler (*_set_isr)(int n, xt_handler f, void *arg);
+    void (*_ints_on)(unsigned int mask);
+    void (*_interrupt_disable)(void);
+    void (*_interrupt_restore)(void);
+    void (*_task_yield)(void);
+    void (*_task_yield_from_isr)(void);
+    void *(*_semphr_create)(uint32_t max, uint32_t init);
+    void (*_semphr_delete)(void *semphr);
+    int32_t (*_semphr_take_from_isr)(void *semphr, void *hptw);
+    int32_t (*_semphr_give_from_isr)(void *semphr, void *hptw);
+    int32_t (*_semphr_take)(void *semphr, uint32_t block_time_ms);
+    int32_t (*_semphr_give)(void *semphr);
+    void *(*_mutex_create)(void);
+    void (*_mutex_delete)(void *mutex);
+    int32_t (*_mutex_lock)(void *mutex);
+    int32_t (*_mutex_unlock)(void *mutex);
+    void *(* _queue_create)(uint32_t queue_len, uint32_t item_size);
+    void (* _queue_delete)(void *queue);
+    int32_t (* _queue_send)(void *queue, void *item, uint32_t block_time_ms);
+    int32_t (* _queue_send_from_isr)(void *queue, void *item, void *hptw);
+    int32_t (* _queue_recv)(void *queue, void *item, uint32_t block_time_ms);
+    int32_t (* _queue_recv_from_isr)(void *queue, void *item, void *hptw);
+    int32_t (* _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)(uint32_t size);
+    void *(* _malloc_internal)(uint32_t size);
+    void (* _free)(void *p);
+    int32_t (* _read_efuse_mac)(uint8_t mac[6]);
+    void (* _srand)(unsigned int seed);
+    int (* _rand)(void);
+    uint32_t (* _btdm_lpcycles_2_us)(uint32_t cycles);
+    uint32_t (* _btdm_us_2_lpcycles)(uint32_t us);
+    bool (* _btdm_sleep_check_duration)(uint32_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 */
+    bool (* _coex_bt_wakeup_request)(void);
+    void (* _coex_bt_wakeup_request_end)(void);
+    int (* _coex_bt_request)(uint32_t event,
+                             uint32_t latency,
+                             uint32_t duration);
+    int (* _coex_bt_release)(uint32_t event);
+    int (* _coex_register_bt_cb)(coex_func_cb_t cb);
+    uint32_t (* _coex_bb_reset_lock)(void);
+    void (* _coex_bb_reset_unlock)(uint32_t restore);
+    int (* _coex_schm_register_btdm_callback)(void *callback);
+    void (* _coex_schm_status_bit_clear)(uint32_t type, uint32_t status);
+    void (* _coex_schm_status_bit_set)(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 (* _coex_wifi_channel_get)(uint8_t *primary, uint8_t *secondary);
+    int (* _coex_register_wifi_channel_change_callback)(void *cb);
+    uint32_t _magic;
+};
+
+/****************************************************************************
+ * Private Function
+ ****************************************************************************/
+
+static xt_handler esp_ble_set_isr(int n, xt_handler f, void *arg);
+static void IRAM_ATTR interrupt_disable(void);
+static void IRAM_ATTR interrupt_restore(void);
+static void IRAM_ATTR task_yield_from_isr(void);
+static void *semphr_create_wrapper(uint32_t max, uint32_t init);
+static void semphr_delete_wrapper(void *semphr);
+static int IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw);
+static int IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw);
+static int  semphr_take_wrapper(void *semphr, uint32_t block_time_ms);
+static int  semphr_give_wrapper(void *semphr);
+static void *mutex_create_wrapper(void);
+static void mutex_delete_wrapper(void *mutex);
+static int mutex_lock_wrapper(void *mutex);
+static int mutex_unlock_wrapper(void *mutex);
+static int IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item,
+                                                 void *hptw);
+static int IRAM_ATTR queue_recv_from_isr_wrapper(void *queue, void *item,
+                                                 void *hptw);
+static int task_create_wrapper(void *task_func, const char *name,
+                               uint32_t stack_depth, void *param,
+                               uint32_t prio, void *task_handle,
+                               uint32_t core_id);
+static void task_delete_wrapper(void *task_handle);
+static bool IRAM_ATTR is_in_isr_wrapper(void);
+static void *malloc_wrapper(size_t size);
+static void IRAM_ATTR cause_sw_intr(void *arg);
+static int IRAM_ATTR cause_sw_intr_to_core_wrapper(int core_id, int intr_no);
+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_us(uint32_t cycles);
+static uint32_t IRAM_ATTR btdm_us_2_lpcycles(uint32_t us);
+static void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size);
+static int queue_send_wrapper(void *queue, void *item,
+                              uint32_t block_time_ms);
+static int queue_recv_wrapper(void *queue, void *item,
+                              uint32_t block_time_ms);
+static void queue_delete_wrapper(void *queue);
+static void esp32_ints_on(uint32_t mask);
+static int adapter_coex_register_bt_cb_wrapper(coex_func_cb_t cb);
+static int adapter_coex_schm_register_btdm_callback(void *callback);
+static int adapter_coex_register_wifi_channel_change_callback(void *cb);
+static int adapter_coex_wifi_channel_get(uint8_t *primary,
+                                         uint8_t *secondary);
+static void adapter_coex_schm_status_bit_clear(uint32_t type,
+                                               uint32_t status);
+static void adapter_coex_schm_status_bit_set(uint32_t type, uint32_t status);
+static uint32_t adapter_coex_schm_interval_get(void);
+static uint8_t adapter_coex_schm_curr_period_get(void);
+static void *adapter_coex_schm_curr_phase_get(void);
+
+#ifdef CONFIG_PM
+static bool IRAM_ATTR btdm_sleep_check_duration(int32_t *half_slot_cnt);
+static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles);
+static void btdm_sleep_enter_phase2_wrapper(void);
+static void btdm_sleep_exit_phase3_wrapper(void);
+#endif
+
+static bool coex_bt_wakeup_request(void);
+static void coex_bt_wakeup_request_end(void);
+static int esp_int_adpt_cb(int irq, void *context, void *arg);
+
+/****************************************************************************
+ * Extern Functions declaration and value
+ ****************************************************************************/
+
+extern int btdm_osi_funcs_register(void *osi_funcs);
+extern void btdm_controller_rom_data_init(void);
+extern void coex_bt_high_prio(void);
+
+/* Initialise and De-initialise */
+
+extern int btdm_controller_init(uint32_t config_mask,
+                                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 void btdm_controller_set_sleep_mode(uint8_t mode);
+extern uint8_t btdm_controller_get_sleep_mode(void);
+extern bool btdm_power_state_active(void);
+extern void btdm_wakeup_request(bool request_lock);
+extern void btdm_wakeup_request_end(void);
+
+/* 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 int bredr_txpwr_set(int min_power_level, int max_power_level);
+extern int bredr_txpwr_get(int *min_power_level, int *max_power_level);
+extern void bredr_sco_datapath_set(uint8_t data_path);
+extern void btdm_controller_scan_duplicate_list_clear(void);
+
+/* Coexistence */
+
+int coex_bt_request_wrapper(uint32_t event,
+                            uint32_t latency,
+                            uint32_t duration);
+int coex_bt_release_wrapper(uint32_t event);
+uint32_t coex_bb_reset_lock_wrapper(void);
+void coex_bb_reset_unlock_wrapper(uint32_t restore);
+extern void coex_ble_adv_priority_high_set(bool high);
+
+extern char _bss_start_btdm;
+extern char _bss_end_btdm;
+extern char _data_start_btdm;
+extern char _data_end_btdm;
+extern uint32_t _data_start_btdm_rom;
+extern uint32_t _data_end_btdm_rom;
+
+extern uint32_t _bt_bss_start;
+extern uint32_t _bt_bss_end;
+extern uint32_t _btdm_bss_start;
+extern uint32_t _btdm_bss_end;
+extern uint32_t _bt_data_start;
+extern uint32_t _bt_data_end;
+extern uint32_t _btdm_data_start;
+extern uint32_t _btdm_data_end;
+
+extern char _bt_tmp_bss_start;
+extern char _bt_tmp_bss_end;
+
+void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Controller status */
+
+static DRAM_ATTR esp_bt_controller_status_t btdm_controller_status =
+                        ESP_BT_CONTROLLER_STATUS_IDLE;
+
+/* low power control struct */
+
+static DRAM_ATTR btdm_lpcntl_t g_lp_cntl;
+
+/* low power status struct */
+
+static DRAM_ATTR btdm_lpstat_t g_lp_stat;
+
+/* measured average low power clock period in micro seconds */
+
+static DRAM_ATTR uint32_t g_btdm_lpcycle_us = 0;
+
+/* number of fractional bit for g_btdm_lpcycle_us */
+
+static DRAM_ATTR uint8_t g_btdm_lpcycle_us_frac = 0;
+
+#ifdef CONFIG_PM
+/* semaphore used for blocking VHCI API to wait for controller to wake up */
+
+static DRAM_ATTR void * g_wakeup_req_sem  = NULL;
+
+/* wakeup timer */
+
+static DRAM_ATTR esp_timer_handle_t g_btdm_slp_tmr;
+#endif
+
+/* BT interrupt private data */
+
+static irqstate_t g_inter_flags;
+static uint32_t g_phy_clk_en_cnt;
+static int64_t g_phy_rf_en_ts;
+static uint8_t g_phy_access_ref;
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* BLE OS adapter data */
+
+static struct osi_funcs_s g_osi_funcs =
+{
+  ._magic = OSI_MAGIC_VALUE,
+  ._version = OSI_VERSION,
+  ._set_isr = esp_ble_set_isr,
+  ._ints_on = esp32_ints_on,
+  ._interrupt_disable = interrupt_disable,
+  ._interrupt_restore = interrupt_restore,
+  ._task_yield = task_yield_from_isr,
+  ._task_yield_from_isr = task_yield_from_isr,
+  ._semphr_create = semphr_create_wrapper,
+  ._semphr_delete = semphr_delete_wrapper,
+  ._semphr_take_from_isr = semphr_take_from_isr_wrapper,
+  ._semphr_give_from_isr = semphr_give_from_isr_wrapper,
+  ._semphr_take = semphr_take_wrapper,
+  ._semphr_give = semphr_give_wrapper,
+  ._mutex_create = mutex_create_wrapper,
+  ._mutex_delete = mutex_delete_wrapper,
+  ._mutex_lock = mutex_lock_wrapper,
+  ._mutex_unlock = mutex_unlock_wrapper,
+  ._queue_create = queue_create_wrapper,
+  ._queue_delete = queue_delete_wrapper,
+  ._queue_send = queue_send_wrapper,
+  ._queue_send_from_isr = queue_send_from_isr_wrapper,
+  ._queue_recv = queue_recv_wrapper,
+  ._queue_recv_from_isr = queue_recv_from_isr_wrapper,
+  ._task_create = task_create_wrapper,
+  ._task_delete = task_delete_wrapper,
+  ._is_in_isr = is_in_isr_wrapper,
+  ._cause_sw_intr_to_core = cause_sw_intr_to_core_wrapper,
+  ._malloc = malloc_wrapper,
+  ._malloc_internal = malloc_internal_wrapper,
+  ._free = free,
+  ._read_efuse_mac = read_mac_wrapper,
+  ._srand = srand_wrapper,
+  ._rand = rand_wrapper,
+  ._btdm_lpcycles_2_us = btdm_lpcycles_2_us,
+  ._btdm_us_2_lpcycles = btdm_us_2_lpcycles,
+#ifdef CONFIG_PM
+  ._btdm_sleep_check_duration = btdm_sleep_check_duration,
+  ._btdm_sleep_enter_phase1 = btdm_sleep_enter_phase1_wrapper,
+  ._btdm_sleep_enter_phase2 = btdm_sleep_enter_phase2_wrapper,
+  ._btdm_sleep_exit_phase3 = btdm_sleep_exit_phase3_wrapper,
+#endif
+  ._coex_bt_wakeup_request = coex_bt_wakeup_request,
+  ._coex_bt_wakeup_request_end = coex_bt_wakeup_request_end,
+  ._coex_bt_request = coex_bt_request_wrapper,
+  ._coex_bt_release = coex_bt_release_wrapper,
+  ._coex_register_bt_cb = adapter_coex_register_bt_cb_wrapper,
+  ._coex_register_wifi_channel_change_callback =
+                 adapter_coex_register_wifi_channel_change_callback,
+  ._coex_wifi_channel_get = adapter_coex_wifi_channel_get,
+  ._coex_schm_status_bit_clear = adapter_coex_schm_status_bit_clear,
+  ._coex_schm_status_bit_set = adapter_coex_schm_status_bit_set,
+  ._coex_schm_interval_get = adapter_coex_schm_interval_get,
+  ._coex_schm_curr_period_get = adapter_coex_schm_curr_period_get,
+  ._coex_schm_curr_phase_get = adapter_coex_schm_curr_phase_get,
+  ._coex_schm_register_btdm_callback =
+                         adapter_coex_schm_register_btdm_callback,
+  ._coex_bb_reset_lock = coex_bb_reset_lock_wrapper,
+  ._coex_bb_reset_unlock = coex_bb_reset_unlock_wrapper,
+};
+
+/* The mode column will be modified by release function to indicate the
+ * available region
+ */
+
+static btdm_dram_available_region_t btdm_dram_available_region[] =
+{
+  /* following is .data */
+
+  {
+    ESP_BT_MODE_BTDM,
+    SOC_MEM_BT_DATA_START,
+    SOC_MEM_BT_DATA_END
+  },
+
+  /* following is memory which HW will use */
+
+  {
+    ESP_BT_MODE_BTDM,
+    SOC_MEM_BT_EM_BTDM0_START,
+    SOC_MEM_BT_EM_BTDM0_END
+  },
+  {
+    ESP_BT_MODE_BLE,
+    SOC_MEM_BT_EM_BLE_START,
+    SOC_MEM_BT_EM_BLE_END
+  },
+  {
+    ESP_BT_MODE_BTDM,
+    SOC_MEM_BT_EM_BTDM1_START,
+    SOC_MEM_BT_EM_BTDM1_END
+  },
+  {
+    ESP_BT_MODE_CLASSIC_BT,
+    SOC_MEM_BT_EM_BREDR_START,
+    SOC_MEM_BT_EM_BREDR_REAL_END
+  },
+
+  /* following is .bss */
+
+  {
+    ESP_BT_MODE_BTDM,
+    SOC_MEM_BT_BSS_START,
+    SOC_MEM_BT_BSS_END
+  },
+  {
+    ESP_BT_MODE_BTDM,
+    SOC_MEM_BT_MISC_START,
+    SOC_MEM_BT_MISC_END
+  },
+};
+
+/****************************************************************************
+ * Private Functions and Public Functions only used by libraries
+ ****************************************************************************/
+
+static int adapter_coex_register_bt_cb_wrapper(coex_func_cb_t cb)
+{
+  return ESP_ERR_INVALID_STATE;
+}
+
+static int adapter_coex_schm_register_btdm_callback(void *callback)
+{
+  return ESP_ERR_INVALID_STATE;
+}
+
+static int adapter_coex_register_wifi_channel_change_callback(void *cb)
+{
+  return ESP_ERR_INVALID_STATE;
+}
+
+static int adapter_coex_wifi_channel_get(uint8_t *primary,
+                                         uint8_t *secondary)
+{
+  return -ERROR;
+}
+
+static void adapter_coex_schm_status_bit_clear(uint32_t type,
+                                               uint32_t status)
+{
+}
+
+static void adapter_coex_schm_status_bit_set(uint32_t type, uint32_t status)
+{
+}
+
+static uint32_t adapter_coex_schm_interval_get(void)
+{
+  return ESP_ERR_INVALID_STATE;
+}
+
+static uint8_t adapter_coex_schm_curr_period_get(void)
+{
+  return OK;
+}
+
+static void *adapter_coex_schm_curr_phase_get(void)
+{
+  return NULL;
+}
+
+/****************************************************************************
+ * Name: esp_errno_trans
+ *
+ * Description:
+ *   Transform from nuttx error code to Wi-Fi adapter error code
+ *
+ * Input Parameters:
+ *   ret - NuttX error code
+ *
+ * Returned Value:
+ *   Wi-Fi adapter error code
+ *
+ ****************************************************************************/
+
+static inline int32_t esp_errno_trans(int ret)
+{
+  if (!ret)
+  {
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+/****************************************************************************
+ * Name: esp_task_create_pinned_to_core
+ *
+ * Description:
+ *   Create task and bind it to target CPU, the task will run when it
+ *   is created
+ *
+ * Input Parameters:
+ *   entry       - Task entry
+ *   name        - Task name
+ *   stack_depth - Task stack size
+ *   param       - Task private data
+ *   prio        - Task priority
+ *   task_handle - Task handle pointer which is used to pause, resume
+ *                 and delete the task
+ *   core_id     - CPU which the task runs in
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int32_t esp_task_create_pinned_to_core(void *entry,
+                                              const char *name,
+                                              uint32_t stack_depth,
+                                              void *param,
+                                              uint32_t prio,
+                                              void *task_handle,
+                                              uint32_t core_id)
+{
+  int pid;
+#ifdef CONFIG_SMP
+  int ret;
+  cpu_set_t cpuset;
+#endif
+
+  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;
+        }
+
+#ifdef CONFIG_SMP
+      if (core_id < CONFIG_SMP_NCPUS)
+        {
+          CPU_ZERO(&cpuset);
+          CPU_SET(core_id, &cpuset);
+          ret = nxsched_set_affinity(pid, sizeof(cpuset), &cpuset);
+          if (ret)
+            {
+              wlerr("Failed to set affinity error=%d\n", ret);
+              return false;
+            }
+        }
+#endif
+    }
+  else
+    {
+      wlerr("Failed to create task, error %d\n", pid);
+    }
+
+  return pid > 0 ? true : false;
+}
+
+/****************************************************************************
+ * Name: esp_set_isr
+ *
+ * Description:
+ *   Register interrupt function
+ *
+ * Input Parameters:
+ *   n   - Interrupt ID
+ *   f   - Interrupt function
+ *   arg - Function private data
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static xt_handler esp_ble_set_isr(int n, xt_handler f, void *arg)
+{
+  int ret;
+  uint32_t tmp;
+  struct irq_adpt_s *adapter;
+  int irq = n + XTENSA_IRQ_FIRSTPERIPH;
+
+  wlinfo("n=%d f=%p arg=%p irq=%d\n", n, f, arg, irq);
+
+  if (g_irqvector[irq].handler &&
+      g_irqvector[irq].handler != irq_unexpected_isr)
+    {
+      wlinfo("irq=%d has been set handler=%p\n", irq,
+             g_irqvector[irq].handler);
+      return NULL;
+    }
+
+  tmp = sizeof(struct irq_adpt_s);
+  adapter = kmm_malloc(tmp);
+  if (!adapter)
+    {
+      wlerr("Failed to alloc %d memory\n", tmp);
+      assert(0);
+      return NULL;
+    }
+
+  adapter->func = f;
+  adapter->arg = arg;
+
+  ret = irq_attach(irq, esp_int_adpt_cb, adapter);
+  if (ret)
+    {
+      wlerr("Failed to attach IRQ %d\n", irq);
+      assert(0);
+      return NULL;
+    }
+
+  return NULL;
+}
+
+/****************************************************************************
+ * Name: esp32_ints_on
+ *
+ * Description:
+ *   Enable BLE interrupt
+ *
+ * Input Parameters:
+ *   mask - Mask used to indicate the bits to enable interrupt.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void esp32_ints_on(uint32_t mask)
+{
+  uint32_t bit;
+
+  for (int i = 0; i < 32; i++)
+    {
+      bit = 1 << i;
+      if (bit & mask)
+      {
+        wlinfo("Enabled bit %d\n", i);
+        up_enable_irq(i);
+      }
+    }
+}
+
+/****************************************************************************
+ * Name: is_wifi_clk_peripheral
+ *
+ * Description:
+ *     Checks if the peripheral module needs WiFi Clock.
+ *
+ * Input Parameters:
+ *     periph - The peripheral module
+ *
+ * Returned Value:
+ *    true if it depends on WiFi clock or false otherwise.
+ *
+ ****************************************************************************/
+
+static bool is_wifi_clk_peripheral(periph_module_e periph)
+{
+  /* A small subset of peripherals use WIFI_CLK_EN_REG and
+   * CORE_RST_EN_REG for their clock & reset registers
+   */
+
+  switch (periph)
+  {
+    case PERIPH_SDMMC_MODULE:
+    case PERIPH_SDIO_SLAVE_MODULE:
+    case PERIPH_EMAC_MODULE:
+    case PERIPH_RNG_MODULE:
+    case PERIPH_WIFI_MODULE:
+    case PERIPH_BT_MODULE:
+    case PERIPH_WIFI_BT_COMMON_MODULE:
+    case PERIPH_BT_BASEBAND_MODULE:
+    case PERIPH_BT_LC_MODULE:
+        return true;
+    default:
+        return false;
+  }
+}
+
+/****************************************************************************
+ * Name: get_clk_en_mask
+ *
+ * Description:
+ *     Returns the WIFI_BT clock mask case it is BLE peripheral.
+ *
+ * Input Parameters:
+ *     periph - The peripheral module
+ *
+ * Returned Value:
+ *    The clock peripheral mask.
+ *
+ ****************************************************************************/
+
+static uint32_t get_clk_en_mask(periph_module_e periph)
+{
+  switch (periph)
+  {
+    case PERIPH_BT_MODULE:
+      return DPORT_WIFI_CLK_BT_EN_M;
+    default:
+      return 0;
+  }
+}
+
+/****************************************************************************
+ * Name: get_rst_en_mask
+ *
+ * Description:
+ *     Returns the WIFI_BT reset mask
+ *
+ * Input Parameters:
+ *     periph - The peripheral module
+ *     enable - Enable/Disable
+ *
+ * Returned Value:
+ *    The reset peripheral mask.
+ *
+ ****************************************************************************/
+
+static uint32_t get_rst_en_mask(periph_module_e periph, bool enable)
+{
+  return 0;
+}
+
+/****************************************************************************
+ * Name: get_clk_en_reg
+ *
+ * Description:
+ *     Returns the WIFI_BT clock register
+ *
+ * Input Parameters:
+ *     periph - The peripheral module
+ *
+ * Returned Value:
+ *    The clock peripheral register.
+ *
+ ****************************************************************************/
+
+static uint32_t get_clk_en_reg(periph_module_e periph)
+{
+  return is_wifi_clk_peripheral(periph) ? DPORT_WIFI_CLK_EN_REG :
+                                          DPORT_PERIP_CLK_EN_REG;
+}
+
+/****************************************************************************
+ * Name: get_rst_en_reg
+ *
+ * Description:
+ *     Returns the WIFI_BT reset register
+ *
+ * Input Parameters:
+ *     periph - The peripheral module
+ *
+ * Returned Value:
+ *    The reset peripheral register.
+ *
+ ****************************************************************************/
+
+static uint32_t get_rst_en_reg(periph_module_e periph)
+{
+  return is_wifi_clk_peripheral(periph) ? DPORT_CORE_RST_EN_REG :
+                                          DPORT_PERIP_RST_EN_REG;
+}
+
+/****************************************************************************
+ * Name: bt_periph_module_enable
+ *
+ * Description:
+ *     Enable the bluetooth module
+ *
+ * Input Parameters:
+ *     periph - The peripheral module
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+static void bt_periph_module_enable(periph_module_e periph)
+{
+  modifyreg32(get_clk_en_reg(periph), 0, get_clk_en_mask(periph));
+  modifyreg32(get_rst_en_reg(periph), get_rst_en_mask(periph, true), 0);
+}
+
+/****************************************************************************
+ * Name: esp_int_adpt_cb
+ *
+ * Description:
+ *   BT interrupt adapter callback function
+ *
+ * Input Parameters:
+ *   arg - interrupt adapter private data
+ *
+ * Returned Value:
+ *   NuttX error code
+ *
+ ****************************************************************************/
+
+static int esp_int_adpt_cb(int irq, void *context, void *arg)
+{
+  struct irq_adpt_s *adapter = (struct irq_adpt_s *)arg;
+
+  adapter->func(adapter->arg);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: interrupt_disable
+ *
+ * Description:
+ *   Enter critical section by disabling interrupts and taking the spin lock
+ *   if in SMP mode.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR interrupt_disable(void)
+{
+  g_inter_flags = enter_critical_section();
+}
+
+/****************************************************************************
+ * Name: interrupt_restore
+ *
+ * Description:
+ *   Exit from critical section by enabling interrupts and releasing the spin
+ *   lock if in SMP mode.
+ *
+ * Input Parameters:
+ *  None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR interrupt_restore(void)
+{
+  leave_critical_section(g_inter_flags);
+}
+
+/****************************************************************************
+ * Name: task_yield_from_isr
+ *
+ * Description:
+ *   Do nothing in NuttX
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR task_yield_from_isr(void)
+{
+}
+
+/****************************************************************************
+ * Name: semphr_create_wrapper
+ *
+ * Description:
+ *   Create and initialize semaphore
+ *
+ * Input Parameters:
+ *   max  - Unused
+ *   init - semaphore initialization value
+ *
+ * Returned Value:
+ *   Semaphore data pointer
+ *
+ ****************************************************************************/
+
+static void *semphr_create_wrapper(uint32_t max, uint32_t init)
+{
+  int ret;
+  sem_t *sem;
+  int tmp;
+
+  tmp = sizeof(sem_t);
+  sem = kmm_malloc(tmp);
+  if (!sem)
+    {
+      wlerr("ERROR: Failed to alloc %d memory\n", tmp);
+      return NULL;
+    }
+
+  ret = sem_init(sem, 0, init);
+  if (ret)
+    {
+      wlerr("ERROR: Failed to initialize sem error=%d\n", ret);
+      kmm_free(sem);
+      return NULL;
+    }
+
+  return sem;
+}
+
+/****************************************************************************
+ * Name: semphr_delete_wrapper
+ *
+ * Description:
+ *   Delete semaphore
+ *
+ * Input Parameters:
+ *   semphr - Semaphore data pointer
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void semphr_delete_wrapper(void *semphr)
+{
+  sem_t *sem = (sem_t *)semphr;
+  sem_destroy(sem);
+  kmm_free(sem);
+}
+
+/****************************************************************************
+ * Name: semphr_take_from_isr_wrapper
+ *
+ * Description:
+ *   Take a semaphore from an ISR
+ *
+ * Input Parameters:
+ *   semphr - Semaphore data pointer.
+ *   hptw     - Unused.
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw)
+{
+  return esp_errno_trans(sem_trywait(semphr));
+}
+
+/****************************************************************************
+ * Name: semphr_give_from_isr_wrapper
+ *
+ * Description:
+ *   Post semaphore
+ *
+ * Input Parameters:
+ *   semphr - Semaphore data pointer
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw)
+{
+  return semphr_give_wrapper(semphr);
+}
+
+/****************************************************************************
+ * Name: esp_update_time
+ *
+ * Description:
+ *   Transform ticks to time and add this time to timespec value
+ *
+ * Input Parameters:
+ *   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: semphr_take_wrapper
+ *
+ * Description:
+ *   Wait semaphore within a certain period of time
+ *
+ * Input Parameters:
+ *   semphr         - Semaphore data pointer
+ *   block_time_ms  - Wait time
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int semphr_take_wrapper(void *semphr, uint32_t block_time_ms)
+{
+  int ret;
+  struct timespec timeout;
+  sem_t *sem = (sem_t *)semphr;
+
+  if (block_time_ms == OSI_FUNCS_TIME_BLOCKING)
+    {
+      ret = sem_wait(sem);
+      if (ret)
+        {
+          wlerr("Failed to wait sem %d\n", ret);
+        }
+    }
+  else
+    {
+      ret = clock_gettime(CLOCK_REALTIME, &timeout);
+      if (ret < 0)
+        {
+          wlerr("Failed to get time\n");
+          return esp_errno_trans(ret);
+        }
+
+      if (block_time_ms)
+        {
+          esp_update_time(&timeout, MSEC2TICK(block_time_ms));
+        }
+
+      ret = sem_timedwait(sem, &timeout);
+    }
+
+  return esp_errno_trans(ret);
+}
+
+/****************************************************************************
+ * Name: semphr_give_wrapper
+ *
+ * Description:
+ *   Post semaphore
+ *
+ * Input Parameters:
+ *   semphr - Semaphore data pointer
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int semphr_give_wrapper(void *semphr)
+{
+  int ret;
+  sem_t *sem = (sem_t *)semphr;
+
+  ret = sem_post(sem);
+  if (ret)
+    {
+      wlerr("Failed to post sem error=%d\n", ret);
+    }
+
+  return esp_errno_trans(ret);
+}
+
+/****************************************************************************
+ * Name: mutex_create_wrapper
+ *
+ * Description:
+ *   Create mutex
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Mutex data pointer
+ *
+ ****************************************************************************/
+
+static void *mutex_create_wrapper(void)
+{
+  int ret;
+  pthread_mutex_t *mutex;
+  int tmp;
+
+  tmp = sizeof(pthread_mutex_t);
+  mutex = kmm_malloc(tmp);
+  DEBUGASSERT(mutex);
+
+  ret = pthread_mutex_init(mutex, NULL);
+  if (ret)
+    {
+      wlerr("Failed to initialize mutex error=%d\n", ret);
+      kmm_free(mutex);
+      return NULL;
+    }
+
+  return mutex;
+}
+
+/****************************************************************************
+ * Name: mutex_delete_wrapper
+ *
+ * Description:
+ *   Delete mutex
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Mutex data pointer
+ *
+ ****************************************************************************/
+
+static void mutex_delete_wrapper(void *mutex)
+{
+  pthread_mutex_destroy(mutex);
+  kmm_free(mutex);
+}
+
+/****************************************************************************
+ * Name: mutex_lock_wrapper
+ *
+ * Description:
+ *   Lock mutex
+ *
+ * Input Parameters:
+ *   mutex_data - mutex data pointer
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int mutex_lock_wrapper(void *mutex)
+{
+  int ret;
+
+  ret = pthread_mutex_lock(mutex);
+  if (ret)
+    {
+      wlerr("Failed to lock mutex error=%d\n", ret);
+    }
+
+  return esp_errno_trans(ret);
+}
+
+/****************************************************************************
+ * Name: mutex_unlock_wrapper
+ *
+ * Description:
+ *   Unlock mutex
+ *
+ * Input Parameters:
+ *   mutex_data - mutex data pointer
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int mutex_unlock_wrapper(void *mutex)
+{
+  int ret;
+
+  ret = pthread_mutex_unlock(mutex);
+  if (ret)
+    {
+      wlerr("Failed to unlock mutex error=%d\n", ret);
+    }
+
+  return esp_errno_trans(ret);
+}
+
+/****************************************************************************
+ * Name: esp_queue_send_generic
+ *
+ * Description:
+ *   Generic send message to queue within a certain period of time
+ *
+ * Input Parameters:
+ *   queue - Message queue data pointer
+ *   item  - Message data pointer
+ *   ticks - Wait ticks
+ *   prio  - Message priority
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int32_t esp_queue_send_generic(void *queue, void *item,
+                                      uint32_t ticks, int prio)
+{
+  int ret;
+  struct timespec timeout;
+  struct mq_adpt_s *mq_adpt = (struct mq_adpt_s *)queue;
+
+  if (ticks == OSI_FUNCS_TIME_BLOCKING || ticks == 0)
+    {
+      /**
+       * BLE interrupt function will call this adapter function to send
+       * message to message queue, so here we should call kernel API
+       * instead of application API
+       */
+
+      ret = file_mq_send(&mq_adpt->mq, (const char *)item,
+                         mq_adpt->msgsize, prio);
+      if (ret < 0)
+        {
+          wlerr("Failed to send message to mqueue error=%d\n", ret);
+        }
+    }
+  else
+    {
+      ret = clock_gettime(CLOCK_REALTIME, &timeout);
+      if (ret < 0)
+        {
+          wlerr("Failed to get time %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: 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)
+{
+  *((int *)hptw) = false;
+  return esp_queue_send_generic(queue, item, 0, 0);
+}
+
+/****************************************************************************
+ * Name: queue_recv_from_isr_wrapper
+ *
+ * Description:
+ *   Receive message from queue within a certain period of time
+ *
+ * Input Parameters:
+ *   queue - Message queue data pointer
+ *   item  - Message data pointer
+ *   hptw - Unused
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR queue_recv_from_isr_wrapper(void *queue,
+                                                 void *item,
+                                                 void *hptw)
+{
+  return 0;
+}
+
+/****************************************************************************
+ * Name: task_create_wrapper
+ *
+ * Description:
+ *   Create task and the task will run when it is created
+ *
+ * Input Parameters:
+ *   entry       - Task entry
+ *   name        - Task name
+ *   stack_depth - Task stack size
+ *   param       - Task private data
+ *   prio        - Task priority
+ *   task_handle - Task handle pointer which is used to pause, resume
+ *                 and delete the task
+ *
+ * Returned Value:
+ *   True if success or false if fail
+ *
+ ****************************************************************************/
+
+static int task_create_wrapper(void *task_func, const char *name,
+                               uint32_t stack_depth, void *param,
+                               uint32_t prio, void *task_handle,
+                               uint32_t core_id)
+{
+  return esp_task_create_pinned_to_core(task_func, name,
+                                        stack_depth, param,
+                                        prio, task_handle, UINT32_MAX);
+}
+
+/****************************************************************************
+ * Name: task_delete_wrapper
+ *
+ * Description:
+ *   Delete the target task
+ *
+ * Input Parameters:
+ *   task_handle - Task handle pointer which is used to pause, resume
+ *                 and delete the task
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void task_delete_wrapper(void *task_handle)
+{
+  pid_t pid = (pid_t)((uintptr_t)task_handle);
+  kthread_delete(pid);
+}
+
+/****************************************************************************
+ * Name: is_in_isr_wrapper
+ *
+ * Description:
+ *
+ * Input Parameters:
+ *  None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static bool IRAM_ATTR is_in_isr_wrapper(void)
+{
+  return false;
+}
+
+/****************************************************************************
+ * Name: malloc_wrapper
+ *
+ * Description:
+ *   Malloc buffer
+ *
+ * Input Parameters:
+ *  size - buffer size
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void *malloc_wrapper(size_t size)
+{
+  void * p = NULL;
+
+  p = kmm_malloc(size);
+  DEBUGASSERT(p);
+
+  return p;
+}
+
+/****************************************************************************
+ * Name: cause_sw_intr
+ *
+ * Description:
+ *   Set a software interrupt bit
+ *
+ * Input Parameters:
+ *  arg - number of the bit as void pointer
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR cause_sw_intr(void *arg)
+{
+  /* just convert void * to int, because the width is the same */
+
+  uint32_t intr_no = (uint32_t)arg;
+  XTHAL_SET_INTSET((1 << intr_no));
+}
+
+/****************************************************************************
+ * Name: cause_sw_intr_to_core_wrapper
+ *
+ * Description:
+ *   Just a wrapper to cause_sw_intr
+ *
+ * Input Parameters:
+ *  core_id - ID of the CPU core, not used.
+ *  intr_no - Number of the software interrupt
+ *
+ * Returned Value:
+ *   Always return OK.
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR cause_sw_intr_to_core_wrapper(int core_id, int intr_no)
+{
+  cause_sw_intr((void *)intr_no);
+  return ESP_OK;
+}
+
+/****************************************************************************
+ * Name: malloc_internal_wrapper
+ *
+ * Description:
+ *   Malloc buffer in DRAM
+ *
+ * Input Parameters:
+ *  szie - buffer size
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void *malloc_internal_wrapper(size_t size)
+{
+  void * p = NULL;
+
+  p = kmm_malloc(size);
+  DEBUGASSERT(p);
+
+  return p;
+}
+
+/****************************************************************************
+ * Name: read_mac_wrapper
+ *
+ * Description:
+ *   Get Mac Address
+ *
+ * Input Parameters:
+ *  mac - mac address
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR read_mac_wrapper(uint8_t mac[6])
+{
+  return esp_read_mac(mac, ESP_MAC_BT);
+}
+
+/****************************************************************************
+ * Name: srand_wrapper
+ *
+ * Description:
+ *
+ * Input Parameters:
+ *  None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR srand_wrapper(unsigned int seed)
+{
+  /* empty function */
+}
+
+/****************************************************************************
+ * Name: rand_wrapper
+ *
+ * Description:
+ *    Get random value.
+ *
+ * Input Parameters:
+ *  None
+ *
+ * Returned Value:
+ *   Random value
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR rand_wrapper(void)
+{
+  return random();
+}
+
+/****************************************************************************
+ * Name: btdm_lpcycles_2_us
+ *
+ * Description:
+ *    Converts a number of low power clock cycles into a duration in us
+ *
+ * Input Parameters:
+ *    cycles - number of CPU cycles
+ *
+ * Returned Value:
+ *    us - value equivalent to the CPU cycles
+ *
+ ****************************************************************************/
+
+static uint32_t IRAM_ATTR btdm_lpcycles_2_us(uint32_t cycles)
+{
+  uint64_t us = (uint64_t)g_btdm_lpcycle_us * cycles;
+  us = (us + (1 << (g_btdm_lpcycle_us_frac - 1))) >> g_btdm_lpcycle_us_frac;
+  return (uint32_t)us;
+}
+
+/****************************************************************************
+ * Name: btdm_us_2_lpcycles
+ *
+ * Description:
+ * Converts a duration in half us into a number of low power clock cycles.
+ *
+ * Input Parameters:
+ *  us
+ *
+ * Returned Value:
+ *   cycles
+ *
+ ****************************************************************************/
+
+static uint32_t IRAM_ATTR btdm_us_2_lpcycles(uint32_t us)
+{
+  uint64_t cycles;
+  cycles = ((uint64_t)(us) << g_btdm_lpcycle_us_frac) / g_btdm_lpcycle_us;
+  return (uint32_t)cycles;
+}
+
+#ifdef CONFIG_PM
+/****************************************************************************
+ * Name: btdm_sleep_exit_phase0
+ *
+ * Description:
+ *   Acquire PM lock and stop esp timer.
+ *
+ * Input Parameters:
+ *   param - wakeup event
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR btdm_sleep_exit_phase0(void *param)
+{
+  int event = (int) param;
+
+  DEBUGASSERT(g_lp_cntl.enable == true);
+
+  if (g_lp_stat.pm_lock_released)
+    {
+      esp32_pm_lockacquire();
+      g_lp_stat.pm_lock_released = false;
+    }
+
+  if (event == BTDM_ASYNC_WAKEUP_SRC_VHCI ||
+      event == BTDM_ASYNC_WAKEUP_SRC_DISA)
+    {
+      btdm_wakeup_request();
+    }
+
+  if (g_lp_cntl.wakeup_timer_required && g_lp_stat.wakeup_timer_started)
+    {
+      esp_timer_stop(g_btdm_slp_tmr);
+      g_lp_stat.wakeup_timer_started = false;
+    }
+
+  if (event == BTDM_ASYNC_WAKEUP_SRC_VHCI ||
+      event == BTDM_ASYNC_WAKEUP_SRC_DISA)
+    {
+      semphr_give_wrapper(g_wakeup_req_sem);
+    }
+}
+
+/****************************************************************************
+ * Name: btdm_slp_tmr_callback
+ *
+ * Description:
+ *   ESP BLE sleep callback function.
+ *
+ * Input Parameters:
+ *   arg - Unused
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR btdm_slp_tmr_callback(void *arg)
+{
+  btdm_vnd_offload_post(BTDM_VND_OL_SIG_WAKEUP_TMR,
+                        (void *)BTDM_ASYNC_WAKEUP_SRC_TMR);
+}
+
+/****************************************************************************
+ * Name: btdm_sleep_check_duration
+ *
+ * Description:
+ *   Wake up in advance considering the delay in enabling PHY/RF.
+ *
+ * Input Parameters:
+ *   half_slot_cnt - half slots to allow to fall into modem sleep
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static bool IRAM_ATTR btdm_sleep_check_duration(int32_t *half_slot_cnt)
+{
+  if (*half_slot_cnt < BTDM_MIN_SLEEP_DURATION)
+    {
+      return false;
+    }
+
+  *half_slot_cnt -= BTDM_MODEM_WAKE_UP_DELAY;
+  return true;
+}
+
+/****************************************************************************
+ * Name: btdm_sleep_enter_phase1_wrapper
+ *
+ * Description:
+ *   ESP32 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 == false)
+    {
+      return;
+    }
+
+  /* start a timer to wake up and acquire the pm_lock before sleep awakes */
+
+  us_to_sleep = btdm_lpcycles_2_us(lpcycles, NULL);
+
+  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 == false);
+
+  if (esp_timer_start_once(g_btdm_slp_tmr,
+                           us_to_sleep - uncertainty) == ESP_OK)
+    {
+      g_lp_stat.wakeup_timer_started = true;
+    }
+  else
+    {
+      wlerr("timer start failed");
+      DEBUGASSERT(0);
+    }
+}
+
+/****************************************************************************
+ * Name: btdm_sleep_enter_phase2_wrapper
+ *
+ * Description:
+ *   ESP32 BLE lightsleep callback function.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void btdm_sleep_enter_phase2_wrapper(void)
+{
+  if (btdm_controller_get_sleep_mode() == ESP_BT_SLEEP_MODE_1)
+    {
+      if (g_lp_stat.phy_enabled)
+        {
+          bt_phy_disable();
+          g_lp_stat.phy_enabled = false;
+        }
+      else
+        {
+          DEBUGASSERT(0);
+        }
+
+      if (g_lp_stat.pm_lock_released == false)
+        {
+          esp32_pm_lockrelease();
+          g_lp_stat.pm_lock_released = true;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: btdm_sleep_exit_phase3_wrapper
+ *
+ * Description:
+ *   ESP32 BLE lightsleep callback function..
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void btdm_sleep_exit_phase3_wrapper(void)
+{
+  if (g_lp_stat.pm_lock_released)
+    {
+      esp32_pm_lockacquire();
+      g_lp_stat.pm_lock_released = false;
+    }
+
+  if (btdm_sleep_clock_sync())
+    {
+      wlerr("sleep eco state err\n");
+      DEBUGASSERT(0);
+    }
+
+  if (btdm_controller_get_sleep_mode() == ESP_BT_SLEEP_MODE_1)
+    {
+      if (g_lp_stat.phy_enabled == false)
+        {
+          bt_phy_enable();
+          g_lp_stat.phy_enabled = true;
+        }
+    }
+
+  if (g_lp_cntl.wakeup_timer_required && g_lp_stat.wakeup_timer_started)
+    {
+      esp_timer_stop(g_btdm_slp_tmr);
+      g_lp_stat.wakeup_timer_started = false;
+    }
+}
+#endif
+
+/****************************************************************************
+ * Name: 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)
+{
+  int btdm_dram_regions;
+
+  /* initialise .data section */
+
+  memcpy(&_data_start_btdm, (void *)_data_start_btdm_rom,
+         &_data_end_btdm - &_data_start_btdm);
+
+  wlinfo(".data initialise [0x%08x] <== [0x%08x]\n",
+         (uint32_t)&_data_start_btdm, _data_start_btdm_rom);
+
+  /* initial em, .bss section */
+
+  btdm_dram_regions = sizeof(btdm_dram_available_region)
+                      / sizeof(btdm_dram_available_region_t);
+
+  for (int i = 1; i < btdm_dram_regions; i++)
+    {
+      if (btdm_dram_available_region[i].mode != ESP_BT_MODE_IDLE)
+        {
+          memset((void *)btdm_dram_available_region[i].start, 0x0,
+                 btdm_dram_available_region[i].end - \
+                 btdm_dram_available_region[i].start);
+          wlinfo(".bss initialise [0x%08x] - [0x%08x]\n",
+                 btdm_dram_available_region[i].start,
+                 btdm_dram_available_region[i].end);
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: phy_printf_ble
+ *
+ * Description:
+ *   Output format string and its arguments
+ *
+ * Input Parameters:
+ *   format - format string
+ *
+ * Returned Value:
+ *   0
+ *
+ ****************************************************************************/
+
+int phy_printf_ble(const char *format, ...)
+{
+#ifdef CONFIG_DEBUG_WIRELESS_INFO
+  va_list arg;
+
+  va_start(arg, format);
+  vsyslog(LOG_INFO, format, arg);
+  va_end(arg);
+#endif
+
+  return 0;
+}
+
+int coexist_printf(const char *format, ...)
+{
+#ifdef CONFIG_DEBUG_WIRELESS_INFO
+  va_list arg;
+
+  va_start(arg, format);
+  vsyslog(LOG_INFO, format, arg);
+  va_end(arg);
+#endif
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: bt_phy_enable_clock
+ *
+ * Description:
+ *    Enable BT clock.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+static void bt_phy_enable_clock(void)
+{
+  irqstate_t flags;
+
+  flags = enter_critical_section();
+
+  if (g_phy_clk_en_cnt == 0)
+    {
+      modifyreg32(DPORT_WIFI_CLK_EN_REG, 0,
+                  DPORT_WIFI_CLK_WIFI_BT_COMMON_M);
+    }
+
+  g_phy_clk_en_cnt++;
+
+  leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: bt_phy_disable_clock
+ *
+ * Description:
+ *    Disable BT clock.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+static void bt_phy_disable_clock(void)
+{
+  irqstate_t flags;
+
+  flags = enter_critical_section();
+
+  if (g_phy_clk_en_cnt)
+    {
+      g_phy_clk_en_cnt--;
+      if (!g_phy_clk_en_cnt)
+        {
+          modifyreg32(DPORT_WIFI_CLK_EN_REG,
+                      DPORT_WIFI_CLK_WIFI_BT_COMMON_M,
+                      0);
+        }
+    }
+
+  leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: bt_phy_disable
+ *
+ * Description:
+ *    Disable BT phy.
+ *
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+static void bt_phy_disable(void)
+{
+  irqstate_t flags;
+  flags = enter_critical_section();
+
+  g_phy_access_ref--;
+
+  if (g_phy_access_ref == 0)
+    {
+      /* Disable PHY and RF. */
+
+      phy_close_rf();
+
+      /* Disable Wi-Fi/BT common peripheral clock.
+       * Do not disable clock for hardware RNG.
+       */
+
+      bt_phy_disable_clock();
+    }
+
+  leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: bt_phy_enable
+ *
+ * Description:
+ *    Enable BT phy.
+ *
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+static void bt_phy_enable(void)
+{
+  irqstate_t flags;
+  esp_phy_calibration_data_t *cal_data;
+
+  cal_data = kmm_zalloc(sizeof(esp_phy_calibration_data_t));
+  if (cal_data == NULL)
+    {
+      wlerr("Failed to kmm_zalloc");
+      DEBUGASSERT(0);
+    }
+
+  flags = enter_critical_section();
+
+  if (g_phy_access_ref == 0)
+    {
+      /* Update time stamp */
+
+      g_phy_rf_en_ts = (int64_t)rt_timer_time_us();
+
+      bt_phy_enable_clock();
+      phy_set_wifi_mode_only(0);
+      register_chipv7_phy(&phy_init_data, cal_data, PHY_RF_CAL_NONE);
+#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
+      coex_pti_v2();
+#endif
+    }
+
+  g_phy_access_ref++;
+  leave_critical_section(flags);
+  kmm_free(cal_data);
+}
+
+/****************************************************************************
+ * 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;
+  return (void *)mq_adpt;
+}
+
+/****************************************************************************
+ * Name: queue_send_wrapper
+ *
+ * Description:
+ *   Generic send message to queue within a certain period of time
+ *
+ * Input Parameters:
+ *   queue         - Message queue data pointer
+ *   item          - 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_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)
+        {
+          wlerr("Failed to timedreceive from mqueue error=%d\n", ret);
+        }
+    }
+
+  return ret > 0 ? true : false;
+}
+
+/****************************************************************************
+ * Name: queue_delete_wrapper
+ *
+ * Description:
+ *   Delete message queue
+ *
+ * Input Parameters:
+ *   queue - Message queue data pointer
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void queue_delete_wrapper(void *queue)
+{
+  struct mq_adpt_s *mq_adpt = (struct mq_adpt_s *)queue;
+
+  file_mq_close(&mq_adpt->mq);
+  file_mq_unlink(mq_adpt->name);
+  kmm_free(mq_adpt);
+}
+
+/****************************************************************************
+ * Name: btdm_config_mask_load
+ *
+ * Description:
+ *   Create a mask with all ESP32 BLE supported features
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   The uint32_t mask
+ *
+ ****************************************************************************/
+
+static uint32_t btdm_config_mask_load(void)
+{
+    uint32_t mask = 0x0;
+
+#ifdef CONFIG_UART_BTH4
+    mask |= BTDM_CFG_HCI_UART;
+#endif
+
+#ifdef CONFIG_ESP32_BLE_RUN_APP_CPU
+    mask |= BTDM_CFG_CONTROLLER_RUN_APP_CPU;
+#endif
+
+#ifdef CONFIG_ESP32_BLE_FULL_SCAN
+    mask |= BTDM_CFG_BLE_FULL_SCAN_SUPPORTED;
+#endif
+
+    mask |= BTDM_CFG_SCAN_DUPLICATE_OPTIONS;
+
+    mask |= BTDM_CFG_SEND_ADV_RESERVED_SIZE;
+
+    return mask;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32_bt_controller_init
+ *
+ * Description:
+ *    Init  BT controller.
+ *
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32_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 err;
+  uint32_t btdm_cfg_mask = 0;
+
+  if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE)
+    {
+      wlerr("Invalid controller status");
+      return -ERROR;
+    }
+
+  if (btdm_osi_funcs_register(&g_osi_funcs) != 0)
+    {
+      wlinfo("Error, probably invalid OSI Functions\n");
+      return -EINVAL;
+    }
+
+  wlinfo("BT controller compile version [%s]\n",
+                              btdm_controller_get_compile_version());
+
+  /* If all the bt available memory was already released,
+   * cannot initialize bluetooth controller
+   */
+
+  if (btdm_dram_available_region[0].mode == ESP_BT_MODE_IDLE)
+    {
+      wlerr("Error, bt available memory was released\n");
+      return ESP_ERR_INVALID_STATE;
+    }
+
+  if (cfg == NULL)
+    {
+      wlerr("%s  %d\n", __func__, __LINE__);
+      return -EINVAL;
+    }
+
+  cfg->controller_task_stack_size  = CONFIG_ESP32_BLE_TASK_STACK_SIZE;
+  cfg->controller_task_prio        = CONFIG_ESP32_BLE_TASK_PRIORITY;
+
+  cfg->bt_max_sync_conn            = CONFIG_ESP32_BLE_MAX_CONN;
+  cfg->magic                       = ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL;
+
+  if (((cfg->mode & ESP_BT_MODE_BLE) && (cfg->ble_max_conn <= 0 ||
+        cfg->ble_max_conn > BTDM_CONTROLLER_BLE_MAX_CONN_LIMIT)) ||
+      ((cfg->mode & ESP_BT_MODE_CLASSIC_BT) && (cfg->bt_max_acl_conn <= 0 ||
+        cfg->bt_max_acl_conn > BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_LIMIT)) ||
+      ((cfg->mode & ESP_BT_MODE_CLASSIC_BT) &&
+       (cfg->bt_max_sync_conn > BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_LIMIT)))
+    {
+      wlerr("%s  %d\n", __func__, __LINE__);
+      return -EINVAL;
+    }
+
+  wlinfo("BT controller compile version [%s]",
+         btdm_controller_get_compile_version());
+
+  btdm_controller_mem_init();
+
+  wlinfo("Memory initialized!\n");
+
+  bt_periph_module_enable(PERIPH_BT_MODULE);
+
+  /* set default 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);
+
+  btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE);
+
+  btdm_cfg_mask = btdm_config_mask_load();
+
+  wlinfo("Going to call btdm_controller_init\n");
+
+  if (btdm_controller_init(btdm_cfg_mask, cfg) != 0)
+    {
+      wlerr("Failed to initialize the BLE Controller\n");
+      err = -ENOMEM;
+      goto error;
+    }
+
+  wlinfo("The btdm_controller_init was initialized\n");
+
+#ifdef CONFIG_BTDM_COEX_BLE_ADV_HIGH_PRIORITY
+  coex_ble_adv_priority_high_set(true);
+#else
+  coex_ble_adv_priority_high_set(false);
+#endif
+
+  btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
+
+  return OK;
+
+error:
+  return err;
+}
+
+/****************************************************************************
+ * Name: esp32_bt_controller_deinit
+ *
+ * Description:
+ *    Deinit  BT controller.
+ *
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32_bt_controller_deinit(void)
+{
+  if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED)
+    {
+      return -ERROR;
+    }
+
+  btdm_controller_deinit();
+
+  if (g_lp_stat.phy_enabled)
+    {
+      bt_phy_disable();
+      g_lp_stat.phy_enabled = false;
+    }
+  else
+    {
+      DEBUGASSERT(0);
+    }
+
+#ifdef CONFIG_PM
+  /* deinit low power control resources */
+
+  g_lp_stat.pm_lock_released = false;
+
+  if (g_lp_cntl.wakeup_timer_required)
+    {
+      if (g_lp_stat.wakeup_timer_started)
+        {
+          esp_timer_stop(g_btdm_slp_tmr);
+        }
+
+      g_lp_stat.wakeup_timer_started = false;
+      esp_timer_delete(g_btdm_slp_tmr);
+      g_btdm_slp_tmr = NULL;
+    }
+
+  if (g_lp_cntl.enable)
+    {
+      btdm_vnd_offload_task_deregister(BTDM_VND_OL_SIG_WAKEUP_TMR);
+      semphr_delete_wrapper(g_wakeup_req_sem);
+      g_wakeup_req_sem = NULL;
+    }
+#endif
+
+  btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
+  g_btdm_lpcycle_us = 0;
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32_bt_controller_disable
+ *
+ * Description:
+ *    Disable  BT controller.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32_bt_controller_disable(void)
+{
+  if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED)
+    {
+      return -ERROR;
+    }
+
+  while (!btdm_power_state_active())
+    {
+      usleep(1000); /* wait */
+    }
+
+  btdm_controller_disable();
+
+#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
+  coex_disable();
+#endif
+
+  btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
+
+#ifdef CONFIG_PM
+  /* disable low power mode */
+
+  if (g_lp_stat.pm_lock_released == false)
+    {
+      esp32_pm_lockrelease();
+      g_lp_stat.pm_lock_released = true;
+    }
+  else
+    {
+      DEBUGASSERT(0);
+    }
+#endif
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: esp32_bt_controller_enable
+ *
+ * Description:
+ *    Enable  BT controller.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32_bt_controller_enable(esp_bt_mode_t mode)
+{
+  int ret = 0;
+
+  if (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 -1;
+    }
+
+  bt_phy_enable();
+
+  btdm_rf_bb_init_phase2();
+
+  coex_bt_high_prio();
+
+#ifdef CONFIG_ESP32_WIFI_BT_COEXIST
+  coex_enable();
+#endif
+
+#ifdef CONFIG_PM
+  /* enable low power mode */
+
+  esp32_pm_lockacquire();
+  g_lp_stat.pm_lock_released = false;
+
+  if (g_lp_cntl.enable)
+    {
+      btdm_controller_enable_sleep(true);
+    }
+#endif
+
+  if (g_lp_cntl.enable)
+    {
+        btdm_controller_enable_sleep(true);
+    }
+
+  if (btdm_controller_enable(mode) != 0)
+    {
+      ret = -1;
+      goto error;
+    }
+
+  btdm_controller_status = ESP_BT_CONTROLLER_STATUS_ENABLED;
+
+  return ret;
+
+error:
+
+  /* disable low power mode */
+
+  btdm_controller_enable_sleep(false);
+
+#ifdef CONFIG_PM
+  if (g_lp_stat.pm_lock_released == false)
+    {
+      esp32_pm_lockrelease();
+      g_lp_stat.pm_lock_released = true;
+    }
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32_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 esp32_bt_controller_get_status(void)
+{
+  return btdm_controller_status;
+}
+
+/****************************************************************************
+ * 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 request_lock = false;
+  bool do_wakeup_request = false;
+
+  switch (event)
+    {
+      case BTDM_ASYNC_WAKEUP_REQ_HCI:
+        request_lock = true;
+        break;
+      case BTDM_ASYNC_WAKEUP_REQ_COEX:
+        request_lock = false;
+        break;
+      default:
+        return false;
+    }
+
+  if (!btdm_power_state_active())
+    {
+      do_wakeup_request = true;
+      btdm_wakeup_request(request_lock);
+    }
+
+  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 request_lock = false;
+
+  switch (event)
+    {
+      case BTDM_ASYNC_WAKEUP_REQ_HCI:
+        request_lock = true;
+        break;
+      case BTDM_ASYNC_WAKEUP_REQ_COEX:
+        request_lock = false;
+        break;
+      default:
+        return;
+    }
+
+  if (request_lock)
+    {
+      btdm_wakeup_request_end();
+    }
+
+  return;
+}
+
+/****************************************************************************
+ * Name: coex_bt_wakeup_request
+ *
+ * Description:
+ *   Request a WiFi/BLE Coex wakeup request
+ *
+ * Input Parameters:
+ *   none
+ *
+ * Returned Value:
+ *   true if request lock is needed, false otherwise
+ *
+ ****************************************************************************/
+
+static bool coex_bt_wakeup_request(void)
+{
+  return async_wakeup_request(BTDM_ASYNC_WAKEUP_REQ_COEX);
+}
+
+/****************************************************************************
+ * Name: coex_bt_wakeup_request_end
+ *
+ * Description:
+ *   Finish WiFi/BLE Coex wakeup request
+ *
+ * Input Parameters:
+ *   none
+ *
+ * Returned Value:
+ *   none
+ *
+ ****************************************************************************/
+
+static void coex_bt_wakeup_request_end(void)
+{
+  async_wakeup_request_end(BTDM_ASYNC_WAKEUP_REQ_COEX);
+  return;
+}
+
+/****************************************************************************
+ * Name: esp32_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 esp32_vhci_host_check_send_available(void)
+{
+  if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED)
+    {
+      return false;
+    }
+
+  return api_vhci_host_check_send_available();
+}
+
+/****************************************************************************
+ * Name: esp32_vhci_host_send_packet
+ *
+ * Description:
+ *    Host send packet to controller.
+ * Input Parameters:
+ *  data - the packet pointer
+ *  len - the packet length
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32_vhci_host_send_packet(uint8_t *data, uint16_t len)
+{
+  wlinfo("len: %d\n", len);
+  for (uint16_t i = 0; i < len; i++)
+    {
+      wlinfo("%02x\n", data[i]);
+    }
+
+  if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED)
+    {
+      return;
+    }
+
+  api_vhci_host_send_packet(data, len);
+}
+
+/****************************************************************************
+ * Name: esp32_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 esp32_vhci_register_callback(const esp_vhci_host_callback_t *callback)
+{
+  int ret = -ERROR;
+  if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED)
+    {
+      return ret;
+    }
+
+  ret = api_vhci_host_register_callback(
+            (const vhci_host_callback_t *)callback) == 0 ? 0 : -1;
+  return ret;
+}
+
+int coex_bt_request_wrapper(uint32_t event,
+                            uint32_t latency,
+                            uint32_t duration)
+{
+  return 0;
+}
+
+int coex_bt_release_wrapper(uint32_t event)
+{
+  return 0;
+}
+
+uint32_t coex_bb_reset_lock_wrapper(void)
+{
+  return 0;
+}
+
+void coex_bb_reset_unlock_wrapper(uint32_t restore)
+{
+  return;
+}
+
diff --git a/arch/xtensa/src/esp32/esp32_ble_adapter.h b/arch/xtensa/src/esp32/esp32_ble_adapter.h
new file mode 100644
index 0000000..447b111
--- /dev/null
+++ b/arch/xtensa/src/esp32/esp32_ble_adapter.h
@@ -0,0 +1,200 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32/esp32_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_XTENSA_SRC_ESP32_ESP32_BLE_ADAPTER_H
+#define __ARCH_XTENSA_SRC_ESP32_ESP32_BLE_ADAPTER_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "esp_bt.h"
+
+/* Bluetooth system and controller config */
+
+#define BTDM_CFG_BT_DATA_RELEASE            (1 << 0)
+#define BTDM_CFG_HCI_UART                   (1 << 1)
+#define BTDM_CFG_CONTROLLER_RUN_APP_CPU     (1 << 2)
+#define BTDM_CFG_SCAN_DUPLICATE_OPTIONS     (1 << 3)
+#define BTDM_CFG_SEND_ADV_RESERVED_SIZE     (1 << 4)
+#define BTDM_CFG_BLE_FULL_SCAN_SUPPORTED    (1 << 5)
+
+/* Bluetooth memory regions */
+
+#define SOC_MEM_BT_DATA_START               0x3ffae6e0
+#define SOC_MEM_BT_DATA_END                 0x3ffaff10
+#define SOC_MEM_BT_EM_START                 0x3ffb0000
+#define SOC_MEM_BT_EM_END                   0x3ffb7cd8
+#define SOC_MEM_BT_EM_BTDM0_START           0x3ffb0000
+#define SOC_MEM_BT_EM_BTDM0_END             0x3ffb09a8
+#define SOC_MEM_BT_EM_BLE_START             0x3ffb09a8
+#define SOC_MEM_BT_EM_BLE_END               0x3ffb1ddc
+#define SOC_MEM_BT_EM_BTDM1_START           0x3ffb1ddc
+#define SOC_MEM_BT_EM_BTDM1_END             0x3ffb2730
+#define SOC_MEM_BT_EM_BREDR_START           0x3ffb2730
+#define SOC_MEM_BT_EM_BREDR_NO_SYNC_END     0x3ffb6388  /* Not calculate with synchronize connection support */
+#define SOC_MEM_BT_EM_BREDR_END             0x3ffb7cd8  /* Calculate with synchronize connection support */
+#define SOC_MEM_BT_EM_SYNC0_START           0x3ffb6388
+#define SOC_MEM_BT_EM_SYNC0_END             0x3ffb6bf8
+#define SOC_MEM_BT_EM_SYNC1_START           0x3ffb6bf8
+#define SOC_MEM_BT_EM_SYNC1_END             0x3ffb7468
+#define SOC_MEM_BT_EM_SYNC2_START           0x3ffb7468
+#define SOC_MEM_BT_EM_SYNC2_END             0x3ffb7cd8
+#define SOC_MEM_BT_BSS_START                0x3ffb8000
+#define SOC_MEM_BT_BSS_END                  0x3ffb9a20
+#define SOC_MEM_BT_MISC_START               0x3ffbdb28
+#define SOC_MEM_BT_MISC_END                 0x3ffbdb5c
+
+#define SOC_MEM_BT_EM_PER_SYNC_SIZE         0x870
+
+#define SOC_MEM_BT_EM_BREDR_REAL_END        (SOC_MEM_BT_EM_BREDR_NO_SYNC_END + CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF * SOC_MEM_BT_EM_PER_SYNC_SIZE)
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32_bt_controller_init
+ *
+ * Description:
+ *    Init  BT controller.
+ *
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32_bt_controller_init(void);
+
+/****************************************************************************
+ * Name: esp32_bt_controller_deinit
+ *
+ * Description:
+ *    Deinit  BT controller.
+ * Input Parameters:
+ *    cfg -  Initial configuration of BT controller.
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32_bt_controller_deinit(void);
+
+/****************************************************************************
+ * Name: esp32_bt_controller_enable
+ *
+ * Description:
+ *    disable  BT controller.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32_bt_controller_enable(esp_bt_mode_t mode);
+
+/****************************************************************************
+ * Name: esp32_bt_controller_disable
+ *
+ * Description:
+ *    disable  BT controller.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+int esp32_bt_controller_disable(void);
+
+/****************************************************************************
+ * Name: esp32_bt_controller_enable
+ *
+ * Description:
+ *    Enable  BT controller.
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *    None
+ *
+ ****************************************************************************/
+
+esp_bt_controller_status_t esp32_bt_controller_get_status(void);
+
+/****************************************************************************
+ * Name: esp32_vhci_host_check_send_available
+ *
+ * Description:
+ * used for check actively if the host can send packet to controller or not.
+ * Input Parameters:
+ *  None
+ *
+ * Returned Value:
+ *   bool - true or false
+ *
+ ****************************************************************************/
+
+bool esp32_vhci_host_check_send_available(void);
+
+/****************************************************************************
+ * Name: esp32_vhci_host_send_packet
+ *
+ * Description:
+ *    host send packet to controller.
+ * Input Parameters:
+ *  data - the packet point
+ *  len - the packet length
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32_vhci_host_send_packet(uint8_t *data, uint16_t len);
+
+/****************************************************************************
+ * Name: esp32_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 esp32_vhci_register_callback(
+                            const esp_vhci_host_callback_t *callback);
+
+#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_BLE_ADAPTER_H */
diff --git a/arch/xtensa/src/esp32/esp32_irq.c b/arch/xtensa/src/esp32/esp32_irq.c
index bb3f137..1b36d1f 100644
--- a/arch/xtensa/src/esp32/esp32_irq.c
+++ b/arch/xtensa/src/esp32/esp32_irq.c
@@ -102,6 +102,14 @@
 #  define ESP32_WIRELESS_RESERVE_INT  0
 #endif
 
+#ifdef CONFIG_ESP32_BLE
+#  define ESP32_BLE_RESERVE_INT ((1 << ESP32_PERIPH_BT_BB_NMI) | \
+                                 (1 << ESP32_PERIPH_RWBLE_IRQ) | \
+                                 (1 << ESP32_PERIPH_RWBT_NMI))
+#else
+#  define ESP32_BLE_RESERVE_INT 0
+#endif
+
 /****************************************************************************
  * Public Data
  ****************************************************************************/
@@ -171,10 +179,12 @@ static uint32_t g_intenable[1];
  */
 
 static uint32_t g_cpu0_freeints = ESP32_CPUINT_PERIPHSET &
-                                  (~ESP32_WIRELESS_RESERVE_INT);
+                                  (~ESP32_WIRELESS_RESERVE_INT &
+                                   ~ESP32_BLE_RESERVE_INT);
 #ifdef CONFIG_SMP
 static uint32_t g_cpu1_freeints = ESP32_CPUINT_PERIPHSET &
-                                  (~ESP32_WIRELESS_RESERVE_INT);
+                                  (~ESP32_WIRELESS_RESERVE_INT &
+                                   ~ESP32_BLE_RESERVE_INT);
 #endif
 
 /* Bitsets for each interrupt priority 1-5 */
@@ -464,6 +474,12 @@ void up_irqinitialize(void)
   g_irqmap[ESP32_IRQ_MAC] = IRQ_MKMAP(0, ESP32_CPUINT_MAC);
 #endif
 
+#ifdef CONFIG_ESP32_BLE
+  g_irqmap[ESP32_IRQ_BT_BB_NMI] = IRQ_MKMAP(0, ESP32_PERIPH_BT_BB_NMI);
+  g_irqmap[ESP32_IRQ_RWBT_NMI]  = IRQ_MKMAP(0, ESP32_PERIPH_RWBT_NMI);
+  g_irqmap[ESP32_IRQ_RWBLE_IRQ] = IRQ_MKMAP(0, ESP32_PERIPH_RWBLE_IRQ);
+#endif
+
   /* Initialize CPU interrupts */
 
   esp32_cpuint_initialize();
@@ -743,6 +759,15 @@ int esp32_cpuint_initialize(void)
   xtensa_enable_cpuint(&g_intenable[0], 1 << ESP32_CPUINT_MAC);
 #endif
 
+#ifdef CONFIG_ESP32_BLE
+  intmap[ESP32_PERIPH_BT_BB_NMI] = CPUINT_ASSIGN(ESP32_IRQ_BT_BB_NMI);
+  intmap[ESP32_PERIPH_RWBT_NMI]  = CPUINT_ASSIGN(ESP32_IRQ_RWBT_NMI);
+  intmap[ESP32_PERIPH_RWBLE_IRQ] = CPUINT_ASSIGN(ESP32_IRQ_RWBLE_IRQ);
+  xtensa_enable_cpuint(&g_intenable[0], 1 << ESP32_PERIPH_BT_BB_NMI);
+  xtensa_enable_cpuint(&g_intenable[0], 1 << ESP32_PERIPH_RWBT_NMI);
+  xtensa_enable_cpuint(&g_intenable[0], 1 << ESP32_PERIPH_RWBLE_IRQ);
+#endif
+
   return OK;
 }
 
diff --git a/arch/xtensa/src/esp32/esp32_wifi_adapter.c b/arch/xtensa/src/esp32/esp32_wifi_adapter.c
index f49ac7b..07c124d 100644
--- a/arch/xtensa/src/esp32/esp32_wifi_adapter.c
+++ b/arch/xtensa/src/esp32/esp32_wifi_adapter.c
@@ -349,6 +349,8 @@ static void *wifi_coex_get_schm_curr_phase(void);
 static int wifi_coex_set_schm_curr_phase_idx(int idx);
 static int wifi_coex_get_schm_curr_phase_idx(void);
 
+extern void coex_bt_high_prio(void);
+
 /****************************************************************************
  * Public Functions declaration
  ****************************************************************************/
@@ -2495,6 +2497,7 @@ static void wifi_phy_enable(void)
       esp_phy_enable_clock();
       phy_set_wifi_mode_only(0);
       register_chipv7_phy(&phy_init_data, cal_data, PHY_RF_CAL_NONE);
+      coex_bt_high_prio();
     }
 
   g_phy_access_ref++;
@@ -2603,7 +2606,7 @@ int32_t esp_read_mac(uint8_t *mac, esp_mac_type_t type)
   uint8_t crc;
   int i;
 
-  if (type > ESP_MAC_WIFI_SOFTAP)
+  if (type > ESP_MAC_BT)
     {
       wlerr("Input type is error=%d\n", type);
       return -1;
@@ -2645,6 +2648,22 @@ int32_t esp_read_mac(uint8_t *mac, esp_mac_type_t type)
         }
     }
 
+  if (type == ESP_MAC_BT)
+    {
+      tmp = mac[0];
+      for (i = 0; i < 64; i++)
+        {
+          mac[0] = tmp | 0x02;
+          mac[0] ^= i << 2;
+
+          if (mac[0] != tmp)
+            {
+              break;
+            }
+        }
+      mac[5] += 1;
+    }
+
   return 0;
 }
 
diff --git a/arch/xtensa/src/esp32/esp32_wifi_adapter.h b/arch/xtensa/src/esp32/esp32_wifi_adapter.h
index dbe595b..ce039e9 100644
--- a/arch/xtensa/src/esp32/esp32_wifi_adapter.h
+++ b/arch/xtensa/src/esp32/esp32_wifi_adapter.h
@@ -26,6 +26,7 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
+#include <nuttx/wireless/wireless.h>
 
 #include <sys/types.h>
 
diff --git a/arch/xtensa/src/esp32/hardware/esp32_dport.h b/arch/xtensa/src/esp32/hardware/esp32_dport.h
index 6aa829d..a545535 100644
--- a/arch/xtensa/src/esp32/hardware/esp32_dport.h
+++ b/arch/xtensa/src/esp32/hardware/esp32_dport.h
@@ -1184,7 +1184,8 @@
 #define DPORT_SLAVE_SPI_MASK_PRO_V  0x1
 #define DPORT_SLAVE_SPI_MASK_PRO_S  0
 
-#define DPORT_WIFI_CLK_EN_REG          (DR_REG_DPORT_BASE + 0x0CC)
+#define DPORT_WIFI_CLK_EN_REG          (DR_REG_DPORT_BASE + 0x0cc)
+#define DPORT_CORE_RST_EN_REG          (DR_REG_DPORT_BASE + 0x0d0)
 
 #define DPORT_EMAC_CLK_EN              (BIT(14))
 
diff --git a/boards/xtensa/esp32/common/scripts/esp32.ld b/boards/xtensa/esp32/common/scripts/esp32.ld
index cce43ee..f047908 100644
--- a/boards/xtensa/esp32/common/scripts/esp32.ld
+++ b/boards/xtensa/esp32/common/scripts/esp32.ld
@@ -93,6 +93,17 @@ SECTIONS
 
     . = ALIGN (8);
     _sbss = ABSOLUTE(.);
+    _bss_start = ABSOLUTE(.);
+    *(.ext_ram.bss*)
+    _bt_bss_start = ABSOLUTE(.);
+    *libbt.a:(.bss .bss.* COMMON)
+    . = ALIGN (4);
+    _bt_bss_end = ABSOLUTE(.);
+    _btdm_bss_start = ABSOLUTE(.);
+    *libbtdm_app.a:(.bss .bss.* COMMON)
+    . = ALIGN (4);
+    _btdm_bss_end = ABSOLUTE(.);
+    . = ALIGN (8);
     *(.dynsbss)
     *(.sbss)
     *(.sbss.*)
@@ -109,6 +120,7 @@ SECTIONS
     *(COMMON)
     *libarch.a:esp32_spiflash.*(.bss  .bss.*  COMMON)
     . = ALIGN(8);
+    _bss_end = ABSOLUTE(.);
     _ebss = ABSOLUTE(.);
   } >dram0_0_seg
 
@@ -126,6 +138,14 @@ SECTIONS
     /* .data initialized on power-up in ROMed configurations. */
 
     _sdata = ABSOLUTE(.);
+    _bt_data_start = ABSOLUTE(.);
+    *libbt.a:(.data .data.*)
+    . = ALIGN (4);
+    _bt_data_end = ABSOLUTE(.);
+    _btdm_data_start = ABSOLUTE(.);
+    *libbtdm_app.a:(.data .data.*)
+    . = ALIGN (4);
+    _btdm_data_end = ABSOLUTE(.);
     KEEP (*(.data))
     KEEP (*(.data.*))
     KEEP (*(.gnu.linkonce.d.*))
diff --git a/boards/xtensa/esp32/common/scripts/esp32.template.ld b/boards/xtensa/esp32/common/scripts/esp32.template.ld
index 7632e2a..36aa1ed 100644
--- a/boards/xtensa/esp32/common/scripts/esp32.template.ld
+++ b/boards/xtensa/esp32/common/scripts/esp32.template.ld
@@ -34,6 +34,7 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
+#include "esp32_aliases.ld"
 
 #ifdef CONFIG_ESP32_FLASH_2M
 #  define FLASH_SIZE 0x200000
diff --git a/boards/xtensa/esp32/common/scripts/esp32_aliases.ld b/boards/xtensa/esp32/common/scripts/esp32_aliases.ld
new file mode 100644
index 0000000..6ffa84d
--- /dev/null
+++ b/boards/xtensa/esp32/common/scripts/esp32_aliases.ld
@@ -0,0 +1,31 @@
+/****************************************************************************
+ * boards/xtensa/esp32/common/scripts/esp32_aliases.ld
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/* Lower-case aliases for symbols not compliant to nxstyle */
+
+/* Bluetooth needs symbol alias, to be removed after IDF rename it */
+
+#ifdef CONFIG_ESP32_BLE
+  api_vhci_host_check_send_available = API_vhci_host_check_send_available;
+  api_vhci_host_send_packet = API_vhci_host_send_packet;
+  api_vhci_host_register_callback = API_vhci_host_register_callback;
+#endif
diff --git a/boards/xtensa/esp32/common/scripts/esp32_rom.ld b/boards/xtensa/esp32/common/scripts/esp32_rom.ld
index a6755fa..c56f28d 100644
--- a/boards/xtensa/esp32/common/scripts/esp32_rom.ld
+++ b/boards/xtensa/esp32/common/scripts/esp32_rom.ld
@@ -181,11 +181,11 @@ PROVIDE ( _sbss_btdm = 0x3ffb8000);
 PROVIDE ( _ebss_btdm = 0x3ffbff70);
 PROVIDE ( _daylight = 0x3ffae0a4 );
 PROVIDE ( dbg_default_handler = 0x3ff97218 );
+PROVIDE ( dbg_default_state = 0x3ff97220 );
 PROVIDE ( dbg_state = 0x3ffb8d5d );
 PROVIDE ( DebugE256PublicKey_x = 0x3ff97428 );
 PROVIDE ( DebugE256PublicKey_y = 0x3ff97408 );
 PROVIDE ( DebugE256SecretKey = 0x3ff973e8 );
-PROVIDE ( _DebugExceptionVector = 0x40000280 );
 PROVIDE ( debug_timer = 0x3ffe042c );
 PROVIDE ( debug_timerfn = 0x3ffe0430 );
 PROVIDE ( dh_group14_generator = 0x3ff9ac60 );
@@ -373,6 +373,7 @@ PROVIDE ( hci_cmd_desc_tab_testing = 0x3ff97a98 );
 PROVIDE ( hci_cmd_desc_tab_vs = 0x3ff97714 );
 PROVIDE ( hci_command_handler = 0x4004c928 );
 PROVIDE ( hci_env = 0x3ffb9350 );
+PROVIDE ( rwip_env = 0x3ffb8bcc );
 PROVIDE ( hci_evt_dbg_desc_tab = 0x3ff9750c );
 PROVIDE ( hci_evt_desc_tab = 0x3ff9751c );
 PROVIDE ( hci_evt_le_desc_tab = 0x3ff974b4 );
@@ -406,6 +407,8 @@ PROVIDE ( __itoa = 0x40056678 );
 PROVIDE ( jd_decomp = 0x400613e8 );
 PROVIDE ( jd_prepare = 0x40060fa8 );
 PROVIDE ( ke_env = 0x3ffb93cc );
+PROVIDE ( ke_handler_search = 0x4001a430 );
+PROVIDE ( ke_task_env = 0x3ffb81d4 );
 PROVIDE ( _KernelExceptionVector = 0x40000300 );
 PROVIDE ( _kill_r = 0x4000bd10 );
 PROVIDE ( labs = 0x40056370 );
@@ -449,9 +452,18 @@ PROVIDE ( llc_state = 0x3ffb96f8 );
 PROVIDE ( lldesc_build_chain = 0x4000a850 );
 PROVIDE ( lldesc_num2link = 0x4000a948 );
 PROVIDE ( lldesc_set_owner = 0x4000a974 );
+PROVIDE ( lld_evt_deferred_elt_push = 0x400466b4 );
+PROVIDE ( lld_evt_deferred_elt_pop = 0x400466dc );
+PROVIDE ( lld_evt_winsize_change = 0x40046730 );
+PROVIDE ( lld_evt_rxwin_compute = 0x400467c8 );
+PROVIDE ( lld_evt_slave_time_compute = 0x40046818 );
 PROVIDE ( lld_evt_env = 0x3ffb9704 );
+PROVIDE ( lld_evt_elt_wait_get = 0x400468e4 );
+PROVIDE ( lld_evt_get_next_free_slot = 0x4004692c );
 PROVIDE ( lld_pdu_adv_pk_desc_tab = 0x3ff98c70 );
 PROVIDE ( lld_pdu_llcp_pk_desc_tab = 0x3ff98b68 );
+PROVIDE ( lld_pdu_tx_flush_list = 0x4004a760 );
+PROVIDE ( lld_pdu_pack = 0x4004ab14 );
 PROVIDE ( LLM_AA_CT1 = 0x3ff98d8a );
 PROVIDE ( LLM_AA_CT2 = 0x3ff98d88 );
 PROVIDE ( llm_default_handler = 0x3ff98d80 );
@@ -581,6 +593,9 @@ PROVIDE ( r_E1 = 0x400108e8 );
 PROVIDE ( r_E21 = 0x40010968 );
 PROVIDE ( r_E22 = 0x400109b4 );
 PROVIDE ( r_E3 = 0x40010a58 );
+PROVIDE ( lm_n192_mod_mul = 0x40011dc0 );
+PROVIDE ( lm_n192_mod_add = 0x40011e9c );
+PROVIDE ( lm_n192_mod_sub = 0x40011eec );
 PROVIDE ( r_ea_alarm_clear = 0x40015ab4 );
 PROVIDE ( r_ea_alarm_set = 0x40015a10 );
 PROVIDE ( read = 0x400017dc );
@@ -598,6 +613,8 @@ PROVIDE ( r_ea_interval_insert = 0x4001557c );
 PROVIDE ( r_ea_interval_remove = 0x40015590 );
 PROVIDE ( realloc = 0x4000becc );
 PROVIDE ( _realloc_r = 0x4000bbe0 );
+PROVIDE ( ea_conflict_check = 0x40014e9c );
+PROVIDE ( ea_prog_timer = 0x40014f88 );
 PROVIDE ( r_ea_offset_req = 0x40015748 );
 PROVIDE ( r_ea_sleep_check = 0x40015928 );
 PROVIDE ( r_ea_sw_isr = 0x40015724 );
@@ -609,6 +626,7 @@ PROVIDE ( r_ecc_gen_new_public_key = 0x400170c0 );
 PROVIDE ( r_ecc_gen_new_secret_key = 0x400170e4 );
 PROVIDE ( r_ecc_get_debug_Keys = 0x40017224 );
 PROVIDE ( r_ecc_init = 0x40016dbc );
+PROVIDE ( ecc_point_multiplication_uint8_256 = 0x40016804 );
 PROVIDE ( RecvBuff = 0x3ffe009c );
 PROVIDE ( recv_packet = 0x40009424 );
 PROVIDE ( r_em_buf_init = 0x4001729c );
@@ -910,6 +928,118 @@ PROVIDE ( r_lc_util_get_offset_clke = 0x4002f538 );
 PROVIDE ( r_lc_util_get_offset_clkn = 0x4002f51c );
 PROVIDE ( r_lc_util_set_loc_trans_coll = 0x4002f500 );
 PROVIDE ( r_lc_version = 0x40020a30 );
+PROVIDE ( lc_set_encap_pdu_data_p192 = 0x4002e4c8 );
+PROVIDE ( lc_set_encap_pdu_data_p256 = 0x4002e454 );
+PROVIDE ( lm_get_auth_method = 0x40023420 );
+PROVIDE ( lmp_accepted_ext_handler = 0x40027290 );
+PROVIDE ( lmp_not_accepted_ext_handler = 0x40029c54 );
+PROVIDE ( lmp_clk_adj_handler = 0x40027468 );
+PROVIDE ( lmp_clk_adj_ack_handler = 0x400274f4 );
+PROVIDE ( lm_get_auth_method = 0x40023420 );
+PROVIDE ( lmp_accepted_ext_handler = 0x40027290 );
+PROVIDE ( lmp_not_accepted_ext_handler = 0x40029c54 );
+PROVIDE ( lmp_clk_adj_handler = 0x40027468 );
+PROVIDE ( lmp_clk_adj_ack_handler = 0x400274f4 );
+PROVIDE ( lmp_clk_adj_req_handler = 0x4002751c );
+PROVIDE ( lmp_feats_res_ext_handler = 0x4002cac4 );
+PROVIDE ( lmp_feats_req_ext_handler = 0x4002ccb0 );
+PROVIDE ( lmp_pkt_type_tbl_req_handler = 0x40027574 );
+PROVIDE ( lmp_esco_link_req_handler = 0x40027610 );
+PROVIDE ( lmp_rmv_esco_link_req_handler = 0x400276e8 );
+PROVIDE ( lmp_ch_class_req_handler = 0x40027730 );
+PROVIDE ( lmp_ch_class_handler = 0x4002ca18 );
+PROVIDE ( lmp_ssr_req_handler = 0x4002780c );
+PROVIDE ( lmp_ssr_res_handler = 0x40027900 );
+PROVIDE ( lmp_pause_enc_aes_req_handler = 0x400279a4 );
+PROVIDE ( lmp_pause_enc_req_handler = 0x4002df90 );
+PROVIDE ( lmp_resume_enc_req_handler = 0x4002e084 );
+PROVIDE ( lmp_num_comparison_fail_handler = 0x40027a74 );
+PROVIDE ( lmp_passkey_fail_handler = 0x40027aec );
+PROVIDE ( lmp_keypress_notif_handler = 0x4002c5c8 );
+PROVIDE ( lmp_pwr_ctrl_req_handler = 0x400263bc );
+PROVIDE ( lmp_pwr_ctrl_res_handler = 0x40026480 );
+PROVIDE ( lmp_auto_rate_handler = 0x40026548 );
+PROVIDE ( lmp_pref_rate_handler = 0x4002657c );
+PROVIDE ( lmp_name_req_handler = 0x40025050 );
+PROVIDE ( lmp_name_res_handler = 0x400250bc );
+PROVIDE ( lmp_not_accepted_handler = 0x400251d0 );
+PROVIDE ( lmp_accepted_handler = 0x4002e894 );
+PROVIDE ( lmp_clk_off_req_handler = 0x40025a44 );
+PROVIDE ( lmp_clk_off_res_handler = 0x40025ab8 );
+PROVIDE ( lmp_detach_handler = 0x40025b74 );
+PROVIDE ( lmp_tempkey_handler = 0x4002b6b0 );
+PROVIDE ( lmp_temprand_handler = 0x4002b74c );
+PROVIDE ( lmp_sres_handler = 0x4002b840 );
+PROVIDE ( lmp_aurand_handler = 0x4002bda0 );
+PROVIDE ( lmp_unitkey_handler = 0x4002c13c );
+PROVIDE ( lmp_combkey_handler = 0x4002c234 );
+PROVIDE ( lmp_inrand_handler = 0x4002c414 );
+PROVIDE ( lmp_oob_fail_handler = 0x40027b84 );
+PROVIDE ( lmp_ping_req_handler = 0x40027c08 );
+PROVIDE ( lmp_ping_res_handler = 0x40027c5c );
+PROVIDE ( lmp_enc_mode_req_handler = 0x40025c60 );
+PROVIDE ( lmp_enc_key_size_req_handler = 0x40025e54 );
+PROVIDE ( lmp_switch_req_handler = 0x40025f84 );
+PROVIDE ( lmp_start_enc_req_handler = 0x4002e124 );
+PROVIDE ( lmp_stop_enc_req_handler = 0x4002de30 );
+PROVIDE ( lmp_sniff_req_handler = 0x400260c8 );
+PROVIDE ( lmp_unsniff_req_handler = 0x400261e0 );
+PROVIDE ( lmp_incr_pwr_req_handler = 0x4002629c );
+PROVIDE ( lmp_decr_pwr_req_handler = 0x400262f8 );
+PROVIDE ( lmp_max_pwr_handler = 0x40026354 );
+PROVIDE ( lmp_min_pwr_handler = 0x40026388 );
+PROVIDE ( lmp_ver_req_handler = 0x400265f0 );
+PROVIDE ( lmp_ver_res_handler = 0x40026670 );
+PROVIDE ( lmp_qos_handler = 0x40026790 );
+PROVIDE ( lmp_qos_req_handler = 0x40026844 );
+PROVIDE ( lmp_sco_link_req_handler = 0x40026930 );
+PROVIDE ( lmp_rmv_sco_link_req_handler = 0x40026a10 );
+PROVIDE ( lmp_max_slot_handler = 0x40026a54 );
+PROVIDE ( lmp_max_slot_req_handler = 0x40026aac );
+PROVIDE ( lmp_timing_accu_req_handler = 0x40026b54 );
+PROVIDE ( lmp_timing_accu_res_handler = 0x40026bcc );
+PROVIDE ( lmp_setup_cmp_handler = 0x40026c84 );
+PROVIDE ( lmp_feats_res_handler = 0x4002b548 );
+PROVIDE ( lmp_feats_req_handler = 0x4002b620 );
+PROVIDE ( lmp_host_con_req_handler = 0x4002b3d8 );
+PROVIDE ( lmp_use_semi_perm_key_handler = 0x4002b4c4 );
+PROVIDE ( lmp_slot_off_handler = 0x40026cc8 );
+PROVIDE ( lmp_page_mode_req_handler = 0x40026d0c );
+PROVIDE ( lmp_page_scan_mode_req_handler = 0x40026d4c );
+PROVIDE ( lmp_supv_to_handler = 0x40026d94 );
+PROVIDE ( lmp_test_activate_handler = 0x40026e7c );
+PROVIDE ( lmp_test_ctrl_handler = 0x40026ee4 );
+PROVIDE ( lmp_enc_key_size_mask_req_handler = 0x40027038 );
+PROVIDE ( lmp_enc_key_size_mask_res_handler = 0x400270a4 );
+PROVIDE ( lmp_set_afh_handler = 0x4002b2e4 );
+PROVIDE ( lmp_encaps_hdr_handler = 0x40027120 );
+PROVIDE ( lmp_encaps_payl_handler = 0x4002e590 );
+PROVIDE ( lmp_sp_nb_handler = 0x4002acf0 );
+PROVIDE ( lmp_sp_cfm_handler = 0x4002b170 );
+PROVIDE ( lmp_dhkey_chk_handler = 0x4002ab48 );
+PROVIDE ( lmp_pause_enc_aes_req_handler = 0x400279a4 );
+PROVIDE ( lmp_io_cap_res_handler = 0x4002c670 );
+PROVIDE ( lmp_io_cap_req_handler = 0x4002c7a4 );
+PROVIDE ( lc_cmd_cmp_bd_addr_send = 0x4002cec4 );
+PROVIDE ( ld_acl_tx_packet_type_select = 0x4002fb40 );
+PROVIDE ( ld_acl_sched = 0x40033268 );
+PROVIDE ( ld_acl_sniff_sched = 0x4003340c );
+PROVIDE ( ld_acl_rx = 0x4003274c );
+PROVIDE ( ld_acl_tx = 0x4002ffdc );
+PROVIDE ( ld_acl_rx_sync = 0x4002fbec );
+PROVIDE ( ld_acl_rx_sync2 = 0x4002fd8c );
+PROVIDE ( ld_acl_rx_no_sync = 0x4002fe78 );
+PROVIDE ( ld_acl_clk_isr = 0x40030cf8 );
+PROVIDE ( ld_acl_rsw_frm_cbk = 0x40033bb0 );
+PROVIDE ( ld_sco_modify = 0x40031778 );
+PROVIDE ( lm_cmd_cmp_send = 0x40051838 );
+PROVIDE ( ld_sco_frm_cbk = 0x400349dc );
+PROVIDE ( ld_acl_sco_rsvd_check = 0x4002fa94 );
+PROVIDE ( ld_acl_sniff_frm_cbk = 0x4003482c );
+PROVIDE ( ld_inq_end = 0x4003ab48 );
+PROVIDE ( ld_inq_sched = 0x4003aba4 );
+PROVIDE ( ld_inq_frm_cbk = 0x4003ae4c );
+PROVIDE ( ld_pscan_frm_cbk = 0x4003ebe4 );
 PROVIDE ( r_ld_acl_active_hop_types_get = 0x40036e10 );
 PROVIDE ( r_ld_acl_afh_confirm = 0x40036d40 );
 PROVIDE ( r_ld_acl_afh_prepare = 0x40036c84 );
@@ -954,6 +1084,11 @@ PROVIDE ( r_ld_acl_timing_accuracy_set = 0x4003673c );
 PROVIDE ( r_ld_acl_t_poll_get = 0x40036024 );
 PROVIDE ( r_ld_acl_t_poll_set = 0x40036068 );
 PROVIDE ( r_ld_acl_tx_enc = 0x400362f8 );
+PROVIDE ( ld_acl_frm_cbk = 0x40034414 );
+PROVIDE ( ld_acl_rsw_end = 0x40032bc0 );
+PROVIDE ( ld_acl_end = 0x40033140 );
+PROVIDE ( ld_acl_resched = 0x40033814 );
+PROVIDE ( ld_acl_test_mode_update = 0x40032050 );
 PROVIDE ( r_ld_acl_unsniff = 0x400361e0 );
 PROVIDE ( r_ld_active_check = 0x4003cac4 );
 PROVIDE ( r_ld_afh_ch_assess_data_get = 0x4003caec );
@@ -1333,6 +1468,13 @@ PROVIDE ( r_lm_num_clk_adj_ack_pending_set = 0x4004f500 );
 PROVIDE ( r_lm_oob_f1 = 0x40012e54 );
 PROVIDE ( r_lm_pca_sscan_link_get = 0x4004f560 );
 PROVIDE ( r_lm_pca_sscan_link_set = 0x4004f550 );
+PROVIDE ( nvds_null_read = 0x400542a0 );
+PROVIDE ( nvds_null_write = 0x400542a8 );
+PROVIDE ( nvds_null_erase = 0x400542b0 );
+PROVIDE ( nvds_read = 0x400542c4 );
+PROVIDE ( nvds_write = 0x400542fc );
+PROVIDE ( nvds_erase = 0x40054334 );
+PROVIDE ( nvds_init_memory = 0x40054358 );
 PROVIDE ( r_lmp_pack = 0x4001135c );
 PROVIDE ( r_lmp_unpack = 0x4001149c );
 PROVIDE ( r_lm_read_features = 0x4004f0d8 );
@@ -1823,7 +1965,23 @@ PROVIDE ( Xthal_intlevel = 0x3ff9c2b4 );
 PROVIDE ( xthal_memcpy = 0x4000c0bc );
 PROVIDE ( xthal_set_ccompare = 0x4000c058 );
 PROVIDE ( xthal_set_intclear = 0x4000c1ec );
+PROVIDE ( _xtos_set_intlevel = 0x4000bfdc );
+PROVIDE ( g_ticks_per_us_pro = 0x3ffe01e0 );
+PROVIDE ( g_ticks_per_us_app = 0x3ffe40f0 );
+PROVIDE ( esp_rom_spiflash_config_param = 0x40063238 );
+PROVIDE ( esp_rom_spiflash_read_user_cmd = 0x400621b0 );
+PROVIDE ( esp_rom_spiflash_write_encrypted_disable = 0x40062e60 );
+PROVIDE ( esp_rom_spiflash_write_encrypted_enable = 0x40062df4 );
+PROVIDE ( esp_rom_spiflash_prepare_encrypted_data = 0x40062e1c );
+PROVIDE ( esp_rom_spiflash_select_qio_pins = 0x40061ddc );
+PROVIDE ( esp_rom_spiflash_attach = 0x40062a6c );
 PROVIDE ( esp_rom_spiflash_config_clk = 0x40062bc8 );
+PROVIDE ( g_rom_spiflash_chip = 0x3ffae270 );
+PROVIDE ( hci_le_rd_rem_used_feats_cmd_handler = 0x400417b4 );
+PROVIDE ( llcp_length_req_handler = 0x40043808 );
+PROVIDE ( llcp_unknown_rsp_handler = 0x40043ba8 );
+PROVIDE ( llcp_channel_map_req_handler = 0x4004291c );
+PROVIDE ( llcp_con_up_req_handler = 0x400426f0 );
 PROVIDE ( _xtos_alloca_handler = 0x40000010 );
 PROVIDE ( _xtos_cause3_handler = 0x40000dd8 );
 PROVIDE ( _xtos_c_handler_table = 0x3ffe0548 );
@@ -1858,3 +2016,35 @@ PROVIDE ( esp_rom_spiflash_prepare_encrypted_data = 0x40062e1c );
 
 PROVIDE ( esp_rom_printf   = ets_printf );
 PROVIDE ( esp_rom_delay_us = ets_delay_us );
+
+/* Following are static data, but can be used, not generated by script <<<<< btdm data */
+
+PROVIDE ( hci_tl_env = 0x3ffb8154 );
+PROVIDE ( ld_acl_env = 0x3ffb8258 );
+PROVIDE ( ea_env = 0x3ffb80ec );
+PROVIDE ( lc_sco_data_path_config = 0x3ffb81f8 );
+PROVIDE ( lc_sco_env = 0x3ffb81fc );
+PROVIDE ( ld_active_ch_map = 0x3ffb8334 );
+PROVIDE ( ld_bcst_acl_env = 0x3ffb8274 );
+PROVIDE ( ld_csb_rx_env = 0x3ffb8278 );
+PROVIDE ( ld_csb_tx_env = 0x3ffb827c );
+PROVIDE ( ld_env = 0x3ffb9510 );
+PROVIDE ( ld_fm_env = 0x3ffb8284 );
+PROVIDE ( ld_inq_env = 0x3ffb82e4 );
+PROVIDE ( ld_iscan_env = 0x3ffb82e8 );
+PROVIDE ( ld_page_env = 0x3ffb82f0 );
+PROVIDE ( ld_pca_env = 0x3ffb82f4 );
+PROVIDE ( ld_pscan_env = 0x3ffb8308 );
+PROVIDE ( ld_sched_env = 0x3ffb830c );
+PROVIDE ( ld_sched_params = 0x3ffb96c0 );
+PROVIDE ( ld_sco_env = 0x3ffb824c );
+PROVIDE ( ld_sscan_env = 0x3ffb832c );
+PROVIDE ( ld_strain_env = 0x3ffb8330 );
+PROVIDE ( LM_Sniff = 0x3ffb8230 );
+PROVIDE ( LM_SniffSubRate = 0x3ffb8214 );
+PROVIDE ( prbs_64bytes = 0x3ff98992 );
+PROVIDE ( nvds_env = 0x3ffb8364 );
+PROVIDE ( nvds_magic_number = 0x3ff9912a );
+PROVIDE ( TASK_DESC_LLD = 0x3ff98b58 );
+/* Above are static data, but can be used, not generated by script >>>>> btdm data */
+
diff --git a/boards/xtensa/esp32/esp32-devkitc/configs/ble/defconfig b/boards/xtensa/esp32/esp32-devkitc/configs/ble/defconfig
new file mode 100644
index 0000000..0783b32
--- /dev/null
+++ b/boards/xtensa/esp32/esp32-devkitc/configs/ble/defconfig
@@ -0,0 +1,60 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_ARCH_LEDS is not set
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+# CONFIG_NSH_CMDPARMS is not set
+CONFIG_ALLOW_BSD_COMPONENTS=y
+CONFIG_ARCH="xtensa"
+CONFIG_ARCH_BOARD="esp32-devkitc"
+CONFIG_ARCH_BOARD_ESP32_DEVKITC=y
+CONFIG_ARCH_CHIP="esp32"
+CONFIG_ARCH_CHIP_ESP32=y
+CONFIG_ARCH_CHIP_ESP32WROVER=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_XTENSA=y
+CONFIG_BOARD_LOOPSPERMSEC=16717
+CONFIG_BTSAK=y
+CONFIG_BUILTIN=y
+CONFIG_DRIVERS_BLUETOOTH=y
+CONFIG_DRIVERS_IEEE80211=y
+CONFIG_DRIVERS_WIRELESS=y
+CONFIG_ESP32_BLE=y
+CONFIG_ESP32_UART0=y
+CONFIG_FS_PROCFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_IDLETHREAD_STACKSIZE=3072
+CONFIG_INTELHEX_BINARY=y
+CONFIG_MM_REGIONS=3
+CONFIG_NETDEV_LATEINIT=y
+CONFIG_NET_BLUETOOTH=y
+CONFIG_NET_SOCKOPTS=y
+CONFIG_NET_TCP=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_PREALLOC_MQ_MSGS=32
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_PTHREAD_MUTEX_TYPES=y
+CONFIG_RAM_SIZE=114688
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_SPINLOCK=y
+CONFIG_START_DAY=6
+CONFIG_START_MONTH=12
+CONFIG_START_YEAR=2011
+CONFIG_SYSTEM_NSH=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_USER_ENTRYPOINT="nsh_main"
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_BLUETOOTH=y
diff --git a/boards/xtensa/esp32/esp32-devkitc/src/Make.defs b/boards/xtensa/esp32/esp32-devkitc/src/Make.defs
index a3ef9b5..658aa43 100644
--- a/boards/xtensa/esp32/esp32-devkitc/src/Make.defs
+++ b/boards/xtensa/esp32/esp32-devkitc/src/Make.defs
@@ -56,7 +56,7 @@ SCRIPTOUT = $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32_out.ld
 .PHONY = context distclean
 
 $(SCRIPTOUT): $(LDSCRIPT_TEMPLATE) $(CONFIGFILE)
-	$(Q) $(CC) -isystem $(TOPDIR)/include -C -P -x c -E $(LDSCRIPT_TEMPLATE) -o $@
+	$(Q) $(CC) -isystem $(TOPDIR)/include -I $(BOARD_COMMON_DIR)$(DELIM)scripts -C -P -x c -E $(LDSCRIPT_TEMPLATE) -o $@
 
 context:: $(SCRIPTOUT)
 
diff --git a/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c
index 77db8c5..106df62 100644
--- a/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c
+++ b/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c
@@ -62,6 +62,10 @@
 #  include "esp32_board_wdt.h"
 #endif
 
+#ifdef CONFIG_ESP32_BLE
+#  include "esp32_ble.h"
+#endif
+
 #ifdef CONFIG_ESP32_WIRELESS
 #  include "esp32_board_wlan.h"
 #endif
@@ -221,6 +225,14 @@ int esp32_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_ESP32_BLE
+  ret = esp32_ble_initialize();
+  if (ret)
+    {
+      syslog(LOG_ERR, "ERROR: Failed to initialize BLE: %d \n", ret);
+    }
+#endif
+
 #ifdef CONFIG_ESP32_WIRELESS
   ret = board_wlan_init();
   if (ret < 0)
diff --git a/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_bringup.c
index 7285d87..f09919f 100644
--- a/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_bringup.c
+++ b/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_bringup.c
@@ -62,6 +62,10 @@
 #  include "esp32_rt_timer.h"
 #endif
 
+#ifdef CONFIG_ESP32_BLE
+#  include "esp32_ble.h"
+#endif
+
 #ifdef CONFIG_ESP32_WIRELESS
 #  include "esp32_board_wlan.h"
 #endif
@@ -166,6 +170,14 @@ int esp32_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_ESP32_BLE
+  ret = esp32_ble_initialize();
+  if (ret)
+    {
+      syslog(LOG_ERR, "ERROR: Failed to initialize BLE: %d \n", ret);
+    }
+#endif
+
 #ifdef CONFIG_ESP32_WIRELESS
   ret = board_wlan_init();
   if (ret < 0)
diff --git a/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_bringup.c
index 52a3991..af7871d 100644
--- a/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_bringup.c
+++ b/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_bringup.c
@@ -61,6 +61,10 @@
 #  include "esp32_board_wdt.h"
 #endif
 
+#ifdef CONFIG_ESP32_BLE
+#  include "esp32_ble.h"
+#endif
+
 #ifdef CONFIG_ESP32_WIRELESS
 #  include "esp32_board_wlan.h"
 #endif
@@ -200,6 +204,14 @@ int esp32_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_ESP32_BLE
+  ret = esp32_ble_initialize();
+  if (ret)
+    {
+      syslog(LOG_ERR, "ERROR: Failed to initialize BLE: %d \n", ret);
+    }
+#endif
+
 #ifdef CONFIG_ESP32_WIRELESS
   ret = board_wlan_init();
   if (ret < 0)
diff --git a/boards/xtensa/esp32/ttgo_lora_esp32/src/esp32_bringup.c b/boards/xtensa/esp32/ttgo_lora_esp32/src/esp32_bringup.c
index 3d307cf..701f611 100644
--- a/boards/xtensa/esp32/ttgo_lora_esp32/src/esp32_bringup.c
+++ b/boards/xtensa/esp32/ttgo_lora_esp32/src/esp32_bringup.c
@@ -62,6 +62,10 @@
 #  include "esp32_board_wdt.h"
 #endif
 
+#ifdef CONFIG_ESP32_BLE
+#  include "esp32_ble.h"
+#endif
+
 #ifdef CONFIG_ESP32_WIRELESS
 #  include "esp32_board_wlan.h"
 #endif
@@ -192,6 +196,14 @@ int esp32_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_ESP32_BLE
+  ret = esp32_ble_initialize();
+  if (ret)
+    {
+      syslog(LOG_ERR, "ERROR: Failed to initialize BLE: %d \n", ret);
+    }
+#endif
+
 #ifdef CONFIG_ESP32_WIRELESS
   ret = board_wlan_init();
   if (ret < 0)